1/* 2 * drivers/media/i2c/lm3646.c 3 * General device driver for TI lm3646, Dual FLASH LED Driver 4 * 5 * Copyright (C) 2014 Texas Instruments 6 * 7 * Contact: Daniel Jeong <gshark.jeong@gmail.com> 8 * Ldd-Mlp <ldd-mlp@list.ti.com> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * version 2 as published by the Free Software Foundation. 13 */ 14 15#include <linux/delay.h> 16#include <linux/i2c.h> 17#include <linux/module.h> 18#include <linux/slab.h> 19#include <linux/regmap.h> 20#include <linux/videodev2.h> 21#include <media/lm3646.h> 22#include <media/v4l2-ctrls.h> 23#include <media/v4l2-device.h> 24 25/* registers definitions */ 26#define REG_ENABLE 0x01 27#define REG_TORCH_BR 0x05 28#define REG_FLASH_BR 0x05 29#define REG_FLASH_TOUT 0x04 30#define REG_FLAG 0x08 31#define REG_STROBE_SRC 0x06 32#define REG_LED1_FLASH_BR 0x06 33#define REG_LED1_TORCH_BR 0x07 34 35#define MASK_ENABLE 0x03 36#define MASK_TORCH_BR 0x70 37#define MASK_FLASH_BR 0x0F 38#define MASK_FLASH_TOUT 0x07 39#define MASK_FLAG 0xFF 40#define MASK_STROBE_SRC 0x80 41 42/* Fault Mask */ 43#define FAULT_TIMEOUT (1<<0) 44#define FAULT_SHORT_CIRCUIT (1<<1) 45#define FAULT_UVLO (1<<2) 46#define FAULT_IVFM (1<<3) 47#define FAULT_OCP (1<<4) 48#define FAULT_OVERTEMP (1<<5) 49#define FAULT_NTC_TRIP (1<<6) 50#define FAULT_OVP (1<<7) 51 52enum led_mode { 53 MODE_SHDN = 0x0, 54 MODE_TORCH = 0x2, 55 MODE_FLASH = 0x3, 56}; 57 58/* 59 * struct lm3646_flash 60 * 61 * @pdata: platform data 62 * @regmap: reg. map for i2c 63 * @lock: muxtex for serial access. 64 * @led_mode: V4L2 LED mode 65 * @ctrls_led: V4L2 contols 66 * @subdev_led: V4L2 subdev 67 * @mode_reg : mode register value 68 */ 69struct lm3646_flash { 70 struct device *dev; 71 struct lm3646_platform_data *pdata; 72 struct regmap *regmap; 73 74 struct v4l2_ctrl_handler ctrls_led; 75 struct v4l2_subdev subdev_led; 76 77 u8 mode_reg; 78}; 79 80#define to_lm3646_flash(_ctrl) \ 81 container_of(_ctrl->handler, struct lm3646_flash, ctrls_led) 82 83/* enable mode control */ 84static int lm3646_mode_ctrl(struct lm3646_flash *flash, 85 enum v4l2_flash_led_mode led_mode) 86{ 87 switch (led_mode) { 88 case V4L2_FLASH_LED_MODE_NONE: 89 return regmap_write(flash->regmap, 90 REG_ENABLE, flash->mode_reg | MODE_SHDN); 91 case V4L2_FLASH_LED_MODE_TORCH: 92 return regmap_write(flash->regmap, 93 REG_ENABLE, flash->mode_reg | MODE_TORCH); 94 case V4L2_FLASH_LED_MODE_FLASH: 95 return regmap_write(flash->regmap, 96 REG_ENABLE, flash->mode_reg | MODE_FLASH); 97 } 98 return -EINVAL; 99} 100 101/* V4L2 controls */ 102static int lm3646_get_ctrl(struct v4l2_ctrl *ctrl) 103{ 104 struct lm3646_flash *flash = to_lm3646_flash(ctrl); 105 unsigned int reg_val; 106 int rval; 107 108 if (ctrl->id != V4L2_CID_FLASH_FAULT) 109 return -EINVAL; 110 111 rval = regmap_read(flash->regmap, REG_FLAG, ®_val); 112 if (rval < 0) 113 return rval; 114 115 ctrl->val = 0; 116 if (reg_val & FAULT_TIMEOUT) 117 ctrl->val |= V4L2_FLASH_FAULT_TIMEOUT; 118 if (reg_val & FAULT_SHORT_CIRCUIT) 119 ctrl->val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT; 120 if (reg_val & FAULT_UVLO) 121 ctrl->val |= V4L2_FLASH_FAULT_UNDER_VOLTAGE; 122 if (reg_val & FAULT_IVFM) 123 ctrl->val |= V4L2_FLASH_FAULT_INPUT_VOLTAGE; 124 if (reg_val & FAULT_OCP) 125 ctrl->val |= V4L2_FLASH_FAULT_OVER_CURRENT; 126 if (reg_val & FAULT_OVERTEMP) 127 ctrl->val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE; 128 if (reg_val & FAULT_NTC_TRIP) 129 ctrl->val |= V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE; 130 if (reg_val & FAULT_OVP) 131 ctrl->val |= V4L2_FLASH_FAULT_OVER_VOLTAGE; 132 133 return 0; 134} 135 136static int lm3646_set_ctrl(struct v4l2_ctrl *ctrl) 137{ 138 struct lm3646_flash *flash = to_lm3646_flash(ctrl); 139 unsigned int reg_val; 140 int rval = -EINVAL; 141 142 switch (ctrl->id) { 143 case V4L2_CID_FLASH_LED_MODE: 144 145 if (ctrl->val != V4L2_FLASH_LED_MODE_FLASH) 146 return lm3646_mode_ctrl(flash, ctrl->val); 147 /* switch to SHDN mode before flash strobe on */ 148 return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE); 149 150 case V4L2_CID_FLASH_STROBE_SOURCE: 151 return regmap_update_bits(flash->regmap, 152 REG_STROBE_SRC, MASK_STROBE_SRC, 153 (ctrl->val) << 7); 154 155 case V4L2_CID_FLASH_STROBE: 156 157 /* read and check current mode of chip to start flash */ 158 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val); 159 if (rval < 0 || ((reg_val & MASK_ENABLE) != MODE_SHDN)) 160 return rval; 161 /* flash on */ 162 return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_FLASH); 163 164 case V4L2_CID_FLASH_STROBE_STOP: 165 166 /* 167 * flash mode will be turned automatically 168 * from FLASH mode to SHDN mode after flash duration timeout 169 * read and check current mode of chip to stop flash 170 */ 171 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val); 172 if (rval < 0) 173 return rval; 174 if ((reg_val & MASK_ENABLE) == MODE_FLASH) 175 return lm3646_mode_ctrl(flash, 176 V4L2_FLASH_LED_MODE_NONE); 177 return rval; 178 179 case V4L2_CID_FLASH_TIMEOUT: 180 return regmap_update_bits(flash->regmap, 181 REG_FLASH_TOUT, MASK_FLASH_TOUT, 182 LM3646_FLASH_TOUT_ms_TO_REG 183 (ctrl->val)); 184 185 case V4L2_CID_FLASH_INTENSITY: 186 return regmap_update_bits(flash->regmap, 187 REG_FLASH_BR, MASK_FLASH_BR, 188 LM3646_TOTAL_FLASH_BRT_uA_TO_REG 189 (ctrl->val)); 190 191 case V4L2_CID_FLASH_TORCH_INTENSITY: 192 return regmap_update_bits(flash->regmap, 193 REG_TORCH_BR, MASK_TORCH_BR, 194 LM3646_TOTAL_TORCH_BRT_uA_TO_REG 195 (ctrl->val) << 4); 196 } 197 198 return -EINVAL; 199} 200 201static const struct v4l2_ctrl_ops lm3646_led_ctrl_ops = { 202 .g_volatile_ctrl = lm3646_get_ctrl, 203 .s_ctrl = lm3646_set_ctrl, 204}; 205 206static int lm3646_init_controls(struct lm3646_flash *flash) 207{ 208 struct v4l2_ctrl *fault; 209 struct v4l2_ctrl_handler *hdl = &flash->ctrls_led; 210 const struct v4l2_ctrl_ops *ops = &lm3646_led_ctrl_ops; 211 212 v4l2_ctrl_handler_init(hdl, 8); 213 /* flash mode */ 214 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE, 215 V4L2_FLASH_LED_MODE_TORCH, ~0x7, 216 V4L2_FLASH_LED_MODE_NONE); 217 218 /* flash source */ 219 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE, 220 0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE); 221 222 /* flash strobe */ 223 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0); 224 /* flash strobe stop */ 225 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0); 226 227 /* flash strobe timeout */ 228 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT, 229 LM3646_FLASH_TOUT_MIN, 230 LM3646_FLASH_TOUT_MAX, 231 LM3646_FLASH_TOUT_STEP, flash->pdata->flash_timeout); 232 233 /* max flash current */ 234 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY, 235 LM3646_TOTAL_FLASH_BRT_MIN, 236 LM3646_TOTAL_FLASH_BRT_MAX, 237 LM3646_TOTAL_FLASH_BRT_STEP, 238 LM3646_TOTAL_FLASH_BRT_MAX); 239 240 /* max torch current */ 241 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY, 242 LM3646_TOTAL_TORCH_BRT_MIN, 243 LM3646_TOTAL_TORCH_BRT_MAX, 244 LM3646_TOTAL_TORCH_BRT_STEP, 245 LM3646_TOTAL_TORCH_BRT_MAX); 246 247 /* fault */ 248 fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0, 249 V4L2_FLASH_FAULT_OVER_VOLTAGE 250 | V4L2_FLASH_FAULT_OVER_TEMPERATURE 251 | V4L2_FLASH_FAULT_SHORT_CIRCUIT 252 | V4L2_FLASH_FAULT_TIMEOUT, 0, 0); 253 if (fault != NULL) 254 fault->flags |= V4L2_CTRL_FLAG_VOLATILE; 255 256 if (hdl->error) 257 return hdl->error; 258 259 flash->subdev_led.ctrl_handler = hdl; 260 return 0; 261} 262 263/* initialize device */ 264static const struct v4l2_subdev_ops lm3646_ops = { 265 .core = NULL, 266}; 267 268static const struct regmap_config lm3646_regmap = { 269 .reg_bits = 8, 270 .val_bits = 8, 271 .max_register = 0xFF, 272}; 273 274static int lm3646_subdev_init(struct lm3646_flash *flash) 275{ 276 struct i2c_client *client = to_i2c_client(flash->dev); 277 int rval; 278 279 v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3646_ops); 280 flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 281 strcpy(flash->subdev_led.name, LM3646_NAME); 282 rval = lm3646_init_controls(flash); 283 if (rval) 284 goto err_out; 285 rval = media_entity_init(&flash->subdev_led.entity, 0, NULL, 0); 286 if (rval < 0) 287 goto err_out; 288 flash->subdev_led.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; 289 return rval; 290 291err_out: 292 v4l2_ctrl_handler_free(&flash->ctrls_led); 293 return rval; 294} 295 296static int lm3646_init_device(struct lm3646_flash *flash) 297{ 298 unsigned int reg_val; 299 int rval; 300 301 /* read the value of mode register to reduce redundant i2c accesses */ 302 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val); 303 if (rval < 0) 304 return rval; 305 flash->mode_reg = reg_val & 0xfc; 306 307 /* output disable */ 308 rval = lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE); 309 if (rval < 0) 310 return rval; 311 312 /* 313 * LED1 flash current setting 314 * LED2 flash current = Total(Max) flash current - LED1 flash current 315 */ 316 rval = regmap_update_bits(flash->regmap, 317 REG_LED1_FLASH_BR, 0x7F, 318 LM3646_LED1_FLASH_BRT_uA_TO_REG 319 (flash->pdata->led1_flash_brt)); 320 321 if (rval < 0) 322 return rval; 323 324 /* 325 * LED1 torch current setting 326 * LED2 torch current = Total(Max) torch current - LED1 torch current 327 */ 328 rval = regmap_update_bits(flash->regmap, 329 REG_LED1_TORCH_BR, 0x7F, 330 LM3646_LED1_TORCH_BRT_uA_TO_REG 331 (flash->pdata->led1_torch_brt)); 332 if (rval < 0) 333 return rval; 334 335 /* Reset flag register */ 336 return regmap_read(flash->regmap, REG_FLAG, ®_val); 337} 338 339static int lm3646_probe(struct i2c_client *client, 340 const struct i2c_device_id *devid) 341{ 342 struct lm3646_flash *flash; 343 struct lm3646_platform_data *pdata = dev_get_platdata(&client->dev); 344 int rval; 345 346 flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); 347 if (flash == NULL) 348 return -ENOMEM; 349 350 flash->regmap = devm_regmap_init_i2c(client, &lm3646_regmap); 351 if (IS_ERR(flash->regmap)) 352 return PTR_ERR(flash->regmap); 353 354 /* check device tree if there is no platform data */ 355 if (pdata == NULL) { 356 pdata = devm_kzalloc(&client->dev, 357 sizeof(struct lm3646_platform_data), 358 GFP_KERNEL); 359 if (pdata == NULL) 360 return -ENOMEM; 361 /* use default data in case of no platform data */ 362 pdata->flash_timeout = LM3646_FLASH_TOUT_MAX; 363 pdata->led1_torch_brt = LM3646_LED1_TORCH_BRT_MAX; 364 pdata->led1_flash_brt = LM3646_LED1_FLASH_BRT_MAX; 365 } 366 flash->pdata = pdata; 367 flash->dev = &client->dev; 368 369 rval = lm3646_subdev_init(flash); 370 if (rval < 0) 371 return rval; 372 373 rval = lm3646_init_device(flash); 374 if (rval < 0) 375 return rval; 376 377 i2c_set_clientdata(client, flash); 378 379 return 0; 380} 381 382static int lm3646_remove(struct i2c_client *client) 383{ 384 struct lm3646_flash *flash = i2c_get_clientdata(client); 385 386 v4l2_device_unregister_subdev(&flash->subdev_led); 387 v4l2_ctrl_handler_free(&flash->ctrls_led); 388 media_entity_cleanup(&flash->subdev_led.entity); 389 390 return 0; 391} 392 393static const struct i2c_device_id lm3646_id_table[] = { 394 {LM3646_NAME, 0}, 395 {} 396}; 397 398MODULE_DEVICE_TABLE(i2c, lm3646_id_table); 399 400static struct i2c_driver lm3646_i2c_driver = { 401 .driver = { 402 .name = LM3646_NAME, 403 }, 404 .probe = lm3646_probe, 405 .remove = lm3646_remove, 406 .id_table = lm3646_id_table, 407}; 408 409module_i2c_driver(lm3646_i2c_driver); 410 411MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>"); 412MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>"); 413MODULE_DESCRIPTION("Texas Instruments LM3646 Dual Flash LED driver"); 414MODULE_LICENSE("GPL"); 415