| .. | .. |
|---|
| 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 | + sc132gs_modify_fps_info(sc132gs); |
|---|
| 1144 | + break; |
|---|
| 942 | 1145 | break; |
|---|
| 943 | 1146 | case V4L2_CID_TEST_PATTERN: |
|---|
| 944 | 1147 | ret = sc132gs_enable_test_pattern(sc132gs, ctrl->val); |
|---|
| .. | .. |
|---|
| 962 | 1165 | { |
|---|
| 963 | 1166 | const struct sc132gs_mode *mode; |
|---|
| 964 | 1167 | struct v4l2_ctrl_handler *handler; |
|---|
| 965 | | - struct v4l2_ctrl *ctrl; |
|---|
| 966 | 1168 | s64 exposure_max, vblank_def; |
|---|
| 967 | 1169 | u32 h_blank; |
|---|
| 968 | 1170 | int ret; |
|---|
| .. | .. |
|---|
| 974 | 1176 | return ret; |
|---|
| 975 | 1177 | handler->lock = &sc132gs->mutex; |
|---|
| 976 | 1178 | |
|---|
| 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; |
|---|
| 1179 | + sc132gs->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, |
|---|
| 1180 | + ARRAY_SIZE(link_freq_menu_items) - 1, 0, |
|---|
| 1181 | + link_freq_menu_items); |
|---|
| 981 | 1182 | |
|---|
| 982 | | - v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, |
|---|
| 983 | | - 0, SC132GS_PIXEL_RATE, 1, SC132GS_PIXEL_RATE); |
|---|
| 1183 | + sc132gs->pixel_rate = v4l2_ctrl_new_std(handler, NULL, |
|---|
| 1184 | + V4L2_CID_PIXEL_RATE, |
|---|
| 1185 | + 0, PIXEL_RATE_WITH_360M, |
|---|
| 1186 | + 1, mode->pixel_rate); |
|---|
| 1187 | + |
|---|
| 1188 | + __v4l2_ctrl_s_ctrl(sc132gs->link_freq, mode->pixel_rate); |
|---|
| 984 | 1189 | |
|---|
| 985 | 1190 | h_blank = mode->hts_def - mode->width; |
|---|
| 986 | 1191 | sc132gs->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, |
|---|
| .. | .. |
|---|
| 1016 | 1221 | "Failed to init controls(%d)\n", ret); |
|---|
| 1017 | 1222 | goto err_free_handler; |
|---|
| 1018 | 1223 | } |
|---|
| 1019 | | - |
|---|
| 1224 | + sc132gs->cur_fps = mode->max_fps; |
|---|
| 1225 | + sc132gs->cur_vts = mode->vts_def; |
|---|
| 1020 | 1226 | sc132gs->subdev.ctrl_handler = handler; |
|---|
| 1021 | 1227 | |
|---|
| 1022 | 1228 | return 0; |
|---|
| .. | .. |
|---|
| 1098 | 1304 | return -EINVAL; |
|---|
| 1099 | 1305 | } |
|---|
| 1100 | 1306 | |
|---|
| 1307 | + sc132gs->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
|---|
| 1308 | + if (IS_ERR(sc132gs->reset_gpio)) |
|---|
| 1309 | + dev_warn(dev, "Failed to get reset-gpios\n"); |
|---|
| 1310 | + |
|---|
| 1101 | 1311 | sc132gs->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
|---|
| 1102 | 1312 | if (IS_ERR(sc132gs->pwdn_gpio)) |
|---|
| 1103 | 1313 | dev_warn(dev, "Failed to get pwdn-gpios\n"); |
|---|