static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
        struct flash_node_data *flash_node)
{
    int rc;
    u8 val, tmp;

    rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
                                 led->spmi_dev->sid,
                                 FLASH_LED_STROBE_CTRL(led->base),
                                 &val, 1);
    if (rc) {
        dev_err(&led->spmi_dev->dev,
                "Unable to read module enable reg\n");
        return -EINVAL;
    }

    tmp = ~flash_node->trigger & val;
    if (!tmp) {
        if (flash_node->type == TORCH) {
            rc = qpnp_led_masked_write(led->spmi_dev,
                                       FLASH_LED_UNLOCK_SECURE(led->base),
                                       FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
            if (rc) {
                dev_err(&led->spmi_dev->dev,
                        "Secure reg write failed\n");
                return -EINVAL;
            }

            rc = qpnp_led_masked_write(led->spmi_dev,
                                       FLASH_TORCH(led->base),
                                       FLASH_TORCH_MASK, FLASH_LED_TORCH_DISABLE);
            if (rc) {
                dev_err(&led->spmi_dev->dev,
                        "Torch reg write failed\n");
                return -EINVAL;
            }
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MODULE_ENABLE_CTRL(led->base),
                                   FLASH_MODULE_ENABLE_MASK, FLASH_LED_DISABLE);
        if (rc) {
            dev_err(&led->spmi_dev->dev, "Module disable failed\n");
            return -EINVAL;
        }
    } else {
        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MODULE_ENABLE_CTRL(led->base),
                                   flash_node->enable, flash_node->enable);
        if (rc) {
            dev_err(&led->spmi_dev->dev, "Module disable failed\n");
            return -EINVAL;
        }
    }
    return 0;
}
static void qpnp_flash_led_work(struct work_struct *work)
{
    struct flash_node_data *flash_node = container_of(work,
                                         struct flash_node_data, work);
    struct qpnp_flash_led *led =
        dev_get_drvdata(&flash_node->spmi_dev->dev);
    int rc, brightness = flash_node->cdev.brightness;
    int max_curr_avail_ma;
    u8 val;

    mutex_lock(&led->flash_led_lock);

    if (!brightness)
        goto turn_off;

    if (brightness < FLASH_LED_MIN_CURRENT_MA)
        brightness = FLASH_LED_MIN_CURRENT_MA;

    flash_node->prgm_current = brightness;

    if (flash_node->boost_regulator && !flash_node->flash_on) {
        if (regulator_count_voltages(flash_node->boost_regulator) > 0) {
            rc = regulator_set_voltage(flash_node->boost_regulator,
                                       flash_node->boost_voltage_max,
                                       flash_node->boost_voltage_max);
            if (rc) {
                dev_err(&led->spmi_dev->dev,
                        "boost regulator set voltage failed\n");
                mutex_unlock(&led->flash_led_lock);
                return;
            }
        }

        rc = regulator_enable(flash_node->boost_regulator);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Boost regulator enablement failed\n");
            goto error_regulator_enable;
        }
    }

    if (flash_node->type == TORCH) {
        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_LED_UNLOCK_SECURE(led->base),
                                   FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Secure reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_TORCH(led->base),
                                   FLASH_TORCH_MASK, FLASH_LED_TORCH_ENABLE);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Torch reg write failed\n");
            goto exit_flash_led_work;
        }

        val = (u8)(flash_node->prgm_current * FLASH_TORCH_MAX_LEVEL
                   / flash_node->max_current);
        rc = qpnp_led_masked_write(led->spmi_dev,
                                   flash_node->current_addr,
                                   FLASH_CURRENT_MASK, val);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Current reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MAX_CURRENT(led->base),
                                   FLASH_CURRENT_MASK, FLASH_TORCH_MAX_LEVEL);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Max current reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MODULE_ENABLE_CTRL(led->base),
                                   FLASH_MODULE_ENABLE | flash_node->enable,
                                   FLASH_MODULE_ENABLE | flash_node->enable);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Module enable reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_LED_STROBE_CTRL(led->base),
                                   flash_node->trigger,
                                   flash_node->trigger);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Strobe ctrl reg write failed\n");
            goto exit_flash_led_work;
        }
    } else if (flash_node->type == FLASH) {
        if (led->pdata->power_detect_en) {
            max_curr_avail_ma =
                qpnp_flash_led_get_max_avail_current
                (flash_node, led);
            if (max_curr_avail_ma < 0) {
                dev_err(&led->spmi_dev->dev,
                        "Failed to get Max available curr\n");
                goto exit_flash_led_work;
            } else {
                if (max_curr_avail_ma <
                        flash_node->prgm_current) {
                    dev_err(&led->spmi_dev->dev,
                            "battery only supports %d mA.\n",
                            max_curr_avail_ma);
                    flash_node->prgm_current =
                        (u16) max_curr_avail_ma;
                }
            }
        }
        val = (u8)((flash_node->duration - FLASH_DURATION_DIVIDER)
                   / FLASH_DURATION_DIVIDER);
        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_SAFETY_TIMER(led->base),
                                   FLASH_SAFETY_TIMER_MASK, val);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Safety timer reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MAX_CURRENT(led->base),
                                   FLASH_CURRENT_MASK, FLASH_MAX_LEVEL);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Max current reg write failed\n");
            goto exit_flash_led_work;
        }

        val = (u8)(flash_node->prgm_current * FLASH_MAX_LEVEL
                   / flash_node->max_current);
        rc = qpnp_led_masked_write(led->spmi_dev,
                                   flash_node->current_addr,
                                   FLASH_CURRENT_MASK, val);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Current reg write failed\n");
            goto exit_flash_led_work;
        }

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_MODULE_ENABLE_CTRL(led->base),
                                   FLASH_MODULE_ENABLE |
                                   flash_node->enable,
                                   FLASH_MODULE_ENABLE |
                                   flash_node->enable);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Module enable reg write failed\n");
            goto exit_flash_led_work;
        }

        usleep(FLASH_RAMP_UP_DELAY_US);

        rc = qpnp_led_masked_write(led->spmi_dev,
                                   FLASH_LED_STROBE_CTRL(led->base),
                                   flash_node->trigger,
                                   flash_node->trigger);
        if (rc) {
            dev_err(&led->spmi_dev->dev,
                    "Strobe reg write failed\n");
            goto exit_flash_led_work;
        }
    }

    flash_node->flash_on = true;
    mutex_unlock(&led->flash_led_lock);

    return;

turn_off:
    rc = qpnp_led_masked_write(led->spmi_dev,
                               FLASH_LED_STROBE_CTRL(led->base),
                               flash_node->trigger, FLASH_LED_DISABLE);
    if (rc) {
        dev_err(&led->spmi_dev->dev, "Strobe disable failed\n");
        goto exit_flash_led_work;
    }

    usleep(FLASH_RAMP_DN_DELAY_US);

    rc = qpnp_flash_led_module_disable(led, flash_node);
    if (rc) {
        dev_err(&led->spmi_dev->dev, "Module disable failed\n");
        goto exit_flash_led_work;
    }

exit_flash_led_work:
    if (flash_node->boost_regulator && flash_node->flash_on) {
        regulator_disable(flash_node->boost_regulator);
error_regulator_enable:
        if (regulator_count_voltages(flash_node->boost_regulator) > 0)
            regulator_set_voltage(flash_node->boost_regulator,
                                  0, flash_node->boost_voltage_max);
    }

    flash_node->flash_on = false;
    mutex_unlock(&led->flash_led_lock);

    return;
}
static int qpnp_flash_led_module_disable(struct qpnp_flash_led *led,
				struct flash_node_data *flash_node)
{
	union power_supply_propval psy_prop;
	int rc;
	u8 val, tmp;

	rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
				led->spmi_dev->sid,
				FLASH_LED_STROBE_CTRL(led->base),
				&val, 1);
	if (rc) {
		dev_err(&led->spmi_dev->dev,
				"Unable to read module enable reg\n");
		return -EINVAL;
	}

	tmp = ~flash_node->trigger & val;
	if (!tmp) {
		if (flash_node->type == TORCH) {
			rc = qpnp_led_masked_write(led->spmi_dev,
				FLASH_LED_UNLOCK_SECURE(led->base),
				FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
			if (rc) {
				dev_err(&led->spmi_dev->dev,
					"Secure reg write failed\n");
				return -EINVAL;
			}

			rc = qpnp_led_masked_write(led->spmi_dev,
				FLASH_TORCH(led->base),
				FLASH_TORCH_MASK, FLASH_LED_TORCH_DISABLE);
			if (rc) {
				dev_err(&led->spmi_dev->dev,
					"Torch reg write failed\n");
				return -EINVAL;
			}
		}

		rc = qpnp_led_masked_write(led->spmi_dev,
			FLASH_MODULE_ENABLE_CTRL(led->base),
			FLASH_MODULE_ENABLE_MASK, FLASH_LED_DISABLE);
		if (rc) {
			dev_err(&led->spmi_dev->dev, "Module disable failed\n");
			return -EINVAL;
		}

		if (led->battery_psy) {
			psy_prop.intval = false;
			rc = led->battery_psy->set_property(led->battery_psy,
						POWER_SUPPLY_PROP_FLASH_ACTIVE,
								&psy_prop);
			if (rc) {
				dev_err(&led->spmi_dev->dev,
					"Failed to setup OTG pulse skip enable\n");
				return -EINVAL;
			}
		}
	} else {
		rc = qpnp_led_masked_write(led->spmi_dev,
			FLASH_MODULE_ENABLE_CTRL(led->base),
			flash_node->enable, flash_node->enable);
		if (rc) {
			dev_err(&led->spmi_dev->dev, "Module disable failed\n");
			return -EINVAL;
		}
	}
	return 0;
}