• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * flash subdev driver module
3  *
4  * Copyright (c) 2017 by Allwinnertech Co., Ltd.  http://www.allwinnertech.com
5  *
6  * Authors:  Zhao Wei <zhaowei@allwinnertech.com>
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17 
18 #include <linux/platform_device.h>
19 #include <linux/delay.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <media/v4l2-device.h>
23 #include <media/v4l2-mediabus.h>
24 #include <media/v4l2-subdev.h>
25 #include <media/sunxi_camera_v2.h>
26 
27 #include "../../platform/platform_cfg.h"
28 #include "../../vin-video/vin_core.h"
29 
30 #include "flash.h"
31 
32 #ifdef CONFIG_FLASH_MODULE
33 static LIST_HEAD(flash_drv_list);
34 
35 #define FLASH_MODULE_NAME "vin_flash"
36 
37 #define FLASH_EN_POL 1
38 #define FLASH_MODE_POL 1
39 
40 static int flash_power_flag;
41 
io_set_flash_ctrl(struct v4l2_subdev * sd,enum sunxi_flash_ctrl ctrl)42 int io_set_flash_ctrl(struct v4l2_subdev *sd, enum sunxi_flash_ctrl ctrl)
43 {
44 	int ret = 0;
45 	unsigned int flash_en, flash_dis, flash_mode, torch_mode;
46 	struct flash_dev_info *fls_info = NULL;
47 	struct flash_dev *flash = (sd == NULL) ? NULL : v4l2_get_subdevdata(sd);
48 
49 	if (!flash)
50 		return 0;
51 
52 	fls_info = &flash->fl_info;
53 
54 	flash_en = (fls_info->en_pol != 0) ? 1 : 0;
55 	flash_dis = !flash_en;
56 	flash_mode = (fls_info->fl_mode_pol != 0) ? 1 : 0;
57 	torch_mode = !flash_mode;
58 
59 	if (fls_info->flash_driver_ic == FLASH_RELATING) {
60 		switch (ctrl) {
61 		case SW_CTRL_FLASH_OFF:
62 			vin_log(VIN_LOG_FLASH, "FLASH_RELATING SW_CTRL_FLASH_OFF\n");
63 			vin_gpio_set_status(sd, FLASH_EN, 1);
64 			vin_gpio_set_status(sd, FLASH_MODE, 1);
65 			ret |= vin_gpio_write(sd, FLASH_EN, flash_dis);
66 			ret |= vin_gpio_write(sd, FLASH_MODE, torch_mode);
67 			break;
68 		case SW_CTRL_FLASH_ON:
69 			vin_log(VIN_LOG_FLASH, "FLASH_RELATING SW_CTRL_FLASH_ON\n");
70 			vin_gpio_set_status(sd, FLASH_EN, 1);
71 			vin_gpio_set_status(sd, FLASH_MODE, 1);
72 			ret |= vin_gpio_write(sd, FLASH_MODE, flash_mode);
73 			ret |= vin_gpio_write(sd, FLASH_EN, flash_en);
74 			break;
75 		case SW_CTRL_TORCH_ON:
76 			vin_log(VIN_LOG_FLASH, "FLASH_RELATING SW_CTRL_TORCH_ON\n");
77 			vin_gpio_set_status(sd, FLASH_EN, 1);
78 			vin_gpio_set_status(sd, FLASH_MODE, 1);
79 			ret |= vin_gpio_write(sd, FLASH_MODE, torch_mode);
80 			ret |= vin_gpio_write(sd, FLASH_EN, flash_en);
81 			break;
82 		default:
83 			return -EINVAL;
84 		}
85 	} else if (fls_info->flash_driver_ic == FLASH_EN_INDEPEND) {
86 		switch (ctrl) {
87 		case SW_CTRL_FLASH_OFF:
88 			vin_log(VIN_LOG_FLASH, "FLASH_EN_INDEPEND SW_CTRL_FLASH_OFF\n");
89 			vin_gpio_set_status(sd, FLASH_EN, 1);
90 			vin_gpio_set_status(sd, FLASH_MODE, 1);
91 			ret |= vin_gpio_write(sd, FLASH_EN, 0);
92 			ret |= vin_gpio_write(sd, FLASH_MODE, 0);
93 			break;
94 		case SW_CTRL_FLASH_ON:
95 			vin_log(VIN_LOG_FLASH, "FLASH_EN_INDEPEND SW_CTRL_FLASH_ON\n");
96 			vin_gpio_set_status(sd, FLASH_EN, 1);
97 			vin_gpio_set_status(sd, FLASH_MODE, 1);
98 			ret |= vin_gpio_write(sd, FLASH_MODE, 1);
99 			ret |= vin_gpio_write(sd, FLASH_EN, 0);
100 			break;
101 		case SW_CTRL_TORCH_ON:
102 			vin_log(VIN_LOG_FLASH, "FLASH_EN_INDEPEND SW_CTRL_TORCH_ON\n");
103 			vin_gpio_set_status(sd, FLASH_EN, 1);
104 			vin_gpio_set_status(sd, FLASH_MODE, 1);
105 			ret |= vin_gpio_write(sd, FLASH_MODE, 0);
106 			ret |= vin_gpio_write(sd, FLASH_EN, 1);
107 			break;
108 		default:
109 			return -EINVAL;
110 		}
111 	} else if (fls_info->flash_driver_ic == FLASH_VIRTUAL) {
112 		switch (ctrl) {
113 		case SW_CTRL_FLASH_OFF:
114 			vin_log(VIN_LOG_FLASH, "FLASH_VIRTUAL SW_CTRL_FLASH_OFF\n");
115 			vin_gpio_set_status(sd, FLASH_EN, 1);
116 			//vin_gpio_set_status(sd, FLASH_MODE, 1);
117 			ret |= vin_gpio_write(sd, FLASH_EN, 0);
118 			//ret |= vin_gpio_write(sd, FLASH_MODE, 0);
119 			break;
120 		case SW_CTRL_FLASH_ON:
121 			vin_log(VIN_LOG_FLASH, "FLASH_VIRTUAL SW_CTRL_FLASH_ON\n");
122 			vin_gpio_set_status(sd, FLASH_EN, 1);
123 			//vin_gpio_set_status(sd, FLASH_MODE, 1);
124 			ret |= vin_gpio_write(sd, FLASH_EN, 1);
125 			//ret |= vin_gpio_write(sd, FLASH_MODE, 0);
126 			break;
127 		case SW_CTRL_TORCH_ON:
128 			vin_log(VIN_LOG_FLASH, "FLASH_VIRTUAL SW_CTRL_TORCH_ON\n");
129 			vin_gpio_set_status(sd, FLASH_EN, 1);
130 			//vin_gpio_set_status(sd, FLASH_MODE, 1);
131 			ret |= vin_gpio_write(sd, FLASH_EN, 1);
132 			//ret |= vin_gpio_write(sd, FLASH_MODE, 0);
133 			break;
134 		default:
135 			return -EINVAL;
136 		}
137 	} else {
138 		switch (ctrl) {
139 		case SW_CTRL_FLASH_OFF:
140 			vin_log(VIN_LOG_FLASH, "FLASH_POWER SW_CTRL_FLASH_OFF\n");
141 			if (flash_power_flag == 1) {
142 				vin_set_pmu_channel(sd, FLVDD, OFF);
143 				flash_power_flag--;
144 			}
145 			break;
146 		case SW_CTRL_FLASH_ON:
147 			vin_log(VIN_LOG_FLASH, "FLASH_POWER SW_CTRL_FLASH_ON\n");
148 			if (flash_power_flag == 0) {
149 				vin_set_pmu_channel(sd, FLVDD, ON);
150 				flash_power_flag++;
151 			}
152 			break;
153 		case SW_CTRL_TORCH_ON:
154 			vin_log(VIN_LOG_FLASH, "FLASH_POWER SW_CTRL_TORCH_ON\n");
155 			if (flash_power_flag == 0) {
156 				vin_set_pmu_channel(sd, FLVDD, ON);
157 				flash_power_flag++;
158 			}
159 			break;
160 		default:
161 			return -EINVAL;
162 		}
163 	}
164 	if (ret != 0) {
165 		vin_log(VIN_LOG_FLASH, "flash set ctrl fail, force shut off\n");
166 		ret |= vin_gpio_write(sd, FLASH_EN, flash_dis);
167 		ret |= vin_gpio_write(sd, FLASH_MODE, torch_mode);
168 	}
169 	return ret;
170 }
171 
sunxi_flash_check_to_start(struct v4l2_subdev * sd,enum sunxi_flash_ctrl ctrl)172 int sunxi_flash_check_to_start(struct v4l2_subdev *sd,
173 			       enum sunxi_flash_ctrl ctrl)
174 {
175 	struct modules_config *modules = sd ? sd_to_modules(sd) : NULL;
176 	struct flash_dev *flash = sd ? v4l2_get_subdevdata(sd) : NULL;
177 	struct v4l2_subdev *sensor = NULL;
178 	unsigned int flag = 0, to_flash;
179 
180 	if (!flash)
181 		return 0;
182 
183 	if (flash->fl_info.flash_mode == V4L2_FLASH_LED_MODE_FLASH) {
184 		to_flash = 1;
185 	} else if (flash->fl_info.flash_mode == V4L2_FLASH_LED_MODE_AUTO) {
186 		if (!modules)
187 			return 0;
188 		sensor = modules->modules.sensor[modules->sensors.valid_idx].sd;
189 		v4l2_subdev_call(sensor, core, ioctl, GET_FLASH_FLAG, &flag);
190 		if (flag)
191 			to_flash = 1;
192 		else
193 			to_flash = 0;
194 	} else {
195 		to_flash = 0;
196 	}
197 
198 	if (to_flash)
199 		io_set_flash_ctrl(sd, ctrl);
200 
201 	return 0;
202 }
203 
sunxi_flash_stop(struct v4l2_subdev * sd)204 int sunxi_flash_stop(struct v4l2_subdev *sd)
205 {
206 	struct flash_dev *flash = (sd == NULL) ? NULL : v4l2_get_subdevdata(sd);
207 
208 	if (!flash)
209 		return 0;
210 
211 	if (flash->fl_info.flash_mode != V4L2_FLASH_LED_MODE_NONE)
212 		io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF);
213 	return 0;
214 }
215 
config_flash_mode(struct v4l2_subdev * sd,enum v4l2_flash_led_mode mode,struct flash_dev_info * fls_info)216 static int config_flash_mode(struct v4l2_subdev *sd,
217 			     enum v4l2_flash_led_mode mode,
218 			     struct flash_dev_info *fls_info)
219 {
220 	if (fls_info == NULL) {
221 		vin_err("camera flash not support!\n");
222 		return -1;
223 	}
224 	if ((fls_info->light_src != 0x01) && (fls_info->light_src != 0x02)
225 	    && (fls_info->light_src != 0x10)) {
226 		vin_err("unsupported light source, force LEDx1\n");
227 		fls_info->light_src = 0x01;
228 	}
229 	fls_info->flash_mode = mode;
230 	if (mode == V4L2_FLASH_LED_MODE_TORCH)
231 		io_set_flash_ctrl(sd, SW_CTRL_TORCH_ON);
232 	else if (mode == V4L2_FLASH_LED_MODE_NONE)
233 		io_set_flash_ctrl(sd, SW_CTRL_FLASH_OFF);
234 
235 	return 0;
236 }
237 
sunxi_flash_g_ctrl(struct v4l2_ctrl * ctrl)238 static int sunxi_flash_g_ctrl(struct v4l2_ctrl *ctrl)
239 {
240 	struct flash_dev *flash =
241 			container_of(ctrl->handler, struct flash_dev, handler);
242 
243 	if (!flash)
244 		return 0;
245 
246 	switch (ctrl->id) {
247 	case V4L2_CID_FLASH_LED_MODE:
248 		ctrl->val = flash->fl_info.flash_mode;
249 		return 0;
250 	default:
251 		break;
252 	}
253 	return -EINVAL;
254 }
255 
sunxi_flash_s_ctrl(struct v4l2_ctrl * ctrl)256 static int sunxi_flash_s_ctrl(struct v4l2_ctrl *ctrl)
257 {
258 	struct flash_dev *flash =
259 			container_of(ctrl->handler, struct flash_dev, handler);
260 	struct v4l2_subdev *sd = &flash->subdev;
261 
262 
263 	if (!flash)
264 		return 0;
265 
266 	switch (ctrl->id) {
267 	case V4L2_CID_FLASH_LED_MODE:
268 		return config_flash_mode(sd, ctrl->val, &flash->fl_info);
269 	case V4L2_CID_FLASH_LED_MODE_V1:
270 		return 0;
271 	default:
272 		break;
273 	}
274 	return -EINVAL;
275 }
276 static const struct v4l2_ctrl_ops sunxi_flash_ctrl_ops = {
277 	.g_volatile_ctrl = sunxi_flash_g_ctrl,
278 	.s_ctrl = sunxi_flash_s_ctrl,
279 };
280 static const struct v4l2_ctrl_config custom_ctrls[] = {
281 	{
282 		.ops = &sunxi_flash_ctrl_ops,
283 		.id = V4L2_CID_FLASH_LED_MODE_V1,
284 		.name = "VIN Flash ctrl1",
285 		.type = V4L2_CTRL_TYPE_MENU,
286 		.min = 0,
287 		.max = 2,
288 		.def = 0,
289 		.menu_skip_mask = 0x0,
290 		.qmenu = flash_led_mode_v1,
291 		.step = 0,
292 		.flags = 0,
293 	},
294 };
295 
sunxi_flash_controls_init(struct v4l2_subdev * sd)296 static int sunxi_flash_controls_init(struct v4l2_subdev *sd)
297 {
298 	struct flash_dev *flash = container_of(sd, struct flash_dev, subdev);
299 	struct v4l2_ctrl_handler *handler = &flash->handler;
300 	int i, ret = 0;
301 
302 	v4l2_ctrl_handler_init(handler, 1 + ARRAY_SIZE(custom_ctrls));
303 	v4l2_ctrl_new_std_menu(handler, &sunxi_flash_ctrl_ops,
304 					V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_RED_EYE,
305 					0, V4L2_FLASH_LED_MODE_NONE);
306 
307 	for (i = 0; i < ARRAY_SIZE(custom_ctrls); i++)
308 		v4l2_ctrl_new_custom(handler, &custom_ctrls[i], NULL);
309 
310 	if (handler->error) {
311 		ret =  handler->error;
312 		v4l2_ctrl_handler_free(handler);
313 	}
314 
315 	sd->ctrl_handler = handler;
316 
317 	return ret;
318 }
sunxi_flash_subdev_init(struct flash_dev * flash)319 static int sunxi_flash_subdev_init(struct flash_dev *flash)
320 {
321 	struct v4l2_subdev *sd = &flash->subdev;
322 
323 	snprintf(sd->name, sizeof(sd->name), "sunxi_flash.%u", flash->id);
324 
325 	sunxi_flash_controls_init(sd);
326 	flash->fl_info.dev_if = 0;
327 	flash->fl_info.en_pol = FLASH_EN_POL;
328 	flash->fl_info.fl_mode_pol = FLASH_MODE_POL;
329 	flash->fl_info.light_src = 0x01;
330 	flash->fl_info.flash_intensity = 400;
331 	flash->fl_info.flash_level = 0x01;
332 	flash->fl_info.torch_intensity = 200;
333 	flash->fl_info.torch_level = 0x01;
334 	flash->fl_info.timeout_counter = 300 * 1000;
335 
336 	config_flash_mode(sd, V4L2_FLASH_LED_MODE_NONE, &flash->fl_info);
337 
338 	v4l2_set_subdevdata(sd, flash);
339 
340 	media_entity_pads_init(&sd->entity, 0, NULL);
341 	sd->entity.function = MEDIA_ENT_F_FLASH;
342 
343 	return 0;
344 }
345 
flash_probe(struct platform_device * pdev)346 static int flash_probe(struct platform_device *pdev)
347 {
348 	struct device_node *np = pdev->dev.of_node;
349 	struct flash_dev *flash = NULL;
350 	char property_name[32] = { 0 };
351 	int ret = 0;
352 
353 	if (np == NULL) {
354 		vin_err("flash failed to get of node\n");
355 		return -ENODEV;
356 	}
357 
358 	flash = kzalloc(sizeof(struct flash_dev), GFP_KERNEL);
359 	if (!flash) {
360 		ret = -ENOMEM;
361 		vin_err("sunxi flash kzalloc failed!\n");
362 		goto ekzalloc;
363 	}
364 
365 	of_property_read_u32(np, "device_id", &pdev->id);
366 	if (pdev->id < 0) {
367 		vin_err("flash failed to get device id\n");
368 		ret = -EINVAL;
369 		goto freedev;
370 	}
371 	sprintf(property_name, "flash%d_type", pdev->id);
372 	ret = of_property_read_u32(np, property_name,
373 				 &flash->fl_info.flash_driver_ic);
374 	if (ret) {
375 		flash->fl_info.flash_driver_ic = 0;
376 		vin_warn("fetch %s from device_tree failed\n", property_name);
377 		return -EINVAL;
378 	}
379 
380 	flash->id = pdev->id;
381 	flash->pdev = pdev;
382 	list_add_tail(&flash->flash_list, &flash_drv_list);
383 
384 	sunxi_flash_subdev_init(flash);
385 	platform_set_drvdata(pdev, flash);
386 	vin_log(VIN_LOG_FLASH, "flash%d probe end!\n", flash->id);
387 
388 	return 0;
389 freedev:
390 	kfree(flash);
391 ekzalloc:
392 	vin_err("flash probe err!\n");
393 	return ret;
394 }
395 
flash_remove(struct platform_device * pdev)396 static int flash_remove(struct platform_device *pdev)
397 {
398 	struct flash_dev *flash = platform_get_drvdata(pdev);
399 	struct v4l2_subdev *sd = &flash->subdev;
400 
401 	platform_set_drvdata(pdev, NULL);
402 	v4l2_device_unregister_subdev(sd);
403 	v4l2_set_subdevdata(sd, NULL);
404 	list_del(&flash->flash_list);
405 
406 	kfree(flash);
407 	return 0;
408 }
409 
410 static const struct of_device_id sunxi_flash_match[] = {
411 	{.compatible = "allwinner,sunxi-flash",},
412 	{},
413 };
414 
415 static struct platform_driver flash_platform_driver = {
416 	.probe = flash_probe,
417 	.remove = flash_remove,
418 	.driver = {
419 		   .name = FLASH_MODULE_NAME,
420 		   .owner = THIS_MODULE,
421 		   .of_match_table = sunxi_flash_match,
422 		   },
423 };
sunxi_flash_get_subdev(int id)424 struct v4l2_subdev *sunxi_flash_get_subdev(int id)
425 {
426 	struct flash_dev *flash;
427 
428 	list_for_each_entry(flash, &flash_drv_list, flash_list) {
429 		if (flash->id == id) {
430 			flash->use_cnt++;
431 			return &flash->subdev;
432 		}
433 	}
434 	return NULL;
435 }
436 
sunxi_flash_platform_register(void)437 int sunxi_flash_platform_register(void)
438 {
439 	return platform_driver_register(&flash_platform_driver);
440 }
441 
sunxi_flash_platform_unregister(void)442 void sunxi_flash_platform_unregister(void)
443 {
444 	platform_driver_unregister(&flash_platform_driver);
445 	vin_log(VIN_LOG_FLASH, "flash_exit end\n");
446 }
447 #else
io_set_flash_ctrl(struct v4l2_subdev * sd,enum sunxi_flash_ctrl ctrl)448 int io_set_flash_ctrl(struct v4l2_subdev *sd, enum sunxi_flash_ctrl ctrl)
449 {
450 	return 0;
451 }
452 
sunxi_flash_check_to_start(struct v4l2_subdev * sd,enum sunxi_flash_ctrl ctrl)453 int sunxi_flash_check_to_start(struct v4l2_subdev *sd,
454 			       enum sunxi_flash_ctrl ctrl)
455 {
456 	return 0;
457 }
458 
sunxi_flash_stop(struct v4l2_subdev * sd)459 int sunxi_flash_stop(struct v4l2_subdev *sd)
460 {
461 	return 0;
462 }
463 
sunxi_flash_get_subdev(int id)464 struct v4l2_subdev *sunxi_flash_get_subdev(int id)
465 {
466 	return NULL;
467 }
468 
sunxi_flash_platform_register(void)469 int sunxi_flash_platform_register(void)
470 {
471 	return 0;
472 }
473 
sunxi_flash_platform_unregister(void)474 void sunxi_flash_platform_unregister(void)
475 {
476 }
477 #endif
478