leds: qti-flash: Add individual APIs to enable and disable switch

Currently qti_flash_led_switch_brightness_set() is used to enable or
disable switch. Split it into separate APIs to enable and disable
switch. This will make it easier to control switches which is required
for implementing slow-sync flash feature.

Change-Id: I668ab872d1d646f97ed8fbfba4dfca6b4db5bc70
Signed-off-by: Shyam Kumar Thella <sthella@codeaurora.org>
This commit is contained in:
Shyam Kumar Thella 2020-02-07 16:26:00 +05:30 committed by David Collins
parent 94dbc769e4
commit 6a1350e53d

View File

@ -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);
&val, 1);
if (rc < 0)
goto error;
return rc;
}
led->ref_count++;
rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL,
FLASH_LED_ENABLE(fnode->id),
FLASH_LED_ENABLE(fnode->id));
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);
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);
&val, 1);
if (rc < 0)
goto error;
return rc;
}
}
if (!rc)
fnode->enabled = enable;
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,
mask, value);
if (rc < 0)
goto error;
} else {
rc = qti_flash_led_masked_write(led, FLASH_EN_LED_CTRL,
mask, value);
if (rc < 0)
goto error;
rc = qti_flash_led_module_control(led, enable);
if (rc < 0)
goto error;
}
error:
spin_unlock(&led->lock);
@ -468,12 +478,73 @@ static int qti_flash_led_symmetry_config(
return 0;
}
static int qti_flash_switch_enable(struct flash_switch_data *snode)
{
struct qti_flash_led *led = snode->led;
int rc = 0, i;
u8 led_en = 0;
/* If symmetry enabled switch, then turn ON all its LEDs */
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 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;
led_en |= (1 << led->fnode[i].id);
}
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);
}
static void qti_flash_led_switch_brightness_set(
struct led_classdev *led_cdev, enum led_brightness value)
{
struct qti_flash_led *led = NULL;
struct flash_switch_data *snode = NULL;
int rc = 0, i;
int rc = 0;
bool state = value > 0;
snode = container_of(led_cdev, struct flash_switch_data, cdev);
@ -484,42 +555,15 @@ static void qti_flash_led_switch_brightness_set(
return;
}
led = snode->led;
if (state)
rc = qti_flash_switch_enable(snode);
else
rc = qti_flash_switch_disable(snode);
/* If symmetry enabled switch, then turn ON all its LEDs */
if (state && 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;
}
}
for (i = 0; i < led->num_fnodes; i++) {
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;
}
if (!state) {
rc = qti_flash_led_disable(&led->fnode[i]);
if (rc < 0) {
pr_err("Failed to disable LED%d\n",
&led->fnode[i].id);
break;
}
}
}
if (!rc)
if (rc < 0)
pr_err("Failed to %s switch, rc=%d\n",
state ? "enable" : "disable", rc);
else
snode->enabled = state;
}
@ -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,