.. | .. |
---|
8 | 8 | * V0.0X01.0X03 add enum_frame_interval function. |
---|
9 | 9 | * V0.0X01.0X04 add quick stream on/off |
---|
10 | 10 | * V0.0X01.0X05 add function g_mbus_config |
---|
| 11 | + * V0.0X01.0X06 add function reset gpio control |
---|
| 12 | + * V0.0X01.0X06 add 2-lane mode as default |
---|
11 | 13 | */ |
---|
12 | 14 | |
---|
13 | 15 | #include <linux/clk.h> |
---|
.. | .. |
---|
28 | 30 | #include <media/v4l2-subdev.h> |
---|
29 | 31 | #include <linux/pinctrl/consumer.h> |
---|
30 | 32 | |
---|
31 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05) |
---|
| 33 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07) |
---|
32 | 34 | #ifndef V4L2_CID_DIGITAL_GAIN |
---|
33 | 35 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
---|
34 | 36 | #endif |
---|
35 | 37 | |
---|
36 | | -#define SC132GS_PIXEL_RATE (72 * 1000 * 1000) |
---|
| 38 | +#define MIPI_FREQ_180M 180000000 |
---|
| 39 | +#define MIPI_FREQ_360M 360000000 |
---|
| 40 | + |
---|
| 41 | +#define PIXEL_RATE_WITH_180M (MIPI_FREQ_180M * 2 / 10 * 2) |
---|
| 42 | +#define PIXEL_RATE_WITH_360M (MIPI_FREQ_360M * 2 / 8 * 1) |
---|
| 43 | + |
---|
37 | 44 | #define SC132GS_XVCLK_FREQ 24000000 |
---|
38 | 45 | |
---|
39 | 46 | #define CHIP_ID 0x0132 |
---|
.. | .. |
---|
69 | 76 | |
---|
70 | 77 | #define SC132GS_NAME "sc132gs" |
---|
71 | 78 | |
---|
72 | | -#define PIX_FORMAT MEDIA_BUS_FMT_Y8_1X8 |
---|
73 | | - |
---|
74 | 79 | #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" |
---|
75 | 80 | #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" |
---|
76 | | - |
---|
77 | | -#define SC132GS_LANES 1 |
---|
78 | | -#define SC132GS_BITS_PER_SAMPLE 8 |
---|
79 | 81 | |
---|
80 | 82 | static const char * const sc132gs_supply_names[] = { |
---|
81 | 83 | "avdd", /* Analog power */ |
---|
.. | .. |
---|
84 | 86 | }; |
---|
85 | 87 | |
---|
86 | 88 | #define SC132GS_NUM_SUPPLIES ARRAY_SIZE(sc132gs_supply_names) |
---|
| 89 | + |
---|
| 90 | +enum { |
---|
| 91 | + LINK_FREQ_180M_INDEX, |
---|
| 92 | + LINK_FREQ_360M_INDEX, |
---|
| 93 | +}; |
---|
87 | 94 | |
---|
88 | 95 | struct regval { |
---|
89 | 96 | u16 addr; |
---|
.. | .. |
---|
97 | 104 | u32 hts_def; |
---|
98 | 105 | u32 vts_def; |
---|
99 | 106 | u32 exp_def; |
---|
| 107 | + u32 link_freq_index; |
---|
| 108 | + u64 pixel_rate; |
---|
100 | 109 | const struct regval *reg_list; |
---|
| 110 | + u32 lanes; |
---|
| 111 | + u32 bus_fmt; |
---|
101 | 112 | }; |
---|
102 | 113 | |
---|
103 | 114 | struct sc132gs { |
---|
104 | 115 | struct i2c_client *client; |
---|
105 | 116 | struct clk *xvclk; |
---|
| 117 | + struct gpio_desc *reset_gpio; |
---|
106 | 118 | struct gpio_desc *pwdn_gpio; |
---|
107 | 119 | struct regulator_bulk_data supplies[SC132GS_NUM_SUPPLIES]; |
---|
108 | 120 | struct pinctrl *pinctrl; |
---|
.. | .. |
---|
117 | 129 | struct v4l2_ctrl *hblank; |
---|
118 | 130 | struct v4l2_ctrl *vblank; |
---|
119 | 131 | struct v4l2_ctrl *test_pattern; |
---|
| 132 | + struct v4l2_ctrl *pixel_rate; |
---|
| 133 | + struct v4l2_ctrl *link_freq; |
---|
120 | 134 | struct mutex mutex; |
---|
| 135 | + struct v4l2_fract cur_fps; |
---|
| 136 | + u32 cur_vts; |
---|
121 | 137 | bool streaming; |
---|
122 | 138 | bool power_on; |
---|
123 | 139 | const struct sc132gs_mode *cur_mode; |
---|
.. | .. |
---|
131 | 147 | |
---|
132 | 148 | /* |
---|
133 | 149 | * Xclk 24Mhz |
---|
134 | | - * Pclk 72Mhz |
---|
| 150 | + * Pclk 90Mhz |
---|
135 | 151 | * linelength 1696(0x06a0) |
---|
136 | 152 | * framelength 2122(0x084a) |
---|
137 | 153 | * grabwindow_width 1080 |
---|
.. | .. |
---|
140 | 156 | * max_framerate 30fps |
---|
141 | 157 | * mipi_datarate per lane 720Mbps |
---|
142 | 158 | */ |
---|
143 | | -static const struct regval sc132gs_global_regs[] = { |
---|
| 159 | +static const struct regval sc132gs_1lane_8bit_regs[] = { |
---|
144 | 160 | {0x0103, 0x01}, |
---|
145 | 161 | {0x0100, 0x00}, |
---|
146 | 162 | |
---|
.. | .. |
---|
247 | 263 | {REG_NULL, 0x00}, |
---|
248 | 264 | }; |
---|
249 | 265 | |
---|
| 266 | +/* |
---|
| 267 | + * Xclk 24Mhz |
---|
| 268 | + * Pclk 72Mhz |
---|
| 269 | + * linelength 1696(0x06a0) |
---|
| 270 | + * framelength 2122(0x084a) |
---|
| 271 | + * grabwindow_width 1080 |
---|
| 272 | + * grabwindow_height 1280 |
---|
| 273 | + * mipi 2 lane |
---|
| 274 | + * max_framerate 30fps |
---|
| 275 | + * mipi_datarate per lane 360Mbps |
---|
| 276 | + */ |
---|
| 277 | +static const struct regval sc132gs_2lane_10bit_regs[] = { |
---|
| 278 | + {0x0103, 0x01}, |
---|
| 279 | + {0x0100, 0x00}, |
---|
| 280 | + |
---|
| 281 | + //PLL bypass |
---|
| 282 | + {0x36e9, 0x80}, |
---|
| 283 | + {0x36f9, 0x80}, |
---|
| 284 | + |
---|
| 285 | + {0x3018, 0x32}, |
---|
| 286 | + {0x3019, 0x0c}, |
---|
| 287 | + {0x301a, 0xb4}, |
---|
| 288 | + {0x3031, 0x0a}, |
---|
| 289 | + {0x3032, 0x60}, |
---|
| 290 | + {0x3038, 0x44}, |
---|
| 291 | + {0x3207, 0x17}, |
---|
| 292 | + {0x320c, 0x05}, |
---|
| 293 | + {0x320d, 0xdc}, |
---|
| 294 | + {0x320e, 0x09}, |
---|
| 295 | + {0x320f, 0x60}, |
---|
| 296 | + {0x3250, 0xcc}, |
---|
| 297 | + {0x3251, 0x02}, |
---|
| 298 | + {0x3252, 0x09}, |
---|
| 299 | + {0x3253, 0x5b}, |
---|
| 300 | + {0x3254, 0x05}, |
---|
| 301 | + {0x3255, 0x3b}, |
---|
| 302 | + {0x3306, 0x78}, |
---|
| 303 | + {0x330a, 0x00}, |
---|
| 304 | + {0x330b, 0xc8}, |
---|
| 305 | + {0x330f, 0x24}, |
---|
| 306 | + {0x3314, 0x80}, |
---|
| 307 | + {0x3315, 0x40}, |
---|
| 308 | + {0x3317, 0xf0}, |
---|
| 309 | + {0x331f, 0x12}, |
---|
| 310 | + {0x3364, 0x00}, |
---|
| 311 | + {0x3385, 0x41}, |
---|
| 312 | + {0x3387, 0x41}, |
---|
| 313 | + {0x3389, 0x09}, |
---|
| 314 | + {0x33ab, 0x00}, |
---|
| 315 | + {0x33ac, 0x00}, |
---|
| 316 | + {0x33b1, 0x03}, |
---|
| 317 | + {0x33b2, 0x12}, |
---|
| 318 | + {0x33f8, 0x02}, |
---|
| 319 | + {0x33fa, 0x01}, |
---|
| 320 | + {0x3409, 0x08}, |
---|
| 321 | + {0x34f0, 0xc0}, |
---|
| 322 | + {0x34f1, 0x20}, |
---|
| 323 | + {0x34f2, 0x03}, |
---|
| 324 | + {0x3622, 0xf5}, |
---|
| 325 | + {0x3630, 0x5c}, |
---|
| 326 | + {0x3631, 0x80}, |
---|
| 327 | + {0x3632, 0xc8}, |
---|
| 328 | + {0x3633, 0x32}, |
---|
| 329 | + {0x3638, 0x2a}, |
---|
| 330 | + {0x3639, 0x07}, |
---|
| 331 | + {0x363b, 0x48}, |
---|
| 332 | + {0x363c, 0x83}, |
---|
| 333 | + {0x363d, 0x10}, |
---|
| 334 | + {0x36ea, 0x38}, |
---|
| 335 | + {0x36fa, 0x25}, |
---|
| 336 | + {0x36fb, 0x05}, |
---|
| 337 | + {0x36fd, 0x04}, |
---|
| 338 | + {0x3900, 0x11}, |
---|
| 339 | + {0x3901, 0x05}, |
---|
| 340 | + {0x3902, 0xc5}, |
---|
| 341 | + {0x3904, 0x04}, |
---|
| 342 | + {0x3908, 0x91}, |
---|
| 343 | + {0x391e, 0x00}, |
---|
| 344 | + {0x3e01, 0x11}, |
---|
| 345 | + {0x3e02, 0x20}, |
---|
| 346 | + {0x3e09, 0x20}, |
---|
| 347 | + {0x3e0e, 0xd2}, |
---|
| 348 | + {0x3e14, 0xb0}, |
---|
| 349 | + {0x3e1e, 0x7c}, |
---|
| 350 | + {0x3e26, 0x20}, |
---|
| 351 | + {0x4418, 0x38}, |
---|
| 352 | + {0x4503, 0x10}, |
---|
| 353 | + {0x4837, 0x21}, |
---|
| 354 | + {0x5000, 0x0e}, |
---|
| 355 | + {0x540c, 0x51}, |
---|
| 356 | + {0x550f, 0x38}, |
---|
| 357 | + {0x5780, 0x67}, |
---|
| 358 | + {0x5784, 0x10}, |
---|
| 359 | + {0x5785, 0x06}, |
---|
| 360 | + {0x5787, 0x02}, |
---|
| 361 | + {0x5788, 0x00}, |
---|
| 362 | + {0x5789, 0x00}, |
---|
| 363 | + {0x578a, 0x02}, |
---|
| 364 | + {0x578b, 0x00}, |
---|
| 365 | + {0x578c, 0x00}, |
---|
| 366 | + {0x5790, 0x00}, |
---|
| 367 | + {0x5791, 0x00}, |
---|
| 368 | + {0x5792, 0x00}, |
---|
| 369 | + {0x5793, 0x00}, |
---|
| 370 | + {0x5794, 0x00}, |
---|
| 371 | + {0x5795, 0x00}, |
---|
| 372 | + {0x5799, 0x04}, |
---|
| 373 | + |
---|
| 374 | + //flip |
---|
| 375 | + //{0x3221, (0x3 << 5)}, |
---|
| 376 | + |
---|
| 377 | + //mirror |
---|
| 378 | + {0x3221, (0x3 << 1)}, |
---|
| 379 | + |
---|
| 380 | + //flip & mirror |
---|
| 381 | + //{0x3221, ((0x3 << 1)|(0x3 << 5))}, |
---|
| 382 | + |
---|
| 383 | + //PLL set |
---|
| 384 | + {0x36e9, 0x20}, |
---|
| 385 | + {0x36f9, 0x24}, |
---|
| 386 | + |
---|
| 387 | + {REG_NULL, 0x00}, |
---|
| 388 | +}; |
---|
| 389 | + |
---|
250 | 390 | static const struct sc132gs_mode supported_modes[] = { |
---|
251 | 391 | { |
---|
252 | 392 | .width = 1080, |
---|
.. | .. |
---|
258 | 398 | .exp_def = 0x0148, |
---|
259 | 399 | .hts_def = 0x06a0, |
---|
260 | 400 | .vts_def = 0x084a, |
---|
261 | | - .reg_list = sc132gs_global_regs, |
---|
| 401 | + .link_freq_index = LINK_FREQ_180M_INDEX, |
---|
| 402 | + .pixel_rate = PIXEL_RATE_WITH_180M, |
---|
| 403 | + .reg_list = sc132gs_2lane_10bit_regs, |
---|
| 404 | + .lanes = 2, |
---|
| 405 | + .bus_fmt = MEDIA_BUS_FMT_Y10_1X10, |
---|
| 406 | + }, |
---|
| 407 | + |
---|
| 408 | + { |
---|
| 409 | + .width = 1080, |
---|
| 410 | + .height = 1280, |
---|
| 411 | + .max_fps = { |
---|
| 412 | + .numerator = 10000, |
---|
| 413 | + .denominator = 300000, |
---|
| 414 | + }, |
---|
| 415 | + .exp_def = 0x0148, |
---|
| 416 | + .hts_def = 0x06a0, |
---|
| 417 | + .vts_def = 0x084a, |
---|
| 418 | + .link_freq_index = LINK_FREQ_360M_INDEX, |
---|
| 419 | + .pixel_rate = PIXEL_RATE_WITH_360M, |
---|
| 420 | + .reg_list = sc132gs_1lane_8bit_regs, |
---|
| 421 | + .lanes = 1, |
---|
| 422 | + .bus_fmt = MEDIA_BUS_FMT_Y8_1X8, |
---|
262 | 423 | }, |
---|
263 | 424 | }; |
---|
264 | 425 | |
---|
.. | .. |
---|
270 | 431 | "Vertical Color Bar Type 4" |
---|
271 | 432 | }; |
---|
272 | 433 | |
---|
273 | | -#define SC132GS_LINK_FREQ_360MHZ (360 * 1000 * 1000) |
---|
274 | | - |
---|
275 | 434 | static const s64 link_freq_menu_items[] = { |
---|
276 | | - SC132GS_LINK_FREQ_360MHZ |
---|
| 435 | + MIPI_FREQ_180M, |
---|
| 436 | + MIPI_FREQ_360M, |
---|
277 | 437 | }; |
---|
278 | 438 | |
---|
279 | 439 | /* Write registers up to 4 at a time */ |
---|
.. | .. |
---|
374 | 534 | |
---|
375 | 535 | for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { |
---|
376 | 536 | dist = sc132gs_get_reso_dist(&supported_modes[i], framefmt); |
---|
377 | | - if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { |
---|
| 537 | + if ((cur_best_fit_dist == -1 || dist < cur_best_fit_dist) && |
---|
| 538 | + (supported_modes[i].bus_fmt == framefmt->code)) { |
---|
378 | 539 | cur_best_fit_dist = dist; |
---|
379 | 540 | cur_best_fit = i; |
---|
380 | 541 | } |
---|
.. | .. |
---|
393 | 554 | mutex_lock(&sc132gs->mutex); |
---|
394 | 555 | |
---|
395 | 556 | mode = sc132gs_find_best_fit(fmt); |
---|
396 | | - fmt->format.code = PIX_FORMAT; |
---|
| 557 | + fmt->format.code = mode->bus_fmt; |
---|
397 | 558 | fmt->format.width = mode->width; |
---|
398 | 559 | fmt->format.height = mode->height; |
---|
399 | 560 | fmt->format.field = V4L2_FIELD_NONE; |
---|
.. | .. |
---|
413 | 574 | __v4l2_ctrl_modify_range(sc132gs->vblank, vblank_def, |
---|
414 | 575 | SC132GS_VTS_MAX - mode->height, |
---|
415 | 576 | 1, vblank_def); |
---|
| 577 | + __v4l2_ctrl_s_ctrl_int64(sc132gs->pixel_rate, mode->pixel_rate); |
---|
| 578 | + __v4l2_ctrl_s_ctrl(sc132gs->link_freq, mode->link_freq_index); |
---|
| 579 | + sc132gs->cur_fps = mode->max_fps; |
---|
| 580 | + sc132gs->cur_vts = mode->vts_def; |
---|
416 | 581 | } |
---|
417 | 582 | |
---|
418 | 583 | mutex_unlock(&sc132gs->mutex); |
---|
.. | .. |
---|
438 | 603 | } else { |
---|
439 | 604 | fmt->format.width = mode->width; |
---|
440 | 605 | fmt->format.height = mode->height; |
---|
441 | | - fmt->format.code = PIX_FORMAT; |
---|
| 606 | + fmt->format.code = mode->bus_fmt; |
---|
442 | 607 | fmt->format.field = V4L2_FIELD_NONE; |
---|
443 | 608 | } |
---|
444 | 609 | mutex_unlock(&sc132gs->mutex); |
---|
.. | .. |
---|
450 | 615 | struct v4l2_subdev_pad_config *cfg, |
---|
451 | 616 | struct v4l2_subdev_mbus_code_enum *code) |
---|
452 | 617 | { |
---|
| 618 | + struct sc132gs *sc132gs = to_sc132gs(sd); |
---|
| 619 | + |
---|
453 | 620 | if (code->index != 0) |
---|
454 | 621 | return -EINVAL; |
---|
455 | | - code->code = PIX_FORMAT; |
---|
| 622 | + code->code = sc132gs->cur_mode->bus_fmt; |
---|
456 | 623 | |
---|
457 | 624 | return 0; |
---|
458 | 625 | } |
---|
.. | .. |
---|
464 | 631 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
---|
465 | 632 | return -EINVAL; |
---|
466 | 633 | |
---|
467 | | - if (fse->code != PIX_FORMAT) |
---|
| 634 | + if (fse->code != supported_modes[fse->index].bus_fmt) |
---|
468 | 635 | return -EINVAL; |
---|
469 | 636 | |
---|
470 | 637 | fse->min_width = supported_modes[fse->index].width; |
---|
.. | .. |
---|
533 | 700 | { |
---|
534 | 701 | void __user *up = compat_ptr(arg); |
---|
535 | 702 | struct rkmodule_inf *inf; |
---|
536 | | - long ret; |
---|
| 703 | + long ret = 0; |
---|
537 | 704 | u32 stream = 0; |
---|
538 | 705 | |
---|
539 | 706 | switch (cmd) { |
---|
.. | .. |
---|
545 | 712 | } |
---|
546 | 713 | |
---|
547 | 714 | ret = sc132gs_ioctl(sd, cmd, inf); |
---|
548 | | - if (!ret) |
---|
| 715 | + if (!ret) { |
---|
549 | 716 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 717 | + if (ret) |
---|
| 718 | + ret = -EFAULT; |
---|
| 719 | + } |
---|
550 | 720 | kfree(inf); |
---|
551 | 721 | break; |
---|
552 | 722 | case RKMODULE_SET_QUICK_STREAM: |
---|
553 | | - ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
554 | | - if (!ret) |
---|
555 | | - ret = sc132gs_ioctl(sd, cmd, &stream); |
---|
| 723 | + if (copy_from_user(&stream, up, sizeof(u32))) |
---|
| 724 | + return -EFAULT; |
---|
| 725 | + |
---|
| 726 | + ret = sc132gs_ioctl(sd, cmd, &stream); |
---|
556 | 727 | break; |
---|
557 | 728 | default: |
---|
558 | 729 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
649 | 820 | { |
---|
650 | 821 | struct sc132gs *sc132gs = to_sc132gs(sd); |
---|
651 | 822 | struct i2c_client *client = sc132gs->client; |
---|
| 823 | + unsigned int fps; |
---|
652 | 824 | int ret = 0; |
---|
653 | 825 | |
---|
654 | 826 | mutex_lock(&sc132gs->mutex); |
---|
655 | 827 | on = !!on; |
---|
656 | 828 | if (on == sc132gs->streaming) |
---|
657 | 829 | goto unlock_and_return; |
---|
| 830 | + |
---|
| 831 | + fps = DIV_ROUND_CLOSEST(sc132gs->cur_mode->max_fps.denominator, |
---|
| 832 | + sc132gs->cur_mode->max_fps.numerator); |
---|
| 833 | + |
---|
| 834 | + dev_info(&sc132gs->client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, |
---|
| 835 | + sc132gs->cur_mode->width, |
---|
| 836 | + sc132gs->cur_mode->height, |
---|
| 837 | + fps); |
---|
658 | 838 | |
---|
659 | 839 | if (on) { |
---|
660 | 840 | ret = pm_runtime_get_sync(&client->dev); |
---|
.. | .. |
---|
718 | 898 | struct sc132gs *sc132gs = to_sc132gs(sd); |
---|
719 | 899 | const struct sc132gs_mode *mode = sc132gs->cur_mode; |
---|
720 | 900 | |
---|
721 | | - mutex_lock(&sc132gs->mutex); |
---|
722 | | - fi->interval = mode->max_fps; |
---|
723 | | - mutex_unlock(&sc132gs->mutex); |
---|
| 901 | + if (sc132gs->streaming) |
---|
| 902 | + fi->interval = sc132gs->cur_fps; |
---|
| 903 | + else |
---|
| 904 | + fi->interval = mode->max_fps; |
---|
724 | 905 | |
---|
725 | 906 | return 0; |
---|
726 | 907 | } |
---|
.. | .. |
---|
761 | 942 | goto disable_clk; |
---|
762 | 943 | } |
---|
763 | 944 | |
---|
| 945 | + if (!IS_ERR(sc132gs->reset_gpio)) |
---|
| 946 | + gpiod_set_value_cansleep(sc132gs->reset_gpio, 1); |
---|
| 947 | + |
---|
| 948 | + usleep_range(1000, 2000); |
---|
| 949 | + |
---|
764 | 950 | if (!IS_ERR(sc132gs->pwdn_gpio)) |
---|
765 | 951 | gpiod_set_value_cansleep(sc132gs->pwdn_gpio, 1); |
---|
| 952 | + |
---|
| 953 | + if (!IS_ERR(sc132gs->reset_gpio)) |
---|
| 954 | + gpiod_set_value_cansleep(sc132gs->reset_gpio, 0); |
---|
766 | 955 | |
---|
767 | 956 | /* 8192 cycles prior to first SCCB transaction */ |
---|
768 | 957 | delay_us = sc132gs_cal_delay(8192); |
---|
.. | .. |
---|
779 | 968 | static void __sc132gs_power_off(struct sc132gs *sc132gs) |
---|
780 | 969 | { |
---|
781 | 970 | int ret; |
---|
| 971 | + |
---|
| 972 | + if (!IS_ERR(sc132gs->reset_gpio)) |
---|
| 973 | + gpiod_set_value_cansleep(sc132gs->reset_gpio, 1); |
---|
782 | 974 | |
---|
783 | 975 | if (!IS_ERR(sc132gs->pwdn_gpio)) |
---|
784 | 976 | gpiod_set_value_cansleep(sc132gs->pwdn_gpio, 0); |
---|
.. | .. |
---|
824 | 1016 | /* Initialize try_fmt */ |
---|
825 | 1017 | try_fmt->width = def_mode->width; |
---|
826 | 1018 | try_fmt->height = def_mode->height; |
---|
827 | | - try_fmt->code = PIX_FORMAT; |
---|
| 1019 | + try_fmt->code = def_mode->bus_fmt; |
---|
828 | 1020 | try_fmt->field = V4L2_FIELD_NONE; |
---|
829 | 1021 | |
---|
830 | 1022 | mutex_unlock(&sc132gs->mutex); |
---|
.. | .. |
---|
841 | 1033 | if (fie->index >= ARRAY_SIZE(supported_modes)) |
---|
842 | 1034 | return -EINVAL; |
---|
843 | 1035 | |
---|
844 | | - if (fie->code != PIX_FORMAT) |
---|
845 | | - return -EINVAL; |
---|
846 | | - |
---|
| 1036 | + fie->code = supported_modes[fie->index].bus_fmt; |
---|
847 | 1037 | fie->width = supported_modes[fie->index].width; |
---|
848 | 1038 | fie->height = supported_modes[fie->index].height; |
---|
849 | 1039 | fie->interval = supported_modes[fie->index].max_fps; |
---|
850 | 1040 | return 0; |
---|
851 | 1041 | } |
---|
852 | 1042 | |
---|
853 | | -static int sc132gs_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 1043 | +static int sc132gs_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
854 | 1044 | struct v4l2_mbus_config *config) |
---|
855 | 1045 | { |
---|
856 | 1046 | u32 val = 0; |
---|
| 1047 | + struct sc132gs *sc132gs = to_sc132gs(sd); |
---|
857 | 1048 | |
---|
858 | | - val = 1 << (SC132GS_LANES - 1) | |
---|
| 1049 | + val = 1 << (sc132gs->cur_mode->lanes - 1) | |
---|
859 | 1050 | V4L2_MBUS_CSI2_CHANNEL_0 | |
---|
860 | 1051 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
861 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 1052 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
862 | 1053 | config->flags = val; |
---|
863 | 1054 | |
---|
864 | 1055 | return 0; |
---|
.. | .. |
---|
886 | 1077 | static const struct v4l2_subdev_video_ops sc132gs_video_ops = { |
---|
887 | 1078 | .s_stream = sc132gs_s_stream, |
---|
888 | 1079 | .g_frame_interval = sc132gs_g_frame_interval, |
---|
889 | | - .g_mbus_config = sc132gs_g_mbus_config, |
---|
890 | 1080 | }; |
---|
891 | 1081 | |
---|
892 | 1082 | static const struct v4l2_subdev_pad_ops sc132gs_pad_ops = { |
---|
.. | .. |
---|
895 | 1085 | .enum_frame_interval = sc132gs_enum_frame_interval, |
---|
896 | 1086 | .get_fmt = sc132gs_get_fmt, |
---|
897 | 1087 | .set_fmt = sc132gs_set_fmt, |
---|
| 1088 | + .get_mbus_config = sc132gs_g_mbus_config, |
---|
898 | 1089 | }; |
---|
899 | 1090 | |
---|
900 | 1091 | static const struct v4l2_subdev_ops sc132gs_subdev_ops = { |
---|
.. | .. |
---|
902 | 1093 | .video = &sc132gs_video_ops, |
---|
903 | 1094 | .pad = &sc132gs_pad_ops, |
---|
904 | 1095 | }; |
---|
| 1096 | + |
---|
| 1097 | +static void sc132gs_modify_fps_info(struct sc132gs *sc132gs) |
---|
| 1098 | +{ |
---|
| 1099 | + const struct sc132gs_mode *mode = sc132gs->cur_mode; |
---|
| 1100 | + |
---|
| 1101 | + sc132gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 1102 | + sc132gs->cur_vts; |
---|
| 1103 | +} |
---|
905 | 1104 | |
---|
906 | 1105 | static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
907 | 1106 | { |
---|
.. | .. |
---|
939 | 1138 | ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_VTS, |
---|
940 | 1139 | SC132GS_REG_VALUE_16BIT, |
---|
941 | 1140 | ctrl->val + sc132gs->cur_mode->height); |
---|
| 1141 | + if (!ret) |
---|
| 1142 | + sc132gs->cur_vts = ctrl->val + sc132gs->cur_mode->height; |
---|
| 1143 | + if (sc132gs->cur_vts != sc132gs->cur_mode->vts_def) |
---|
| 1144 | + sc132gs_modify_fps_info(sc132gs); |
---|
| 1145 | + break; |
---|
942 | 1146 | break; |
---|
943 | 1147 | case V4L2_CID_TEST_PATTERN: |
---|
944 | 1148 | ret = sc132gs_enable_test_pattern(sc132gs, ctrl->val); |
---|
.. | .. |
---|
962 | 1166 | { |
---|
963 | 1167 | const struct sc132gs_mode *mode; |
---|
964 | 1168 | struct v4l2_ctrl_handler *handler; |
---|
965 | | - struct v4l2_ctrl *ctrl; |
---|
966 | 1169 | s64 exposure_max, vblank_def; |
---|
967 | 1170 | u32 h_blank; |
---|
968 | 1171 | int ret; |
---|
.. | .. |
---|
974 | 1177 | return ret; |
---|
975 | 1178 | handler->lock = &sc132gs->mutex; |
---|
976 | 1179 | |
---|
977 | | - ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, |
---|
978 | | - 0, 0, link_freq_menu_items); |
---|
979 | | - if (ctrl) |
---|
980 | | - ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
| 1180 | + sc132gs->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, |
---|
| 1181 | + ARRAY_SIZE(link_freq_menu_items) - 1, 0, |
---|
| 1182 | + link_freq_menu_items); |
---|
981 | 1183 | |
---|
982 | | - v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, |
---|
983 | | - 0, SC132GS_PIXEL_RATE, 1, SC132GS_PIXEL_RATE); |
---|
| 1184 | + sc132gs->pixel_rate = v4l2_ctrl_new_std(handler, NULL, |
---|
| 1185 | + V4L2_CID_PIXEL_RATE, |
---|
| 1186 | + 0, PIXEL_RATE_WITH_360M, |
---|
| 1187 | + 1, mode->pixel_rate); |
---|
| 1188 | + |
---|
| 1189 | + __v4l2_ctrl_s_ctrl(sc132gs->link_freq, mode->pixel_rate); |
---|
984 | 1190 | |
---|
985 | 1191 | h_blank = mode->hts_def - mode->width; |
---|
986 | 1192 | sc132gs->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, |
---|
.. | .. |
---|
1016 | 1222 | "Failed to init controls(%d)\n", ret); |
---|
1017 | 1223 | goto err_free_handler; |
---|
1018 | 1224 | } |
---|
1019 | | - |
---|
| 1225 | + sc132gs->cur_fps = mode->max_fps; |
---|
| 1226 | + sc132gs->cur_vts = mode->vts_def; |
---|
1020 | 1227 | sc132gs->subdev.ctrl_handler = handler; |
---|
1021 | 1228 | |
---|
1022 | 1229 | return 0; |
---|
.. | .. |
---|
1098 | 1305 | return -EINVAL; |
---|
1099 | 1306 | } |
---|
1100 | 1307 | |
---|
| 1308 | + sc132gs->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
| 1309 | + if (IS_ERR(sc132gs->reset_gpio)) |
---|
| 1310 | + dev_warn(dev, "Failed to get reset-gpios\n"); |
---|
| 1311 | + |
---|
1101 | 1312 | sc132gs->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
---|
1102 | 1313 | if (IS_ERR(sc132gs->pwdn_gpio)) |
---|
1103 | 1314 | dev_warn(dev, "Failed to get pwdn-gpios\n"); |
---|