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; }