Loading drivers/leds/leds-qpnp-flash.c +66 −1 Original line number Diff line number Diff line Loading @@ -26,9 +26,10 @@ #include <linux/power_supply.h> #include <linux/qpnp/qpnp-adc.h> #include <linux/qpnp/qpnp-revid.h> #include "leds.h" #include <linux/leds-qpnp-flash.h> #include <linux/debugfs.h> #include <linux/uaccess.h> #include "leds.h" #define FLASH_LED_PERIPHERAL_SUBTYPE(base) (base + 0x05) #define FLASH_SAFETY_TIMER(base) (base + 0x40) Loading Loading @@ -79,6 +80,7 @@ #define FLASH_LED_HDRM_SNS_ENABLE_MASK 0x81 #define FLASH_MASK_MODULE_CONTRL_MASK 0xE0 #define FLASH_FOLLOW_OTST2_RB_MASK 0x08 #define FLASH_PREPARE_OPTIONS_MASK 0x07 #define FLASH_LED_TRIGGER_DEFAULT "none" #define FLASH_LED_HEADROOM_DEFAULT_MV 500 Loading Loading @@ -188,6 +190,7 @@ struct flash_node_data { u8 trigger; u8 enable; u8 num_regulators; bool regulators_on; bool flash_on; }; Loading Loading @@ -1148,6 +1151,9 @@ static int flash_regulator_enable(struct qpnp_flash_led *led, { int i, rc = 0; if (flash_node->regulators_on == on) return 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_enable; Loading @@ -1162,12 +1168,71 @@ static int flash_regulator_enable(struct qpnp_flash_led *led, } } flash_node->regulators_on = true; return rc; error_regulator_enable: while (i--) regulator_disable(flash_node->reg_data[i].regs); flash_node->regulators_on = false; return rc; } int qpnp_flash_led_prepare(struct led_trigger *trig, int options, int *max_current) { struct led_classdev *led_cdev = trigger_to_lcdev(trig); struct flash_node_data *flash_node; struct qpnp_flash_led *led; int rc; if (!led_cdev) { pr_err("Invalid led_trigger provided\n"); return -EINVAL; } flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); if (!(options & FLASH_PREPARE_OPTIONS_MASK)) { dev_err(&led->spmi_dev->dev, "Invalid options %d\n", options); return -EINVAL; } mutex_lock(&led->flash_led_lock); if (options & ENABLE_REGULATOR) { rc = flash_regulator_enable(led, flash_node, true); if (rc < 0) { dev_err(&led->spmi_dev->dev, "enable regulator failed, rc=%d\n", rc); goto out; } } if (options & DISABLE_REGULATOR) { rc = flash_regulator_enable(led, flash_node, false); if (rc < 0) { dev_err(&led->spmi_dev->dev, "disable regulator failed, rc=%d\n", rc); goto out; } } if (options & QUERY_MAX_CURRENT) { rc = qpnp_flash_led_get_max_avail_current(flash_node, led); if (rc < 0) { dev_err(&led->spmi_dev->dev, "query max current failed, rc=%d\n", rc); goto out; } *max_current = rc; rc = 0; } out: mutex_unlock(&led->flash_led_lock); return rc; } Loading drivers/leds/leds.h +17 −0 Original line number Diff line number Diff line Loading @@ -48,11 +48,28 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) return led_cdev->trigger_data; } static inline struct led_classdev *trigger_to_lcdev(struct led_trigger *trig) { struct led_classdev *led_cdev; read_lock(&trig->leddev_list_lock); list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { if (!strcmp(led_cdev->default_trigger, trig->name)) { read_unlock(&trig->leddev_list_lock); return led_cdev; } } read_unlock(&trig->leddev_list_lock); return NULL; } #else #define led_trigger_set_default(x) do {} while (0) #define led_trigger_set(x, y) do {} while (0) #define led_trigger_remove(x) do {} while (0) #define led_get_trigger_data(x) (NULL) #define trigger_to_lcdev(x) (NULL) #endif ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, Loading include/linux/leds-qpnp-flash.h 0 → 100644 +25 −0 Original line number Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __LEDS_QPNP_FLASH_H #define __LEDS_QPNP_FLASH_H #include <linux/leds.h> #define ENABLE_REGULATOR BIT(0) #define DISABLE_REGULATOR BIT(1) #define QUERY_MAX_CURRENT BIT(2) int qpnp_flash_led_prepare(struct led_trigger *trig, int options, int *max_current); #endif Loading
drivers/leds/leds-qpnp-flash.c +66 −1 Original line number Diff line number Diff line Loading @@ -26,9 +26,10 @@ #include <linux/power_supply.h> #include <linux/qpnp/qpnp-adc.h> #include <linux/qpnp/qpnp-revid.h> #include "leds.h" #include <linux/leds-qpnp-flash.h> #include <linux/debugfs.h> #include <linux/uaccess.h> #include "leds.h" #define FLASH_LED_PERIPHERAL_SUBTYPE(base) (base + 0x05) #define FLASH_SAFETY_TIMER(base) (base + 0x40) Loading Loading @@ -79,6 +80,7 @@ #define FLASH_LED_HDRM_SNS_ENABLE_MASK 0x81 #define FLASH_MASK_MODULE_CONTRL_MASK 0xE0 #define FLASH_FOLLOW_OTST2_RB_MASK 0x08 #define FLASH_PREPARE_OPTIONS_MASK 0x07 #define FLASH_LED_TRIGGER_DEFAULT "none" #define FLASH_LED_HEADROOM_DEFAULT_MV 500 Loading Loading @@ -188,6 +190,7 @@ struct flash_node_data { u8 trigger; u8 enable; u8 num_regulators; bool regulators_on; bool flash_on; }; Loading Loading @@ -1148,6 +1151,9 @@ static int flash_regulator_enable(struct qpnp_flash_led *led, { int i, rc = 0; if (flash_node->regulators_on == on) return 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_enable; Loading @@ -1162,12 +1168,71 @@ static int flash_regulator_enable(struct qpnp_flash_led *led, } } flash_node->regulators_on = true; return rc; error_regulator_enable: while (i--) regulator_disable(flash_node->reg_data[i].regs); flash_node->regulators_on = false; return rc; } int qpnp_flash_led_prepare(struct led_trigger *trig, int options, int *max_current) { struct led_classdev *led_cdev = trigger_to_lcdev(trig); struct flash_node_data *flash_node; struct qpnp_flash_led *led; int rc; if (!led_cdev) { pr_err("Invalid led_trigger provided\n"); return -EINVAL; } flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); if (!(options & FLASH_PREPARE_OPTIONS_MASK)) { dev_err(&led->spmi_dev->dev, "Invalid options %d\n", options); return -EINVAL; } mutex_lock(&led->flash_led_lock); if (options & ENABLE_REGULATOR) { rc = flash_regulator_enable(led, flash_node, true); if (rc < 0) { dev_err(&led->spmi_dev->dev, "enable regulator failed, rc=%d\n", rc); goto out; } } if (options & DISABLE_REGULATOR) { rc = flash_regulator_enable(led, flash_node, false); if (rc < 0) { dev_err(&led->spmi_dev->dev, "disable regulator failed, rc=%d\n", rc); goto out; } } if (options & QUERY_MAX_CURRENT) { rc = qpnp_flash_led_get_max_avail_current(flash_node, led); if (rc < 0) { dev_err(&led->spmi_dev->dev, "query max current failed, rc=%d\n", rc); goto out; } *max_current = rc; rc = 0; } out: mutex_unlock(&led->flash_led_lock); return rc; } Loading
drivers/leds/leds.h +17 −0 Original line number Diff line number Diff line Loading @@ -48,11 +48,28 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) return led_cdev->trigger_data; } static inline struct led_classdev *trigger_to_lcdev(struct led_trigger *trig) { struct led_classdev *led_cdev; read_lock(&trig->leddev_list_lock); list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { if (!strcmp(led_cdev->default_trigger, trig->name)) { read_unlock(&trig->leddev_list_lock); return led_cdev; } } read_unlock(&trig->leddev_list_lock); return NULL; } #else #define led_trigger_set_default(x) do {} while (0) #define led_trigger_set(x, y) do {} while (0) #define led_trigger_remove(x) do {} while (0) #define led_get_trigger_data(x) (NULL) #define trigger_to_lcdev(x) (NULL) #endif ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, Loading
include/linux/leds-qpnp-flash.h 0 → 100644 +25 −0 Original line number Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __LEDS_QPNP_FLASH_H #define __LEDS_QPNP_FLASH_H #include <linux/leds.h> #define ENABLE_REGULATOR BIT(0) #define DISABLE_REGULATOR BIT(1) #define QUERY_MAX_CURRENT BIT(2) int qpnp_flash_led_prepare(struct led_trigger *trig, int options, int *max_current); #endif