2 * Samsung Exynos5 SoC series Flash driver
5 * Copyright (c) 2018 Samsung Electronics Co., Ltd
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/gpio.h>
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/platform_device.h>
17 #include <linux/of_gpio.h>
19 #include <linux/videodev2.h>
20 #include <linux/videodev2_exynos_camera.h>
22 #include "fimc-is-device-sensor.h"
23 #include "fimc-is-device-sensor-peri.h"
24 #include "fimc-is-core.h"
26 #include <linux/leds-s2mu106.h>
28 #define CAPTURE_MAX_TOTAL_CURRENT (1500)
29 #define TORCH_MAX_TOTAL_CURRENT (150)
30 #define MAX_FLASH_INTENSITY (256)
32 static int flash_s2mu106_init(struct v4l2_subdev
*subdev
, u32 val
)
35 struct fimc_is_flash
*flash
;
40 flash
= (struct fimc_is_flash
*)v4l2_get_subdevdata(subdev
);
44 /* TODO: init flash driver */
45 flash
->flash_data
.mode
= CAM2_FLASH_MODE_OFF
;
46 flash
->flash_data
.intensity
= 100; /* TODO: Need to figure out min/max range */
47 flash
->flash_data
.firing_time_us
= 1 * 1000 * 1000; /* Max firing time is 1sec */
48 flash
->flash_data
.flash_fired
= false;
49 flash
->flash_data
.cal_en
= false;
51 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++) {
52 if (flash
->led_ch
[i
] >= 0)
53 s2mu106_fled_set_mode_ctrl(flash
->led_ch
[i
], CAM_FLASH_MODE_OFF
);
59 static int flash_s2mu106_adj_current(struct fimc_is_flash
*flash
, enum flash_mode mode
, u32 intensity
)
66 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++) {
67 if (flash
->led_ch
[i
] != -1)
72 err("wrong flash led number, set to 0");
76 if (mode
== CAM2_FLASH_MODE_SINGLE
)
77 max_current
= CAPTURE_MAX_TOTAL_CURRENT
;
78 else if (mode
== CAM2_FLASH_MODE_TORCH
)
79 max_current
= TORCH_MAX_TOTAL_CURRENT
;
83 #ifdef FLASH_CAL_DATA_ENABLE
85 warn("Num of LED is over 2: %d\n", led_num
);
89 if (flash
->flash_data
.cal_en
== false) {
90 /* flash or torch set by ddk */
91 adj_current
= ((max_current
* intensity
) / MAX_FLASH_INTENSITY
);
93 if (adj_current
> max_current
) {
94 warn("flash intensity(%d) > max(%d), set to max forcely",
95 adj_current
, max_current
);
96 adj_current
= max_current
;
99 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++) {
100 if (flash
->led_ch
[i
] == -1)
105 flash
->flash_data
.inp_current
[i
] = adj_current
;
106 dbg_flash("[CH: %d] Flash set with adj_current: %d\n",
107 flash
->led_ch
[i
], flash
->flash_data
.inp_current
[i
]);
108 } else if (led_num
== 2) {
109 flash
->flash_data
.inp_current
[i
] = max_current
- adj_current
;
110 dbg_flash("[CH: %d] Flash set with adj_current: %d\n",
111 flash
->led_ch
[i
], flash
->flash_data
.inp_current
[i
]);
113 warn("skip set current value\n");
117 /* flash or torch set by hal */
118 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++) {
119 if (flash
->led_ch
[i
] != -1) {
121 adj_current
= flash
->flash_data
.inp_current
[i
];
122 if (adj_current
> max_current
) {
123 warn("flash intensity(%d) > max(%d), set to max forcely",
124 adj_current
, max_current
);
125 flash
->flash_data
.inp_current
[i
] = max_current
;
127 dbg_flash("[CH: %d] Flash set with adj_current: %d\n",
128 flash
->led_ch
[i
], flash
->flash_data
.inp_current
[i
]);
133 dbg_flash("%s: mode: %s, led_numt: %d\n", __func__
,
134 mode
== CAM2_FLASH_MODE_OFF
? "OFF" :
135 mode
== CAM2_FLASH_MODE_SINGLE
? "FLASH" : "TORCH",
140 if (intensity
> MAX_FLASH_INTENSITY
) {
141 warn("flash intensity(%d) > max(%d), set to max forcely",
142 intensity
, MAX_FLASH_INTENSITY
);
143 intensity
= MAX_FLASH_INTENSITY
;
146 adj_current
= ((max_current
* intensity
) / MAX_FLASH_INTENSITY
) / led_num
;
148 dbg_flash("%s: mode: %s, adj_current: %d\n", __func__
,
149 mode
== CAM2_FLASH_MODE_OFF
? "OFF" :
150 mode
== CAM2_FLASH_MODE_SINGLE
? "FLASH" : "TORCH",
157 static int flash_s2mu106_control(struct v4l2_subdev
*subdev
, enum flash_mode mode
, u32 intensity
)
160 struct fimc_is_flash
*flash
= NULL
;
166 flash
= (struct fimc_is_flash
*)v4l2_get_subdevdata(subdev
);
169 dbg_flash("%s : mode = %s, intensity = %d\n", __func__
,
170 mode
== CAM2_FLASH_MODE_OFF
? "OFF" :
171 mode
== CAM2_FLASH_MODE_SINGLE
? "FLASH" : "TORCH",
174 adj_current
= flash_s2mu106_adj_current(flash
, mode
, intensity
);
176 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++) {
177 if (flash
->led_ch
[i
] == -1)
179 #ifdef FLASH_CAL_DATA_ENABLE
180 adj_current
= flash
->flash_data
.inp_current
[i
];
182 /* If adj_current value is zero, it must be skipped to set */
183 /* Even if zero is set to flash, 50mA will flow, because 50mA is minimized value */
184 if (adj_current
== 0 && mode
!= CAM2_FLASH_MODE_OFF
) {
185 dbg_flash("[CH: %d] current value is 0, so current set need to skip\n", flash
->led_ch
[i
]);
189 dbg_flash("[CH: %d] current is set with val: %d\n", flash
->led_ch
[i
], adj_current
);
192 case CAM2_FLASH_MODE_OFF
:
193 ret
= s2mu106_fled_set_mode_ctrl(flash
->led_ch
[i
], CAM_FLASH_MODE_OFF
);
195 err("flash off fail(led_ch:%d)", flash
->led_ch
[i
]);
199 case CAM2_FLASH_MODE_SINGLE
:
200 ret
= s2mu106_fled_set_curr(flash
->led_ch
[i
], CAM_FLASH_MODE_SINGLE
, adj_current
);
202 err("capture flash set current fail(led_ch:%d)", flash
->led_ch
[i
]);
206 ret
|= s2mu106_fled_set_mode_ctrl(flash
->led_ch
[i
], CAM_FLASH_MODE_SINGLE
);
208 err("capture flash on fail(led_ch:%d)", flash
->led_ch
[i
]);
212 case CAM2_FLASH_MODE_TORCH
:
213 ret
= s2mu106_fled_set_curr(flash
->led_ch
[i
], CAM_FLASH_MODE_TORCH
, adj_current
);
215 err("torch flash set current fail(led_ch:%d)", flash
->led_ch
[i
]);
219 ret
|= s2mu106_fled_set_mode_ctrl(flash
->led_ch
[i
], CAM_FLASH_MODE_TORCH
);
221 err("torch flash on fail(led_ch:%d)", flash
->led_ch
[i
]);
226 err("Invalid flash mode");
236 int flash_s2mu106_s_ctrl(struct v4l2_subdev
*subdev
, struct v4l2_control
*ctrl
)
239 struct fimc_is_flash
*flash
= NULL
;
243 flash
= (struct fimc_is_flash
*)v4l2_get_subdevdata(subdev
);
247 #ifdef FLASH_CAL_DATA_ENABLE
248 case V4L2_CID_FLASH_SET_CAL_EN
:
249 if (ctrl
->value
< 0) {
250 err("failed to flash set cal_en: %d\n", ctrl
->value
);
254 flash
->flash_data
.cal_en
= ctrl
->value
;
255 dbg_flash("cal_en ctrl set: %s\n", (flash
->flash_data
.cal_en
? "enable" : "disable"));
257 case V4L2_CID_FLASH_SET_BY_CAL_CH0
:
258 if (ctrl
->value
< 0) {
259 err("[ch0] failed to flash set current val by cal: %d\n", ctrl
->value
);
263 flash
->flash_data
.inp_current
[0] = ctrl
->value
;
265 case V4L2_CID_FLASH_SET_BY_CAL_CH1
:
266 if (ctrl
->value
< 0) {
267 err("[ch1] failed to flash set current val by cal: %d\n", ctrl
->value
);
271 flash
->flash_data
.inp_current
[1] = ctrl
->value
;
274 case V4L2_CID_FLASH_SET_INTENSITY
:
275 /* TODO : Check min/max intensity */
276 if (ctrl
->value
< 0) {
277 err("failed to flash set intensity: %d\n", ctrl
->value
);
281 flash
->flash_data
.intensity
= ctrl
->value
;
284 case V4L2_CID_FLASH_SET_FIRING_TIME
:
285 /* TODO : Check min/max firing time */
286 if (ctrl
->value
< 0) {
287 err("failed to flash set firing time: %d\n", ctrl
->value
);
291 flash
->flash_data
.firing_time_us
= ctrl
->value
;
293 case V4L2_CID_FLASH_SET_FIRE
:
294 ret
= flash_s2mu106_control(subdev
, flash
->flash_data
.mode
, ctrl
->value
);
296 err("flash_s2mu106_control(mode:%d, val:%d) is fail(%d)",
297 (int)flash
->flash_data
.mode
, ctrl
->value
, ret
);
302 err("err!!! Unknown CID(%#x)", ctrl
->id
);
311 static const struct v4l2_subdev_core_ops core_ops
= {
312 .init
= flash_s2mu106_init
,
313 .s_ctrl
= flash_s2mu106_s_ctrl
,
316 static const struct v4l2_subdev_ops subdev_ops
= {
320 static int __init
flash_s2mu106_probe(struct device
*dev
, struct i2c_client
*client
)
323 struct fimc_is_core
*core
;
324 struct v4l2_subdev
*subdev_flash
;
325 struct fimc_is_device_sensor
*device
;
326 struct fimc_is_flash
*flash
;
328 struct device_node
*dnode
;
331 FIMC_BUG(!fimc_is_dev
);
334 dnode
= dev
->of_node
;
336 ret
= of_property_read_u32(dnode
, "id", &sensor_id
);
338 err("id read is fail(%d)", ret
);
342 core
= (struct fimc_is_core
*)dev_get_drvdata(fimc_is_dev
);
344 probe_info("core device is not yet probed");
349 device
= &core
->sensor
[sensor_id
];
351 flash
= kzalloc(sizeof(struct fimc_is_flash
), GFP_KERNEL
);
353 err("flash is NULL");
358 subdev_flash
= kzalloc(sizeof(struct v4l2_subdev
), GFP_KERNEL
);
360 err("subdev_flash is NULL");
366 flash
->id
= FLADRV_NAME_S2MU106
;
367 flash
->subdev
= subdev_flash
;
368 flash
->client
= client
;
370 flash
->flash_data
.mode
= CAM2_FLASH_MODE_OFF
;
371 flash
->flash_data
.intensity
= 100; /* TODO: Need to figure out min/max range */
372 flash
->flash_data
.firing_time_us
= 1 * 1000 * 1000; /* Max firing time is 1sec */
374 /* get flash_led ch by dt */
375 for (i
= 0; i
< FLASH_LED_CH_MAX
; i
++)
376 flash
->led_ch
[i
] = -1;
378 elements
= of_property_count_u32_elems(dnode
, "led_ch");
379 if (elements
< 0 || elements
> FLASH_LED_CH_MAX
) {
380 warn("flash led elements is too much or wrong(%d), set to max(%d)\n",
381 elements
, FLASH_LED_CH_MAX
);
382 elements
= FLASH_LED_CH_MAX
;
386 if (of_property_read_u32_array(dnode
, "led_ch", flash
->led_ch
, elements
)) {
387 err("cannot get flash led_ch, set only ch1\n");
388 flash
->led_ch
[0] = 1;
391 probe_info("set flash_ch as default(only ch1)\n");
392 flash
->led_ch
[0] = 1;
395 device
->subdev_flash
= subdev_flash
;
396 device
->flash
= flash
;
398 v4l2_subdev_init(subdev_flash
, &subdev_ops
);
400 v4l2_set_subdevdata(subdev_flash
, flash
);
401 v4l2_set_subdev_hostdata(subdev_flash
, device
);
402 snprintf(subdev_flash
->name
, V4L2_SUBDEV_NAME_SIZE
, "flash-subdev.%d", flash
->id
);
408 static int __init
flash_s2mu106_platform_probe(struct platform_device
*pdev
)
417 ret
= flash_s2mu106_probe(dev
, NULL
);
419 probe_err("flash gpio probe fail(%d)\n", ret
);
423 probe_info("%s done\n", __func__
);
429 static const struct of_device_id exynos_fimc_is_sensor_flash_s2mu106_match
[] = {
431 .compatible
= "samsung,sensor-flash-s2mu106",
434 .compatible
= "samsung,sensor-front-flash-s2mu106",
438 MODULE_DEVICE_TABLE(of
, exynos_fimc_is_sensor_flash_s2mu106_match
);
440 /* register platform driver */
441 static struct platform_driver sensor_flash_s2mu106_platform_driver
= {
443 .name
= "FIMC-IS-SENSOR-FLASH-S2MU106-PLATFORM",
444 .owner
= THIS_MODULE
,
445 .of_match_table
= exynos_fimc_is_sensor_flash_s2mu106_match
,
449 static int __init
fimc_is_sensor_flash_s2mu106_init(void)
453 ret
= platform_driver_probe(&sensor_flash_s2mu106_platform_driver
,
454 flash_s2mu106_platform_probe
);
456 err("failed to probe %s driver: %d\n",
457 sensor_flash_s2mu106_platform_driver
.driver
.name
, ret
);
461 late_initcall_sync(fimc_is_sensor_flash_s2mu106_init
);