/* * Only one set of flash control logic, use the flag to avoid strobe is * currently used.
*/ if (priv->fled_strobe_used) {
dev_warn(lcdev->dev, "Please disable strobe first [%d]\n",
priv->fled_strobe_used);
ret = -EBUSY; goto unlock;
}
if (level) {
ret = regmap_update_bits(priv->regmap,
MT6360_REG_FLEDITOR(led->led_no),
MT6360_ITORCH_MASK, level - 1); if (ret) goto unlock;
}
ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask,
val); if (ret) goto unlock;
priv->fled_torch_used = curr;
unlock:
mutex_unlock(&priv->lock); return ret;
}
staticint mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev,
u32 brightness)
{ /* * Due to the current spike when turning on flash, let brightness to be * kept by framework. * This empty function is used to prevent led_classdev_flash register * ops check failure.
*/ return 0;
}
/* * If the state of the upcoming change is the same as the current LED * device state, then skip the subsequent code to avoid conflict * with the flow of turning on LED torch mode in V4L2.
*/ if (state == !!(BIT(led->led_no) & prev)) {
dev_info(lcdev->dev, "No change in strobe state [0x%x]\n", prev); goto unlock;
}
/* * Only one set of flash control logic, use the flag to avoid torch is * currently used
*/ if (priv->fled_torch_used) {
dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n",
priv->fled_torch_used);
ret = -EBUSY; goto unlock;
}
ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask,
val); if (ret) {
dev_err(lcdev->dev, "[%d] control current source %d fail\n",
led->led_no, state); goto unlock;
}
/* * If the flash need to be on, config the flash current ramping up to * the setting value. * Else, always recover back to the minimum one
*/
ret = _mt6360_flash_brightness_set(fl_cdev, state ? s->val : s->min); if (ret) goto unlock;
/* * For the flash turn on/off, HW rampping up/down time is 5ms/500us, * respectively.
*/ if (!prev && curr)
usleep_range(5000, 6000); elseif (prev && !curr)
udelay(500);
if ((led->led_no == MT6360_LED_ISNK1 ||
led->led_no == MT6360_VIRTUAL_MULTICOLOR) &&
(priv->leds_active & BIT(MT6360_LED_ISNK1))) { /* * Change isink1 to SW control mode, disconnect it with * charger state
*/
ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN,
MT6360_CHRINDSEL_MASK,
MT6360_CHRINDSEL_MASK); if (ret) {
dev_err(parent, "Failed to config ISNK1 to SW mode\n"); return ret;
}
}
switch (led->led_no) { case MT6360_VIRTUAL_MULTICOLOR:
ret = mt6360_mc_brightness_set(&led->mc.led_cdev, LED_OFF); if (ret) {
dev_err(parent, "Failed to init multicolor brightness\n"); return ret;
}
ret = devm_led_classdev_multicolor_register_ext(parent,
&led->mc, init_data); if (ret) {
dev_err(parent, "Couldn't register multicolor\n"); return ret;
} break; case MT6360_LED_ISNK1 ... MT6360_LED_ISNKML:
ret = mt6360_isnk_init_default_state(led); if (ret) {
dev_err(parent, "Failed to init %d isnk state\n",
led->led_no); return ret;
}
ret = devm_led_classdev_register_ext(parent, &led->isnk,
init_data); if (ret) {
dev_err(parent, "Couldn't register isink %d\n",
led->led_no); return ret;
} break; default:
ret = mt6360_flash_init_default_state(led); if (ret) {
dev_err(parent, "Failed to init %d flash state\n",
led->led_no); return ret;
}
ret = devm_led_classdev_flash_register_ext(parent, &led->flash,
init_data); if (ret) {
dev_err(parent, "Couldn't register flash %d\n",
led->led_no); return ret;
}
ret = fwnode_property_read_u32(child, "reg", ®); if (ret || reg > MT6360_LED_ISNK3 ||
priv->leds_active & BIT(reg)) {
fwnode_handle_put(child); return -EINVAL;
}
ret = fwnode_property_read_u32(child, "color", &color); if (ret) {
dev_err(priv->dev, "led %d, no color specified\n",
led->led_no);
fwnode_handle_put(child); return ret;
}
ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
&val); if (ret) {
dev_warn(priv->dev, "Not specified led-max-microamp, config to the minimum\n");
val = step_uA;
} else
val = clamp_align(val, 0, max_uA, step_uA);
ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp",
&val); if (ret) {
dev_warn(priv->dev, "Not specified led-max-microamp, config to the minimum\n");
val = MT6360_ITORCH_MINUA;
} else
val = clamp_align(val, MT6360_ITORCH_MINUA, MT6360_ITORCH_MAXUA,
MT6360_ITORCH_STEPUA);
ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-microamp",
&val); if (ret) {
dev_warn(priv->dev, "Not specified flash-max-microamp, config to the minimum\n");
val = MT6360_ISTRB_MINUA;
} else
val = clamp_align(val, MT6360_ISTRB_MINUA, MT6360_ISTRB_MAXUA,
MT6360_ISTRB_STEPUA);
/* * Always configure as min level when off to prevent flash current * spike.
*/
ret = _mt6360_flash_brightness_set(flash, s->min); if (ret) return ret;
ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-timeout-us", &val); if (ret) {
dev_warn(priv->dev, "Not specified flash-max-timeout-us, config to the minimum\n");
val = MT6360_STRBTO_MINUS;
} else
val = clamp_align(val, MT6360_STRBTO_MINUS, MT6360_STRBTO_MAXUS,
MT6360_STRBTO_STEPUS);
staticvoid mt6360_v4l2_flash_release(struct mt6360_priv *priv)
{ int i;
for (i = 0; i < priv->leds_count; i++) { struct mt6360_led *led = priv->leds + i;
if (led->v4l2_flash)
v4l2_flash_release(led->v4l2_flash);
}
}
staticint mt6360_led_probe(struct platform_device *pdev)
{ struct mt6360_priv *priv;
size_t count; int i = 0, ret;
count = device_get_child_node_count(&pdev->dev); if (!count || count > MT6360_MAX_LEDS) {
dev_err(&pdev->dev, "No child node or node count over max led number %zu\n",
count); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.