| .. | .. |
|---|
| 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]); |
|---|
| .. | .. |
|---|
| 731 | 574 | break; |
|---|
| 732 | 575 | case V4L2_CID_VBLANK: |
|---|
| 733 | 576 | vts = ctrl->val + gc2053->cur_mode->height; |
|---|
| 577 | + /* Note: In master-slave mode, Galaxycore request slave sensor frame rate bigger than master. */ |
|---|
| 578 | + if (gc2053->sync_mode == INTERNAL_MASTER_MODE) |
|---|
| 579 | + vts += 10; |
|---|
| 734 | 580 | ret = gc2053_write_reg(gc2053->client, GC2053_REG_VTS_H, (vts >> 8) & 0x3f); |
|---|
| 735 | 581 | ret |= gc2053_write_reg(gc2053->client, GC2053_REG_VTS_L, vts & 0xff); |
|---|
| 582 | + /* TBD: master and slave not sync to streaming, but except sleep 20ms below */ |
|---|
| 583 | + usleep_range(20000, 50000); |
|---|
| 736 | 584 | break; |
|---|
| 737 | 585 | case V4L2_CID_HFLIP: |
|---|
| 738 | 586 | if (ctrl->val) |
|---|
| .. | .. |
|---|
| 772 | 620 | gc2053->supplies); |
|---|
| 773 | 621 | } |
|---|
| 774 | 622 | |
|---|
| 775 | | -static int __maybe_unused gc2053_parse_of_mipi(struct gc2053 *gc2053) |
|---|
| 623 | +static int gc2053_parse_of(struct gc2053 *gc2053) |
|---|
| 776 | 624 | { |
|---|
| 777 | 625 | struct device *dev = &gc2053->client->dev; |
|---|
| 778 | 626 | struct device_node *endpoint; |
|---|
| .. | .. |
|---|
| 795 | 643 | if (2 == gc2053->lane_num) { |
|---|
| 796 | 644 | gc2053->cur_mode = &supported_modes[0]; |
|---|
| 797 | 645 | gc2053->cfg_num = ARRAY_SIZE(supported_modes); |
|---|
| 798 | | - gc2053->cur_vts = gc2053->cur_mode->vts_def; |
|---|
| 799 | 646 | |
|---|
| 800 | 647 | /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ |
|---|
| 801 | 648 | gc2053->pixel_rate = MIPI_FREQ_297M * 2U * (gc2053->lane_num) / 10U; |
|---|
| .. | .. |
|---|
| 811 | 658 | { |
|---|
| 812 | 659 | const struct gc2053_mode *mode; |
|---|
| 813 | 660 | struct v4l2_ctrl_handler *handler; |
|---|
| 814 | | - struct v4l2_ctrl __maybe_unused *ctrl; |
|---|
| 661 | + struct v4l2_ctrl *ctrl; |
|---|
| 815 | 662 | s64 exposure_max, vblank_def; |
|---|
| 816 | 663 | u32 h_blank; |
|---|
| 817 | 664 | int ret; |
|---|
| .. | .. |
|---|
| 823 | 670 | return ret; |
|---|
| 824 | 671 | handler->lock = &gc2053->mutex; |
|---|
| 825 | 672 | |
|---|
| 826 | | -#if !USE_DVP_INTERFACE |
|---|
| 827 | 673 | ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, |
|---|
| 828 | 674 | 0, 0, link_freq_menu_items); |
|---|
| 829 | 675 | if (ctrl) |
|---|
| 830 | 676 | ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
|---|
| 831 | | -#endif |
|---|
| 832 | 677 | |
|---|
| 833 | 678 | v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, |
|---|
| 834 | 679 | 0, gc2053->pixel_rate, 1, gc2053->pixel_rate); |
|---|
| .. | .. |
|---|
| 1013 | 858 | |
|---|
| 1014 | 859 | static int __gc2053_start_stream(struct gc2053 *gc2053) |
|---|
| 1015 | 860 | { |
|---|
| 861 | + struct i2c_client *client = gc2053->client; |
|---|
| 1016 | 862 | int ret; |
|---|
| 1017 | 863 | |
|---|
| 1018 | | - ret = gc2053_write_array(gc2053->client, gc2053->cur_mode->reg_list); |
|---|
| 864 | + ret = gc2053_write_array(client, gc2053->cur_mode->reg_list); |
|---|
| 1019 | 865 | if (ret) |
|---|
| 1020 | 866 | return ret; |
|---|
| 1021 | 867 | |
|---|
| 1022 | 868 | /* In case these controls are set before streaming */ |
|---|
| 1023 | 869 | mutex_unlock(&gc2053->mutex); |
|---|
| 1024 | | - v4l2_ctrl_handler_setup(&gc2053->ctrl_handler); |
|---|
| 870 | + ret = v4l2_ctrl_handler_setup(&gc2053->ctrl_handler); |
|---|
| 1025 | 871 | mutex_lock(&gc2053->mutex); |
|---|
| 1026 | 872 | |
|---|
| 1027 | | - ret = gc2053_set_flip(gc2053, gc2053->flip); |
|---|
| 873 | + ret |= gc2053_set_flip(gc2053, gc2053->flip); |
|---|
| 1028 | 874 | if (ret) |
|---|
| 1029 | 875 | return ret; |
|---|
| 1030 | | - return gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
|---|
| 876 | + if (gc2053->sync_mode == INTERNAL_MASTER_MODE) { |
|---|
| 877 | + ret = gc2053_write_array(client, gc2053_master_mode_regs); |
|---|
| 878 | + if (ret) |
|---|
| 879 | + dev_err(&client->dev, |
|---|
| 880 | + "write internal master mode reg failed %d\n", ret); |
|---|
| 881 | + } else if (gc2053->sync_mode == EXTERNAL_MASTER_MODE) { |
|---|
| 882 | + ret = gc2053_write_array(client, gc2053_slave_mode_regs); |
|---|
| 883 | + if (ret) |
|---|
| 884 | + dev_err(&client->dev, |
|---|
| 885 | + "write external master mode reg failed %d\n", ret); |
|---|
| 886 | + } else if (gc2053->sync_mode == SLAVE_MODE) { |
|---|
| 887 | + ret = gc2053_write_array(gc2053->client, gc2053_slave_mode_regs); |
|---|
| 888 | + if (ret) |
|---|
| 889 | + dev_err(&client->dev, "write slave mode reg failed %d\n", ret); |
|---|
| 890 | + } |
|---|
| 891 | + |
|---|
| 892 | + ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
|---|
| 1031 | 893 | GC2053_MODE_STREAMING); |
|---|
| 894 | + |
|---|
| 895 | + return ret; |
|---|
| 1032 | 896 | } |
|---|
| 1033 | 897 | |
|---|
| 1034 | 898 | static int __gc2053_stop_stream(struct gc2053 *gc2053) |
|---|
| .. | .. |
|---|
| 1041 | 905 | struct rkmodule_inf *inf) |
|---|
| 1042 | 906 | { |
|---|
| 1043 | 907 | memset(inf, 0, sizeof(*inf)); |
|---|
| 1044 | | - strscpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor)); |
|---|
| 1045 | | - strscpy(inf->base.module, gc2053->module_name, |
|---|
| 908 | + strlcpy(inf->base.sensor, GC2053_NAME, sizeof(inf->base.sensor)); |
|---|
| 909 | + strlcpy(inf->base.module, gc2053->module_name, |
|---|
| 1046 | 910 | sizeof(inf->base.module)); |
|---|
| 1047 | | - strscpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens)); |
|---|
| 911 | + strlcpy(inf->base.lens, gc2053->len_name, sizeof(inf->base.lens)); |
|---|
| 912 | +} |
|---|
| 913 | + |
|---|
| 914 | +static void gc2053_set_awb_cfg(struct gc2053 *gc2053, |
|---|
| 915 | + struct rkmodule_awb_cfg *cfg) |
|---|
| 916 | +{ |
|---|
| 917 | + mutex_lock(&gc2053->mutex); |
|---|
| 918 | + memcpy(&gc2053->awb_cfg, cfg, sizeof(*cfg)); |
|---|
| 919 | + mutex_unlock(&gc2053->mutex); |
|---|
| 920 | +} |
|---|
| 921 | + |
|---|
| 922 | +static void gc2053_set_lsc_cfg(struct gc2053 *gc2053, |
|---|
| 923 | + struct rkmodule_lsc_cfg *cfg) |
|---|
| 924 | +{ |
|---|
| 925 | + mutex_lock(&gc2053->mutex); |
|---|
| 926 | + memcpy(&gc2053->lsc_cfg, cfg, sizeof(*cfg)); |
|---|
| 927 | + mutex_unlock(&gc2053->mutex); |
|---|
| 1048 | 928 | } |
|---|
| 1049 | 929 | |
|---|
| 1050 | 930 | static long gc2053_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
|---|
| .. | .. |
|---|
| 1053 | 933 | long ret = 0; |
|---|
| 1054 | 934 | struct rkmodule_hdr_cfg *hdr_cfg; |
|---|
| 1055 | 935 | u32 stream = 0; |
|---|
| 936 | + u32 *sync_mode = NULL; |
|---|
| 1056 | 937 | |
|---|
| 1057 | 938 | switch (cmd) { |
|---|
| 1058 | 939 | case RKMODULE_GET_HDR_CFG: |
|---|
| .. | .. |
|---|
| 1060 | 941 | hdr_cfg->esp.mode = HDR_NORMAL_VC; |
|---|
| 1061 | 942 | hdr_cfg->hdr_mode = gc2053->cur_mode->hdr_mode; |
|---|
| 1062 | 943 | 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 | 944 | case RKMODULE_GET_MODULE_INFO: |
|---|
| 1068 | 945 | gc2053_get_module_inf(gc2053, (struct rkmodule_inf *)arg); |
|---|
| 946 | + break; |
|---|
| 947 | + case RKMODULE_AWB_CFG: |
|---|
| 948 | + gc2053_set_awb_cfg(gc2053, (struct rkmodule_awb_cfg *)arg); |
|---|
| 949 | + break; |
|---|
| 950 | + case RKMODULE_LSC_CFG: |
|---|
| 951 | + gc2053_set_lsc_cfg(gc2053, (struct rkmodule_lsc_cfg *)arg); |
|---|
| 1069 | 952 | break; |
|---|
| 1070 | 953 | case RKMODULE_SET_QUICK_STREAM: |
|---|
| 1071 | 954 | |
|---|
| .. | .. |
|---|
| 1077 | 960 | else |
|---|
| 1078 | 961 | ret = gc2053_write_reg(gc2053->client, GC2053_REG_CTRL_MODE, |
|---|
| 1079 | 962 | GC2053_MODE_SW_STANDBY); |
|---|
| 963 | + break; |
|---|
| 964 | + case RKMODULE_GET_SYNC_MODE: |
|---|
| 965 | + sync_mode = (u32 *)arg; |
|---|
| 966 | + *sync_mode = gc2053->sync_mode; |
|---|
| 967 | + break; |
|---|
| 968 | + case RKMODULE_SET_SYNC_MODE: |
|---|
| 969 | + sync_mode = (u32 *)arg; |
|---|
| 970 | + gc2053->sync_mode = *sync_mode; |
|---|
| 1080 | 971 | break; |
|---|
| 1081 | 972 | default: |
|---|
| 1082 | 973 | ret = -ENOTTY; |
|---|
| .. | .. |
|---|
| 1091 | 982 | { |
|---|
| 1092 | 983 | void __user *up = compat_ptr(arg); |
|---|
| 1093 | 984 | struct rkmodule_inf *inf; |
|---|
| 985 | + struct rkmodule_awb_cfg *awb_cfg; |
|---|
| 986 | + struct rkmodule_lsc_cfg *lsc_cfg; |
|---|
| 1094 | 987 | struct rkmodule_hdr_cfg *hdr; |
|---|
| 1095 | 988 | long ret = 0; |
|---|
| 1096 | 989 | u32 stream = 0; |
|---|
| 990 | + u32 sync_mode; |
|---|
| 1097 | 991 | |
|---|
| 1098 | 992 | switch (cmd) { |
|---|
| 1099 | 993 | case RKMODULE_GET_MODULE_INFO: |
|---|
| .. | .. |
|---|
| 1110 | 1004 | ret = -EFAULT; |
|---|
| 1111 | 1005 | } |
|---|
| 1112 | 1006 | kfree(inf); |
|---|
| 1007 | + break; |
|---|
| 1008 | + case RKMODULE_AWB_CFG: |
|---|
| 1009 | + awb_cfg = kzalloc(sizeof(*awb_cfg), GFP_KERNEL); |
|---|
| 1010 | + if (!awb_cfg) { |
|---|
| 1011 | + ret = -ENOMEM; |
|---|
| 1012 | + return ret; |
|---|
| 1013 | + } |
|---|
| 1014 | + |
|---|
| 1015 | + if (copy_from_user(awb_cfg, up, sizeof(*awb_cfg))) { |
|---|
| 1016 | + kfree(awb_cfg); |
|---|
| 1017 | + return -EFAULT; |
|---|
| 1018 | + } |
|---|
| 1019 | + |
|---|
| 1020 | + ret = gc2053_ioctl(sd, cmd, awb_cfg); |
|---|
| 1021 | + kfree(awb_cfg); |
|---|
| 1022 | + break; |
|---|
| 1023 | + case RKMODULE_LSC_CFG: |
|---|
| 1024 | + lsc_cfg = kzalloc(sizeof(*lsc_cfg), GFP_KERNEL); |
|---|
| 1025 | + if (!lsc_cfg) { |
|---|
| 1026 | + ret = -ENOMEM; |
|---|
| 1027 | + return ret; |
|---|
| 1028 | + } |
|---|
| 1029 | + |
|---|
| 1030 | + if (copy_from_user(lsc_cfg, up, sizeof(*lsc_cfg))) { |
|---|
| 1031 | + kfree(lsc_cfg); |
|---|
| 1032 | + return -EFAULT; |
|---|
| 1033 | + } |
|---|
| 1034 | + |
|---|
| 1035 | + ret = gc2053_ioctl(sd, cmd, lsc_cfg); |
|---|
| 1036 | + kfree(lsc_cfg); |
|---|
| 1113 | 1037 | break; |
|---|
| 1114 | 1038 | case RKMODULE_GET_HDR_CFG: |
|---|
| 1115 | 1039 | hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1133 | 1057 | return ret; |
|---|
| 1134 | 1058 | } |
|---|
| 1135 | 1059 | |
|---|
| 1136 | | - if (copy_from_user(hdr, up, sizeof(*hdr))) |
|---|
| 1060 | + if (copy_from_user(hdr, up, sizeof(*hdr))) { |
|---|
| 1061 | + kfree(hdr); |
|---|
| 1137 | 1062 | return -EFAULT; |
|---|
| 1063 | + } |
|---|
| 1138 | 1064 | |
|---|
| 1139 | 1065 | ret = gc2053_ioctl(sd, cmd, hdr); |
|---|
| 1140 | 1066 | kfree(hdr); |
|---|
| .. | .. |
|---|
| 1145 | 1071 | |
|---|
| 1146 | 1072 | ret = gc2053_ioctl(sd, cmd, &stream); |
|---|
| 1147 | 1073 | break; |
|---|
| 1074 | + case RKMODULE_GET_SYNC_MODE: |
|---|
| 1075 | + ret = gc2053_ioctl(sd, cmd, &sync_mode); |
|---|
| 1076 | + if (!ret) { |
|---|
| 1077 | + ret = copy_to_user(up, &sync_mode, sizeof(u32)); |
|---|
| 1078 | + if (ret) |
|---|
| 1079 | + ret = -EFAULT; |
|---|
| 1080 | + } |
|---|
| 1081 | + break; |
|---|
| 1082 | + case RKMODULE_SET_SYNC_MODE: |
|---|
| 1083 | + ret = copy_from_user(&sync_mode, up, sizeof(u32)); |
|---|
| 1084 | + if (!ret) |
|---|
| 1085 | + ret = gc2053_ioctl(sd, cmd, &sync_mode); |
|---|
| 1086 | + else |
|---|
| 1087 | + ret = -EFAULT; |
|---|
| 1088 | + break; |
|---|
| 1148 | 1089 | default: |
|---|
| 1149 | | - ret = -ENOIOCTLCMD; |
|---|
| 1090 | + ret = -ENOTTY; |
|---|
| 1150 | 1091 | break; |
|---|
| 1151 | 1092 | } |
|---|
| 1152 | 1093 | return ret; |
|---|
| .. | .. |
|---|
| 1195 | 1136 | struct gc2053 *gc2053 = to_gc2053(sd); |
|---|
| 1196 | 1137 | const struct gc2053_mode *mode = gc2053->cur_mode; |
|---|
| 1197 | 1138 | |
|---|
| 1198 | | - mutex_lock(&gc2053->mutex); |
|---|
| 1199 | 1139 | fi->interval = mode->max_fps; |
|---|
| 1200 | | - mutex_unlock(&gc2053->mutex); |
|---|
| 1201 | 1140 | |
|---|
| 1202 | 1141 | return 0; |
|---|
| 1203 | 1142 | } |
|---|
| 1204 | 1143 | |
|---|
| 1205 | | -static int gc2053_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 1144 | +static int gc2053_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
|---|
| 1206 | 1145 | struct v4l2_mbus_config *config) |
|---|
| 1207 | 1146 | { |
|---|
| 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 | 1147 | struct gc2053 *gc2053 = to_gc2053(sd); |
|---|
| 1215 | 1148 | const struct gc2053_mode *mode = gc2053->cur_mode; |
|---|
| 1216 | 1149 | u32 val = 0; |
|---|
| .. | .. |
|---|
| 1220 | 1153 | V4L2_MBUS_CSI2_CHANNEL_0 | |
|---|
| 1221 | 1154 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| 1222 | 1155 | |
|---|
| 1223 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 1156 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 1224 | 1157 | config->flags = val; |
|---|
| 1225 | | -#endif |
|---|
| 1226 | 1158 | return 0; |
|---|
| 1227 | 1159 | } |
|---|
| 1228 | 1160 | static int gc2053_enum_mbus_code(struct v4l2_subdev *sd, |
|---|
| .. | .. |
|---|
| 1409 | 1341 | static const struct v4l2_subdev_video_ops gc2053_video_ops = { |
|---|
| 1410 | 1342 | .s_stream = gc2053_s_stream, |
|---|
| 1411 | 1343 | .g_frame_interval = gc2053_g_frame_interval, |
|---|
| 1412 | | - .g_mbus_config = gc2053_g_mbus_config, |
|---|
| 1413 | 1344 | }; |
|---|
| 1414 | 1345 | |
|---|
| 1415 | 1346 | static const struct v4l2_subdev_pad_ops gc2053_pad_ops = { |
|---|
| .. | .. |
|---|
| 1418 | 1349 | .enum_frame_interval = gc2053_enum_frame_interval, |
|---|
| 1419 | 1350 | .get_fmt = gc2053_get_fmt, |
|---|
| 1420 | 1351 | .set_fmt = gc2053_set_fmt, |
|---|
| 1352 | + .get_mbus_config = gc2053_g_mbus_config, |
|---|
| 1421 | 1353 | }; |
|---|
| 1422 | 1354 | |
|---|
| 1423 | 1355 | static const struct v4l2_subdev_ops gc2053_subdev_ops = { |
|---|
| .. | .. |
|---|
| 1426 | 1358 | .pad = &gc2053_pad_ops, |
|---|
| 1427 | 1359 | }; |
|---|
| 1428 | 1360 | |
|---|
| 1429 | | -static int gc2053_runtime_resume(struct device *dev) |
|---|
| 1361 | +static int __maybe_unused gc2053_runtime_resume(struct device *dev) |
|---|
| 1430 | 1362 | { |
|---|
| 1431 | 1363 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 1432 | 1364 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
|---|
| .. | .. |
|---|
| 1436 | 1368 | return 0; |
|---|
| 1437 | 1369 | } |
|---|
| 1438 | 1370 | |
|---|
| 1439 | | -static int gc2053_runtime_suspend(struct device *dev) |
|---|
| 1371 | +static int __maybe_unused gc2053_runtime_suspend(struct device *dev) |
|---|
| 1440 | 1372 | { |
|---|
| 1441 | 1373 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 1442 | 1374 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
|---|
| .. | .. |
|---|
| 1460 | 1392 | struct v4l2_subdev *sd; |
|---|
| 1461 | 1393 | char facing[2]; |
|---|
| 1462 | 1394 | int ret; |
|---|
| 1395 | + const char *sync_mode_name = NULL; |
|---|
| 1463 | 1396 | |
|---|
| 1464 | 1397 | dev_info(dev, "driver version: %02x.%02x.%02x", |
|---|
| 1465 | 1398 | DRIVER_VERSION >> 16, |
|---|
| .. | .. |
|---|
| 1483 | 1416 | dev_err(dev, |
|---|
| 1484 | 1417 | "could not get module information!\n"); |
|---|
| 1485 | 1418 | return -EINVAL; |
|---|
| 1419 | + } |
|---|
| 1420 | + |
|---|
| 1421 | + ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE, |
|---|
| 1422 | + &sync_mode_name); |
|---|
| 1423 | + if (ret) { |
|---|
| 1424 | + gc2053->sync_mode = NO_SYNC_MODE; |
|---|
| 1425 | + dev_err(dev, "could not get sync mode!\n"); |
|---|
| 1426 | + } else { |
|---|
| 1427 | + if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0) |
|---|
| 1428 | + gc2053->sync_mode = EXTERNAL_MASTER_MODE; |
|---|
| 1429 | + else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0) |
|---|
| 1430 | + gc2053->sync_mode = INTERNAL_MASTER_MODE; |
|---|
| 1431 | + else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0) |
|---|
| 1432 | + gc2053->sync_mode = SLAVE_MODE; |
|---|
| 1486 | 1433 | } |
|---|
| 1487 | 1434 | |
|---|
| 1488 | 1435 | gc2053->xvclk = devm_clk_get(&client->dev, "xvclk"); |
|---|
| .. | .. |
|---|
| 1509 | 1456 | return ret; |
|---|
| 1510 | 1457 | } |
|---|
| 1511 | 1458 | |
|---|
| 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); |
|---|
| 1459 | + ret = gc2053_parse_of(gc2053); |
|---|
| 1522 | 1460 | if (ret != 0) |
|---|
| 1523 | 1461 | return -EINVAL; |
|---|
| 1524 | | - |
|---|
| 1525 | | -#endif |
|---|
| 1526 | 1462 | |
|---|
| 1527 | 1463 | gc2053->pinctrl = devm_pinctrl_get(dev); |
|---|
| 1528 | 1464 | if (!IS_ERR(gc2053->pinctrl)) { |
|---|