0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/delay.h>
0013 #include <linux/i2c.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/regmap.h>
0017 #include <linux/videodev2.h>
0018 #include <media/i2c/lm3646.h>
0019 #include <media/v4l2-ctrls.h>
0020 #include <media/v4l2-device.h>
0021
0022
0023 #define REG_ENABLE 0x01
0024 #define REG_TORCH_BR 0x05
0025 #define REG_FLASH_BR 0x05
0026 #define REG_FLASH_TOUT 0x04
0027 #define REG_FLAG 0x08
0028 #define REG_STROBE_SRC 0x06
0029 #define REG_LED1_FLASH_BR 0x06
0030 #define REG_LED1_TORCH_BR 0x07
0031
0032 #define MASK_ENABLE 0x03
0033 #define MASK_TORCH_BR 0x70
0034 #define MASK_FLASH_BR 0x0F
0035 #define MASK_FLASH_TOUT 0x07
0036 #define MASK_FLAG 0xFF
0037 #define MASK_STROBE_SRC 0x80
0038
0039
0040 #define FAULT_TIMEOUT (1<<0)
0041 #define FAULT_SHORT_CIRCUIT (1<<1)
0042 #define FAULT_UVLO (1<<2)
0043 #define FAULT_IVFM (1<<3)
0044 #define FAULT_OCP (1<<4)
0045 #define FAULT_OVERTEMP (1<<5)
0046 #define FAULT_NTC_TRIP (1<<6)
0047 #define FAULT_OVP (1<<7)
0048
0049 enum led_mode {
0050 MODE_SHDN = 0x0,
0051 MODE_TORCH = 0x2,
0052 MODE_FLASH = 0x3,
0053 };
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 struct lm3646_flash {
0067 struct device *dev;
0068 struct lm3646_platform_data *pdata;
0069 struct regmap *regmap;
0070
0071 struct v4l2_ctrl_handler ctrls_led;
0072 struct v4l2_subdev subdev_led;
0073
0074 u8 mode_reg;
0075 };
0076
0077 #define to_lm3646_flash(_ctrl) \
0078 container_of(_ctrl->handler, struct lm3646_flash, ctrls_led)
0079
0080
0081 static int lm3646_mode_ctrl(struct lm3646_flash *flash,
0082 enum v4l2_flash_led_mode led_mode)
0083 {
0084 switch (led_mode) {
0085 case V4L2_FLASH_LED_MODE_NONE:
0086 return regmap_write(flash->regmap,
0087 REG_ENABLE, flash->mode_reg | MODE_SHDN);
0088 case V4L2_FLASH_LED_MODE_TORCH:
0089 return regmap_write(flash->regmap,
0090 REG_ENABLE, flash->mode_reg | MODE_TORCH);
0091 case V4L2_FLASH_LED_MODE_FLASH:
0092 return regmap_write(flash->regmap,
0093 REG_ENABLE, flash->mode_reg | MODE_FLASH);
0094 }
0095 return -EINVAL;
0096 }
0097
0098
0099 static int lm3646_get_ctrl(struct v4l2_ctrl *ctrl)
0100 {
0101 struct lm3646_flash *flash = to_lm3646_flash(ctrl);
0102 unsigned int reg_val;
0103 int rval;
0104
0105 if (ctrl->id != V4L2_CID_FLASH_FAULT)
0106 return -EINVAL;
0107
0108 rval = regmap_read(flash->regmap, REG_FLAG, ®_val);
0109 if (rval < 0)
0110 return rval;
0111
0112 ctrl->val = 0;
0113 if (reg_val & FAULT_TIMEOUT)
0114 ctrl->val |= V4L2_FLASH_FAULT_TIMEOUT;
0115 if (reg_val & FAULT_SHORT_CIRCUIT)
0116 ctrl->val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
0117 if (reg_val & FAULT_UVLO)
0118 ctrl->val |= V4L2_FLASH_FAULT_UNDER_VOLTAGE;
0119 if (reg_val & FAULT_IVFM)
0120 ctrl->val |= V4L2_FLASH_FAULT_INPUT_VOLTAGE;
0121 if (reg_val & FAULT_OCP)
0122 ctrl->val |= V4L2_FLASH_FAULT_OVER_CURRENT;
0123 if (reg_val & FAULT_OVERTEMP)
0124 ctrl->val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
0125 if (reg_val & FAULT_NTC_TRIP)
0126 ctrl->val |= V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE;
0127 if (reg_val & FAULT_OVP)
0128 ctrl->val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
0129
0130 return 0;
0131 }
0132
0133 static int lm3646_set_ctrl(struct v4l2_ctrl *ctrl)
0134 {
0135 struct lm3646_flash *flash = to_lm3646_flash(ctrl);
0136 unsigned int reg_val;
0137 int rval;
0138
0139 switch (ctrl->id) {
0140 case V4L2_CID_FLASH_LED_MODE:
0141
0142 if (ctrl->val != V4L2_FLASH_LED_MODE_FLASH)
0143 return lm3646_mode_ctrl(flash, ctrl->val);
0144
0145 return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);
0146
0147 case V4L2_CID_FLASH_STROBE_SOURCE:
0148 return regmap_update_bits(flash->regmap,
0149 REG_STROBE_SRC, MASK_STROBE_SRC,
0150 (ctrl->val) << 7);
0151
0152 case V4L2_CID_FLASH_STROBE:
0153
0154
0155 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val);
0156 if (rval < 0 || ((reg_val & MASK_ENABLE) != MODE_SHDN))
0157 return rval;
0158
0159 return lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_FLASH);
0160
0161 case V4L2_CID_FLASH_STROBE_STOP:
0162
0163
0164
0165
0166
0167
0168 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val);
0169 if (rval < 0)
0170 return rval;
0171 if ((reg_val & MASK_ENABLE) == MODE_FLASH)
0172 return lm3646_mode_ctrl(flash,
0173 V4L2_FLASH_LED_MODE_NONE);
0174 return rval;
0175
0176 case V4L2_CID_FLASH_TIMEOUT:
0177 return regmap_update_bits(flash->regmap,
0178 REG_FLASH_TOUT, MASK_FLASH_TOUT,
0179 LM3646_FLASH_TOUT_ms_TO_REG
0180 (ctrl->val));
0181
0182 case V4L2_CID_FLASH_INTENSITY:
0183 return regmap_update_bits(flash->regmap,
0184 REG_FLASH_BR, MASK_FLASH_BR,
0185 LM3646_TOTAL_FLASH_BRT_uA_TO_REG
0186 (ctrl->val));
0187
0188 case V4L2_CID_FLASH_TORCH_INTENSITY:
0189 return regmap_update_bits(flash->regmap,
0190 REG_TORCH_BR, MASK_TORCH_BR,
0191 LM3646_TOTAL_TORCH_BRT_uA_TO_REG
0192 (ctrl->val) << 4);
0193 }
0194
0195 return -EINVAL;
0196 }
0197
0198 static const struct v4l2_ctrl_ops lm3646_led_ctrl_ops = {
0199 .g_volatile_ctrl = lm3646_get_ctrl,
0200 .s_ctrl = lm3646_set_ctrl,
0201 };
0202
0203 static int lm3646_init_controls(struct lm3646_flash *flash)
0204 {
0205 struct v4l2_ctrl *fault;
0206 struct v4l2_ctrl_handler *hdl = &flash->ctrls_led;
0207 const struct v4l2_ctrl_ops *ops = &lm3646_led_ctrl_ops;
0208
0209 v4l2_ctrl_handler_init(hdl, 8);
0210
0211 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
0212 V4L2_FLASH_LED_MODE_TORCH, ~0x7,
0213 V4L2_FLASH_LED_MODE_NONE);
0214
0215
0216 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE,
0217 0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
0218
0219
0220 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
0221
0222 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
0223
0224
0225 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
0226 LM3646_FLASH_TOUT_MIN,
0227 LM3646_FLASH_TOUT_MAX,
0228 LM3646_FLASH_TOUT_STEP, flash->pdata->flash_timeout);
0229
0230
0231 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
0232 LM3646_TOTAL_FLASH_BRT_MIN,
0233 LM3646_TOTAL_FLASH_BRT_MAX,
0234 LM3646_TOTAL_FLASH_BRT_STEP,
0235 LM3646_TOTAL_FLASH_BRT_MAX);
0236
0237
0238 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY,
0239 LM3646_TOTAL_TORCH_BRT_MIN,
0240 LM3646_TOTAL_TORCH_BRT_MAX,
0241 LM3646_TOTAL_TORCH_BRT_STEP,
0242 LM3646_TOTAL_TORCH_BRT_MAX);
0243
0244
0245 fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0,
0246 V4L2_FLASH_FAULT_OVER_VOLTAGE
0247 | V4L2_FLASH_FAULT_OVER_TEMPERATURE
0248 | V4L2_FLASH_FAULT_SHORT_CIRCUIT
0249 | V4L2_FLASH_FAULT_TIMEOUT, 0, 0);
0250 if (fault != NULL)
0251 fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
0252
0253 if (hdl->error)
0254 return hdl->error;
0255
0256 flash->subdev_led.ctrl_handler = hdl;
0257 return 0;
0258 }
0259
0260
0261 static const struct v4l2_subdev_ops lm3646_ops = {
0262 .core = NULL,
0263 };
0264
0265 static const struct regmap_config lm3646_regmap = {
0266 .reg_bits = 8,
0267 .val_bits = 8,
0268 .max_register = 0xFF,
0269 };
0270
0271 static int lm3646_subdev_init(struct lm3646_flash *flash)
0272 {
0273 struct i2c_client *client = to_i2c_client(flash->dev);
0274 int rval;
0275
0276 v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3646_ops);
0277 flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
0278 strscpy(flash->subdev_led.name, LM3646_NAME,
0279 sizeof(flash->subdev_led.name));
0280 rval = lm3646_init_controls(flash);
0281 if (rval)
0282 goto err_out;
0283 rval = media_entity_pads_init(&flash->subdev_led.entity, 0, NULL);
0284 if (rval < 0)
0285 goto err_out;
0286 flash->subdev_led.entity.function = MEDIA_ENT_F_FLASH;
0287 return rval;
0288
0289 err_out:
0290 v4l2_ctrl_handler_free(&flash->ctrls_led);
0291 return rval;
0292 }
0293
0294 static int lm3646_init_device(struct lm3646_flash *flash)
0295 {
0296 unsigned int reg_val;
0297 int rval;
0298
0299
0300 rval = regmap_read(flash->regmap, REG_ENABLE, ®_val);
0301 if (rval < 0)
0302 return rval;
0303 flash->mode_reg = reg_val & 0xfc;
0304
0305
0306 rval = lm3646_mode_ctrl(flash, V4L2_FLASH_LED_MODE_NONE);
0307 if (rval < 0)
0308 return rval;
0309
0310
0311
0312
0313
0314 rval = regmap_update_bits(flash->regmap,
0315 REG_LED1_FLASH_BR, 0x7F,
0316 LM3646_LED1_FLASH_BRT_uA_TO_REG
0317 (flash->pdata->led1_flash_brt));
0318
0319 if (rval < 0)
0320 return rval;
0321
0322
0323
0324
0325
0326 rval = regmap_update_bits(flash->regmap,
0327 REG_LED1_TORCH_BR, 0x7F,
0328 LM3646_LED1_TORCH_BRT_uA_TO_REG
0329 (flash->pdata->led1_torch_brt));
0330 if (rval < 0)
0331 return rval;
0332
0333
0334 return regmap_read(flash->regmap, REG_FLAG, ®_val);
0335 }
0336
0337 static int lm3646_probe(struct i2c_client *client,
0338 const struct i2c_device_id *devid)
0339 {
0340 struct lm3646_flash *flash;
0341 struct lm3646_platform_data *pdata = dev_get_platdata(&client->dev);
0342 int rval;
0343
0344 flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
0345 if (flash == NULL)
0346 return -ENOMEM;
0347
0348 flash->regmap = devm_regmap_init_i2c(client, &lm3646_regmap);
0349 if (IS_ERR(flash->regmap))
0350 return PTR_ERR(flash->regmap);
0351
0352
0353 if (pdata == NULL) {
0354 pdata = devm_kzalloc(&client->dev,
0355 sizeof(struct lm3646_platform_data),
0356 GFP_KERNEL);
0357 if (pdata == NULL)
0358 return -ENOMEM;
0359
0360 pdata->flash_timeout = LM3646_FLASH_TOUT_MAX;
0361 pdata->led1_torch_brt = LM3646_LED1_TORCH_BRT_MAX;
0362 pdata->led1_flash_brt = LM3646_LED1_FLASH_BRT_MAX;
0363 }
0364 flash->pdata = pdata;
0365 flash->dev = &client->dev;
0366
0367 rval = lm3646_subdev_init(flash);
0368 if (rval < 0)
0369 return rval;
0370
0371 rval = lm3646_init_device(flash);
0372 if (rval < 0)
0373 return rval;
0374
0375 i2c_set_clientdata(client, flash);
0376
0377 return 0;
0378 }
0379
0380 static int lm3646_remove(struct i2c_client *client)
0381 {
0382 struct lm3646_flash *flash = i2c_get_clientdata(client);
0383
0384 v4l2_device_unregister_subdev(&flash->subdev_led);
0385 v4l2_ctrl_handler_free(&flash->ctrls_led);
0386 media_entity_cleanup(&flash->subdev_led.entity);
0387
0388 return 0;
0389 }
0390
0391 static const struct i2c_device_id lm3646_id_table[] = {
0392 {LM3646_NAME, 0},
0393 {}
0394 };
0395
0396 MODULE_DEVICE_TABLE(i2c, lm3646_id_table);
0397
0398 static struct i2c_driver lm3646_i2c_driver = {
0399 .driver = {
0400 .name = LM3646_NAME,
0401 },
0402 .probe = lm3646_probe,
0403 .remove = lm3646_remove,
0404 .id_table = lm3646_id_table,
0405 };
0406
0407 module_i2c_driver(lm3646_i2c_driver);
0408
0409 MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
0410 MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
0411 MODULE_DESCRIPTION("Texas Instruments LM3646 Dual Flash LED driver");
0412 MODULE_LICENSE("GPL");