Loading Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt +5 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,10 @@ Optional properties: be edge triggered. Otherwise, it is level triggered. - qcom,hw-strobe-active-low : Boolean property to select strobe signal polarity. If defined, hw-strobe signal polarity is set to active-low, else it is active-high. - qcom,symmetry-en : Boolean property to specify if the flash LEDs under a switch node are controlled symmetrically. This needs to be specified if a group of flash LED channels are connected to a single LED. Example: qcom,leds@d300 { compatible = "qcom,qpnp-flash-led-v2"; Loading Loading @@ -302,6 +306,7 @@ Example: qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; qcom,symmetry-en; }; pmi8998_switch1: qcom,led_switch_1 { Loading drivers/leds/leds-qpnp-flash-v2.c +79 −1 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ enum flash_charger_mitigation { }; enum flash_led_type { FLASH_LED_TYPE_UNKNOWN, FLASH_LED_TYPE_FLASH, FLASH_LED_TYPE_TORCH, }; Loading Loading @@ -204,13 +205,13 @@ struct flash_node_data { int prev_current_ma; u8 duration; u8 id; u8 type; u8 ires_idx; u8 default_ires_idx; u8 hdrm_val; u8 current_reg_val; u8 strobe_ctrl; u8 strobe_sel; enum flash_led_type type; bool led_on; }; Loading @@ -225,6 +226,7 @@ struct flash_switch_data { int led_mask; bool regulator_on; bool enabled; bool symmetry_en; }; /* Loading Loading @@ -1091,6 +1093,71 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) return 0; } static int qpnp_flash_led_symmetry_config(struct flash_switch_data *snode) { struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev); int i, total_curr_ma = 0, num_leds = 0, prgm_current_ma; enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN; for (i = 0; i < led->num_fnodes; i++) { if (snode->led_mask & BIT(led->fnode[i].id)) { if (led->fnode[i].type == FLASH_LED_TYPE_FLASH && led->fnode[i].led_on) type = FLASH_LED_TYPE_FLASH; if (led->fnode[i].type == FLASH_LED_TYPE_TORCH && led->fnode[i].led_on) type = FLASH_LED_TYPE_TORCH; } } if (type == FLASH_LED_TYPE_UNKNOWN) { pr_err("Incorrect type possibly because of no active LEDs\n"); return -EINVAL; } for (i = 0; i < led->num_fnodes; i++) { if ((snode->led_mask & BIT(led->fnode[i].id)) && (led->fnode[i].type == type)) { total_curr_ma += led->fnode[i].current_ma; num_leds++; } } if (num_leds > 0 && total_curr_ma > 0) { prgm_current_ma = total_curr_ma / num_leds; } else { pr_err("Incorrect configuration, num_leds: %d total_curr_ma: %d\n", num_leds, total_curr_ma); return -EINVAL; } if (prgm_current_ma == 0) { pr_warn("prgm_curr_ma cannot be 0\n"); return 0; } pr_debug("num_leds: %d total: %d prgm_curr_ma: %d\n", num_leds, total_curr_ma, prgm_current_ma); for (i = 0; i < led->num_fnodes; i++) { if (snode->led_mask & BIT(led->fnode[i].id) && led->fnode[i].current_ma != prgm_current_ma && led->fnode[i].type == type) { qpnp_flash_led_node_set(&led->fnode[i], prgm_current_ma); pr_debug("%s LED %d current: %d code: %d ires_ua: %d\n", (type == FLASH_LED_TYPE_FLASH) ? "flash" : "torch", led->fnode[i].id, prgm_current_ma, led->fnode[i].current_reg_val, led->fnode[i].ires_ua); } } return 0; } static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) { struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev); Loading @@ -1109,6 +1176,15 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) } /* Iterate over all active leds for this switch node */ if (snode->symmetry_en) { rc = qpnp_flash_led_symmetry_config(snode); if (rc < 0) { pr_err("Failed to configure current symmetrically, rc=%d\n", rc); return rc; } } val = 0; for (i = 0; i < led->num_fnodes; i++) if (led->fnode[i].led_on && Loading Loading @@ -1707,6 +1783,8 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, return rc; } snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en"); if (snode->led_mask < 1 || snode->led_mask > 7) { pr_err("Invalid value for led-mask\n"); return -EINVAL; Loading Loading
Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt +5 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,10 @@ Optional properties: be edge triggered. Otherwise, it is level triggered. - qcom,hw-strobe-active-low : Boolean property to select strobe signal polarity. If defined, hw-strobe signal polarity is set to active-low, else it is active-high. - qcom,symmetry-en : Boolean property to specify if the flash LEDs under a switch node are controlled symmetrically. This needs to be specified if a group of flash LED channels are connected to a single LED. Example: qcom,leds@d300 { compatible = "qcom,qpnp-flash-led-v2"; Loading Loading @@ -302,6 +306,7 @@ Example: qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; qcom,symmetry-en; }; pmi8998_switch1: qcom,led_switch_1 { Loading
drivers/leds/leds-qpnp-flash-v2.c +79 −1 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ enum flash_charger_mitigation { }; enum flash_led_type { FLASH_LED_TYPE_UNKNOWN, FLASH_LED_TYPE_FLASH, FLASH_LED_TYPE_TORCH, }; Loading Loading @@ -204,13 +205,13 @@ struct flash_node_data { int prev_current_ma; u8 duration; u8 id; u8 type; u8 ires_idx; u8 default_ires_idx; u8 hdrm_val; u8 current_reg_val; u8 strobe_ctrl; u8 strobe_sel; enum flash_led_type type; bool led_on; }; Loading @@ -225,6 +226,7 @@ struct flash_switch_data { int led_mask; bool regulator_on; bool enabled; bool symmetry_en; }; /* Loading Loading @@ -1091,6 +1093,71 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) return 0; } static int qpnp_flash_led_symmetry_config(struct flash_switch_data *snode) { struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev); int i, total_curr_ma = 0, num_leds = 0, prgm_current_ma; enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN; for (i = 0; i < led->num_fnodes; i++) { if (snode->led_mask & BIT(led->fnode[i].id)) { if (led->fnode[i].type == FLASH_LED_TYPE_FLASH && led->fnode[i].led_on) type = FLASH_LED_TYPE_FLASH; if (led->fnode[i].type == FLASH_LED_TYPE_TORCH && led->fnode[i].led_on) type = FLASH_LED_TYPE_TORCH; } } if (type == FLASH_LED_TYPE_UNKNOWN) { pr_err("Incorrect type possibly because of no active LEDs\n"); return -EINVAL; } for (i = 0; i < led->num_fnodes; i++) { if ((snode->led_mask & BIT(led->fnode[i].id)) && (led->fnode[i].type == type)) { total_curr_ma += led->fnode[i].current_ma; num_leds++; } } if (num_leds > 0 && total_curr_ma > 0) { prgm_current_ma = total_curr_ma / num_leds; } else { pr_err("Incorrect configuration, num_leds: %d total_curr_ma: %d\n", num_leds, total_curr_ma); return -EINVAL; } if (prgm_current_ma == 0) { pr_warn("prgm_curr_ma cannot be 0\n"); return 0; } pr_debug("num_leds: %d total: %d prgm_curr_ma: %d\n", num_leds, total_curr_ma, prgm_current_ma); for (i = 0; i < led->num_fnodes; i++) { if (snode->led_mask & BIT(led->fnode[i].id) && led->fnode[i].current_ma != prgm_current_ma && led->fnode[i].type == type) { qpnp_flash_led_node_set(&led->fnode[i], prgm_current_ma); pr_debug("%s LED %d current: %d code: %d ires_ua: %d\n", (type == FLASH_LED_TYPE_FLASH) ? "flash" : "torch", led->fnode[i].id, prgm_current_ma, led->fnode[i].current_reg_val, led->fnode[i].ires_ua); } } return 0; } static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) { struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev); Loading @@ -1109,6 +1176,15 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) } /* Iterate over all active leds for this switch node */ if (snode->symmetry_en) { rc = qpnp_flash_led_symmetry_config(snode); if (rc < 0) { pr_err("Failed to configure current symmetrically, rc=%d\n", rc); return rc; } } val = 0; for (i = 0; i < led->num_fnodes; i++) if (led->fnode[i].led_on && Loading Loading @@ -1707,6 +1783,8 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, return rc; } snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en"); if (snode->led_mask < 1 || snode->led_mask > 7) { pr_err("Invalid value for led-mask\n"); return -EINVAL; Loading