1
2 /*
3 * A V4L2 driver for TW2866 YUV cameras.
4 *
5 * Copyright (c) 2017 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
6 *
7 * Authors: Zhao Wei <zhaowei@allwinnertech.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/i2c.h>
19 #include <linux/delay.h>
20 #include <linux/videodev2.h>
21 #include <linux/clk.h>
22 #include <media/v4l2-device.h>
23 #include <media/v4l2-mediabus.h>
24 #include <linux/io.h>
25
26 #include "camera.h"
27 #include "sensor_helper.h"
28
29 MODULE_AUTHOR("zw");
30 MODULE_DESCRIPTION("A low-level driver for TW2866 sensors");
31 MODULE_LICENSE("GPL");
32
33 #define MCLK (24*1000*1000)
34 #define CLK_POL V4L2_MBUS_PCLK_SAMPLE_FALLING
35 #define V4L2_IDENT_SENSOR 0xc8
36
37 /*
38 * Our nominal (default) frame rate.
39 */
40 #define SENSOR_FRAME_RATE 30
41
42 /*
43 * The TW2866 sits on i2c with ID 0x50
44 */
45 #define I2C_ADDR 0x50 /* tw2866 work when CCI in 100k speed */
46 #define SENSOR_NAME "tw2866"
47
48
49 #if 0
50 static struct regval_list read_reg[] = {
51 {0x00, 0x00},
52 {0x01, 0x00},
53 {0x02, 0x00},
54 {0x03, 0x00},
55 {0xFA, 0x00}, /*output clock, base of pclk, 1ch*d1 = 27m */
56 {0xFB, 0x00},
57 {0xFC, 0x00},
58 {0x9C, 0x00}, /*A0 */
59 {0x9E, 0x00},
60 {0xF9, 0x00}, /*Video misc */
61 {0xAA, 0x00}, /*Video AGC */
62 {0x6A, 0x00}, /*CLKPO2/CLKNO2 off */
63 {0x6B, 0x00}, /*CLKPO3/CLKNO3 off */
64 {0x6C, 0x00}, /*CLKPO4/CLKNO4 off */
65 {0x60, 0x00}, /*0x15/0x05�� */
66 {0x61, 0x00},
67 {0xca, 0x00}, /*chmd: 0=1ch 1=2ch 2=4ch */
68 {0xcd, 0x00}, /*1st */
69 {0x42, 0x00}, /*testpattern 75%color bar */
70 };
71
72 #endif
73
74 #if 0
75 static struct regval_list reg_d1_1ch[] = {
76 {0x00, 0x00},
77 {0x01, 0x00},
78 {0x02, 0x64},
79 {0x03, 0x11},
80 {0xFA, 0x40}, /*output clock, base of pclk, 1ch*d1 = 27m */
81 {0xFB, 0x2F},
82 {0xFC, 0xFF},
83 {0x9C, 0x20}, /*A0 */
84 {0x9E, 0x52},
85 {0xF9, 0x11}, /*Video misc */
86 {0xAA, 0x00}, /*Video AGC */
87 {0x6A, 0x0f}, /*CLKPO2/CLKNO2 off */
88 {0x6B, 0x0f}, /*CLKPO3/CLKNO3 off */
89 {0x6C, 0x0f}, /*CLKPO4/CLKNO4 off */
90 {0x60, 0x15}, /*0x15/0x05*/
91 {0x61, 0x03},
92 {0xca, 0x00}, /*chmd: 0=1ch 1=2ch 2=4ch */
93 {0xcd, 0xe4}, /*1st */
94 {0x5b, 0x11}, /*pad drive set */
95 };
96 #endif
97
98 #if 0
99 static struct regval_list reg_d1_2ch[] = {
100 {0x00, 0x00},
101 {0x01, 0x00},
102 {0x02, 0x64},
103 {0x03, 0x11},
104 {0xFA, 0x45}, /*0x45 *//*[7]:v-scale output clock, base of pclk, 2ch*d1 = 54m */
105 {0xFB, 0x2F},
106 {0xFC, 0xFF},
107 {0x9C, 0x20}, /*A0 */
108 {0x9E, 0x52},
109 {0xF9, 0x11}, /*Video misc */
110 {0xAA, 0x00}, /*Video AGC */
111 {0xca, 0x01}, /*chmd: 0=1ch 1=2ch 2=4ch */
112 {0xcd, 0xe4}, /*1st */
113 {0xcc, 0x39}, /*2nd */
114 {0xcb, 0x00}, /*4ch cif */
115 {0x60, 0x15}, /*0x15/0x05*/
116 {0x61, 0x03},
117 {0x5b, 0x00}, /*pad drive set */
118 };
119 #endif
120
121 #if 1
122 static struct regval_list reg_d1_4ch[] = {
123 {0x00, 0x00},
124 {0x01, 0x00},
125 {0x02, 0x64},
126 {0x03, 0x11},
127 {0xFA, 0x4a}, /*output clock, base of pclk, 4ch*cif = 54m 4ch*d1 = 108m */
128 {0xFB, 0x2F},
129 {0xFC, 0xFF},
130 {0x9C, 0x20}, /*A0 */
131 {0x9E, 0x52},
132 {0x6A, 0x05},
133 {0x6B, 0x05},
134 {0x6C, 0x05},
135 {0xF9, 0x11}, /*Video misc */
136 {0xAA, 0x00}, /*Video AGC */
137 {0xca, 0x02}, /*chmd: 0=1ch 1=2ch 2=4ch */
138 {0xcd, 0xe4}, /*1st */
139 {0xcc, 0x39}, /*2nd */
140 {0xcb, 0x00}, /*4ch cif */
141 {0x60, 0x15}, /*0x15/0x05*/
142 {0x61, 0x03},
143 {REG_DLY, 0x20},
144 {0x5b, 0xFF}, /*pad drive set */
145 };
146 #endif
147
148 #if 0
149 static struct regval_list reg_cif_4ch[] = {
150 /*CSI_MODE==CSI_MODE_TW2866_4CH_CIF */
151 {0x00, 0x00},
152 {0x01, 0x00},
153 {0x02, 0x64},
154 {0x03, 0x11},
155 {0xFA, 0x45}, /*output clock, base of pclk, 4ch*cif = 54m 4ch*cif = 54m */
156 {0xFB, 0x2F},
157 {0xFC, 0xFF},
158 {0x9C, 0x20}, /*A0 */
159 {0x9E, 0x52},
160 {0xF9, 0x11}, /*Video misc */
161 {0xAA, 0x00}, /*Video AGC */
162 {0xca, 0x00}, /*chmd: 0=1ch or 4ch-cif 1=2ch 2=4ch-d1 */
163 {0xcd, 0xe4}, /*1st */
164 {0xcc, 0x39}, /*2nd */
165 {0xcb, 0x01}, /*4ch cif */
166 {0x60, 0x17}, /*0x37/0x15/0x05*/
167 {0x61, 0x03},
168 {0x5b, 0x11}, /*pad drive set */
169 {0x9f, 0x00}, /*p clock delay 7ns */
170 };
171 #endif
172
sensor_s_sw_stby(struct v4l2_subdev * sd,int on_off)173 static int sensor_s_sw_stby(struct v4l2_subdev *sd, int on_off)
174 {
175 if (on_off)
176 vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
177 else
178 vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
179 return 0;
180 }
181
sensor_power(struct v4l2_subdev * sd,int on)182 static int sensor_power(struct v4l2_subdev *sd, int on)
183 {
184 switch (on) {
185 case STBY_ON:
186 sensor_dbg("CSI_SUBDEV_STBY_ON!\n");
187 sensor_s_sw_stby(sd, ON);
188 break;
189 case STBY_OFF:
190 sensor_dbg("CSI_SUBDEV_STBY_OFF!\n");
191 sensor_s_sw_stby(sd, OFF);
192 break;
193 case PWR_ON:
194 sensor_dbg("CSI_SUBDEV_PWR_ON!\n");
195 sensor_print("CSI_SUBDEV_PWR_ON!\n");
196 cci_lock(sd);
197 vin_gpio_set_status(sd, PWDN, 1);
198 vin_gpio_set_status(sd, RESET, 1);
199 vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
200 vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
201 usleep_range(1000, 1200);
202 vin_set_mclk_freq(sd, MCLK);
203 vin_set_mclk(sd, ON);
204 usleep_range(10000, 12000);
205 vin_gpio_write(sd, POWER_EN, CSI_GPIO_HIGH);
206 vin_set_pmu_channel(sd, IOVDD, ON);
207 vin_set_pmu_channel(sd, AVDD, ON);
208 vin_set_pmu_channel(sd, DVDD, ON);
209 vin_set_pmu_channel(sd, AFVDD, ON);
210 vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
211 usleep_range(10000, 12000);
212 vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
213 usleep_range(30000, 31000);
214 cci_unlock(sd);
215 break;
216 case PWR_OFF:
217 sensor_dbg("CSI_SUBDEV_PWR_OFF!\n");
218 sensor_print("CSI_SUBDEV_PWR_OFF!\n");
219 cci_lock(sd);
220 vin_set_mclk(sd, OFF);
221 vin_gpio_write(sd, POWER_EN, CSI_GPIO_LOW);
222 vin_set_pmu_channel(sd, AFVDD, OFF);
223 vin_set_pmu_channel(sd, DVDD, OFF);
224 vin_set_pmu_channel(sd, AVDD, OFF);
225 vin_set_pmu_channel(sd, IOVDD, OFF);
226 usleep_range(10000, 12000);
227 vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
228 vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
229 vin_gpio_set_status(sd, RESET, 0);
230 vin_gpio_set_status(sd, PWDN, 0);
231 cci_unlock(sd);
232 break;
233 default:
234 return -EINVAL;
235 }
236
237 return 0;
238 }
239
sensor_reset(struct v4l2_subdev * sd,u32 val)240 static int sensor_reset(struct v4l2_subdev *sd, u32 val)
241 {
242 vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
243 usleep_range(5000, 6000);
244 vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
245 usleep_range(5000, 6000);
246 return 0;
247 }
248
sensor_detect(struct v4l2_subdev * sd)249 static int sensor_detect(struct v4l2_subdev *sd)
250 {
251 data_type rdval = 0;
252 int cnt = 0;
253
254 sensor_read(sd, 0xff, &rdval);
255 sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", rdval);
256
257 while ((rdval != V4L2_IDENT_SENSOR) && (cnt < 5)) {
258 sensor_read(sd, 0xff, &rdval);
259 sensor_print("retry = %d, V4L2_IDENT_SENSOR = %x\n", cnt, rdval);
260 cnt++;
261 }
262
263 if (rdval != V4L2_IDENT_SENSOR)
264 return -ENODEV;
265
266 return 0;
267 }
268
sensor_init(struct v4l2_subdev * sd,u32 val)269 static int sensor_init(struct v4l2_subdev *sd, u32 val)
270 {
271 int ret;
272 struct sensor_info *info = to_state(sd);
273
274 sensor_dbg("sensor_init\n");
275
276 /*Make sure it is a target sensor */
277 ret = sensor_detect(sd);
278 if (ret) {
279 sensor_err("chip found is not an target chip.\n");
280 return ret;
281 }
282
283 info->focus_status = 0;
284 info->low_speed = 0;
285 info->width = VGA_WIDTH;
286 info->height = VGA_HEIGHT;
287 info->hflip = 0;
288 info->vflip = 0;
289
290 info->tpf.numerator = 1;
291 info->tpf.denominator = 30; /* 30fps */
292
293 info->preview_first_flag = 1;
294 return 0;
295 }
296
sensor_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)297 static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
298 {
299 int ret = 0;
300 struct sensor_info *info = to_state(sd);
301
302 switch (cmd) {
303 case GET_CURRENT_WIN_CFG:
304 if (info->current_wins != NULL) {
305 memcpy(arg,
306 info->current_wins,
307 sizeof(struct sensor_win_size));
308 ret = 0;
309 } else {
310 sensor_err("empty wins!\n");
311 ret = -1;
312 }
313 break;
314 case SET_FPS:
315 break;
316 case VIDIOC_VIN_SENSOR_CFG_REQ:
317 sensor_cfg_req(sd, (struct sensor_config *)arg);
318 break;
319 default:
320 return -EINVAL;
321 }
322 return ret;
323 }
324
325 /*
326 * Store information about the video data format.
327 */
328 static struct sensor_format_struct sensor_formats[] = {
329 {
330 .desc = "BT656 4CH",
331 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
332 .regs = NULL,
333 .regs_size = 0,
334 .bpp = 2,
335 },
336 };
337 #define N_FMTS ARRAY_SIZE(sensor_formats)
338
339 /*
340 * Then there is the issue of window sizes. Try to capture the info here.
341 */
342
343 static struct sensor_win_size sensor_win_sizes[] = {
344 {
345 .width = 704,
346 .height = 576,
347 .hoffset = 0,
348 .voffset = 0,
349 .regs = reg_d1_4ch,
350 .regs_size = ARRAY_SIZE(reg_d1_4ch),
351 .set_size = NULL,
352 },
353 };
354
355 #define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes))
356
sensor_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad,struct v4l2_mbus_config * cfg)357 static int sensor_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
358 struct v4l2_mbus_config *cfg)
359 {
360 cfg->type = V4L2_MBUS_BT656;
361 cfg->flags = CLK_POL | CSI_CH_0 | CSI_CH_1 | CSI_CH_2 | CSI_CH_3;
362 //cfg->flags = CLK_POL | CSI_CH_0;
363 return 0;
364 }
365
sensor_g_ctrl(struct v4l2_ctrl * ctrl)366 static int sensor_g_ctrl(struct v4l2_ctrl *ctrl)
367 {
368 return -EINVAL;
369 }
370
sensor_s_ctrl(struct v4l2_ctrl * ctrl)371 static int sensor_s_ctrl(struct v4l2_ctrl *ctrl)
372 {
373 return -EINVAL;
374 }
375
sensor_reg_init(struct sensor_info * info)376 static int sensor_reg_init(struct sensor_info *info)
377 {
378 struct v4l2_subdev *sd = &info->sd;
379 struct sensor_format_struct *sensor_fmt = info->fmt;
380 struct sensor_win_size *wsize = info->current_wins;
381
382 sensor_dbg("sensor_reg_init\n");
383
384 sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size);
385
386 if (wsize->regs)
387 sensor_write_array(sd, wsize->regs, wsize->regs_size);
388
389 if (wsize->set_size)
390 wsize->set_size(sd);
391
392 info->fmt = sensor_fmt;
393 info->width = wsize->width;
394 info->height = wsize->height;
395
396 return 0;
397 }
398
sensor_s_stream(struct v4l2_subdev * sd,int enable)399 static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
400 {
401 struct sensor_info *info = to_state(sd);
402
403 sensor_print("%s on = %d, %d*%d %x\n", __func__, enable,
404 info->current_wins->width,
405 info->current_wins->height, info->fmt->mbus_code);
406
407 if (!enable)
408 return 0;
409 return sensor_reg_init(info);
410 }
411
412 /* ----------------------------------------------------------------------- */
413 static const struct v4l2_ctrl_ops sensor_ctrl_ops = {
414 .g_volatile_ctrl = sensor_g_ctrl,
415 .s_ctrl = sensor_s_ctrl,
416 };
417
418 static const struct v4l2_subdev_core_ops sensor_core_ops = {
419 .s_power = sensor_power,
420 .ioctl = sensor_ioctl,
421 };
422
423 static const struct v4l2_subdev_video_ops sensor_video_ops = {
424 .s_parm = sensor_s_parm,
425 .g_parm = sensor_g_parm,
426 .s_stream = sensor_s_stream,
427 };
428
429 static const struct v4l2_subdev_pad_ops sensor_pad_ops = {
430 .enum_mbus_code = sensor_enum_mbus_code,
431 .enum_frame_size = sensor_enum_frame_size,
432 .get_fmt = sensor_get_fmt,
433 .set_fmt = sensor_set_fmt,
434 .get_mbus_config = sensor_g_mbus_config,
435 };
436
437 static const struct v4l2_subdev_ops sensor_ops = {
438 .core = &sensor_core_ops,
439 .video = &sensor_video_ops,
440 .pad = &sensor_pad_ops,
441 };
442
443
444 /* ----------------------------------------------------------------------- */
445 static struct cci_driver cci_drv = {
446 .name = SENSOR_NAME,
447 .addr_width = CCI_BITS_8,
448 .data_width = CCI_BITS_8,
449 };
450
sensor_init_controls(struct v4l2_subdev * sd,const struct v4l2_ctrl_ops * ops)451 static int sensor_init_controls(struct v4l2_subdev *sd, const struct v4l2_ctrl_ops *ops)
452 {
453 struct sensor_info *info = to_state(sd);
454 struct v4l2_ctrl_handler *handler = &info->handler;
455 struct v4l2_ctrl *ctrl;
456 int ret = 0;
457
458 v4l2_ctrl_handler_init(handler, 2);
459
460 v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 1 * 1600,
461 256 * 1600, 1, 1 * 1600);
462 ctrl = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 0,
463 65536 * 16, 1, 0);
464 if (ctrl != NULL)
465 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
466
467 if (handler->error) {
468 ret = handler->error;
469 v4l2_ctrl_handler_free(handler);
470 }
471
472 sd->ctrl_handler = handler;
473
474 return ret;
475 }
476
477
sensor_probe(struct i2c_client * client,const struct i2c_device_id * id)478 static int sensor_probe(struct i2c_client *client,
479 const struct i2c_device_id *id)
480 {
481 struct v4l2_subdev *sd;
482 struct sensor_info *info;
483
484 info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
485 if (info == NULL)
486 return -ENOMEM;
487 sd = &info->sd;
488 cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv);
489 sensor_init_controls(sd, &sensor_ctrl_ops);
490 mutex_init(&info->lock);
491 #ifdef CONFIG_SAME_I2C
492 info->sensor_i2c_addr = I2C_ADDR >> 1;
493 #endif
494 info->fmt = &sensor_formats[0];
495 info->fmt_pt = &sensor_formats[0];
496 info->win_pt = &sensor_win_sizes[0];
497 info->fmt_num = N_FMTS;
498 info->win_size_num = N_WIN_SIZES;
499 info->sensor_field = V4L2_FIELD_INTERLACED;
500 return 0;
501 }
502
sensor_remove(struct i2c_client * client)503 static int sensor_remove(struct i2c_client *client)
504 {
505 struct v4l2_subdev *sd;
506
507 sd = cci_dev_remove_helper(client, &cci_drv);
508 kfree(to_state(sd));
509 return 0;
510 }
511
512 static const struct i2c_device_id sensor_id[] = {
513 {SENSOR_NAME, 0},
514 {}
515 };
516
517 MODULE_DEVICE_TABLE(i2c, sensor_id);
518
519 static struct i2c_driver sensor_driver = {
520 .driver = {
521 .owner = THIS_MODULE,
522 .name = SENSOR_NAME,
523 },
524 .probe = sensor_probe,
525 .remove = sensor_remove,
526 .id_table = sensor_id,
527 };
init_sensor(void)528 static __init int init_sensor(void)
529 {
530 return cci_dev_init_helper(&sensor_driver);
531 }
532
exit_sensor(void)533 static __exit void exit_sensor(void)
534 {
535 cci_dev_exit_helper(&sensor_driver);
536 }
537
538 module_init(init_sensor);
539 module_exit(exit_sensor);
540