1*02149db2SKaustabh Chakraborty // SPDX-License-Identifier: GPL-2.0 2*02149db2SKaustabh Chakraborty /* 3*02149db2SKaustabh Chakraborty * Flash and Torch LED Driver for Samsung S2M series PMICs. 4*02149db2SKaustabh Chakraborty * 5*02149db2SKaustabh Chakraborty * Copyright (c) 2015 Samsung Electronics Co., Ltd 6*02149db2SKaustabh Chakraborty * Copyright (c) 2026 Kaustabh Chakraborty <kauschluss@disroot.org> 7*02149db2SKaustabh Chakraborty */ 8*02149db2SKaustabh Chakraborty 9*02149db2SKaustabh Chakraborty #include <linux/container_of.h> 10*02149db2SKaustabh Chakraborty #include <linux/led-class-flash.h> 11*02149db2SKaustabh Chakraborty #include <linux/mfd/samsung/core.h> 12*02149db2SKaustabh Chakraborty #include <linux/mfd/samsung/s2mu005.h> 13*02149db2SKaustabh Chakraborty #include <linux/module.h> 14*02149db2SKaustabh Chakraborty #include <linux/of.h> 15*02149db2SKaustabh Chakraborty #include <linux/platform_device.h> 16*02149db2SKaustabh Chakraborty #include <linux/regmap.h> 17*02149db2SKaustabh Chakraborty #include <media/v4l2-flash-led-class.h> 18*02149db2SKaustabh Chakraborty 19*02149db2SKaustabh Chakraborty #define MAX_CHANNELS 2 20*02149db2SKaustabh Chakraborty 21*02149db2SKaustabh Chakraborty struct s2m_led { 22*02149db2SKaustabh Chakraborty struct regmap *regmap; 23*02149db2SKaustabh Chakraborty struct led_classdev_flash fled; 24*02149db2SKaustabh Chakraborty struct v4l2_flash *v4l2_flash; 25*02149db2SKaustabh Chakraborty /* 26*02149db2SKaustabh Chakraborty * The mutex object prevents the concurrent access of flash control 27*02149db2SKaustabh Chakraborty * registers by the LED and V4L2 subsystems. 28*02149db2SKaustabh Chakraborty */ 29*02149db2SKaustabh Chakraborty struct mutex lock; 30*02149db2SKaustabh Chakraborty unsigned int reg_enable; 31*02149db2SKaustabh Chakraborty u8 channel; 32*02149db2SKaustabh Chakraborty u8 flash_brightness; 33*02149db2SKaustabh Chakraborty u8 flash_timeout; 34*02149db2SKaustabh Chakraborty }; 35*02149db2SKaustabh Chakraborty 36*02149db2SKaustabh Chakraborty static struct s2m_led *to_s2m_led(struct led_classdev_flash *fled) 37*02149db2SKaustabh Chakraborty { 38*02149db2SKaustabh Chakraborty return container_of(fled, struct s2m_led, fled); 39*02149db2SKaustabh Chakraborty } 40*02149db2SKaustabh Chakraborty 41*02149db2SKaustabh Chakraborty static struct led_classdev_flash *to_s2m_fled(struct led_classdev *cdev) 42*02149db2SKaustabh Chakraborty { 43*02149db2SKaustabh Chakraborty return container_of(cdev, struct led_classdev_flash, led_cdev); 44*02149db2SKaustabh Chakraborty } 45*02149db2SKaustabh Chakraborty 46*02149db2SKaustabh Chakraborty static int s2m_fled_flash_brightness_set(struct led_classdev_flash *fled, u32 brightness) 47*02149db2SKaustabh Chakraborty { 48*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(fled); 49*02149db2SKaustabh Chakraborty struct led_flash_setting *setting = &fled->brightness; 50*02149db2SKaustabh Chakraborty 51*02149db2SKaustabh Chakraborty mutex_lock(&led->lock); 52*02149db2SKaustabh Chakraborty led->flash_brightness = (brightness - setting->min) / setting->step; 53*02149db2SKaustabh Chakraborty mutex_unlock(&led->lock); 54*02149db2SKaustabh Chakraborty 55*02149db2SKaustabh Chakraborty return 0; 56*02149db2SKaustabh Chakraborty } 57*02149db2SKaustabh Chakraborty 58*02149db2SKaustabh Chakraborty static int s2m_fled_flash_timeout_set(struct led_classdev_flash *fled, u32 timeout) 59*02149db2SKaustabh Chakraborty { 60*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(fled); 61*02149db2SKaustabh Chakraborty struct led_flash_setting *setting = &fled->timeout; 62*02149db2SKaustabh Chakraborty 63*02149db2SKaustabh Chakraborty mutex_lock(&led->lock); 64*02149db2SKaustabh Chakraborty led->flash_timeout = (timeout - setting->min) / setting->step; 65*02149db2SKaustabh Chakraborty mutex_unlock(&led->lock); 66*02149db2SKaustabh Chakraborty 67*02149db2SKaustabh Chakraborty return 0; 68*02149db2SKaustabh Chakraborty } 69*02149db2SKaustabh Chakraborty 70*02149db2SKaustabh Chakraborty #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 71*02149db2SKaustabh Chakraborty static int s2m_fled_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable) 72*02149db2SKaustabh Chakraborty { 73*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(v4l2_flash->fled_cdev); 74*02149db2SKaustabh Chakraborty 75*02149db2SKaustabh Chakraborty return led->fled.ops->strobe_set(&led->fled, enable); 76*02149db2SKaustabh Chakraborty } 77*02149db2SKaustabh Chakraborty 78*02149db2SKaustabh Chakraborty static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops = { 79*02149db2SKaustabh Chakraborty .external_strobe_set = s2m_fled_flash_external_strobe_set, 80*02149db2SKaustabh Chakraborty }; 81*02149db2SKaustabh Chakraborty #else 82*02149db2SKaustabh Chakraborty static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops; 83*02149db2SKaustabh Chakraborty #endif 84*02149db2SKaustabh Chakraborty 85*02149db2SKaustabh Chakraborty static void s2m_fled_v4l2_flash_release(void *v4l2_flash) 86*02149db2SKaustabh Chakraborty { 87*02149db2SKaustabh Chakraborty v4l2_flash_release(v4l2_flash); 88*02149db2SKaustabh Chakraborty } 89*02149db2SKaustabh Chakraborty 90*02149db2SKaustabh Chakraborty static int s2mu005_fled_torch_brightness_set(struct led_classdev *cdev, enum led_brightness value) 91*02149db2SKaustabh Chakraborty { 92*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(to_s2m_fled(cdev)); 93*02149db2SKaustabh Chakraborty int ret; 94*02149db2SKaustabh Chakraborty 95*02149db2SKaustabh Chakraborty mutex_lock(&led->lock); 96*02149db2SKaustabh Chakraborty 97*02149db2SKaustabh Chakraborty if (!value) { 98*02149db2SKaustabh Chakraborty ret = regmap_clear_bits(led->regmap, led->reg_enable, 99*02149db2SKaustabh Chakraborty S2MU005_FLED_TORCH_EN(led->channel)); 100*02149db2SKaustabh Chakraborty if (ret) 101*02149db2SKaustabh Chakraborty dev_err(cdev->dev, "failed to disable torch LED\n"); 102*02149db2SKaustabh Chakraborty goto unlock; 103*02149db2SKaustabh Chakraborty } 104*02149db2SKaustabh Chakraborty 105*02149db2SKaustabh Chakraborty ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL1(led->channel), 106*02149db2SKaustabh Chakraborty S2MU005_FLED_TORCH_IOUT, 107*02149db2SKaustabh Chakraborty FIELD_PREP(S2MU005_FLED_TORCH_IOUT, value - 1)); 108*02149db2SKaustabh Chakraborty if (ret) { 109*02149db2SKaustabh Chakraborty dev_err(cdev->dev, "failed to set torch current\n"); 110*02149db2SKaustabh Chakraborty goto unlock; 111*02149db2SKaustabh Chakraborty } 112*02149db2SKaustabh Chakraborty 113*02149db2SKaustabh Chakraborty ret = regmap_set_bits(led->regmap, led->reg_enable, S2MU005_FLED_TORCH_EN(led->channel)); 114*02149db2SKaustabh Chakraborty if (ret) { 115*02149db2SKaustabh Chakraborty dev_err(cdev->dev, "failed to enable torch LED\n"); 116*02149db2SKaustabh Chakraborty goto unlock; 117*02149db2SKaustabh Chakraborty } 118*02149db2SKaustabh Chakraborty 119*02149db2SKaustabh Chakraborty unlock: 120*02149db2SKaustabh Chakraborty mutex_unlock(&led->lock); 121*02149db2SKaustabh Chakraborty 122*02149db2SKaustabh Chakraborty return ret; 123*02149db2SKaustabh Chakraborty } 124*02149db2SKaustabh Chakraborty 125*02149db2SKaustabh Chakraborty static int s2mu005_fled_flash_strobe_set(struct led_classdev_flash *fled, bool state) 126*02149db2SKaustabh Chakraborty { 127*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(fled); 128*02149db2SKaustabh Chakraborty int ret; 129*02149db2SKaustabh Chakraborty 130*02149db2SKaustabh Chakraborty mutex_lock(&led->lock); 131*02149db2SKaustabh Chakraborty 132*02149db2SKaustabh Chakraborty ret = regmap_clear_bits(led->regmap, led->reg_enable, S2MU005_FLED_FLASH_EN(led->channel)); 133*02149db2SKaustabh Chakraborty if (ret) { 134*02149db2SKaustabh Chakraborty dev_err(fled->led_cdev.dev, "failed to disable flash LED\n"); 135*02149db2SKaustabh Chakraborty goto unlock; 136*02149db2SKaustabh Chakraborty } 137*02149db2SKaustabh Chakraborty 138*02149db2SKaustabh Chakraborty if (!state) 139*02149db2SKaustabh Chakraborty goto unlock; 140*02149db2SKaustabh Chakraborty 141*02149db2SKaustabh Chakraborty ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL0(led->channel), 142*02149db2SKaustabh Chakraborty S2MU005_FLED_FLASH_IOUT, 143*02149db2SKaustabh Chakraborty FIELD_PREP(S2MU005_FLED_FLASH_IOUT, led->flash_brightness)); 144*02149db2SKaustabh Chakraborty if (ret) { 145*02149db2SKaustabh Chakraborty dev_err(fled->led_cdev.dev, "failed to set flash brightness\n"); 146*02149db2SKaustabh Chakraborty goto unlock; 147*02149db2SKaustabh Chakraborty } 148*02149db2SKaustabh Chakraborty 149*02149db2SKaustabh Chakraborty ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL3(led->channel), 150*02149db2SKaustabh Chakraborty S2MU005_FLED_FLASH_TIMEOUT, 151*02149db2SKaustabh Chakraborty FIELD_PREP(S2MU005_FLED_FLASH_TIMEOUT, led->flash_timeout)); 152*02149db2SKaustabh Chakraborty if (ret) { 153*02149db2SKaustabh Chakraborty dev_err(fled->led_cdev.dev, "failed to set flash timeout\n"); 154*02149db2SKaustabh Chakraborty goto unlock; 155*02149db2SKaustabh Chakraborty } 156*02149db2SKaustabh Chakraborty 157*02149db2SKaustabh Chakraborty ret = regmap_set_bits(led->regmap, led->reg_enable, S2MU005_FLED_FLASH_EN(led->channel)); 158*02149db2SKaustabh Chakraborty if (ret) { 159*02149db2SKaustabh Chakraborty dev_err(fled->led_cdev.dev, "failed to enable flash LED\n"); 160*02149db2SKaustabh Chakraborty goto unlock; 161*02149db2SKaustabh Chakraborty } 162*02149db2SKaustabh Chakraborty 163*02149db2SKaustabh Chakraborty unlock: 164*02149db2SKaustabh Chakraborty mutex_unlock(&led->lock); 165*02149db2SKaustabh Chakraborty 166*02149db2SKaustabh Chakraborty return ret; 167*02149db2SKaustabh Chakraborty } 168*02149db2SKaustabh Chakraborty 169*02149db2SKaustabh Chakraborty static int s2mu005_fled_flash_strobe_get(struct led_classdev_flash *fled, bool *state) 170*02149db2SKaustabh Chakraborty { 171*02149db2SKaustabh Chakraborty struct s2m_led *led = to_s2m_led(fled); 172*02149db2SKaustabh Chakraborty u32 val; 173*02149db2SKaustabh Chakraborty int ret; 174*02149db2SKaustabh Chakraborty 175*02149db2SKaustabh Chakraborty mutex_lock(&led->lock); 176*02149db2SKaustabh Chakraborty 177*02149db2SKaustabh Chakraborty ret = regmap_read(led->regmap, S2MU005_REG_FLED_STATUS, &val); 178*02149db2SKaustabh Chakraborty if (ret) { 179*02149db2SKaustabh Chakraborty dev_err(fled->led_cdev.dev, "failed to fetch LED status\n"); 180*02149db2SKaustabh Chakraborty goto unlock; 181*02149db2SKaustabh Chakraborty } 182*02149db2SKaustabh Chakraborty 183*02149db2SKaustabh Chakraborty *state = !!(val & S2MU005_FLED_FLASH_STATUS(led->channel)); 184*02149db2SKaustabh Chakraborty 185*02149db2SKaustabh Chakraborty unlock: 186*02149db2SKaustabh Chakraborty mutex_unlock(&led->lock); 187*02149db2SKaustabh Chakraborty 188*02149db2SKaustabh Chakraborty return ret; 189*02149db2SKaustabh Chakraborty } 190*02149db2SKaustabh Chakraborty 191*02149db2SKaustabh Chakraborty static const struct led_flash_ops s2mu005_fled_flash_ops = { 192*02149db2SKaustabh Chakraborty .flash_brightness_set = s2m_fled_flash_brightness_set, 193*02149db2SKaustabh Chakraborty .timeout_set = s2m_fled_flash_timeout_set, 194*02149db2SKaustabh Chakraborty .strobe_set = s2mu005_fled_flash_strobe_set, 195*02149db2SKaustabh Chakraborty .strobe_get = s2mu005_fled_flash_strobe_get, 196*02149db2SKaustabh Chakraborty }; 197*02149db2SKaustabh Chakraborty 198*02149db2SKaustabh Chakraborty static int s2mu005_fled_init(struct s2m_led *led, struct device *dev, struct regmap *regmap, 199*02149db2SKaustabh Chakraborty unsigned int nr_channels) 200*02149db2SKaustabh Chakraborty { 201*02149db2SKaustabh Chakraborty unsigned int val; 202*02149db2SKaustabh Chakraborty int ret; 203*02149db2SKaustabh Chakraborty 204*02149db2SKaustabh Chakraborty ret = regmap_read(regmap, S2MU005_REG_ID, &val); 205*02149db2SKaustabh Chakraborty if (ret) 206*02149db2SKaustabh Chakraborty return dev_err_probe(dev, ret, "failed to read revision\n"); 207*02149db2SKaustabh Chakraborty 208*02149db2SKaustabh Chakraborty for (int i = 0; i < nr_channels; i++) { 209*02149db2SKaustabh Chakraborty /* 210*02149db2SKaustabh Chakraborty * Read the revision register. Revision EVT0 has the register 211*02149db2SKaustabh Chakraborty * at CTRL4, while EVT1 and higher have it at CTRL6. 212*02149db2SKaustabh Chakraborty */ 213*02149db2SKaustabh Chakraborty if (FIELD_GET(S2MU005_ID_MASK, val) == 0) 214*02149db2SKaustabh Chakraborty led[i].reg_enable = S2MU005_REG_FLED_CTRL4; 215*02149db2SKaustabh Chakraborty else 216*02149db2SKaustabh Chakraborty led[i].reg_enable = S2MU005_REG_FLED_CTRL6; 217*02149db2SKaustabh Chakraborty } 218*02149db2SKaustabh Chakraborty 219*02149db2SKaustabh Chakraborty /* Enable the LED channels. */ 220*02149db2SKaustabh Chakraborty ret = regmap_set_bits(regmap, S2MU005_REG_FLED_CTRL1, S2MU005_FLED_CH_EN); 221*02149db2SKaustabh Chakraborty if (ret) 222*02149db2SKaustabh Chakraborty return dev_err_probe(dev, ret, "failed to enable LED channels\n"); 223*02149db2SKaustabh Chakraborty 224*02149db2SKaustabh Chakraborty return 0; 225*02149db2SKaustabh Chakraborty } 226*02149db2SKaustabh Chakraborty 227*02149db2SKaustabh Chakraborty static int s2mu005_fled_init_channel(struct s2m_led *led, struct device *dev, 228*02149db2SKaustabh Chakraborty struct fwnode_handle *fwnp) 229*02149db2SKaustabh Chakraborty { 230*02149db2SKaustabh Chakraborty struct led_classdev *cdev = &led->fled.led_cdev; 231*02149db2SKaustabh Chakraborty struct led_init_data init_data = {}; 232*02149db2SKaustabh Chakraborty struct v4l2_flash_config v4l2_cfg = {}; 233*02149db2SKaustabh Chakraborty int ret; 234*02149db2SKaustabh Chakraborty 235*02149db2SKaustabh Chakraborty cdev->max_brightness = 16; 236*02149db2SKaustabh Chakraborty cdev->brightness_set_blocking = s2mu005_fled_torch_brightness_set; 237*02149db2SKaustabh Chakraborty cdev->flags |= LED_DEV_CAP_FLASH; 238*02149db2SKaustabh Chakraborty 239*02149db2SKaustabh Chakraborty led->fled.timeout.min = 62000; 240*02149db2SKaustabh Chakraborty led->fled.timeout.step = 62000; 241*02149db2SKaustabh Chakraborty led->fled.timeout.max = 992000; 242*02149db2SKaustabh Chakraborty led->fled.timeout.val = 992000; 243*02149db2SKaustabh Chakraborty 244*02149db2SKaustabh Chakraborty led->fled.brightness.min = 25000; 245*02149db2SKaustabh Chakraborty led->fled.brightness.step = 25000; 246*02149db2SKaustabh Chakraborty led->fled.brightness.max = 375000; /* 400000 causes flickering */ 247*02149db2SKaustabh Chakraborty led->fled.brightness.val = 375000; 248*02149db2SKaustabh Chakraborty 249*02149db2SKaustabh Chakraborty s2m_fled_flash_timeout_set(&led->fled, led->fled.timeout.val); 250*02149db2SKaustabh Chakraborty s2m_fled_flash_brightness_set(&led->fled, led->fled.brightness.val); 251*02149db2SKaustabh Chakraborty 252*02149db2SKaustabh Chakraborty led->fled.ops = &s2mu005_fled_flash_ops; 253*02149db2SKaustabh Chakraborty 254*02149db2SKaustabh Chakraborty init_data.fwnode = fwnp; 255*02149db2SKaustabh Chakraborty ret = devm_led_classdev_flash_register_ext(dev, &led->fled, &init_data); 256*02149db2SKaustabh Chakraborty if (ret) 257*02149db2SKaustabh Chakraborty return dev_err_probe(dev, ret, "failed to create LED flash device\n"); 258*02149db2SKaustabh Chakraborty 259*02149db2SKaustabh Chakraborty v4l2_cfg.intensity.min = led->fled.brightness.min; 260*02149db2SKaustabh Chakraborty v4l2_cfg.intensity.step = led->fled.brightness.step; 261*02149db2SKaustabh Chakraborty v4l2_cfg.intensity.max = led->fled.brightness.max; 262*02149db2SKaustabh Chakraborty v4l2_cfg.intensity.val = led->fled.brightness.val; 263*02149db2SKaustabh Chakraborty 264*02149db2SKaustabh Chakraborty v4l2_cfg.has_external_strobe = true; 265*02149db2SKaustabh Chakraborty 266*02149db2SKaustabh Chakraborty led->v4l2_flash = v4l2_flash_init(dev, fwnp, &led->fled, &s2m_fled_v4l2_flash_ops, 267*02149db2SKaustabh Chakraborty &v4l2_cfg); 268*02149db2SKaustabh Chakraborty if (IS_ERR(led->v4l2_flash)) 269*02149db2SKaustabh Chakraborty return dev_err_probe(dev, PTR_ERR(led->v4l2_flash), 270*02149db2SKaustabh Chakraborty "failed to create V4L2 flash device\n"); 271*02149db2SKaustabh Chakraborty 272*02149db2SKaustabh Chakraborty ret = devm_add_action_or_reset(dev, s2m_fled_v4l2_flash_release, led->v4l2_flash); 273*02149db2SKaustabh Chakraborty if (ret) 274*02149db2SKaustabh Chakraborty return dev_err_probe(dev, ret, "failed to add cleanup action\n"); 275*02149db2SKaustabh Chakraborty 276*02149db2SKaustabh Chakraborty return 0; 277*02149db2SKaustabh Chakraborty } 278*02149db2SKaustabh Chakraborty 279*02149db2SKaustabh Chakraborty static int s2m_fled_probe(struct platform_device *pdev) 280*02149db2SKaustabh Chakraborty { 281*02149db2SKaustabh Chakraborty struct device *dev = &pdev->dev; 282*02149db2SKaustabh Chakraborty struct sec_pmic_dev *ddata = dev_get_drvdata(dev->parent); 283*02149db2SKaustabh Chakraborty struct s2m_led *led; 284*02149db2SKaustabh Chakraborty int ret; 285*02149db2SKaustabh Chakraborty 286*02149db2SKaustabh Chakraborty led = devm_kzalloc(dev, sizeof(*led) * MAX_CHANNELS, GFP_KERNEL); 287*02149db2SKaustabh Chakraborty if (!led) 288*02149db2SKaustabh Chakraborty return -ENOMEM; 289*02149db2SKaustabh Chakraborty 290*02149db2SKaustabh Chakraborty /* Initialize LED controller with variant-specific implementation. */ 291*02149db2SKaustabh Chakraborty ret = s2mu005_fled_init(led, dev, ddata->regmap_pmic, MAX_CHANNELS); 292*02149db2SKaustabh Chakraborty if (ret) 293*02149db2SKaustabh Chakraborty return ret; 294*02149db2SKaustabh Chakraborty 295*02149db2SKaustabh Chakraborty device_for_each_child_node_scoped(dev, child) { 296*02149db2SKaustabh Chakraborty u32 reg; 297*02149db2SKaustabh Chakraborty 298*02149db2SKaustabh Chakraborty if (fwnode_property_read_u32(child, "reg", ®)) 299*02149db2SKaustabh Chakraborty continue; 300*02149db2SKaustabh Chakraborty 301*02149db2SKaustabh Chakraborty if (reg >= MAX_CHANNELS) { 302*02149db2SKaustabh Chakraborty dev_warn(dev, "channel %d is non-existent\n", reg); 303*02149db2SKaustabh Chakraborty continue; 304*02149db2SKaustabh Chakraborty } 305*02149db2SKaustabh Chakraborty 306*02149db2SKaustabh Chakraborty if (led[reg].regmap) { 307*02149db2SKaustabh Chakraborty dev_warn(dev, "duplicate node for channel %d\n", reg); 308*02149db2SKaustabh Chakraborty continue; 309*02149db2SKaustabh Chakraborty } 310*02149db2SKaustabh Chakraborty 311*02149db2SKaustabh Chakraborty led[reg].regmap = ddata->regmap_pmic; 312*02149db2SKaustabh Chakraborty led[reg].channel = (u8)reg; 313*02149db2SKaustabh Chakraborty 314*02149db2SKaustabh Chakraborty ret = devm_mutex_init(dev, &led[reg].lock); 315*02149db2SKaustabh Chakraborty if (ret) 316*02149db2SKaustabh Chakraborty return dev_err_probe(dev, ret, "failed to create mutex\n"); 317*02149db2SKaustabh Chakraborty 318*02149db2SKaustabh Chakraborty /* Initialize LED channel with variant-specific implementation. */ 319*02149db2SKaustabh Chakraborty ret = s2mu005_fled_init_channel(led + reg, dev, child); 320*02149db2SKaustabh Chakraborty if (ret) 321*02149db2SKaustabh Chakraborty return ret; 322*02149db2SKaustabh Chakraborty } 323*02149db2SKaustabh Chakraborty 324*02149db2SKaustabh Chakraborty return 0; 325*02149db2SKaustabh Chakraborty } 326*02149db2SKaustabh Chakraborty 327*02149db2SKaustabh Chakraborty static const struct platform_device_id s2m_fled_id_table[] = { 328*02149db2SKaustabh Chakraborty { "s2mu005-flash", S2MU005 }, 329*02149db2SKaustabh Chakraborty { /* sentinel */ }, 330*02149db2SKaustabh Chakraborty }; 331*02149db2SKaustabh Chakraborty MODULE_DEVICE_TABLE(platform, s2m_fled_id_table); 332*02149db2SKaustabh Chakraborty 333*02149db2SKaustabh Chakraborty static const struct of_device_id s2m_fled_of_match_table[] = { 334*02149db2SKaustabh Chakraborty { .compatible = "samsung,s2mu005-flash", .data = (void *)S2MU005 }, 335*02149db2SKaustabh Chakraborty { /* sentinel */ }, 336*02149db2SKaustabh Chakraborty }; 337*02149db2SKaustabh Chakraborty MODULE_DEVICE_TABLE(of, s2m_fled_of_match_table); 338*02149db2SKaustabh Chakraborty 339*02149db2SKaustabh Chakraborty static struct platform_driver s2m_fled_driver = { 340*02149db2SKaustabh Chakraborty .driver = { 341*02149db2SKaustabh Chakraborty .name = "s2m-flash", 342*02149db2SKaustabh Chakraborty }, 343*02149db2SKaustabh Chakraborty .probe = s2m_fled_probe, 344*02149db2SKaustabh Chakraborty .id_table = s2m_fled_id_table, 345*02149db2SKaustabh Chakraborty }; 346*02149db2SKaustabh Chakraborty module_platform_driver(s2m_fled_driver); 347*02149db2SKaustabh Chakraborty 348*02149db2SKaustabh Chakraborty MODULE_DESCRIPTION("Flash/Torch LED Driver for Samsung S2M Series PMICs"); 349*02149db2SKaustabh Chakraborty MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>"); 350*02149db2SKaustabh Chakraborty MODULE_LICENSE("GPL"); 351