Lines Matching +full:flash +full:- +full:led

1 // SPDX-License-Identifier: GPL-2.0-only
15 #include <linux/led-class-flash.h>
22 #include <media/v4l2-flash-led-class.h>
43 #define MT6370_FLCSEN_MASK(_id) BIT(MT6370_LED_FLASH2 - (_id))
71 struct led_classdev_flash flash; member
89 struct mt6370_led *led = to_mt6370_led(lcdev, flash.led_cdev); in mt6370_torch_brightness_set() local
90 struct mt6370_priv *priv = led->priv; in mt6370_torch_brightness_set()
91 u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : in mt6370_torch_brightness_set()
92 MT6370_FLCSEN_MASK(led->led_no); in mt6370_torch_brightness_set()
98 mutex_lock(&priv->lock); in mt6370_torch_brightness_set()
101 * There is only one set of flash control logic, and this flag is used to check if 'strobe' in mt6370_torch_brightness_set()
104 if (priv->fled_strobe_used) { in mt6370_torch_brightness_set()
105 dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", priv->fled_strobe_used); in mt6370_torch_brightness_set()
106 ret = -EBUSY; in mt6370_torch_brightness_set()
111 curr = priv->fled_torch_used | BIT(led->led_no); in mt6370_torch_brightness_set()
113 curr = priv->fled_torch_used & ~BIT(led->led_no); in mt6370_torch_brightness_set()
119 level -= 1; in mt6370_torch_brightness_set()
120 if (led->led_no == MT6370_LED_JOINT) { in mt6370_torch_brightness_set()
124 * There're two flash channels in MT6370. If joint flash output is used, in mt6370_torch_brightness_set()
128 flevel[1] = level - flevel[0]; in mt6370_torch_brightness_set()
130 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(i), in mt6370_torch_brightness_set()
136 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(led->led_no), in mt6370_torch_brightness_set()
143 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val); in mt6370_torch_brightness_set()
147 priv->fled_torch_used = curr; in mt6370_torch_brightness_set()
150 mutex_unlock(&priv->lock); in mt6370_torch_brightness_set()
157 * Because of the current spikes when turning on the flash, the brightness should be kept in mt6370_flash_brightness_set()
158 * by the LED framework. This empty function is used to prevent checking failure when in mt6370_flash_brightness_set()
166 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); in _mt6370_flash_brightness_set() local
167 struct mt6370_priv *priv = led->priv; in _mt6370_flash_brightness_set()
168 struct led_flash_setting *setting = &fl_cdev->brightness; in _mt6370_flash_brightness_set()
169 u32 val = (brightness - setting->min) / setting->step; in _mt6370_flash_brightness_set()
172 if (led->led_no == MT6370_LED_JOINT) { in _mt6370_flash_brightness_set()
176 * There're two flash channels in MT6370. If joint flash output is used, storbe in _mt6370_flash_brightness_set()
180 flevel[1] = val - flevel[0]; in _mt6370_flash_brightness_set()
182 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDISTRB(i), in _mt6370_flash_brightness_set()
188 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDISTRB(led->led_no), in _mt6370_flash_brightness_set()
197 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); in mt6370_strobe_set() local
198 struct mt6370_priv *priv = led->priv; in mt6370_strobe_set()
199 struct led_classdev *lcdev = &fl_cdev->led_cdev; in mt6370_strobe_set()
200 struct led_flash_setting *s = &fl_cdev->brightness; in mt6370_strobe_set()
201 u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : in mt6370_strobe_set()
202 MT6370_FLCSEN_MASK(led->led_no); in mt6370_strobe_set()
208 mutex_lock(&priv->lock); in mt6370_strobe_set()
211 * There is only one set of flash control logic, and this flag is used to check if 'torch' in mt6370_strobe_set()
214 if (priv->fled_torch_used) { in mt6370_strobe_set()
215 dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", priv->fled_torch_used); in mt6370_strobe_set()
216 ret = -EBUSY; in mt6370_strobe_set()
221 curr = priv->fled_strobe_used | BIT(led->led_no); in mt6370_strobe_set()
223 curr = priv->fled_strobe_used & ~BIT(led->led_no); in mt6370_strobe_set()
228 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val); in mt6370_strobe_set()
230 dev_err(lcdev->dev, "[%d] control current source %d fail\n", led->led_no, state); in mt6370_strobe_set()
235 * If the flash needs to turn on, configure the flash current to ramp up to the setting in mt6370_strobe_set()
238 ret = _mt6370_flash_brightness_set(fl_cdev, state ? s->val : s->min); in mt6370_strobe_set()
240 dev_err(lcdev->dev, "[%d] Failed to set brightness\n", led->led_no); in mt6370_strobe_set()
245 * For the flash to turn on/off, we must wait for HW ramping up/down time 5ms/500us to in mt6370_strobe_set()
248 if (!priv->fled_strobe_used && curr) in mt6370_strobe_set()
250 else if (priv->fled_strobe_used && !curr) in mt6370_strobe_set()
253 priv->fled_strobe_used = curr; in mt6370_strobe_set()
256 mutex_unlock(&priv->lock); in mt6370_strobe_set()
262 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); in mt6370_strobe_get() local
263 struct mt6370_priv *priv = led->priv; in mt6370_strobe_get()
265 mutex_lock(&priv->lock); in mt6370_strobe_get()
266 *state = !!(priv->fled_strobe_used & BIT(led->led_no)); in mt6370_strobe_get()
267 mutex_unlock(&priv->lock); in mt6370_strobe_get()
274 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); in mt6370_timeout_set() local
275 struct mt6370_priv *priv = led->priv; in mt6370_timeout_set()
276 struct led_flash_setting *s = &fl_cdev->timeout; in mt6370_timeout_set()
277 u32 val = (timeout - s->min) / s->step; in mt6370_timeout_set()
279 return regmap_update_bits(priv->regmap, MT6370_REG_STRBTO, MT6370_STRBTO_MASK, val); in mt6370_timeout_set()
284 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); in mt6370_fault_get() local
285 struct mt6370_priv *priv = led->priv; in mt6370_fault_get()
291 ret = regmap_read(priv->regmap, MT6370_REG_CHGSTAT2, &chg_stat); in mt6370_fault_get()
295 ret = regmap_raw_read(priv->regmap, MT6370_REG_FLEDSTAT1, &fled_stat, sizeof(fled_stat)); in mt6370_fault_get()
299 switch (led->led_no) { in mt6370_fault_get()
315 return -EINVAL; in mt6370_fault_get()
346 struct led_classdev_flash *flash = v4l2_flash->fled_cdev; in mt6370_flash_external_strobe_set() local
347 struct mt6370_led *led = to_mt6370_led(flash, flash); in mt6370_flash_external_strobe_set() local
348 struct mt6370_priv *priv = led->priv; in mt6370_flash_external_strobe_set()
349 u32 mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : in mt6370_flash_external_strobe_set()
350 MT6370_FLCSEN_MASK(led->led_no); in mt6370_flash_external_strobe_set()
354 mutex_lock(&priv->lock); in mt6370_flash_external_strobe_set()
356 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, mask, val); in mt6370_flash_external_strobe_set()
361 priv->fled_strobe_used |= BIT(led->led_no); in mt6370_flash_external_strobe_set()
363 priv->fled_strobe_used &= ~BIT(led->led_no); in mt6370_flash_external_strobe_set()
366 mutex_unlock(&priv->lock); in mt6370_flash_external_strobe_set()
374 static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg) in mt6370_init_v4l2_flash_config() argument
377 struct led_flash_setting *s = &cfg->intensity; in mt6370_init_v4l2_flash_config()
379 lcdev = &led->flash.led_cdev; in mt6370_init_v4l2_flash_config()
381 s->min = MT6370_ITORCH_MIN_uA; in mt6370_init_v4l2_flash_config()
382 s->step = MT6370_ITORCH_STEP_uA; in mt6370_init_v4l2_flash_config()
383 s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; in mt6370_init_v4l2_flash_config()
385 cfg->has_external_strobe = 1; in mt6370_init_v4l2_flash_config()
386 strscpy(cfg->dev_name, dev_name(lcdev->dev), sizeof(cfg->dev_name)); in mt6370_init_v4l2_flash_config()
388 cfg->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | in mt6370_init_v4l2_flash_config()
393 static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg) in mt6370_init_v4l2_flash_config() argument
403 static int mt6370_led_register(struct device *parent, struct mt6370_led *led, in mt6370_led_register() argument
410 ret = devm_led_classdev_flash_register_ext(parent, &led->flash, &init_data); in mt6370_led_register()
412 return dev_err_probe(parent, ret, "Couldn't register flash %d\n", led->led_no); in mt6370_led_register()
414 mt6370_init_v4l2_flash_config(led, &v4l2_config); in mt6370_led_register()
415 led->v4l2_flash = v4l2_flash_init(parent, fwnode, &led->flash, &v4l2_flash_ops, in mt6370_led_register()
417 if (IS_ERR(led->v4l2_flash)) in mt6370_led_register()
418 return dev_err_probe(parent, PTR_ERR(led->v4l2_flash), in mt6370_led_register()
419 "Failed to register %d v4l2 sd\n", led->led_no); in mt6370_led_register()
421 return devm_add_action_or_reset(parent, mt6370_v4l2_flash_release, led->v4l2_flash); in mt6370_led_register()
430 retval = rounddown(retval - min, step) + min; in mt6370_clamp()
435 static int mt6370_init_flash_properties(struct device *dev, struct mt6370_led *led, in mt6370_init_flash_properties() argument
438 struct led_classdev_flash *flash = &led->flash; in mt6370_init_flash_properties() local
439 struct led_classdev *lcdev = &flash->led_cdev; in mt6370_init_flash_properties()
440 struct mt6370_priv *priv = led->priv; in mt6370_init_flash_properties()
446 num = fwnode_property_count_u32(fwnode, "led-sources"); in mt6370_init_flash_properties()
448 return dev_err_probe(dev, -EINVAL, in mt6370_init_flash_properties()
449 "Not specified or wrong number of led-sources\n"); in mt6370_init_flash_properties()
451 ret = fwnode_property_read_u32_array(fwnode, "led-sources", sources, num); in mt6370_init_flash_properties()
457 return -EINVAL; in mt6370_init_flash_properties()
458 if (priv->leds_active & BIT(sources[i])) in mt6370_init_flash_properties()
459 return -EINVAL; in mt6370_init_flash_properties()
460 priv->leds_active |= BIT(sources[i]); in mt6370_init_flash_properties()
463 /* If both channels are specified in 'led-sources', joint flash output mode is used */ in mt6370_init_flash_properties()
464 led->led_no = num == 2 ? MT6370_LED_JOINT : sources[0]; in mt6370_init_flash_properties()
468 ret = fwnode_property_read_u32(fwnode, "led-max-microamp", &val); in mt6370_init_flash_properties()
472 lcdev->max_brightness = (val - MT6370_ITORCH_MIN_uA) / MT6370_ITORCH_STEP_uA + 1; in mt6370_init_flash_properties()
473 lcdev->brightness_set_blocking = mt6370_torch_brightness_set; in mt6370_init_flash_properties()
474 lcdev->flags |= LED_DEV_CAP_FLASH; in mt6370_init_flash_properties()
478 ret = fwnode_property_read_u32(fwnode, "flash-max-microamp", &val); in mt6370_init_flash_properties()
482 s = &flash->brightness; in mt6370_init_flash_properties()
483 s->min = MT6370_ISTRB_MIN_uA; in mt6370_init_flash_properties()
484 s->step = MT6370_ISTRB_STEP_uA; in mt6370_init_flash_properties()
485 s->val = s->max = val; in mt6370_init_flash_properties()
487 /* Always configure to the minimum level when off to prevent flash current spikes. */ in mt6370_init_flash_properties()
488 ret = _mt6370_flash_brightness_set(flash, s->min); in mt6370_init_flash_properties()
493 ret = fwnode_property_read_u32(fwnode, "flash-max-timeout-us", &val); in mt6370_init_flash_properties()
498 s = &flash->timeout; in mt6370_init_flash_properties()
499 s->min = MT6370_STRBTO_MIN_US; in mt6370_init_flash_properties()
500 s->step = MT6370_STRBTO_STEP_US; in mt6370_init_flash_properties()
501 s->val = s->max = val; in mt6370_init_flash_properties()
503 flash->ops = &mt6370_flash_ops; in mt6370_init_flash_properties()
510 struct device *dev = &pdev->dev; in mt6370_led_probe()
517 return dev_err_probe(dev, -EINVAL, in mt6370_led_probe()
518 "No child node or node count over max led number %zu\n", count); in mt6370_led_probe()
522 return -ENOMEM; in mt6370_led_probe()
524 priv->leds_count = count; in mt6370_led_probe()
525 mutex_init(&priv->lock); in mt6370_led_probe()
527 priv->regmap = dev_get_regmap(dev->parent, NULL); in mt6370_led_probe()
528 if (!priv->regmap) in mt6370_led_probe()
529 return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); in mt6370_led_probe()
532 struct mt6370_led *led = priv->leds + i; in mt6370_led_probe() local
534 led->priv = priv; in mt6370_led_probe()
536 ret = mt6370_init_flash_properties(dev, led, child); in mt6370_led_probe()
540 ret = mt6370_led_register(dev, led, child); in mt6370_led_probe()
551 { .compatible = "mediatek,mt6370-flashlight" },
558 .name = "mt6370-flashlight",
567 MODULE_DESCRIPTION("MT6370 FLASH LED Driver");