.. | .. |
---|
6 | 6 | * |
---|
7 | 7 | * V0.0X01.0X00 first version. |
---|
8 | 8 | * V0.0X01.0X01 add quick stream on/off |
---|
| 9 | + * V0.0X01.0X02 support slave mode |
---|
9 | 10 | */ |
---|
10 | 11 | |
---|
11 | 12 | #include <linux/clk.h> |
---|
.. | .. |
---|
35 | 36 | #include <media/v4l2-mediabus.h> |
---|
36 | 37 | #include <media/v4l2-subdev.h> |
---|
37 | 38 | |
---|
38 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) |
---|
| 39 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) |
---|
39 | 40 | #define GC2053_NAME "gc2053" |
---|
| 41 | +#define GC2053_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG10_1X10 |
---|
40 | 42 | |
---|
41 | 43 | #define MIPI_FREQ_297M 297000000 |
---|
42 | 44 | #define GC2053_XVCLK_FREQ 24000000 |
---|
.. | .. |
---|
53 | 55 | #define GC2053_REG_VTS_L 0x42 |
---|
54 | 56 | |
---|
55 | 57 | #define GC2053_REG_CTRL_MODE 0x3E |
---|
| 58 | +#define GC2053_MODE_SW_STANDBY 0x11 |
---|
| 59 | +#define GC2053_MODE_STREAMING 0x91 |
---|
56 | 60 | |
---|
57 | 61 | #define REG_NULL 0xFF |
---|
58 | 62 | |
---|
.. | .. |
---|
91 | 95 | #define GC2053_NUM_SUPPLIES ARRAY_SIZE(gc2053_supply_names) |
---|
92 | 96 | |
---|
93 | 97 | #define to_gc2053(sd) container_of(sd, struct gc2053, subdev) |
---|
94 | | - |
---|
95 | | -#define USE_DVP_INTERFACE 0 |
---|
96 | | - |
---|
97 | | -#if USE_DVP_INTERFACE |
---|
98 | | - #define GC2053_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB8_1X8 |
---|
99 | | - #define GC2053_MODE_SW_STANDBY 0x00 |
---|
100 | | - #define GC2053_MODE_STREAMING 0x40 |
---|
101 | | -#else |
---|
102 | | - #define GC2053_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG10_1X10 |
---|
103 | | - #define GC2053_MODE_SW_STANDBY 0x11 |
---|
104 | | - #define GC2053_MODE_STREAMING 0x91 |
---|
105 | | -#endif |
---|
106 | | - |
---|
107 | | -enum gc2053_max_pad { |
---|
108 | | - PAD0, |
---|
109 | | - PAD_MAX, |
---|
110 | | -}; |
---|
111 | 98 | |
---|
112 | 99 | struct regval { |
---|
113 | 100 | u8 addr; |
---|
.. | .. |
---|
154 | 141 | unsigned int lane_num; |
---|
155 | 142 | unsigned int cfg_num; |
---|
156 | 143 | unsigned int pixel_rate; |
---|
157 | | - u32 cur_vts; |
---|
| 144 | + |
---|
158 | 145 | u32 module_index; |
---|
159 | 146 | const char *module_facing; |
---|
160 | 147 | const char *module_name; |
---|
161 | 148 | const char *len_name; |
---|
| 149 | + enum rkmodule_sync_mode sync_mode; |
---|
162 | 150 | struct rkmodule_awb_cfg awb_cfg; |
---|
163 | 151 | struct rkmodule_lsc_cfg lsc_cfg; |
---|
164 | 152 | u8 flip; |
---|
.. | .. |
---|
316 | 304 | {REG_NULL, 0x00}, |
---|
317 | 305 | }; |
---|
318 | 306 | |
---|
319 | | -/* |
---|
320 | | - * window_size=1920*1080 |
---|
321 | | - * mclk=24mhz,pclk=74.25mhz |
---|
322 | | - * pixel_line_total=2200,line_frame_total=1125 |
---|
323 | | - * row_time=29.629us,frame_rate=30fps |
---|
324 | | - */ |
---|
325 | | -static const struct regval __maybe_unused gc2053_1920x1080_regs_dvp[] = { |
---|
326 | | - /****system****/ |
---|
327 | | - {0xfe, 0x80}, |
---|
328 | | - {0xfe, 0x80}, |
---|
329 | | - {0xfe, 0x80}, |
---|
| 307 | +static __maybe_unused const struct regval gc2053_master_mode_regs[] = { |
---|
330 | 308 | {0xfe, 0x00}, |
---|
331 | | - {0xf2, 0x00}, |
---|
332 | | - {0xf3, 0x0f}, |
---|
333 | | - {0xf4, 0x36}, |
---|
334 | | - {0xf5, 0xc0}, |
---|
335 | | - {0xf6, 0x44}, |
---|
336 | | - {0xf7, 0x01}, |
---|
337 | | - {0xf8, 0x63}, |
---|
338 | | - {0xf9, 0x40}, |
---|
339 | | - {0xfc, 0x8e}, |
---|
340 | | - /****CISCTL & ANALOG****/ |
---|
| 309 | + {0x7f, 0x09}, |
---|
| 310 | + {0x82, 0x01}, |
---|
| 311 | + {0x83, 0x0c}, |
---|
| 312 | + {0x84, 0x80}, |
---|
| 313 | + {REG_NULL, 0x00}, |
---|
| 314 | +}; |
---|
| 315 | + |
---|
| 316 | +static __maybe_unused const struct regval gc2053_slave_mode_regs[] = { |
---|
341 | 317 | {0xfe, 0x00}, |
---|
342 | | - {0x87, 0x18}, |
---|
343 | | - {0xee, 0x30}, |
---|
344 | | - {0xd0, 0xb7}, |
---|
345 | | - {0x03, 0x04}, |
---|
346 | | - {0x04, 0x60}, |
---|
347 | | - {0x05, 0x04}, |
---|
348 | | - {0x06, 0x4c}, |
---|
349 | | - {0x07, 0x00}, |
---|
350 | | - {0x08, 0x11}, |
---|
351 | | - {0x09, 0x00}, |
---|
352 | | - {0x0a, 0x02}, |
---|
353 | | - {0x0b, 0x00}, |
---|
354 | | - {0x0c, 0x02}, |
---|
355 | | - {0x0d, 0x04}, |
---|
356 | | - {0x0e, 0x40}, |
---|
357 | | - {0x12, 0xe2}, |
---|
358 | | - {0x13, 0x16}, |
---|
359 | | - {0x19, 0x0a}, |
---|
360 | | - {0x21, 0x1c}, |
---|
361 | | - {0x28, 0x0a}, |
---|
362 | | - {0x29, 0x24}, |
---|
363 | | - {0x2b, 0x04}, |
---|
364 | | - {0x32, 0xf8}, |
---|
365 | | - {0x37, 0x03}, |
---|
366 | | - {0x39, 0x15}, |
---|
367 | | - {0x43, 0x07}, |
---|
368 | | - {0x44, 0x40}, |
---|
369 | | - {0x46, 0x0b}, |
---|
370 | | - {0x4b, 0x20}, |
---|
371 | | - {0x4e, 0x08}, |
---|
372 | | - {0x55, 0x20}, |
---|
373 | | - {0x66, 0x05}, |
---|
374 | | - {0x67, 0x05}, |
---|
375 | | - {0x77, 0x01}, |
---|
376 | | - {0x78, 0x00}, |
---|
377 | | - {0x7c, 0x93}, |
---|
378 | | - {0x8c, 0x12}, |
---|
379 | | - {0x8d, 0x92}, |
---|
380 | | - {0x90, 0x00}, |
---|
381 | | - {0x9d, 0x10}, |
---|
382 | | - {0xce, 0x7c}, |
---|
383 | | - {0xd2, 0x41}, |
---|
384 | | - {0xd3, 0xdc}, |
---|
385 | | - {0xe6, 0x50}, |
---|
386 | | - /*gain*/ |
---|
387 | | - {0xb6, 0xc0}, |
---|
388 | | - {0xb0, 0x70}, |
---|
389 | | - {0xb1, 0x01}, |
---|
390 | | - {0xb2, 0x00}, |
---|
391 | | - {0xb3, 0x00}, |
---|
392 | | - {0xb4, 0x00}, |
---|
393 | | - {0xb8, 0x01}, |
---|
394 | | - {0xb9, 0x00}, |
---|
395 | | - /*blk*/ |
---|
396 | | - {0x26, 0x30}, |
---|
397 | | - {0xfe, 0x01}, |
---|
398 | | - {0x40, 0x23}, |
---|
399 | | - {0x55, 0x07}, |
---|
400 | | - {0x60, 0x40}, |
---|
401 | | - {0xfe, 0x04}, |
---|
402 | | - {0x14, 0x78}, |
---|
403 | | - {0x15, 0x78}, |
---|
404 | | - {0x16, 0x78}, |
---|
405 | | - {0x17, 0x78}, |
---|
406 | | - /*window*/ |
---|
407 | | - {0xfe, 0x01}, |
---|
408 | | - {0x92, 0x00}, |
---|
409 | | - {0x94, 0x03}, |
---|
410 | | - {0x95, 0x04}, |
---|
411 | | - {0x96, 0x38}, |
---|
412 | | - {0x97, 0x07}, |
---|
413 | | - {0x98, 0x80}, |
---|
414 | | - /*ISP*/ |
---|
415 | | - {0xfe, 0x01}, |
---|
416 | | - {0x01, 0x05}, |
---|
417 | | - {0x02, 0x89}, |
---|
418 | | - {0x04, 0x01}, |
---|
419 | | - {0x07, 0xa6}, |
---|
420 | | - {0x08, 0xa9}, |
---|
421 | | - {0x09, 0xa8}, |
---|
422 | | - {0x0a, 0xa7}, |
---|
423 | | - {0x0b, 0xff}, |
---|
424 | | - {0x0c, 0xff}, |
---|
425 | | - {0x0f, 0x00}, |
---|
426 | | - {0x50, 0x1c}, |
---|
427 | | - {0x89, 0x03}, |
---|
428 | | - {0xfe, 0x04}, |
---|
429 | | - {0x28, 0x86}, |
---|
430 | | - {0x29, 0x86}, |
---|
431 | | - {0x2a, 0x86}, |
---|
432 | | - {0x2b, 0x68}, |
---|
433 | | - {0x2c, 0x68}, |
---|
434 | | - {0x2d, 0x68}, |
---|
435 | | - {0x2e, 0x68}, |
---|
436 | | - {0x2f, 0x68}, |
---|
437 | | - {0x30, 0x4f}, |
---|
438 | | - {0x31, 0x68}, |
---|
439 | | - {0x32, 0x67}, |
---|
440 | | - {0x33, 0x66}, |
---|
441 | | - {0x34, 0x66}, |
---|
442 | | - {0x35, 0x66}, |
---|
443 | | - {0x36, 0x66}, |
---|
444 | | - {0x37, 0x66}, |
---|
445 | | - {0x38, 0x62}, |
---|
446 | | - {0x39, 0x62}, |
---|
447 | | - {0x3a, 0x62}, |
---|
448 | | - {0x3b, 0x62}, |
---|
449 | | - {0x3c, 0x62}, |
---|
450 | | - {0x3d, 0x62}, |
---|
451 | | - {0x3e, 0x62}, |
---|
452 | | - {0x3f, 0x62}, |
---|
453 | | - /****DVP & MIPI****/ |
---|
454 | | - {0xfe, 0x01}, |
---|
455 | | - {0x9a, 0x06}, |
---|
456 | | - {0xfe, 0x00}, |
---|
457 | | - {0x7b, 0x2a}, |
---|
458 | | - {0x23, 0x2d}, |
---|
459 | | - {0xfe, 0x03}, |
---|
460 | | - {0x01, 0x20}, |
---|
461 | | - {0x02, 0x56}, |
---|
462 | | - {0x03, 0xb2}, |
---|
463 | | - {0x12, 0x80}, |
---|
464 | | - {0x13, 0x07}, |
---|
465 | | - {0xfe, 0x00}, |
---|
| 318 | + {0x7f, 0x09}, |
---|
| 319 | + {0x82, 0x0a}, |
---|
| 320 | + {0x83, 0x0b}, |
---|
| 321 | + {0x84, 0x80}, |
---|
| 322 | + {0x85, 0x51}, |
---|
466 | 323 | {REG_NULL, 0x00}, |
---|
467 | 324 | }; |
---|
468 | 325 | |
---|
469 | 326 | static const struct gc2053_mode supported_modes[] = { |
---|
470 | | -#if USE_DVP_INTERFACE |
---|
471 | | - { |
---|
472 | | - .width = 1920, |
---|
473 | | - .height = 1080, |
---|
474 | | - .max_fps = { |
---|
475 | | - .numerator = 10000, |
---|
476 | | - .denominator = 300000, |
---|
477 | | - }, |
---|
478 | | - .exp_def = 0x0010, |
---|
479 | | - .hts_def = 0x0898, |
---|
480 | | - .vts_def = 0x0465, |
---|
481 | | - .reg_list = gc2053_1920x1080_regs_dvp, |
---|
482 | | - .hdr_mode = NO_HDR, |
---|
483 | | - .vc[PAD0] = 0, |
---|
484 | | - }, |
---|
485 | | -#endif |
---|
486 | 327 | { |
---|
487 | 328 | .width = 1920, |
---|
488 | 329 | .height = 1080, |
---|
.. | .. |
---|
499 | 340 | }, |
---|
500 | 341 | }; |
---|
501 | 342 | |
---|
502 | | -#if !USE_DVP_INTERFACE |
---|
503 | 343 | static const s64 link_freq_menu_items[] = { |
---|
504 | 344 | MIPI_FREQ_297M |
---|
505 | 345 | }; |
---|
506 | | -#endif |
---|
507 | 346 | |
---|
508 | 347 | /* sensor register write */ |
---|
509 | 348 | static int gc2053_write_reg(struct i2c_client *client, u8 reg, u8 val) |
---|
.. | .. |
---|
606 | 445 | return &supported_modes[cur_best_fit]; |
---|
607 | 446 | } |
---|
608 | 447 | |
---|
609 | | -static uint8_t gain_reg_table[29][4] = { |
---|
| 448 | +static const uint8_t gain_reg_table[29][4] = { |
---|
610 | 449 | {0x00, 0x00, 0x01, 0x00}, |
---|
611 | 450 | {0x00, 0x10, 0x01, 0x0c}, |
---|
612 | 451 | {0x00, 0x20, 0x01, 0x1b}, |
---|
.. | .. |
---|
638 | 477 | {0x00, 0xce, 0x3f, 0x3f}, |
---|
639 | 478 | }; |
---|
640 | 479 | |
---|
641 | | -static uint32_t gain_level_table[29] = { |
---|
| 480 | +static const uint32_t gain_level_table[30] = { |
---|
642 | 481 | 64, |
---|
643 | 482 | 76, |
---|
644 | 483 | 91, |
---|
.. | .. |
---|
668 | 507 | 5572, |
---|
669 | 508 | 6552, |
---|
670 | 509 | 7713, |
---|
| 510 | + 0xffffffff |
---|
671 | 511 | }; |
---|
672 | 512 | |
---|
673 | 513 | static int gc2053_set_gain(struct gc2053 *gc2053, u32 gain) |
---|
.. | .. |
---|
675 | 515 | int ret; |
---|
676 | 516 | uint8_t i = 0; |
---|
677 | 517 | uint8_t total = 0; |
---|
678 | | - uint8_t temp = 0; |
---|
| 518 | + uint32_t temp = 0; |
---|
679 | 519 | |
---|
680 | 520 | total = sizeof(gain_level_table) / sizeof(u32) - 1; |
---|
681 | | - for (i = 0; i < total; i++) { |
---|
| 521 | + for (i = 0; i <= total; i++) { |
---|
682 | 522 | if ((gain_level_table[i] <= gain) && (gain < gain_level_table[i+1])) |
---|
683 | 523 | break; |
---|
684 | 524 | } |
---|
| 525 | + |
---|
| 526 | + if (i > total) |
---|
| 527 | + i = total; |
---|
685 | 528 | |
---|
686 | 529 | ret = gc2053_write_reg(gc2053->client, 0xb4, gain_reg_table[i][0]); |
---|
687 | 530 | ret |= gc2053_write_reg(gc2053->client, 0xb3, gain_reg_table[i][1]); |
---|
.. | .. |
---|
733 | 576 | vts = ctrl->val + gc2053->cur_mode->height; |
---|
734 | 577 | ret = gc2053_write_reg(gc2053->client, GC2053_REG_VTS_H, (vts >> 8) & 0x3f); |
---|
735 | 578 | ret |= gc2053_write_reg(gc2053->client, GC2053_REG_VTS_L, vts & 0xff); |
---|
| 579 | + /* Note: In master-slave mode, Galaxycore request slave sensor frame rate bigger than master. */ |
---|
| 580 | + if (gc2053->sync_mode == INTERNAL_MASTER_MODE) |
---|
| 581 | + gc2053_write_reg(gc2053->client, GC2053_REG_VTS_L, (vts & 0xff) + 10); |
---|
736 | 582 | break; |
---|
737 | 583 | case V4L2_CID_HFLIP: |
---|
738 | 584 | if (ctrl->val) |
---|
.. | .. |
---|
772 | 618 | gc2053->supplies); |
---|
773 | 619 | } |
---|
774 | 620 | |
---|
775 | | -static int __maybe_unused gc2053_parse_of_mipi(struct gc2053 *gc2053) |
---|
| 621 | +static int gc2053_parse_of(struct gc2053 *gc2053) |
---|
776 | 622 | { |
---|
777 | 623 | struct device *dev = &gc2053->client->dev; |
---|
778 | 624 | struct device_node *endpoint; |
---|
.. | .. |
---|
795 | 641 | if (2 == gc2053->lane_num) { |
---|
796 | 642 | gc2053->cur_mode = &supported_modes[0]; |
---|
797 | 643 | gc2053->cfg_num = ARRAY_SIZE(supported_modes); |
---|
798 | | - gc2053->cur_vts = gc2053->cur_mode->vts_def; |
---|
799 | 644 | |
---|
800 | 645 | /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ |
---|
801 | 646 | gc2053->pixel_rate = MIPI_FREQ_297M * 2U * (gc2053->lane_num) / 10U; |
---|
.. | .. |
---|
811 | 656 | { |
---|
812 | 657 | const struct gc2053_mode *mode; |
---|
813 | 658 | struct v4l2_ctrl_handler *handler; |
---|
814 | | - struct v4l2_ctrl __maybe_unused *ctrl; |
---|
| 659 | + struct v4l2_ctrl *ctrl; |
---|
815 | 660 | s64 exposure_max, vblank_def; |
---|
816 | 661 | u32 h_blank; |
---|
817 | 662 | int ret; |
---|
.. | .. |
---|
823 | 668 | return ret; |
---|
824 | 669 | handler->lock = &gc2053->mutex; |
---|
825 | 670 | |
---|
826 | | -#if !USE_DVP_INTERFACE |
---|
827 | 671 | ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, |
---|
828 | 672 | 0, 0, link_freq_menu_items); |
---|
829 | 673 | if (ctrl) |
---|
830 | 674 | ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
831 | | -#endif |
---|
832 | 675 | |
---|
833 | 676 | v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, |
---|
834 | 677 | 0, gc2053->pixel_rate, 1, gc2053->pixel_rate); |
---|
.. | .. |
---|
1013 | 856 | |
---|
1014 | 857 | static int __gc2053_start_stream(struct gc2053 *gc2053) |
---|
1015 | 858 | { |
---|
| 859 | + struct i2c_client *client = gc2053->client; |
---|
1016 | 860 | int ret; |
---|
1017 | 861 | |
---|
1018 | | - ret = gc2053_write_array(gc2053->client, gc2053->cur_mode->reg_list); |
---|
| 862 | + ret = gc2053_write_array(client, gc2053->cur_mode->reg_list); |
---|
1019 | 863 | if (ret) |
---|
1020 | 864 | return ret; |
---|
1021 | 865 | |
---|
1022 | 866 | /* In case these controls are set before streaming */ |
---|
1023 | 867 | mutex_unlock(&gc2053->mutex); |
---|
1024 | | - v4l2_ctrl_handler_setup(&gc2053->ctrl_handler); |
---|
| 868 | + ret = v4l2_ctrl_handler_setup(&gc2053->ctrl_handler); |
---|
1025 | 869 | mutex_lock(&gc2053->mutex); |
---|
1026 | 870 | |
---|
1027 | | - ret = gc2053_set_flip(gc2053, gc2053->flip); |
---|
| 871 | + ret |= gc2053_set_flip(gc2053, gc2053->flip); |
---|
1028 | 872 | if (ret) |
---|
1029 | 873 | return ret; |
---|
1030 | | - return gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
---|
| 874 | + if (gc2053->sync_mode == INTERNAL_MASTER_MODE) { |
---|
| 875 | + ret = gc2053_write_array(client, gc2053_master_mode_regs); |
---|
| 876 | + if (ret) |
---|
| 877 | + dev_err(&client->dev, |
---|
| 878 | + "write internal master mode reg failed %d\n", ret); |
---|
| 879 | + } else if (gc2053->sync_mode == EXTERNAL_MASTER_MODE) { |
---|
| 880 | + ret = gc2053_write_array(client, gc2053_slave_mode_regs); |
---|
| 881 | + if (ret) |
---|
| 882 | + dev_err(&client->dev, |
---|
| 883 | + "write external master mode reg failed %d\n", ret); |
---|
| 884 | + } else if (gc2053->sync_mode == SLAVE_MODE) { |
---|
| 885 | + ret = gc2053_write_array(gc2053->client, gc2053_slave_mode_regs); |
---|
| 886 | + if (ret) |
---|
| 887 | + dev_err(&client->dev, "write slave mode reg failed %d\n", ret); |
---|
| 888 | + } |
---|
| 889 | + |
---|
| 890 | + ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
---|
1031 | 891 | GC2053_MODE_STREAMING); |
---|
| 892 | + |
---|
| 893 | + return ret; |
---|
1032 | 894 | } |
---|
1033 | 895 | |
---|
1034 | 896 | static int __gc2053_stop_stream(struct gc2053 *gc2053) |
---|
.. | .. |
---|
1041 | 903 | struct rkmodule_inf *inf) |
---|
1042 | 904 | { |
---|
1043 | 905 | memset(inf, 0, sizeof(*inf)); |
---|
1044 | | - strscpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor)); |
---|
1045 | | - strscpy(inf->base.module, gc2053->module_name, |
---|
| 906 | + strlcpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor)); |
---|
| 907 | + strlcpy(inf->base.module, gc2053->module_name, |
---|
1046 | 908 | sizeof(inf->base.module)); |
---|
1047 | | - strscpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens)); |
---|
| 909 | + strlcpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens)); |
---|
| 910 | +} |
---|
| 911 | + |
---|
| 912 | +static void gc2053_set_awb_cfg(struct gc2053 *gc2053, |
---|
| 913 | + struct rkmodule_awb_cfg *cfg) |
---|
| 914 | +{ |
---|
| 915 | + mutex_lock(&gc2053->mutex); |
---|
| 916 | + memcpy(&gc2053->awb_cfg, cfg, sizeof(*cfg)); |
---|
| 917 | + mutex_unlock(&gc2053->mutex); |
---|
| 918 | +} |
---|
| 919 | + |
---|
| 920 | +static void gc2053_set_lsc_cfg(struct gc2053 *gc2053, |
---|
| 921 | + struct rkmodule_lsc_cfg *cfg) |
---|
| 922 | +{ |
---|
| 923 | + mutex_lock(&gc2053->mutex); |
---|
| 924 | + memcpy(&gc2053->lsc_cfg, cfg, sizeof(*cfg)); |
---|
| 925 | + mutex_unlock(&gc2053->mutex); |
---|
1048 | 926 | } |
---|
1049 | 927 | |
---|
1050 | 928 | static long gc2053_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
.. | .. |
---|
1053 | 931 | long ret = 0; |
---|
1054 | 932 | struct rkmodule_hdr_cfg *hdr_cfg; |
---|
1055 | 933 | u32 stream = 0; |
---|
| 934 | + u32 *sync_mode = NULL; |
---|
1056 | 935 | |
---|
1057 | 936 | switch (cmd) { |
---|
1058 | 937 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
1060 | 939 | hdr_cfg->esp.mode = HDR_NORMAL_VC; |
---|
1061 | 940 | hdr_cfg->hdr_mode = gc2053->cur_mode->hdr_mode; |
---|
1062 | 941 | break; |
---|
1063 | | - case RKMODULE_SET_HDR_CFG: |
---|
1064 | | - ret = -EINVAL; |
---|
1065 | | - dev_err(&gc2053->client->dev, "gc2053 not support hdr mode\n"); |
---|
1066 | | - break; |
---|
1067 | 942 | case RKMODULE_GET_MODULE_INFO: |
---|
1068 | 943 | gc2053_get_module_inf(gc2053, (struct rkmodule_inf *)arg); |
---|
| 944 | + break; |
---|
| 945 | + case RKMODULE_AWB_CFG: |
---|
| 946 | + gc2053_set_awb_cfg(gc2053, (struct rkmodule_awb_cfg *)arg); |
---|
| 947 | + break; |
---|
| 948 | + case RKMODULE_LSC_CFG: |
---|
| 949 | + gc2053_set_lsc_cfg(gc2053, (struct rkmodule_lsc_cfg *)arg); |
---|
1069 | 950 | break; |
---|
1070 | 951 | case RKMODULE_SET_QUICK_STREAM: |
---|
1071 | 952 | |
---|
.. | .. |
---|
1077 | 958 | else |
---|
1078 | 959 | ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
---|
1079 | 960 | GC2053_MODE_SW_STANDBY); |
---|
| 961 | + break; |
---|
| 962 | + case RKMODULE_GET_SYNC_MODE: |
---|
| 963 | + sync_mode = (u32 *)arg; |
---|
| 964 | + *sync_mode = gc2053->sync_mode; |
---|
| 965 | + break; |
---|
| 966 | + case RKMODULE_SET_SYNC_MODE: |
---|
| 967 | + sync_mode = (u32 *)arg; |
---|
| 968 | + gc2053->sync_mode = *sync_mode; |
---|
1080 | 969 | break; |
---|
1081 | 970 | default: |
---|
1082 | 971 | ret = -ENOTTY; |
---|
.. | .. |
---|
1091 | 980 | { |
---|
1092 | 981 | void __user *up = compat_ptr(arg); |
---|
1093 | 982 | struct rkmodule_inf *inf; |
---|
| 983 | + struct rkmodule_awb_cfg *awb_cfg; |
---|
| 984 | + struct rkmodule_lsc_cfg *lsc_cfg; |
---|
1094 | 985 | struct rkmodule_hdr_cfg *hdr; |
---|
1095 | 986 | long ret = 0; |
---|
1096 | 987 | u32 stream = 0; |
---|
| 988 | + u32 sync_mode; |
---|
1097 | 989 | |
---|
1098 | 990 | switch (cmd) { |
---|
1099 | 991 | case RKMODULE_GET_MODULE_INFO: |
---|
.. | .. |
---|
1110 | 1002 | ret = -EFAULT; |
---|
1111 | 1003 | } |
---|
1112 | 1004 | kfree(inf); |
---|
| 1005 | + break; |
---|
| 1006 | + case RKMODULE_AWB_CFG: |
---|
| 1007 | + awb_cfg = kzalloc(sizeof(*awb_cfg), GFP_KERNEL); |
---|
| 1008 | + if (!awb_cfg) { |
---|
| 1009 | + ret = -ENOMEM; |
---|
| 1010 | + return ret; |
---|
| 1011 | + } |
---|
| 1012 | + |
---|
| 1013 | + if (copy_from_user(awb_cfg, up, sizeof(*awb_cfg))) { |
---|
| 1014 | + kfree(awb_cfg); |
---|
| 1015 | + return -EFAULT; |
---|
| 1016 | + } |
---|
| 1017 | + |
---|
| 1018 | + ret = gc2053_ioctl(sd, cmd, awb_cfg); |
---|
| 1019 | + kfree(awb_cfg); |
---|
| 1020 | + break; |
---|
| 1021 | + case RKMODULE_LSC_CFG: |
---|
| 1022 | + lsc_cfg = kzalloc(sizeof(*lsc_cfg), GFP_KERNEL); |
---|
| 1023 | + if (!lsc_cfg) { |
---|
| 1024 | + ret = -ENOMEM; |
---|
| 1025 | + return ret; |
---|
| 1026 | + } |
---|
| 1027 | + |
---|
| 1028 | + if (copy_from_user(lsc_cfg, up, sizeof(*lsc_cfg))) { |
---|
| 1029 | + kfree(lsc_cfg); |
---|
| 1030 | + return -EFAULT; |
---|
| 1031 | + } |
---|
| 1032 | + |
---|
| 1033 | + ret = gc2053_ioctl(sd, cmd, lsc_cfg); |
---|
| 1034 | + kfree(lsc_cfg); |
---|
1113 | 1035 | break; |
---|
1114 | 1036 | case RKMODULE_GET_HDR_CFG: |
---|
1115 | 1037 | hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); |
---|
.. | .. |
---|
1133 | 1055 | return ret; |
---|
1134 | 1056 | } |
---|
1135 | 1057 | |
---|
1136 | | - if (copy_from_user(hdr, up, sizeof(*hdr))) |
---|
| 1058 | + if (copy_from_user(hdr, up, sizeof(*hdr))) { |
---|
| 1059 | + kfree(hdr); |
---|
1137 | 1060 | return -EFAULT; |
---|
| 1061 | + } |
---|
1138 | 1062 | |
---|
1139 | 1063 | ret = gc2053_ioctl(sd, cmd, hdr); |
---|
1140 | 1064 | kfree(hdr); |
---|
.. | .. |
---|
1145 | 1069 | |
---|
1146 | 1070 | ret = gc2053_ioctl(sd, cmd, &stream); |
---|
1147 | 1071 | break; |
---|
| 1072 | + case RKMODULE_GET_SYNC_MODE: |
---|
| 1073 | + ret = gc2053_ioctl(sd, cmd, &sync_mode); |
---|
| 1074 | + if (!ret) { |
---|
| 1075 | + ret = copy_to_user(up, &sync_mode, sizeof(u32)); |
---|
| 1076 | + if (ret) |
---|
| 1077 | + ret = -EFAULT; |
---|
| 1078 | + } |
---|
| 1079 | + break; |
---|
| 1080 | + case RKMODULE_SET_SYNC_MODE: |
---|
| 1081 | + ret = copy_from_user(&sync_mode, up, sizeof(u32)); |
---|
| 1082 | + if (!ret) |
---|
| 1083 | + ret = gc2053_ioctl(sd, cmd, &sync_mode); |
---|
| 1084 | + else |
---|
| 1085 | + ret = -EFAULT; |
---|
| 1086 | + break; |
---|
1148 | 1087 | default: |
---|
1149 | | - ret = -ENOIOCTLCMD; |
---|
| 1088 | + ret = -ENOTTY; |
---|
1150 | 1089 | break; |
---|
1151 | 1090 | } |
---|
1152 | 1091 | return ret; |
---|
.. | .. |
---|
1195 | 1134 | struct gc2053 *gc2053 = to_gc2053(sd); |
---|
1196 | 1135 | const struct gc2053_mode *mode = gc2053->cur_mode; |
---|
1197 | 1136 | |
---|
1198 | | - mutex_lock(&gc2053->mutex); |
---|
1199 | 1137 | fi->interval = mode->max_fps; |
---|
1200 | | - mutex_unlock(&gc2053->mutex); |
---|
1201 | 1138 | |
---|
1202 | 1139 | return 0; |
---|
1203 | 1140 | } |
---|
1204 | 1141 | |
---|
1205 | | -static int gc2053_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 1142 | +static int gc2053_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
1206 | 1143 | struct v4l2_mbus_config *config) |
---|
1207 | 1144 | { |
---|
1208 | | -#if USE_DVP_INTERFACE |
---|
1209 | | - config->type = V4L2_MBUS_PARALLEL; |
---|
1210 | | - config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH | |
---|
1211 | | - V4L2_MBUS_VSYNC_ACTIVE_LOW | |
---|
1212 | | - V4L2_MBUS_PCLK_SAMPLE_RISING; |
---|
1213 | | -#else |
---|
1214 | 1145 | struct gc2053 *gc2053 = to_gc2053(sd); |
---|
1215 | 1146 | const struct gc2053_mode *mode = gc2053->cur_mode; |
---|
1216 | 1147 | u32 val = 0; |
---|
.. | .. |
---|
1220 | 1151 | V4L2_MBUS_CSI2_CHANNEL_0 | |
---|
1221 | 1152 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
1222 | 1153 | |
---|
1223 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1154 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
1224 | 1155 | config->flags = val; |
---|
1225 | | -#endif |
---|
1226 | 1156 | return 0; |
---|
1227 | 1157 | } |
---|
1228 | 1158 | static int gc2053_enum_mbus_code(struct v4l2_subdev *sd, |
---|
.. | .. |
---|
1409 | 1339 | static const struct v4l2_subdev_video_ops gc2053_video_ops = { |
---|
1410 | 1340 | .s_stream = gc2053_s_stream, |
---|
1411 | 1341 | .g_frame_interval = gc2053_g_frame_interval, |
---|
1412 | | - .g_mbus_config = gc2053_g_mbus_config, |
---|
1413 | 1342 | }; |
---|
1414 | 1343 | |
---|
1415 | 1344 | static const struct v4l2_subdev_pad_ops gc2053_pad_ops = { |
---|
.. | .. |
---|
1418 | 1347 | .enum_frame_interval = gc2053_enum_frame_interval, |
---|
1419 | 1348 | .get_fmt = gc2053_get_fmt, |
---|
1420 | 1349 | .set_fmt = gc2053_set_fmt, |
---|
| 1350 | + .get_mbus_config = gc2053_g_mbus_config, |
---|
1421 | 1351 | }; |
---|
1422 | 1352 | |
---|
1423 | 1353 | static const struct v4l2_subdev_ops gc2053_subdev_ops = { |
---|
.. | .. |
---|
1426 | 1356 | .pad = &gc2053_pad_ops, |
---|
1427 | 1357 | }; |
---|
1428 | 1358 | |
---|
1429 | | -static int gc2053_runtime_resume(struct device *dev) |
---|
| 1359 | +static int __maybe_unused gc2053_runtime_resume(struct device *dev) |
---|
1430 | 1360 | { |
---|
1431 | 1361 | struct i2c_client *client = to_i2c_client(dev); |
---|
1432 | 1362 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
1436 | 1366 | return 0; |
---|
1437 | 1367 | } |
---|
1438 | 1368 | |
---|
1439 | | -static int gc2053_runtime_suspend(struct device *dev) |
---|
| 1369 | +static int __maybe_unused gc2053_runtime_suspend(struct device *dev) |
---|
1440 | 1370 | { |
---|
1441 | 1371 | struct i2c_client *client = to_i2c_client(dev); |
---|
1442 | 1372 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
1460 | 1390 | struct v4l2_subdev *sd; |
---|
1461 | 1391 | char facing[2]; |
---|
1462 | 1392 | int ret; |
---|
| 1393 | + const char *sync_mode_name = NULL; |
---|
1463 | 1394 | |
---|
1464 | 1395 | dev_info(dev, "driver version: %02x.%02x.%02x", |
---|
1465 | 1396 | DRIVER_VERSION >> 16, |
---|
.. | .. |
---|
1483 | 1414 | dev_err(dev, |
---|
1484 | 1415 | "could not get module information!\n"); |
---|
1485 | 1416 | return -EINVAL; |
---|
| 1417 | + } |
---|
| 1418 | + |
---|
| 1419 | + ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE, |
---|
| 1420 | + &sync_mode_name); |
---|
| 1421 | + if (ret) { |
---|
| 1422 | + gc2053->sync_mode = NO_SYNC_MODE; |
---|
| 1423 | + dev_err(dev, "could not get sync mode!\n"); |
---|
| 1424 | + } else { |
---|
| 1425 | + if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0) |
---|
| 1426 | + gc2053->sync_mode = EXTERNAL_MASTER_MODE; |
---|
| 1427 | + else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0) |
---|
| 1428 | + gc2053->sync_mode = INTERNAL_MASTER_MODE; |
---|
| 1429 | + else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0) |
---|
| 1430 | + gc2053->sync_mode = SLAVE_MODE; |
---|
1486 | 1431 | } |
---|
1487 | 1432 | |
---|
1488 | 1433 | gc2053->xvclk = devm_clk_get(&client->dev, "xvclk"); |
---|
.. | .. |
---|
1509 | 1454 | return ret; |
---|
1510 | 1455 | } |
---|
1511 | 1456 | |
---|
1512 | | -#if USE_DVP_INTERFACE |
---|
1513 | | - gc2053->cur_mode = &supported_modes[0]; |
---|
1514 | | - gc2053->cfg_num = 1; |
---|
1515 | | - gc2053->cur_vts = gc2053->cur_mode->vts_def; |
---|
1516 | | - |
---|
1517 | | - gc2053->pixel_rate = gc2053->cur_mode->width * |
---|
1518 | | - gc2053->cur_mode->height * 8 * 30 / 8; |
---|
1519 | | - |
---|
1520 | | -#else |
---|
1521 | | - ret = gc2053_parse_of_mipi(gc2053); |
---|
| 1457 | + ret = gc2053_parse_of(gc2053); |
---|
1522 | 1458 | if (ret != 0) |
---|
1523 | 1459 | return -EINVAL; |
---|
1524 | | - |
---|
1525 | | -#endif |
---|
1526 | 1460 | |
---|
1527 | 1461 | gc2053->pinctrl = devm_pinctrl_get(dev); |
---|
1528 | 1462 | if (!IS_ERR(gc2053->pinctrl)) { |
---|