Loading drivers/leds/leds-qti-flash.c +117 −58 Original line number Diff line number Diff line Loading @@ -223,56 +223,66 @@ static int qti_flash_led_masked_write(struct qti_flash_led *led, return rc; } static int qti_flash_led_strobe(struct flash_node_data *fnode, static int qti_flash_led_module_control(struct qti_flash_led *led, bool enable) { struct qti_flash_led *led = fnode->led; int rc; int rc = 0; u8 val; if (fnode->enabled == enable) return 0; spin_lock(&led->lock); if (enable) { if (!led->ref_count) { val = FLASH_MODULE_ENABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); if (rc < 0) goto error; return rc; } led->ref_count++; } else { if (led->ref_count) led->ref_count--; if (!led->ref_count) { val = FLASH_MODULE_DISABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); if (rc < 0) return rc; } } return rc; } static int qti_flash_led_strobe(struct qti_flash_led *led, u8 mask, u8 value) { int rc; bool enable = mask & value; spin_lock(&led->lock); if (enable) { rc = qti_flash_led_module_control(led, enable); if (rc < 0) goto error; rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL, FLASH_LED_ENABLE(fnode->id), FLASH_LED_ENABLE(fnode->id)); mask, value); if (rc < 0) goto error; } else { rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL, FLASH_LED_ENABLE(fnode->id), FLASH_LED_DISABLE); mask, value); if (rc < 0) goto error; fnode->configured = false; if (led->ref_count) led->ref_count--; if (!led->ref_count) { val = FLASH_MODULE_DISABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); rc = qti_flash_led_module_control(led, enable); if (rc < 0) goto error; } } if (!rc) fnode->enabled = enable; error: spin_unlock(&led->lock); Loading Loading @@ -468,58 +478,92 @@ static int qti_flash_led_symmetry_config( return 0; } static void qti_flash_led_switch_brightness_set( struct led_classdev *led_cdev, enum led_brightness value) static int qti_flash_switch_enable(struct flash_switch_data *snode) { struct qti_flash_led *led = NULL; struct flash_switch_data *snode = NULL; struct qti_flash_led *led = snode->led; int rc = 0, i; bool state = value > 0; snode = container_of(led_cdev, struct flash_switch_data, cdev); if (snode->enabled == state) { pr_debug("Switch is already %s!\n", state ? "enabled" : "disabled"); return; } led = snode->led; u8 led_en = 0; /* If symmetry enabled switch, then turn ON all its LEDs */ if (state && snode->symmetry_en) { if (snode->symmetry_en) { rc = qti_flash_led_symmetry_config(snode); if (rc < 0) { pr_err("Failed to configure switch symmetrically, rc=%d\n", rc); return; return rc; } } for (i = 0; i < led->num_fnodes; i++) { /* * Do not turn ON flash/torch device if * i. the device is not under this switch or * ii. brightness is not configured for device under this switch */ if (!(snode->led_mask & BIT(led->fnode[i].id)) || !led->fnode[i].configured) continue; rc = qti_flash_led_strobe(&led->fnode[i], state); if (rc < 0) { pr_err("Failed to %s LED%d\n", state ? "strobe" : "destrobe", &led->fnode[i].id); break; led_en |= (1 << led->fnode[i].id); } if (!state) { return qti_flash_led_strobe(led, snode->led_mask, led_en); } static int qti_flash_switch_disable(struct flash_switch_data *snode) { struct qti_flash_led *led = snode->led; int rc = 0, i; u8 led_dis = 0; for (i = 0; i < led->num_fnodes; i++) { /* * Do not turn OFF flash/torch device if * i. the device is not under this switch or * ii. brightness is not configured for device under this switch */ if (!(snode->led_mask & BIT(led->fnode[i].id)) || !led->fnode[i].configured) continue; rc = qti_flash_led_disable(&led->fnode[i]); if (rc < 0) { pr_err("Failed to disable LED%d\n", &led->fnode[i].id); break; } led_dis |= (1 << led->fnode[i].id); led->fnode[i].configured = false; } return qti_flash_led_strobe(led, led_dis, ~led_dis); } if (!rc) static void qti_flash_led_switch_brightness_set( struct led_classdev *led_cdev, enum led_brightness value) { struct flash_switch_data *snode = NULL; int rc = 0; bool state = value > 0; snode = container_of(led_cdev, struct flash_switch_data, cdev); if (snode->enabled == state) { pr_debug("Switch is already %s!\n", state ? "enabled" : "disabled"); return; } if (state) rc = qti_flash_switch_enable(snode); else rc = qti_flash_switch_disable(snode); if (rc < 0) pr_err("Failed to %s switch, rc=%d\n", state ? "enable" : "disable", rc); else snode->enabled = state; } Loading Loading @@ -551,10 +595,25 @@ static int qti_flash_strobe_set(struct led_classdev_flash *fdev, bool state) { struct flash_node_data *fnode; int rc; u8 mask, value; fnode = container_of(fdev, struct flash_node_data, fdev); return qti_flash_led_strobe(fnode, state); if (fnode->enabled == state) return 0; mask = FLASH_LED_ENABLE(fnode->id); value = state ? FLASH_LED_ENABLE(fnode->id) : 0; rc = qti_flash_led_strobe(fnode->led, mask, value); if (!rc) { fnode->enabled = state; if (!state) fnode->configured = false; } return rc; } static int qti_flash_strobe_get(struct led_classdev_flash *fdev, Loading Loading
drivers/leds/leds-qti-flash.c +117 −58 Original line number Diff line number Diff line Loading @@ -223,56 +223,66 @@ static int qti_flash_led_masked_write(struct qti_flash_led *led, return rc; } static int qti_flash_led_strobe(struct flash_node_data *fnode, static int qti_flash_led_module_control(struct qti_flash_led *led, bool enable) { struct qti_flash_led *led = fnode->led; int rc; int rc = 0; u8 val; if (fnode->enabled == enable) return 0; spin_lock(&led->lock); if (enable) { if (!led->ref_count) { val = FLASH_MODULE_ENABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); if (rc < 0) goto error; return rc; } led->ref_count++; } else { if (led->ref_count) led->ref_count--; if (!led->ref_count) { val = FLASH_MODULE_DISABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); if (rc < 0) return rc; } } return rc; } static int qti_flash_led_strobe(struct qti_flash_led *led, u8 mask, u8 value) { int rc; bool enable = mask & value; spin_lock(&led->lock); if (enable) { rc = qti_flash_led_module_control(led, enable); if (rc < 0) goto error; rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL, FLASH_LED_ENABLE(fnode->id), FLASH_LED_ENABLE(fnode->id)); mask, value); if (rc < 0) goto error; } else { rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL, FLASH_LED_ENABLE(fnode->id), FLASH_LED_DISABLE); mask, value); if (rc < 0) goto error; fnode->configured = false; if (led->ref_count) led->ref_count--; if (!led->ref_count) { val = FLASH_MODULE_DISABLE; rc = qti_flash_led_write(led, FLASH_ENABLE_CONTROL, &val, 1); rc = qti_flash_led_module_control(led, enable); if (rc < 0) goto error; } } if (!rc) fnode->enabled = enable; error: spin_unlock(&led->lock); Loading Loading @@ -468,58 +478,92 @@ static int qti_flash_led_symmetry_config( return 0; } static void qti_flash_led_switch_brightness_set( struct led_classdev *led_cdev, enum led_brightness value) static int qti_flash_switch_enable(struct flash_switch_data *snode) { struct qti_flash_led *led = NULL; struct flash_switch_data *snode = NULL; struct qti_flash_led *led = snode->led; int rc = 0, i; bool state = value > 0; snode = container_of(led_cdev, struct flash_switch_data, cdev); if (snode->enabled == state) { pr_debug("Switch is already %s!\n", state ? "enabled" : "disabled"); return; } led = snode->led; u8 led_en = 0; /* If symmetry enabled switch, then turn ON all its LEDs */ if (state && snode->symmetry_en) { if (snode->symmetry_en) { rc = qti_flash_led_symmetry_config(snode); if (rc < 0) { pr_err("Failed to configure switch symmetrically, rc=%d\n", rc); return; return rc; } } for (i = 0; i < led->num_fnodes; i++) { /* * Do not turn ON flash/torch device if * i. the device is not under this switch or * ii. brightness is not configured for device under this switch */ if (!(snode->led_mask & BIT(led->fnode[i].id)) || !led->fnode[i].configured) continue; rc = qti_flash_led_strobe(&led->fnode[i], state); if (rc < 0) { pr_err("Failed to %s LED%d\n", state ? "strobe" : "destrobe", &led->fnode[i].id); break; led_en |= (1 << led->fnode[i].id); } if (!state) { return qti_flash_led_strobe(led, snode->led_mask, led_en); } static int qti_flash_switch_disable(struct flash_switch_data *snode) { struct qti_flash_led *led = snode->led; int rc = 0, i; u8 led_dis = 0; for (i = 0; i < led->num_fnodes; i++) { /* * Do not turn OFF flash/torch device if * i. the device is not under this switch or * ii. brightness is not configured for device under this switch */ if (!(snode->led_mask & BIT(led->fnode[i].id)) || !led->fnode[i].configured) continue; rc = qti_flash_led_disable(&led->fnode[i]); if (rc < 0) { pr_err("Failed to disable LED%d\n", &led->fnode[i].id); break; } led_dis |= (1 << led->fnode[i].id); led->fnode[i].configured = false; } return qti_flash_led_strobe(led, led_dis, ~led_dis); } if (!rc) static void qti_flash_led_switch_brightness_set( struct led_classdev *led_cdev, enum led_brightness value) { struct flash_switch_data *snode = NULL; int rc = 0; bool state = value > 0; snode = container_of(led_cdev, struct flash_switch_data, cdev); if (snode->enabled == state) { pr_debug("Switch is already %s!\n", state ? "enabled" : "disabled"); return; } if (state) rc = qti_flash_switch_enable(snode); else rc = qti_flash_switch_disable(snode); if (rc < 0) pr_err("Failed to %s switch, rc=%d\n", state ? "enable" : "disable", rc); else snode->enabled = state; } Loading Loading @@ -551,10 +595,25 @@ static int qti_flash_strobe_set(struct led_classdev_flash *fdev, bool state) { struct flash_node_data *fnode; int rc; u8 mask, value; fnode = container_of(fdev, struct flash_node_data, fdev); return qti_flash_led_strobe(fnode, state); if (fnode->enabled == state) return 0; mask = FLASH_LED_ENABLE(fnode->id); value = state ? FLASH_LED_ENABLE(fnode->id) : 0; rc = qti_flash_led_strobe(fnode->led, mask, value); if (!rc) { fnode->enabled = state; if (!state) fnode->configured = false; } return rc; } static int qti_flash_strobe_get(struct led_classdev_flash *fdev, Loading