1 /*
2 * sensor_helper.c: helper function for sensors.
3 *
4 * Copyright (c) 2017 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
5 *
6 * Authors: Zhao Wei <zhaowei@allwinnertech.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13 #include <linux/module.h>
14 #include <linux/videodev2.h>
15 #include <linux/v4l2-subdev.h>
16 #include <media/v4l2-dev.h>
17
18 #include "camera.h"
19 #include "sensor_helper.h"
20 #include "../../vin-cci/sunxi_cci.h"
21
22 char ccm0[I2C_NAME_SIZE] = "";
23 char ccm1[I2C_NAME_SIZE] = "";
24
25 #define SENSOR_MODULE_NAME "vin_sensor_helper"
26
27 struct sensor_helper_dev *glb_sensor_helper[VIN_MAX_CSI];
28
29 module_param_string(ccm0, ccm0, sizeof(ccm0), S_IRUGO | S_IWUSR);
30 module_param_string(ccm1, ccm1, sizeof(ccm1), S_IRUGO | S_IWUSR);
31
to_state(struct v4l2_subdev * sd)32 struct sensor_info *to_state(struct v4l2_subdev *sd)
33 {
34 return container_of(sd, struct sensor_info, sd);
35 }
36 EXPORT_SYMBOL_GPL(to_state);
37
sensor_cfg_req(struct v4l2_subdev * sd,struct sensor_config * cfg)38 void sensor_cfg_req(struct v4l2_subdev *sd, struct sensor_config *cfg)
39 {
40 struct sensor_info *info = to_state(sd);
41
42 if (info == NULL) {
43 pr_err("%s is not initialized\n", sd->name);
44 return;
45 }
46 if (info->current_wins == NULL) {
47 pr_err("%s format is not initialized\n", sd->name);
48 return;
49 }
50
51 cfg->width = info->current_wins->width_input;
52 cfg->height = info->current_wins->height_input;
53 cfg->hoffset = info->current_wins->hoffset;
54 cfg->voffset = info->current_wins->voffset;
55 cfg->hts = info->current_wins->hts;
56 cfg->vts = info->current_wins->vts;
57 cfg->pclk = info->current_wins->pclk;
58 cfg->fps_fixed = info->current_wins->fps_fixed;
59 cfg->bin_factor = info->current_wins->bin_factor;
60 cfg->intg_min = info->current_wins->intg_min;
61 cfg->intg_max = info->current_wins->intg_max;
62 cfg->gain_min = info->current_wins->gain_min;
63 cfg->gain_max = info->current_wins->gain_max;
64 cfg->mbus_code = info->fmt->mbus_code;
65 cfg->wdr_mode = info->current_wins->wdr_mode;
66 }
67 EXPORT_SYMBOL_GPL(sensor_cfg_req);
68
sensor_isp_input(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * mf)69 void sensor_isp_input(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
70 {
71 struct sensor_info *info = to_state(sd);
72
73 if (info == NULL) {
74 pr_err("%s is not initialized\n", sd->name);
75 return;
76 }
77 if (info->current_wins == NULL) {
78 pr_err("%s format is not initialized\n", sd->name);
79 return;
80 }
81
82 info->current_wins->width_input = mf->width;
83 info->current_wins->height_input = mf->height;
84 }
85 EXPORT_SYMBOL_GPL(sensor_isp_input);
86
sensor_get_exp(struct v4l2_subdev * sd)87 unsigned int sensor_get_exp(struct v4l2_subdev *sd)
88 {
89 struct sensor_info *info = to_state(sd);
90 unsigned int exp_us = 0;
91 if (info == NULL) {
92 pr_err("%s is not initialized\n", sd->name);
93 return -1;
94 }
95 if (info->exp == 0) {
96 return -1;
97 }
98 exp_us = info->exp/16*info->current_wins->hts/(info->current_wins->pclk/1000000);
99 return exp_us;
100 }
101 EXPORT_SYMBOL_GPL(sensor_get_exp);
102
103 #if defined CONFIG_ARCH_SUN8IW16P1
__sensor_get_parameter(struct v4l2_subdev * sd,struct v4l2_mbus_config * cfg)104 static unsigned int __sensor_get_parameter(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg)
105 {
106 struct sensor_info *info = to_state(sd);
107 unsigned flags = cfg->flags & 0xf;
108
109 switch (flags) {
110 case V4L2_MBUS_CSI2_1_LANE:
111 info->lane_num = 1;
112 break;
113 case V4L2_MBUS_CSI2_2_LANE:
114 info->lane_num = 2;
115 break;
116 case V4L2_MBUS_CSI2_3_LANE:
117 info->lane_num = 3;
118 break;
119 case V4L2_MBUS_CSI2_4_LANE:
120 info->lane_num = 4;
121 break;
122 default:
123 return -1;
124 }
125
126 switch (info->fmt->mbus_code) {
127 case MEDIA_BUS_FMT_SBGGR8_1X8:
128 case MEDIA_BUS_FMT_SGBRG8_1X8:
129 case MEDIA_BUS_FMT_SGRBG8_1X8:
130 case MEDIA_BUS_FMT_SRGGB8_1X8:
131 info->bit_width = 8;
132 break;
133 case MEDIA_BUS_FMT_SBGGR10_1X10:
134 case MEDIA_BUS_FMT_SGBRG10_1X10:
135 case MEDIA_BUS_FMT_SGRBG10_1X10:
136 case MEDIA_BUS_FMT_SRGGB10_1X10:
137 info->bit_width = 10;
138 break;
139 case MEDIA_BUS_FMT_SBGGR12_1X12:
140 case MEDIA_BUS_FMT_SGBRG12_1X12:
141 case MEDIA_BUS_FMT_SGRBG12_1X12:
142 case MEDIA_BUS_FMT_SRGGB12_1X12:
143 info->bit_width = 12;
144 break;
145 default:
146 return -1;
147 }
148
149 return 0;
150 }
151
sensor_get_clk(struct v4l2_subdev * sd,struct v4l2_mbus_config * cfg,unsigned long * top_clk,unsigned long * isp_clk)152 unsigned int sensor_get_clk(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg,
153 unsigned long *top_clk, unsigned long *isp_clk)
154 {
155 struct sensor_info *info = to_state(sd);
156 unsigned long topclk_theory, ispclk_theory;
157 unsigned long topclk_max = 432*1000*1000;
158 unsigned long ispclk_max = 432*1000*1000;
159 unsigned int hblank;
160 unsigned int hblank_cmp = 128;
161 int ret;
162
163 if (info->current_wins->top_clk && info->current_wins->isp_clk) {
164 *top_clk = info->current_wins->top_clk;
165 *isp_clk = info->current_wins->isp_clk;
166 } else if (info->current_wins->mipi_bps && info->current_wins->hts && info->current_wins->pclk) {
167 ret = __sensor_get_parameter(sd, cfg);
168 if (ret) {
169 vin_warn("__sensor_get_parameter warning! sensor is not mipi or raw sensor!\n");
170 return -1;
171 }
172
173 if (info->current_wins->hts <= info->current_wins->width) {
174 vin_warn("%s warning! hts must be greater than width!\n", __func__);
175 return -1;
176 }
177 hblank = info->current_wins->hts - info->current_wins->width;
178 topclk_theory = info->current_wins->mipi_bps * info->lane_num / info->bit_width;
179 ispclk_theory = max(topclk_theory, (unsigned long)info->current_wins->pclk) /
180 info->current_wins->hts *
181 (info->current_wins->width + max(hblank_cmp, hblank/10));
182
183 *top_clk = min(topclk_max, roundup(topclk_theory + topclk_theory*5/100, 1000000));
184 *isp_clk = min(ispclk_max, roundup(ispclk_theory + ispclk_theory*5/100, 1000000));
185 if (!(*top_clk) || !(*isp_clk)) {
186 vin_warn("%s warning! top_clk = %ld, isp_clk = %ld\n", __func__, *top_clk, *isp_clk);
187 return -1;
188 }
189 } else
190 return -1;
191
192 return 0;
193 }
194 EXPORT_SYMBOL_GPL(sensor_get_clk);
195 #endif
196
sensor_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)197 int sensor_enum_mbus_code(struct v4l2_subdev *sd,
198 struct v4l2_subdev_pad_config *cfg,
199 struct v4l2_subdev_mbus_code_enum *code)
200 {
201 struct sensor_info *info = to_state(sd);
202
203 if (code->index >= info->fmt_num)
204 return -EINVAL;
205 code->code = info->fmt_pt[code->index].mbus_code;
206 return 0;
207 }
208 EXPORT_SYMBOL_GPL(sensor_enum_mbus_code);
209
sensor_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)210 int sensor_enum_frame_size(struct v4l2_subdev *sd,
211 struct v4l2_subdev_pad_config *cfg,
212 struct v4l2_subdev_frame_size_enum *fse)
213 {
214 struct sensor_info *info = to_state(sd);
215
216 if (fse->index >= info->win_size_num)
217 return -EINVAL;
218 fse->min_width = info->win_pt[fse->index].width;
219 fse->max_width = fse->min_width;
220 fse->max_height = info->win_pt[fse->index].height;
221 fse->min_height = fse->max_height;
222 return 0;
223 }
224 EXPORT_SYMBOL_GPL(sensor_enum_frame_size);
225
sensor_find_mbus_code(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * fmt)226 static struct sensor_format_struct *sensor_find_mbus_code(struct v4l2_subdev *sd,
227 struct v4l2_mbus_framefmt *fmt)
228 {
229 struct sensor_info *info = to_state(sd);
230 int i;
231
232 for (i = 0; i < info->fmt_num; ++i) {
233 if (info->fmt_pt[i].mbus_code == fmt->code)
234 break;
235 }
236 if (i >= info->fmt_num)
237 return info->fmt_pt;
238 return &info->fmt_pt[i];
239 }
240
sensor_find_frame_size(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * fmt)241 static struct sensor_win_size *sensor_find_frame_size(struct v4l2_subdev *sd,
242 struct v4l2_mbus_framefmt *fmt)
243 {
244 struct sensor_info *info = to_state(sd);
245 struct sensor_win_size *ws = info->win_pt;
246 struct sensor_win_size *best_ws = &ws[0];
247 int best_dist = INT_MAX;
248 int fps_flag = 0;
249 int i;
250
251 /*judge if sensor have wdr command win*/
252 if (info->isp_wdr_mode == ISP_COMANDING_MODE) {
253 for (i = 0; i < info->win_size_num; ++i) {
254 if (ws->wdr_mode == ISP_COMANDING_MODE) {
255 best_ws = ws;
256 break;
257 }
258 ++ws;
259 }
260 if (i == info->win_size_num)
261 info->isp_wdr_mode = 0;
262 }
263
264 /*judge if sensor have wdr dol win*/
265 ws = info->win_pt;
266 if (info->isp_wdr_mode == ISP_DOL_WDR_MODE) {
267 for (i = 0; i < info->win_size_num; ++i) {
268 if (ws->wdr_mode == ISP_DOL_WDR_MODE) {
269 best_ws = ws;
270 break;
271 }
272 ++ws;
273 }
274 if (i == info->win_size_num)
275 info->isp_wdr_mode = 0;
276 }
277
278 /*judge if sensor have the right fps win*/
279 ws = info->win_pt;
280 if (info->isp_wdr_mode == ISP_COMANDING_MODE) {
281 for (i = 0; i < info->win_size_num; ++i) {
282 if ((ws->fps_fixed == info->tpf.denominator) &&
283 (ws->wdr_mode == ISP_COMANDING_MODE)) {
284 best_ws = ws;
285 fps_flag = 1;
286 break;
287 }
288 ++ws;
289 }
290 } else if (info->isp_wdr_mode == ISP_DOL_WDR_MODE) {
291 for (i = 0; i < info->win_size_num; ++i) {
292 if ((ws->fps_fixed == info->tpf.denominator) &&
293 (ws->wdr_mode == ISP_DOL_WDR_MODE)) {
294 best_ws = ws;
295 fps_flag = 1;
296 break;
297 }
298 ++ws;
299 }
300 } else {
301 for (i = 0; i < info->win_size_num; ++i) {
302 if ((ws->fps_fixed == info->tpf.denominator) &&
303 (ws->wdr_mode == ISP_NORMAL_MODE)) {
304 best_ws = ws;
305 fps_flag = 1;
306 break;
307 }
308 ++ws;
309 }
310 }
311
312 /*judge if sensor have the right resoulution win*/
313 ws = info->win_pt;
314 if (info->isp_wdr_mode == ISP_COMANDING_MODE) {
315 if (fps_flag) {
316 for (i = 0; i < info->win_size_num; ++i) {
317 int dist = abs(ws->width - fmt->width) +
318 abs(ws->height - fmt->height);
319
320 if ((dist < best_dist) &&
321 (ws->width >= fmt->width) &&
322 (ws->height >= fmt->height) &&
323 (ws->wdr_mode == ISP_COMANDING_MODE) &&
324 (ws->fps_fixed == info->tpf.denominator)) {
325 best_dist = dist;
326 best_ws = ws;
327 }
328 ++ws;
329 }
330 } else {
331 for (i = 0; i < info->win_size_num; ++i) {
332 int dist = abs(ws->width - fmt->width) +
333 abs(ws->height - fmt->height);
334
335 if ((dist < best_dist) &&
336 (ws->width >= fmt->width) &&
337 (ws->height >= fmt->height) &&
338 (ws->wdr_mode == ISP_COMANDING_MODE)) {
339 best_dist = dist;
340 best_ws = ws;
341 }
342 ++ws;
343 }
344 }
345 } else if (info->isp_wdr_mode == ISP_DOL_WDR_MODE) {
346 if (fps_flag) {
347 for (i = 0; i < info->win_size_num; ++i) {
348 int dist = abs(ws->width - fmt->width) +
349 abs(ws->height - fmt->height);
350
351 if ((dist < best_dist) &&
352 (ws->width >= fmt->width) &&
353 (ws->height >= fmt->height) &&
354 (ws->wdr_mode == ISP_DOL_WDR_MODE) &&
355 (ws->fps_fixed == info->tpf.denominator)) {
356 best_dist = dist;
357 best_ws = ws;
358 }
359 ++ws;
360 }
361 } else {
362 for (i = 0; i < info->win_size_num; ++i) {
363 int dist = abs(ws->width - fmt->width) +
364 abs(ws->height - fmt->height);
365
366 if ((dist < best_dist) &&
367 (ws->width >= fmt->width) &&
368 (ws->height >= fmt->height) &&
369 (ws->wdr_mode == ISP_DOL_WDR_MODE)) {
370 best_dist = dist;
371 best_ws = ws;
372 }
373 ++ws;
374 }
375 }
376 } else {
377 if (fps_flag) {
378 for (i = 0; i < info->win_size_num; ++i) {
379 int dist = abs(ws->width - fmt->width) +
380 abs(ws->height - fmt->height);
381
382 if ((dist < best_dist) &&
383 (ws->width >= fmt->width) &&
384 (ws->height >= fmt->height) &&
385 (ws->wdr_mode == ISP_NORMAL_MODE) &&
386 (ws->fps_fixed == info->tpf.denominator)) {
387 best_dist = dist;
388 best_ws = ws;
389 }
390 ++ws;
391 }
392 } else {
393 for (i = 0; i < info->win_size_num; ++i) {
394 int dist = abs(ws->width - fmt->width) +
395 abs(ws->height - fmt->height);
396
397 if ((dist < best_dist) &&
398 (ws->width >= fmt->width) &&
399 (ws->height >= fmt->height) &&
400 (ws->wdr_mode == ISP_NORMAL_MODE)) {
401 best_dist = dist;
402 best_ws = ws;
403 }
404 ++ws;
405 }
406 }
407 }
408
409 info->isp_wdr_mode = best_ws->wdr_mode;
410
411 return best_ws;
412 }
413
sensor_fill_mbus_fmt(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * mf,const struct sensor_win_size * ws,u32 code)414 static void sensor_fill_mbus_fmt(struct v4l2_subdev *sd,
415 struct v4l2_mbus_framefmt *mf,
416 const struct sensor_win_size *ws, u32 code)
417 {
418 struct sensor_info *info = to_state(sd);
419 struct mbus_framefmt_res *res = (void *)mf->reserved;
420
421 mf->width = ws->width;
422 mf->height = ws->height;
423 mf->code = code;
424 mf->field = info->sensor_field;
425 res->res_mipi_bps = ws->mipi_bps;
426 res->res_combo_mode = info->combo_mode | ws->if_mode;
427 res->res_wdr_mode = ws->wdr_mode;
428 res->res_lp_mode = ws->lp_mode;
429 res->res_time_hs = info->time_hs;
430 res->fps = ws->fps_fixed;
431 }
432
sensor_try_format(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt,struct sensor_win_size ** ws,struct sensor_format_struct ** sf)433 static void sensor_try_format(struct v4l2_subdev *sd,
434 struct v4l2_subdev_pad_config *cfg,
435 struct v4l2_subdev_format *fmt,
436 struct sensor_win_size **ws,
437 struct sensor_format_struct **sf)
438 {
439 struct sensor_info *info = to_state(sd);
440 u32 code = MEDIA_BUS_FMT_YUYV8_2X8;
441
442 if (fmt->pad == SENSOR_PAD_SOURCE) {
443 if ((sd->entity.stream_count > 0 || info->use_current_win) &&
444 info->current_wins != NULL) {
445 code = info->fmt->mbus_code;
446 *ws = info->current_wins;
447 *sf = info->fmt;
448 info->isp_wdr_mode = info->current_wins->wdr_mode;
449 } else {
450 *ws = sensor_find_frame_size(sd, &fmt->format);
451 *sf = sensor_find_mbus_code(sd, &fmt->format);
452 code = (*sf)->mbus_code;
453 }
454 }
455 sensor_fill_mbus_fmt(sd, &fmt->format, *ws, code);
456 }
457
sensor_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)458 int sensor_get_fmt(struct v4l2_subdev *sd,
459 struct v4l2_subdev_pad_config *cfg,
460 struct v4l2_subdev_format *fmt)
461 {
462 struct sensor_info *info = to_state(sd);
463 const struct sensor_win_size *ws;
464 u32 code;
465
466 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
467 if (cfg == NULL) {
468 pr_err("%s cfg is NULL!\n", sd->name);
469 return -EINVAL;
470 }
471 fmt->format = cfg->try_fmt;
472 return 0;
473 }
474 mutex_lock(&info->lock);
475 switch (fmt->pad) {
476 case SENSOR_PAD_SOURCE:
477 code = info->fmt->mbus_code;
478 ws = info->current_wins;
479 break;
480 default:
481 mutex_unlock(&info->lock);
482 return -EINVAL;
483 }
484 sensor_fill_mbus_fmt(sd, &fmt->format, ws, code);
485 mutex_unlock(&info->lock);
486 return 0;
487 }
488 EXPORT_SYMBOL_GPL(sensor_get_fmt);
489
sensor_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)490 int sensor_set_fmt(struct v4l2_subdev *sd,
491 struct v4l2_subdev_pad_config *cfg,
492 struct v4l2_subdev_format *fmt)
493 {
494 struct sensor_info *info = to_state(sd);
495 struct sensor_win_size *ws = NULL;
496 struct sensor_format_struct *sf = NULL;
497 struct v4l2_mbus_framefmt *mf;
498 int ret = 0;
499
500 mutex_lock(&info->lock);
501 vin_log(VIN_LOG_FMT, "%s %s %d*%d 0x%x 0x%x\n", sd->name, __func__,
502 fmt->format.width, fmt->format.height,
503 fmt->format.code, fmt->format.field);
504 sensor_try_format(sd, cfg, fmt, &ws, &sf);
505 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
506 if (cfg == NULL) {
507 pr_err("%s cfg is NULL!\n", sd->name);
508 mutex_unlock(&info->lock);
509 return -EINVAL;
510 }
511 mf = &cfg->try_fmt;
512 *mf = fmt->format;
513 } else {
514 switch (fmt->pad) {
515 case SENSOR_PAD_SOURCE:
516 info->current_wins = ws;
517 info->fmt = sf;
518 break;
519 default:
520 ret = -EBUSY;
521 }
522 }
523 mutex_unlock(&info->lock);
524 return ret;
525 }
526 EXPORT_SYMBOL_GPL(sensor_set_fmt);
527
sensor_g_parm(struct v4l2_subdev * sd,struct v4l2_streamparm * parms)528 int sensor_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
529 {
530 struct v4l2_captureparm *cp = &parms->parm.capture;
531 struct sensor_info *info = to_state(sd);
532
533 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
534 return -EINVAL;
535 memset(cp, 0, sizeof(struct v4l2_captureparm));
536 cp->capability = V4L2_CAP_TIMEPERFRAME;
537 cp->capturemode = info->capture_mode;
538 if (info->current_wins && info->current_wins->fps_fixed)
539 cp->timeperframe.denominator = info->current_wins->fps_fixed;
540 else
541 cp->timeperframe.denominator = info->tpf.denominator;
542 cp->timeperframe.numerator = 1;
543 return 0;
544 }
545 EXPORT_SYMBOL_GPL(sensor_g_parm);
546
sensor_s_parm(struct v4l2_subdev * sd,struct v4l2_streamparm * parms)547 int sensor_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
548 {
549 struct v4l2_captureparm *cp = &parms->parm.capture;
550 struct sensor_info *info = to_state(sd);
551
552 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
553 return -EINVAL;
554 if (info->tpf.numerator == 0)
555 return -EINVAL;
556 info->capture_mode = cp->capturemode;
557 info->tpf = cp->timeperframe;
558 info->use_current_win = cp->reserved[0];
559 info->isp_wdr_mode = cp->reserved[1];
560 return 0;
561 }
562 EXPORT_SYMBOL_GPL(sensor_s_parm);
563
sensor_try_ctrl(struct v4l2_ctrl * ctrl)564 int sensor_try_ctrl(struct v4l2_ctrl *ctrl)
565 {
566 /*
567 * to cheat control framework, because of when ctrl->cur.val == ctrl->val
568 * s_ctrl would not be called
569 */
570 if ((ctrl->minimum == 0) && (ctrl->maximum == 1)) {
571 if (ctrl->val)
572 ctrl->cur.val = 0;
573 else
574 ctrl->cur.val = 1;
575 } else {
576 if (ctrl->val == ctrl->maximum)
577 ctrl->cur.val = ctrl->val - 1;
578 else
579 ctrl->cur.val = ctrl->val + 1;
580 }
581
582 /*
583 * to cheat control framework, because of when ctrl->flags is
584 * V4L2_CTRL_FLAG_VOLATILE, s_ctrl would not be called
585 */
586 switch (ctrl->id) {
587 case V4L2_CID_EXPOSURE:
588 case V4L2_CID_EXPOSURE_ABSOLUTE:
589 case V4L2_CID_GAIN:
590 if (ctrl->val != ctrl->cur.val)
591 ctrl->flags &= ~V4L2_CTRL_FLAG_VOLATILE;
592 break;
593 default:
594 break;
595 }
596 return 0;
597 }
598 EXPORT_SYMBOL_GPL(sensor_try_ctrl);
599
actuator_init(struct v4l2_subdev * sd,struct actuator_para * range)600 int actuator_init(struct v4l2_subdev *sd, struct actuator_para *range)
601 {
602 #ifdef CONFIG_ACTUATOR_MODULE
603 struct modules_config *modules = sd_to_modules(sd);
604 struct v4l2_subdev *act_sd = NULL;
605 struct actuator_para_t vcm_para;
606
607 if (modules == NULL)
608 return -EINVAL;
609
610 act_sd = modules->modules.act[modules->sensors.valid_idx].sd;
611 if (act_sd == NULL)
612 return 0;
613
614 if (act_sd->entity.use_count > 0)
615 return 0;
616
617 vcm_para.active_min = range->code_min;
618 vcm_para.active_max = range->code_max;
619 return v4l2_subdev_call(act_sd, core, ioctl, ACT_INIT, &vcm_para);
620 #else
621 return 0;
622 #endif
623 }
624 EXPORT_SYMBOL_GPL(actuator_init);
625
actuator_set_code(struct v4l2_subdev * sd,struct actuator_ctrl * pos)626 int actuator_set_code(struct v4l2_subdev *sd, struct actuator_ctrl *pos)
627 {
628 #ifdef CONFIG_ACTUATOR_MODULE
629 struct modules_config *modules = sd_to_modules(sd);
630 struct v4l2_subdev *act_sd = NULL;
631 struct actuator_ctrl_word_t vcm_ctrl;
632
633 if (modules == NULL)
634 return -EINVAL;
635
636 act_sd = modules->modules.act[modules->sensors.valid_idx].sd;
637 if (act_sd == NULL)
638 return 0;
639
640 vcm_ctrl.code = pos->code;
641 vcm_ctrl.sr = 0x0;
642 return v4l2_subdev_call(act_sd, core, ioctl, ACT_SET_CODE, &vcm_ctrl);
643 #else
644 return 0;
645 #endif
646 }
647 EXPORT_SYMBOL_GPL(actuator_set_code);
648
flash_en(struct v4l2_subdev * sd,struct flash_para * para)649 int flash_en(struct v4l2_subdev *sd, struct flash_para *para)
650 {
651 #ifdef CONFIG_FLASH_MODULE
652 struct modules_config *modules = sd_to_modules(sd);
653 struct v4l2_subdev *flash_sd = NULL;
654 int ret = 0;
655
656 if (modules == NULL)
657 return -EINVAL;
658
659 flash_sd = modules->modules.flash.sd;
660 if (flash_sd == NULL)
661 return 0;
662
663 switch (para->mode) {
664 case V4L2_FLASH_LED_MODE_NONE:
665 ret = io_set_flash_ctrl(flash_sd, SW_CTRL_FLASH_OFF);
666 break;
667 case V4L2_FLASH_LED_MODE_FLASH:
668 ret = io_set_flash_ctrl(flash_sd, SW_CTRL_FLASH_ON);
669 break;
670 case V4L2_FLASH_LED_MODE_TORCH:
671 ret = io_set_flash_ctrl(flash_sd, SW_CTRL_TORCH_ON);
672 break;
673 default:
674 ret = -1;
675 break;
676 }
677
678 return ret;
679 #else
680 return 0;
681 #endif
682 }
683 EXPORT_SYMBOL_GPL(flash_en);
684
685 #if !defined SENSOR_POER_BEFORE_VIN
sensor_helper_probe(struct platform_device * pdev)686 static int sensor_helper_probe(struct platform_device *pdev)
687 {
688 struct device_node *np = pdev->dev.of_node;
689 struct device *dev = &pdev->dev;
690 struct sensor_helper_dev *sensor_helper = NULL;
691 char power_supply[20] = {0};
692 char property_name[16] = {0};
693 const char *ccm_name;
694 int ret;
695
696 if (np == NULL) {
697 vin_err("sensor_helper failed to get of node\n");
698 return -ENODEV;
699 }
700 sensor_helper = kzalloc(sizeof(struct sensor_helper_dev), GFP_KERNEL);
701 if (!sensor_helper) {
702 ret = -ENOMEM;
703 goto ekzalloc;
704 }
705
706 of_property_read_u32(np, "device_id", &pdev->id);
707 if (pdev->id < 0) {
708 vin_err("sensor_helper failed to get device id\n");
709 ret = -EINVAL;
710 goto freedev;
711 }
712 sensor_helper->id = pdev->id;
713
714 #ifndef FPGA_VER
715 if (sensor_helper->id == 0)
716 strcpy(sensor_helper->name, ccm0);
717 else if (sensor_helper->id == 1)
718 strcpy(sensor_helper->name, ccm1);
719
720 if (!strcmp(sensor_helper->name, "")) {
721 snprintf(property_name, sizeof(property_name), "sensor%d_mname", pdev->id);
722 ret = of_property_read_string(np, property_name, &ccm_name);
723 if (ret) {
724 vin_warn("fetch %s from device_tree failed\n", property_name);
725 return -EINVAL;
726 } else
727 strcpy(sensor_helper->name, ccm_name);
728 }
729 vin_log(VIN_LOG_POWER, "sensor_helper get name is %s\n", sensor_helper->name);
730
731 snprintf(power_supply, sizeof(power_supply), "sensor%d_cameravdd", pdev->id);
732 sensor_helper->pmic[CAMERAVDD] = regulator_get_optional(dev, power_supply);
733 if (IS_ERR(sensor_helper->pmic[CAMERAVDD])) {
734 vin_warn("%s: cannot get %s supply, setting it to NULL!\n", __func__, power_supply);
735 sensor_helper->pmic[CAMERAVDD] = NULL;
736 }
737
738 snprintf(power_supply, sizeof(power_supply), "sensor%d_iovdd", pdev->id);
739 sensor_helper->pmic[IOVDD] = regulator_get_optional(dev, power_supply);
740 if (IS_ERR(sensor_helper->pmic[IOVDD])) {
741 vin_warn("%s: cannot get %s supply, setting it to NULL!\n", __func__, power_supply);
742 sensor_helper->pmic[IOVDD] = NULL;
743 }
744
745 snprintf(power_supply, sizeof(power_supply), "sensor%d_avdd", pdev->id);
746 sensor_helper->pmic[AVDD] = regulator_get_optional(dev, power_supply);
747 if (IS_ERR(sensor_helper->pmic[AVDD])) {
748 vin_warn("%s: cannot get %s supply, setting it to NULL!\n", __func__, power_supply);
749 sensor_helper->pmic[AVDD] = NULL;
750 }
751
752 snprintf(power_supply, sizeof(power_supply), "sensor%d_dvdd", pdev->id);
753 sensor_helper->pmic[DVDD] = regulator_get_optional(dev, power_supply);
754 if (IS_ERR(sensor_helper->pmic[DVDD])) {
755 vin_warn("%s: cannot get %s supply, setting it to NULL!\n", __func__, power_supply);
756 sensor_helper->pmic[DVDD] = NULL;
757 }
758 #endif
759 glb_sensor_helper[pdev->id] = sensor_helper;
760
761 platform_set_drvdata(pdev, sensor_helper);
762
763 vin_log(VIN_LOG_POWER, "sensor_helper probe end sensor_sel = %d!\n", sensor_helper->id);
764
765 return 0;
766 freedev:
767 kfree(sensor_helper);
768 ekzalloc:
769 vin_err("sensor_helper probe err!\n");
770 return ret;
771 }
772
sensor_helper_remove(struct platform_device * pdev)773 static int sensor_helper_remove(struct platform_device *pdev)
774 {
775 struct sensor_helper_dev *sensor_helper = platform_get_drvdata(pdev);
776
777 platform_set_drvdata(pdev, NULL);
778 #ifndef FPGA_VER
779 regulator_put(sensor_helper->pmic[CAMERAVDD]);
780 sensor_helper->pmic[CAMERAVDD] = NULL;
781 regulator_put(sensor_helper->pmic[IOVDD]);
782 sensor_helper->pmic[IOVDD] = NULL;
783 regulator_put(sensor_helper->pmic[AVDD]);
784 sensor_helper->pmic[AVDD] = NULL;
785 regulator_put(sensor_helper->pmic[DVDD]);
786 sensor_helper->pmic[DVDD] = NULL;
787 #endif
788 kfree(sensor_helper);
789 return 0;
790 }
791
792 static const struct of_device_id sunxi_sensor_helper_match[] = {
793 {.compatible = "allwinner,sunxi-sensor",},
794 {},
795 };
796
797 static struct platform_driver sensor_helper_platform_driver = {
798 .probe = sensor_helper_probe,
799 .remove = sensor_helper_remove,
800 .driver = {
801 .name = SENSOR_MODULE_NAME,
802 .owner = THIS_MODULE,
803 .of_match_table = sunxi_sensor_helper_match,
804 },
805 };
806 #endif
vin_io_init(void)807 static int __init vin_io_init(void)
808 {
809 int ret;
810
811 ret = sunxi_cci_platform_register();
812 if (ret)
813 return ret;
814
815 #if !defined SENSOR_POER_BEFORE_VIN
816 ret = platform_driver_register(&sensor_helper_platform_driver);
817 if (ret) {
818 vin_err("sensor helper platform driver register failed\n");
819 return ret;
820 }
821 vin_log(VIN_LOG_POWER, "sensor_helper_init end\n");
822 #endif
823
824 return 0;
825 }
826
vin_io_exit(void)827 static void __exit vin_io_exit(void)
828 {
829 sunxi_cci_platform_unregister();
830
831 #if !defined SENSOR_POER_BEFORE_VIN
832 platform_driver_unregister(&sensor_helper_platform_driver);
833 #endif
834
835 vin_log(VIN_LOG_POWER, "sensor_helper_exit end\n");
836 }
837
838 #ifdef CONFIG_VIDEO_SUNXI_VIN_SPECIAL
839 subsys_initcall_sync(vin_io_init);
840 #else
841 module_init(vin_io_init);
842 #endif
843 module_exit(vin_io_exit);
844
845 MODULE_AUTHOR("zhengzequn");
846 MODULE_LICENSE("Dual BSD/GPL");
847 MODULE_DESCRIPTION("Camera and CCI DRIVER for sunxi");
848
849
850