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