1*e1c6edcbSLinus Walleij // SPDX-License-Identifier: GPL-2.0-or-later 2*e1c6edcbSLinus Walleij /* 3*e1c6edcbSLinus Walleij * LED driver for Richtek RT8515 flash/torch white LEDs 4*e1c6edcbSLinus Walleij * found on some Samsung mobile phones. 5*e1c6edcbSLinus Walleij * 6*e1c6edcbSLinus Walleij * This is a 1.5A Boost dual channel driver produced around 2011. 7*e1c6edcbSLinus Walleij * 8*e1c6edcbSLinus Walleij * The component lacks a datasheet, but in the schematic picture 9*e1c6edcbSLinus Walleij * from the LG P970 service manual you can see the connections 10*e1c6edcbSLinus Walleij * from the RT8515 to the LED, with two resistors connected 11*e1c6edcbSLinus Walleij * from the pins "RFS" and "RTS" to ground. 12*e1c6edcbSLinus Walleij * 13*e1c6edcbSLinus Walleij * On the LG P970: 14*e1c6edcbSLinus Walleij * RFS (resistance flash setting?) is 20 kOhm 15*e1c6edcbSLinus Walleij * RTS (resistance torch setting?) is 39 kOhm 16*e1c6edcbSLinus Walleij * 17*e1c6edcbSLinus Walleij * Some sleuthing finds us the RT9387A which we have a datasheet for: 18*e1c6edcbSLinus Walleij * https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf 19*e1c6edcbSLinus Walleij * This apparently works the same way so in theory this driver 20*e1c6edcbSLinus Walleij * should cover RT9387A as well. This has not been tested, please 21*e1c6edcbSLinus Walleij * update the compatibles if you add RT9387A support. 22*e1c6edcbSLinus Walleij * 23*e1c6edcbSLinus Walleij * Linus Walleij <linus.walleij@linaro.org> 24*e1c6edcbSLinus Walleij */ 25*e1c6edcbSLinus Walleij #include <linux/delay.h> 26*e1c6edcbSLinus Walleij #include <linux/err.h> 27*e1c6edcbSLinus Walleij #include <linux/gpio/consumer.h> 28*e1c6edcbSLinus Walleij #include <linux/led-class-flash.h> 29*e1c6edcbSLinus Walleij #include <linux/mod_devicetable.h> 30*e1c6edcbSLinus Walleij #include <linux/module.h> 31*e1c6edcbSLinus Walleij #include <linux/platform_device.h> 32*e1c6edcbSLinus Walleij #include <linux/property.h> 33*e1c6edcbSLinus Walleij #include <linux/regulator/consumer.h> 34*e1c6edcbSLinus Walleij 35*e1c6edcbSLinus Walleij #include <media/v4l2-flash-led-class.h> 36*e1c6edcbSLinus Walleij 37*e1c6edcbSLinus Walleij /* We can provide 15-700 mA out to the LED */ 38*e1c6edcbSLinus Walleij #define RT8515_MIN_IOUT_MA 15 39*e1c6edcbSLinus Walleij #define RT8515_MAX_IOUT_MA 700 40*e1c6edcbSLinus Walleij /* The maximum intensity is 1-16 for flash and 1-100 for torch */ 41*e1c6edcbSLinus Walleij #define RT8515_FLASH_MAX 16 42*e1c6edcbSLinus Walleij #define RT8515_TORCH_MAX 100 43*e1c6edcbSLinus Walleij 44*e1c6edcbSLinus Walleij #define RT8515_TIMEOUT_US 250000U 45*e1c6edcbSLinus Walleij #define RT8515_MAX_TIMEOUT_US 300000U 46*e1c6edcbSLinus Walleij 47*e1c6edcbSLinus Walleij struct rt8515 { 48*e1c6edcbSLinus Walleij struct led_classdev_flash fled; 49*e1c6edcbSLinus Walleij struct device *dev; 50*e1c6edcbSLinus Walleij struct v4l2_flash *v4l2_flash; 51*e1c6edcbSLinus Walleij struct mutex lock; 52*e1c6edcbSLinus Walleij struct regulator *reg; 53*e1c6edcbSLinus Walleij struct gpio_desc *enable_torch; 54*e1c6edcbSLinus Walleij struct gpio_desc *enable_flash; 55*e1c6edcbSLinus Walleij struct timer_list powerdown_timer; 56*e1c6edcbSLinus Walleij u32 max_timeout; /* Flash max timeout */ 57*e1c6edcbSLinus Walleij int flash_max_intensity; 58*e1c6edcbSLinus Walleij int torch_max_intensity; 59*e1c6edcbSLinus Walleij }; 60*e1c6edcbSLinus Walleij 61*e1c6edcbSLinus Walleij static struct rt8515 *to_rt8515(struct led_classdev_flash *fled) 62*e1c6edcbSLinus Walleij { 63*e1c6edcbSLinus Walleij return container_of(fled, struct rt8515, fled); 64*e1c6edcbSLinus Walleij } 65*e1c6edcbSLinus Walleij 66*e1c6edcbSLinus Walleij static void rt8515_gpio_led_off(struct rt8515 *rt) 67*e1c6edcbSLinus Walleij { 68*e1c6edcbSLinus Walleij gpiod_set_value(rt->enable_flash, 0); 69*e1c6edcbSLinus Walleij gpiod_set_value(rt->enable_torch, 0); 70*e1c6edcbSLinus Walleij } 71*e1c6edcbSLinus Walleij 72*e1c6edcbSLinus Walleij static void rt8515_gpio_brightness_commit(struct gpio_desc *gpiod, 73*e1c6edcbSLinus Walleij int brightness) 74*e1c6edcbSLinus Walleij { 75*e1c6edcbSLinus Walleij int i; 76*e1c6edcbSLinus Walleij 77*e1c6edcbSLinus Walleij /* 78*e1c6edcbSLinus Walleij * Toggling a GPIO line with a small delay increases the 79*e1c6edcbSLinus Walleij * brightness one step at a time. 80*e1c6edcbSLinus Walleij */ 81*e1c6edcbSLinus Walleij for (i = 0; i < brightness; i++) { 82*e1c6edcbSLinus Walleij gpiod_set_value(gpiod, 0); 83*e1c6edcbSLinus Walleij udelay(1); 84*e1c6edcbSLinus Walleij gpiod_set_value(gpiod, 1); 85*e1c6edcbSLinus Walleij udelay(1); 86*e1c6edcbSLinus Walleij } 87*e1c6edcbSLinus Walleij } 88*e1c6edcbSLinus Walleij 89*e1c6edcbSLinus Walleij /* This is setting the torch light level */ 90*e1c6edcbSLinus Walleij static int rt8515_led_brightness_set(struct led_classdev *led, 91*e1c6edcbSLinus Walleij enum led_brightness brightness) 92*e1c6edcbSLinus Walleij { 93*e1c6edcbSLinus Walleij struct led_classdev_flash *fled = lcdev_to_flcdev(led); 94*e1c6edcbSLinus Walleij struct rt8515 *rt = to_rt8515(fled); 95*e1c6edcbSLinus Walleij 96*e1c6edcbSLinus Walleij mutex_lock(&rt->lock); 97*e1c6edcbSLinus Walleij 98*e1c6edcbSLinus Walleij if (brightness == LED_OFF) { 99*e1c6edcbSLinus Walleij /* Off */ 100*e1c6edcbSLinus Walleij rt8515_gpio_led_off(rt); 101*e1c6edcbSLinus Walleij } else if (brightness < RT8515_TORCH_MAX) { 102*e1c6edcbSLinus Walleij /* Step it up to movie mode brightness using the flash pin */ 103*e1c6edcbSLinus Walleij rt8515_gpio_brightness_commit(rt->enable_torch, brightness); 104*e1c6edcbSLinus Walleij } else { 105*e1c6edcbSLinus Walleij /* Max torch brightness requested */ 106*e1c6edcbSLinus Walleij gpiod_set_value(rt->enable_torch, 1); 107*e1c6edcbSLinus Walleij } 108*e1c6edcbSLinus Walleij 109*e1c6edcbSLinus Walleij mutex_unlock(&rt->lock); 110*e1c6edcbSLinus Walleij 111*e1c6edcbSLinus Walleij return 0; 112*e1c6edcbSLinus Walleij } 113*e1c6edcbSLinus Walleij 114*e1c6edcbSLinus Walleij static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled, 115*e1c6edcbSLinus Walleij bool state) 116*e1c6edcbSLinus Walleij { 117*e1c6edcbSLinus Walleij struct rt8515 *rt = to_rt8515(fled); 118*e1c6edcbSLinus Walleij struct led_flash_setting *timeout = &fled->timeout; 119*e1c6edcbSLinus Walleij int brightness = rt->flash_max_intensity; 120*e1c6edcbSLinus Walleij 121*e1c6edcbSLinus Walleij mutex_lock(&rt->lock); 122*e1c6edcbSLinus Walleij 123*e1c6edcbSLinus Walleij if (state) { 124*e1c6edcbSLinus Walleij /* Enable LED flash mode and set brightness */ 125*e1c6edcbSLinus Walleij rt8515_gpio_brightness_commit(rt->enable_flash, brightness); 126*e1c6edcbSLinus Walleij /* Set timeout */ 127*e1c6edcbSLinus Walleij mod_timer(&rt->powerdown_timer, 128*e1c6edcbSLinus Walleij jiffies + usecs_to_jiffies(timeout->val)); 129*e1c6edcbSLinus Walleij } else { 130*e1c6edcbSLinus Walleij del_timer_sync(&rt->powerdown_timer); 131*e1c6edcbSLinus Walleij /* Turn the LED off */ 132*e1c6edcbSLinus Walleij rt8515_gpio_led_off(rt); 133*e1c6edcbSLinus Walleij } 134*e1c6edcbSLinus Walleij 135*e1c6edcbSLinus Walleij fled->led_cdev.brightness = LED_OFF; 136*e1c6edcbSLinus Walleij /* After this the torch LED will be disabled */ 137*e1c6edcbSLinus Walleij 138*e1c6edcbSLinus Walleij mutex_unlock(&rt->lock); 139*e1c6edcbSLinus Walleij 140*e1c6edcbSLinus Walleij return 0; 141*e1c6edcbSLinus Walleij } 142*e1c6edcbSLinus Walleij 143*e1c6edcbSLinus Walleij static int rt8515_led_flash_strobe_get(struct led_classdev_flash *fled, 144*e1c6edcbSLinus Walleij bool *state) 145*e1c6edcbSLinus Walleij { 146*e1c6edcbSLinus Walleij struct rt8515 *rt = to_rt8515(fled); 147*e1c6edcbSLinus Walleij 148*e1c6edcbSLinus Walleij *state = timer_pending(&rt->powerdown_timer); 149*e1c6edcbSLinus Walleij 150*e1c6edcbSLinus Walleij return 0; 151*e1c6edcbSLinus Walleij } 152*e1c6edcbSLinus Walleij 153*e1c6edcbSLinus Walleij static int rt8515_led_flash_timeout_set(struct led_classdev_flash *fled, 154*e1c6edcbSLinus Walleij u32 timeout) 155*e1c6edcbSLinus Walleij { 156*e1c6edcbSLinus Walleij /* The timeout is stored in the led-class-flash core */ 157*e1c6edcbSLinus Walleij return 0; 158*e1c6edcbSLinus Walleij } 159*e1c6edcbSLinus Walleij 160*e1c6edcbSLinus Walleij static const struct led_flash_ops rt8515_flash_ops = { 161*e1c6edcbSLinus Walleij .strobe_set = rt8515_led_flash_strobe_set, 162*e1c6edcbSLinus Walleij .strobe_get = rt8515_led_flash_strobe_get, 163*e1c6edcbSLinus Walleij .timeout_set = rt8515_led_flash_timeout_set, 164*e1c6edcbSLinus Walleij }; 165*e1c6edcbSLinus Walleij 166*e1c6edcbSLinus Walleij static void rt8515_powerdown_timer(struct timer_list *t) 167*e1c6edcbSLinus Walleij { 168*e1c6edcbSLinus Walleij struct rt8515 *rt = from_timer(rt, t, powerdown_timer); 169*e1c6edcbSLinus Walleij 170*e1c6edcbSLinus Walleij /* Turn the LED off */ 171*e1c6edcbSLinus Walleij rt8515_gpio_led_off(rt); 172*e1c6edcbSLinus Walleij } 173*e1c6edcbSLinus Walleij 174*e1c6edcbSLinus Walleij static void rt8515_init_flash_timeout(struct rt8515 *rt) 175*e1c6edcbSLinus Walleij { 176*e1c6edcbSLinus Walleij struct led_classdev_flash *fled = &rt->fled; 177*e1c6edcbSLinus Walleij struct led_flash_setting *s; 178*e1c6edcbSLinus Walleij 179*e1c6edcbSLinus Walleij /* Init flash timeout setting */ 180*e1c6edcbSLinus Walleij s = &fled->timeout; 181*e1c6edcbSLinus Walleij s->min = 1; 182*e1c6edcbSLinus Walleij s->max = rt->max_timeout; 183*e1c6edcbSLinus Walleij s->step = 1; 184*e1c6edcbSLinus Walleij /* 185*e1c6edcbSLinus Walleij * Set default timeout to RT8515_TIMEOUT_US except if 186*e1c6edcbSLinus Walleij * max_timeout from DT is lower. 187*e1c6edcbSLinus Walleij */ 188*e1c6edcbSLinus Walleij s->val = min(rt->max_timeout, RT8515_TIMEOUT_US); 189*e1c6edcbSLinus Walleij } 190*e1c6edcbSLinus Walleij 191*e1c6edcbSLinus Walleij #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 192*e1c6edcbSLinus Walleij /* Configure the V2L2 flash subdevice */ 193*e1c6edcbSLinus Walleij static void rt8515_init_v4l2_flash_config(struct rt8515 *rt, 194*e1c6edcbSLinus Walleij struct v4l2_flash_config *v4l2_sd_cfg) 195*e1c6edcbSLinus Walleij { 196*e1c6edcbSLinus Walleij struct led_classdev *led = &rt->fled.led_cdev; 197*e1c6edcbSLinus Walleij struct led_flash_setting *s; 198*e1c6edcbSLinus Walleij 199*e1c6edcbSLinus Walleij strscpy(v4l2_sd_cfg->dev_name, led->dev->kobj.name, 200*e1c6edcbSLinus Walleij sizeof(v4l2_sd_cfg->dev_name)); 201*e1c6edcbSLinus Walleij 202*e1c6edcbSLinus Walleij /* 203*e1c6edcbSLinus Walleij * Init flash intensity setting: this is a linear scale 204*e1c6edcbSLinus Walleij * capped from the device tree max intensity setting 205*e1c6edcbSLinus Walleij * 1..flash_max_intensity 206*e1c6edcbSLinus Walleij */ 207*e1c6edcbSLinus Walleij s = &v4l2_sd_cfg->intensity; 208*e1c6edcbSLinus Walleij s->min = 1; 209*e1c6edcbSLinus Walleij s->max = rt->flash_max_intensity; 210*e1c6edcbSLinus Walleij s->step = 1; 211*e1c6edcbSLinus Walleij s->val = s->max; 212*e1c6edcbSLinus Walleij } 213*e1c6edcbSLinus Walleij 214*e1c6edcbSLinus Walleij static void rt8515_v4l2_flash_release(struct rt8515 *rt) 215*e1c6edcbSLinus Walleij { 216*e1c6edcbSLinus Walleij v4l2_flash_release(rt->v4l2_flash); 217*e1c6edcbSLinus Walleij } 218*e1c6edcbSLinus Walleij 219*e1c6edcbSLinus Walleij #else 220*e1c6edcbSLinus Walleij static void rt8515_init_v4l2_flash_config(struct rt8515 *rt, 221*e1c6edcbSLinus Walleij struct v4l2_flash_config *v4l2_sd_cfg) 222*e1c6edcbSLinus Walleij { 223*e1c6edcbSLinus Walleij } 224*e1c6edcbSLinus Walleij 225*e1c6edcbSLinus Walleij static void rt8515_v4l2_flash_release(struct rt8515 *rt) 226*e1c6edcbSLinus Walleij { 227*e1c6edcbSLinus Walleij } 228*e1c6edcbSLinus Walleij #endif 229*e1c6edcbSLinus Walleij 230*e1c6edcbSLinus Walleij static void rt8515_determine_max_intensity(struct rt8515 *rt, 231*e1c6edcbSLinus Walleij struct fwnode_handle *led, 232*e1c6edcbSLinus Walleij const char *resistance, 233*e1c6edcbSLinus Walleij const char *max_ua_prop, int hw_max, 234*e1c6edcbSLinus Walleij int *max_intensity_setting) 235*e1c6edcbSLinus Walleij { 236*e1c6edcbSLinus Walleij u32 res = 0; /* Can't be 0 so 0 is undefined */ 237*e1c6edcbSLinus Walleij u32 ua; 238*e1c6edcbSLinus Walleij u32 max_ma; 239*e1c6edcbSLinus Walleij int max_intensity; 240*e1c6edcbSLinus Walleij int ret; 241*e1c6edcbSLinus Walleij 242*e1c6edcbSLinus Walleij fwnode_property_read_u32(rt->dev->fwnode, resistance, &res); 243*e1c6edcbSLinus Walleij ret = fwnode_property_read_u32(led, max_ua_prop, &ua); 244*e1c6edcbSLinus Walleij 245*e1c6edcbSLinus Walleij /* Missing info in DT, OK go with hardware maxima */ 246*e1c6edcbSLinus Walleij if (ret || res == 0) { 247*e1c6edcbSLinus Walleij dev_err(rt->dev, 248*e1c6edcbSLinus Walleij "either %s or %s missing from DT, using HW max\n", 249*e1c6edcbSLinus Walleij resistance, max_ua_prop); 250*e1c6edcbSLinus Walleij max_ma = RT8515_MAX_IOUT_MA; 251*e1c6edcbSLinus Walleij max_intensity = hw_max; 252*e1c6edcbSLinus Walleij goto out_assign_max; 253*e1c6edcbSLinus Walleij } 254*e1c6edcbSLinus Walleij 255*e1c6edcbSLinus Walleij /* 256*e1c6edcbSLinus Walleij * Formula from the datasheet, this is the maximum current 257*e1c6edcbSLinus Walleij * defined by the hardware. 258*e1c6edcbSLinus Walleij */ 259*e1c6edcbSLinus Walleij max_ma = (5500 * 1000) / res; 260*e1c6edcbSLinus Walleij /* 261*e1c6edcbSLinus Walleij * Calculate max intensity (linear scaling) 262*e1c6edcbSLinus Walleij * Formula is ((ua / 1000) / max_ma) * 100, then simplified 263*e1c6edcbSLinus Walleij */ 264*e1c6edcbSLinus Walleij max_intensity = (ua / 10) / max_ma; 265*e1c6edcbSLinus Walleij 266*e1c6edcbSLinus Walleij dev_info(rt->dev, 267*e1c6edcbSLinus Walleij "current restricted from %u to %u mA, max intensity %d/100\n", 268*e1c6edcbSLinus Walleij max_ma, (ua / 1000), max_intensity); 269*e1c6edcbSLinus Walleij 270*e1c6edcbSLinus Walleij out_assign_max: 271*e1c6edcbSLinus Walleij dev_info(rt->dev, "max intensity %d/%d = %d mA\n", 272*e1c6edcbSLinus Walleij max_intensity, hw_max, max_ma); 273*e1c6edcbSLinus Walleij *max_intensity_setting = max_intensity; 274*e1c6edcbSLinus Walleij } 275*e1c6edcbSLinus Walleij 276*e1c6edcbSLinus Walleij static int rt8515_probe(struct platform_device *pdev) 277*e1c6edcbSLinus Walleij { 278*e1c6edcbSLinus Walleij struct device *dev = &pdev->dev; 279*e1c6edcbSLinus Walleij struct fwnode_handle *child; 280*e1c6edcbSLinus Walleij struct rt8515 *rt; 281*e1c6edcbSLinus Walleij struct led_classdev *led; 282*e1c6edcbSLinus Walleij struct led_classdev_flash *fled; 283*e1c6edcbSLinus Walleij struct led_init_data init_data = {}; 284*e1c6edcbSLinus Walleij struct v4l2_flash_config v4l2_sd_cfg = {}; 285*e1c6edcbSLinus Walleij int ret; 286*e1c6edcbSLinus Walleij 287*e1c6edcbSLinus Walleij rt = devm_kzalloc(dev, sizeof(*rt), GFP_KERNEL); 288*e1c6edcbSLinus Walleij if (!rt) 289*e1c6edcbSLinus Walleij return -ENOMEM; 290*e1c6edcbSLinus Walleij 291*e1c6edcbSLinus Walleij rt->dev = dev; 292*e1c6edcbSLinus Walleij fled = &rt->fled; 293*e1c6edcbSLinus Walleij led = &fled->led_cdev; 294*e1c6edcbSLinus Walleij 295*e1c6edcbSLinus Walleij /* ENF - Enable Flash line */ 296*e1c6edcbSLinus Walleij rt->enable_flash = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW); 297*e1c6edcbSLinus Walleij if (IS_ERR(rt->enable_flash)) 298*e1c6edcbSLinus Walleij return dev_err_probe(dev, PTR_ERR(rt->enable_flash), 299*e1c6edcbSLinus Walleij "cannot get ENF (enable flash) GPIO\n"); 300*e1c6edcbSLinus Walleij 301*e1c6edcbSLinus Walleij /* ENT - Enable Torch line */ 302*e1c6edcbSLinus Walleij rt->enable_torch = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW); 303*e1c6edcbSLinus Walleij if (IS_ERR(rt->enable_torch)) 304*e1c6edcbSLinus Walleij return dev_err_probe(dev, PTR_ERR(rt->enable_torch), 305*e1c6edcbSLinus Walleij "cannot get ENT (enable torch) GPIO\n"); 306*e1c6edcbSLinus Walleij 307*e1c6edcbSLinus Walleij child = fwnode_get_next_available_child_node(dev->fwnode, NULL); 308*e1c6edcbSLinus Walleij if (!child) { 309*e1c6edcbSLinus Walleij dev_err(dev, 310*e1c6edcbSLinus Walleij "No fwnode child node found for connected LED.\n"); 311*e1c6edcbSLinus Walleij return -EINVAL; 312*e1c6edcbSLinus Walleij } 313*e1c6edcbSLinus Walleij init_data.fwnode = child; 314*e1c6edcbSLinus Walleij 315*e1c6edcbSLinus Walleij rt8515_determine_max_intensity(rt, child, "richtek,rfs-ohms", 316*e1c6edcbSLinus Walleij "flash-max-microamp", 317*e1c6edcbSLinus Walleij RT8515_FLASH_MAX, 318*e1c6edcbSLinus Walleij &rt->flash_max_intensity); 319*e1c6edcbSLinus Walleij rt8515_determine_max_intensity(rt, child, "richtek,rts-ohms", 320*e1c6edcbSLinus Walleij "led-max-microamp", 321*e1c6edcbSLinus Walleij RT8515_TORCH_MAX, 322*e1c6edcbSLinus Walleij &rt->torch_max_intensity); 323*e1c6edcbSLinus Walleij 324*e1c6edcbSLinus Walleij ret = fwnode_property_read_u32(child, "flash-max-timeout-us", 325*e1c6edcbSLinus Walleij &rt->max_timeout); 326*e1c6edcbSLinus Walleij if (ret) { 327*e1c6edcbSLinus Walleij rt->max_timeout = RT8515_MAX_TIMEOUT_US; 328*e1c6edcbSLinus Walleij dev_warn(dev, 329*e1c6edcbSLinus Walleij "flash-max-timeout-us property missing\n"); 330*e1c6edcbSLinus Walleij } 331*e1c6edcbSLinus Walleij timer_setup(&rt->powerdown_timer, rt8515_powerdown_timer, 0); 332*e1c6edcbSLinus Walleij rt8515_init_flash_timeout(rt); 333*e1c6edcbSLinus Walleij 334*e1c6edcbSLinus Walleij fled->ops = &rt8515_flash_ops; 335*e1c6edcbSLinus Walleij 336*e1c6edcbSLinus Walleij led->max_brightness = rt->torch_max_intensity; 337*e1c6edcbSLinus Walleij led->brightness_set_blocking = rt8515_led_brightness_set; 338*e1c6edcbSLinus Walleij led->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH; 339*e1c6edcbSLinus Walleij 340*e1c6edcbSLinus Walleij mutex_init(&rt->lock); 341*e1c6edcbSLinus Walleij 342*e1c6edcbSLinus Walleij platform_set_drvdata(pdev, rt); 343*e1c6edcbSLinus Walleij 344*e1c6edcbSLinus Walleij ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data); 345*e1c6edcbSLinus Walleij if (ret) { 346*e1c6edcbSLinus Walleij dev_err(dev, "can't register LED %s\n", led->name); 347*e1c6edcbSLinus Walleij mutex_destroy(&rt->lock); 348*e1c6edcbSLinus Walleij return ret; 349*e1c6edcbSLinus Walleij } 350*e1c6edcbSLinus Walleij 351*e1c6edcbSLinus Walleij rt8515_init_v4l2_flash_config(rt, &v4l2_sd_cfg); 352*e1c6edcbSLinus Walleij 353*e1c6edcbSLinus Walleij /* Create a V4L2 Flash device if V4L2 flash is enabled */ 354*e1c6edcbSLinus Walleij rt->v4l2_flash = v4l2_flash_init(dev, child, fled, NULL, &v4l2_sd_cfg); 355*e1c6edcbSLinus Walleij if (IS_ERR(rt->v4l2_flash)) { 356*e1c6edcbSLinus Walleij ret = PTR_ERR(rt->v4l2_flash); 357*e1c6edcbSLinus Walleij dev_err(dev, "failed to register V4L2 flash device (%d)\n", 358*e1c6edcbSLinus Walleij ret); 359*e1c6edcbSLinus Walleij /* 360*e1c6edcbSLinus Walleij * Continue without the V4L2 flash 361*e1c6edcbSLinus Walleij * (we still have the classdev) 362*e1c6edcbSLinus Walleij */ 363*e1c6edcbSLinus Walleij } 364*e1c6edcbSLinus Walleij 365*e1c6edcbSLinus Walleij return 0; 366*e1c6edcbSLinus Walleij } 367*e1c6edcbSLinus Walleij 368*e1c6edcbSLinus Walleij static int rt8515_remove(struct platform_device *pdev) 369*e1c6edcbSLinus Walleij { 370*e1c6edcbSLinus Walleij struct rt8515 *rt = platform_get_drvdata(pdev); 371*e1c6edcbSLinus Walleij 372*e1c6edcbSLinus Walleij rt8515_v4l2_flash_release(rt); 373*e1c6edcbSLinus Walleij del_timer_sync(&rt->powerdown_timer); 374*e1c6edcbSLinus Walleij mutex_destroy(&rt->lock); 375*e1c6edcbSLinus Walleij 376*e1c6edcbSLinus Walleij return 0; 377*e1c6edcbSLinus Walleij } 378*e1c6edcbSLinus Walleij 379*e1c6edcbSLinus Walleij static const struct of_device_id rt8515_match[] = { 380*e1c6edcbSLinus Walleij { .compatible = "richtek,rt8515", }, 381*e1c6edcbSLinus Walleij { /* sentinel */ } 382*e1c6edcbSLinus Walleij }; 383*e1c6edcbSLinus Walleij MODULE_DEVICE_TABLE(of, rt8515_match); 384*e1c6edcbSLinus Walleij 385*e1c6edcbSLinus Walleij static struct platform_driver rt8515_driver = { 386*e1c6edcbSLinus Walleij .driver = { 387*e1c6edcbSLinus Walleij .name = "rt8515", 388*e1c6edcbSLinus Walleij .of_match_table = rt8515_match, 389*e1c6edcbSLinus Walleij }, 390*e1c6edcbSLinus Walleij .probe = rt8515_probe, 391*e1c6edcbSLinus Walleij .remove = rt8515_remove, 392*e1c6edcbSLinus Walleij }; 393*e1c6edcbSLinus Walleij module_platform_driver(rt8515_driver); 394*e1c6edcbSLinus Walleij 395*e1c6edcbSLinus Walleij MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 396*e1c6edcbSLinus Walleij MODULE_DESCRIPTION("Richtek RT8515 LED driver"); 397*e1c6edcbSLinus Walleij MODULE_LICENSE("GPL"); 398