| .. | .. |
|---|
| 43 | 43 | #include <linux/printk.h> |
|---|
| 44 | 44 | |
|---|
| 45 | 45 | #include <linux/rk-camera-module.h> |
|---|
| 46 | +#include "../platform/rockchip/isp/rkisp_tb_helper.h" |
|---|
| 46 | 47 | #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) |
|---|
| 47 | 48 | |
|---|
| 48 | 49 | #ifndef V4L2_CID_DIGITAL_GAIN |
|---|
| .. | .. |
|---|
| 52 | 53 | #define SC530AI_LINK_FREQ_396M 198000000 // 396Mbps |
|---|
| 53 | 54 | #define SC530AI_LINK_FREQ_792M 396000000 // 792Mbps |
|---|
| 54 | 55 | #define SC530AI_LINK_FREQ_792M_2LANE 396000000 // 792Mbps |
|---|
| 56 | +#define SC530AI_LINK_FREQ_936M_2LANE 468000000 // 936Mbps |
|---|
| 55 | 57 | |
|---|
| 56 | 58 | #define SC530AI_LINEAR_PIXEL_RATES (SC530AI_LINK_FREQ_396M / 10 * 2 * 4) |
|---|
| 57 | 59 | #define SC530AI_HDR_PIXEL_RATES (SC530AI_LINK_FREQ_792M / 10 * 2 * 4) |
|---|
| .. | .. |
|---|
| 194 | 196 | const char *module_name; |
|---|
| 195 | 197 | const char *len_name; |
|---|
| 196 | 198 | bool has_init_exp; |
|---|
| 199 | + bool is_thunderboot; |
|---|
| 200 | + bool is_first_streamoff; |
|---|
| 197 | 201 | struct preisp_hdrae_exp_s init_hdrae_exp; |
|---|
| 198 | 202 | }; |
|---|
| 199 | 203 | |
|---|
| .. | .. |
|---|
| 520 | 524 | {0x37f9, 0x80}, |
|---|
| 521 | 525 | {0x3018, 0x32}, |
|---|
| 522 | 526 | {0x3019, 0x0c}, |
|---|
| 523 | | - {0x301f, 0x18}, |
|---|
| 527 | + {0x301f, 0x42}, |
|---|
| 528 | + {0x320c, 0x06}, |
|---|
| 529 | + {0x320d, 0x27}, |
|---|
| 530 | + {0x320e, 0x07}, |
|---|
| 531 | + {0x320f, 0xbc}, |
|---|
| 524 | 532 | {0x3250, 0x40}, |
|---|
| 525 | 533 | {0x3251, 0x98}, |
|---|
| 526 | 534 | {0x3253, 0x0c}, |
|---|
| 527 | 535 | {0x325f, 0x20}, |
|---|
| 528 | 536 | {0x3301, 0x08}, |
|---|
| 529 | 537 | {0x3304, 0x50}, |
|---|
| 530 | | - {0x3306, 0x78}, |
|---|
| 538 | + {0x3306, 0x88}, |
|---|
| 531 | 539 | {0x3308, 0x14}, |
|---|
| 532 | 540 | {0x3309, 0x70}, |
|---|
| 533 | 541 | {0x330a, 0x00}, |
|---|
| 534 | | - {0x330b, 0xd8}, |
|---|
| 542 | + {0x330b, 0xf8}, |
|---|
| 535 | 543 | {0x330d, 0x10}, |
|---|
| 536 | 544 | {0x331e, 0x41}, |
|---|
| 537 | 545 | {0x331f, 0x61}, |
|---|
| .. | .. |
|---|
| 560 | 568 | {0x33ae, 0x30}, |
|---|
| 561 | 569 | {0x33af, 0x50}, |
|---|
| 562 | 570 | {0x33b1, 0x80}, |
|---|
| 563 | | - {0x33b2, 0x80}, |
|---|
| 564 | | - {0x33b3, 0x40}, |
|---|
| 571 | + {0x33b2, 0x48}, |
|---|
| 572 | + {0x33b3, 0x30}, |
|---|
| 565 | 573 | {0x349f, 0x02}, |
|---|
| 566 | 574 | {0x34a6, 0x48}, |
|---|
| 567 | | - {0x34a7, 0x49}, |
|---|
| 568 | | - {0x34a8, 0x40}, |
|---|
| 569 | | - {0x34a9, 0x30}, |
|---|
| 570 | | - {0x34f8, 0x4b}, |
|---|
| 571 | | - {0x34f9, 0x30}, |
|---|
| 575 | + {0x34a7, 0x4b}, |
|---|
| 576 | + {0x34a8, 0x30}, |
|---|
| 577 | + {0x34a9, 0x18}, |
|---|
| 578 | + {0x34f8, 0x5f}, |
|---|
| 579 | + {0x34f9, 0x08}, |
|---|
| 572 | 580 | {0x3632, 0x48}, |
|---|
| 573 | 581 | {0x3633, 0x32}, |
|---|
| 574 | | - {0x3637, 0x2b}, |
|---|
| 582 | + {0x3637, 0x29}, |
|---|
| 575 | 583 | {0x3638, 0xc1}, |
|---|
| 576 | 584 | {0x363b, 0x20}, |
|---|
| 577 | 585 | {0x363d, 0x02}, |
|---|
| .. | .. |
|---|
| 582 | 590 | {0x367c, 0x40}, |
|---|
| 583 | 591 | {0x367d, 0x48}, |
|---|
| 584 | 592 | {0x3690, 0x32}, |
|---|
| 585 | | - {0x3691, 0x32}, |
|---|
| 593 | + {0x3691, 0x43}, |
|---|
| 586 | 594 | {0x3692, 0x33}, |
|---|
| 587 | 595 | {0x3693, 0x40}, |
|---|
| 588 | 596 | {0x3694, 0x4b}, |
|---|
| .. | .. |
|---|
| 594 | 602 | {0x36a3, 0x4b}, |
|---|
| 595 | 603 | {0x36a4, 0x4f}, |
|---|
| 596 | 604 | {0x36d0, 0x01}, |
|---|
| 605 | + {0x36ea, 0x0d}, |
|---|
| 606 | + {0x36eb, 0x04}, |
|---|
| 597 | 607 | {0x36ec, 0x03}, |
|---|
| 608 | + {0x36ed, 0x14}, |
|---|
| 598 | 609 | {0x370f, 0x01}, |
|---|
| 599 | 610 | {0x3722, 0x00}, |
|---|
| 600 | 611 | {0x3728, 0x10}, |
|---|
| .. | .. |
|---|
| 603 | 614 | {0x37b2, 0x83}, |
|---|
| 604 | 615 | {0x37b3, 0x48}, |
|---|
| 605 | 616 | {0x37b4, 0x49}, |
|---|
| 606 | | - {0x37fb, 0x25}, |
|---|
| 617 | + {0x37fa, 0x0d}, |
|---|
| 618 | + {0x37fb, 0x24}, |
|---|
| 607 | 619 | {0x37fc, 0x01}, |
|---|
| 620 | + {0x37fd, 0x14}, |
|---|
| 608 | 621 | {0x3901, 0x00}, |
|---|
| 609 | 622 | {0x3902, 0xc5}, |
|---|
| 610 | 623 | {0x3904, 0x08}, |
|---|
| .. | .. |
|---|
| 614 | 627 | {0x391f, 0x44}, |
|---|
| 615 | 628 | {0x3926, 0x21}, |
|---|
| 616 | 629 | {0x3929, 0x18}, |
|---|
| 617 | | - {0x3933, 0x81}, |
|---|
| 618 | | - {0x3934, 0x81}, |
|---|
| 619 | | - {0x3937, 0x69}, |
|---|
| 630 | + {0x3933, 0x82}, |
|---|
| 631 | + {0x3934, 0x0a}, |
|---|
| 632 | + {0x3937, 0x5f}, |
|---|
| 620 | 633 | {0x3939, 0x00}, |
|---|
| 621 | 634 | {0x393a, 0x00}, |
|---|
| 622 | 635 | {0x39dc, 0x02}, |
|---|
| 623 | | - {0x3e01, 0xcd}, |
|---|
| 624 | | - {0x3e02, 0xa0}, |
|---|
| 636 | + {0x3e01, 0xf6}, |
|---|
| 637 | + {0x3e02, 0xe0}, |
|---|
| 625 | 638 | {0x440e, 0x02}, |
|---|
| 626 | 639 | {0x4509, 0x20}, |
|---|
| 627 | | - {0x4800, 0x04}, |
|---|
| 628 | | - {0x4837, 0x14}, |
|---|
| 640 | + {0x4837, 0x22}, |
|---|
| 629 | 641 | {0x5010, 0x10}, |
|---|
| 642 | + {0x5780, 0x66}, |
|---|
| 643 | + {0x578d, 0x40}, |
|---|
| 630 | 644 | {0x5799, 0x06}, |
|---|
| 631 | 645 | {0x57ad, 0x00}, |
|---|
| 632 | 646 | {0x5ae0, 0xfe}, |
|---|
| .. | .. |
|---|
| 658 | 672 | {0x5afe, 0x30}, |
|---|
| 659 | 673 | {0x5aff, 0x28}, |
|---|
| 660 | 674 | {0x36e9, 0x44}, |
|---|
| 661 | | - {0x37f9, 0x34}, |
|---|
| 662 | | -// {0x0100, 0x01}, |
|---|
| 675 | + {0x37f9, 0x44}, |
|---|
| 663 | 676 | {REG_NULL, 0x00}, |
|---|
| 664 | 677 | }; |
|---|
| 665 | 678 | |
|---|
| .. | .. |
|---|
| 713 | 726 | }, |
|---|
| 714 | 727 | .exp_def = 0xcda / 2, |
|---|
| 715 | 728 | .hts_def = 0xb40, |
|---|
| 716 | | - .vts_def = 0x0672, |
|---|
| 729 | + .vts_def = 0x07bc, |
|---|
| 717 | 730 | .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, |
|---|
| 718 | 731 | .reg_list = sc530ai_10_30fps_2880x1620_2lane_regs, |
|---|
| 719 | | - .mipi_freq_idx = 2, |
|---|
| 732 | + .mipi_freq_idx = 3, |
|---|
| 720 | 733 | .bpp = 10, |
|---|
| 721 | 734 | .hdr_mode = NO_HDR, |
|---|
| 722 | 735 | .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
|---|
| .. | .. |
|---|
| 727 | 740 | SC530AI_LINK_FREQ_396M, |
|---|
| 728 | 741 | SC530AI_LINK_FREQ_792M, |
|---|
| 729 | 742 | SC530AI_LINK_FREQ_792M_2LANE, |
|---|
| 743 | + SC530AI_LINK_FREQ_936M_2LANE, |
|---|
| 730 | 744 | }; |
|---|
| 731 | 745 | |
|---|
| 732 | 746 | /* Write registers up to 4 at a time */ |
|---|
| .. | .. |
|---|
| 1340 | 1354 | { |
|---|
| 1341 | 1355 | int ret; |
|---|
| 1342 | 1356 | |
|---|
| 1343 | | - ret = sc530ai_write_array(sc530ai->client, sc530ai->cur_mode->reg_list); |
|---|
| 1344 | | - if (ret) |
|---|
| 1345 | | - return ret; |
|---|
| 1346 | | - |
|---|
| 1347 | | - /* In case these controls are set before streaming */ |
|---|
| 1348 | | - ret = __v4l2_ctrl_handler_setup(&sc530ai->ctrl_handler); |
|---|
| 1349 | | - if (ret) |
|---|
| 1350 | | - return ret; |
|---|
| 1351 | | - if (sc530ai->has_init_exp && sc530ai->cur_mode->hdr_mode != NO_HDR) { |
|---|
| 1352 | | - ret = sc530ai_ioctl(&sc530ai->subdev, PREISP_CMD_SET_HDRAE_EXP, |
|---|
| 1353 | | - &sc530ai->init_hdrae_exp); |
|---|
| 1354 | | - if (ret) { |
|---|
| 1355 | | - dev_err(&sc530ai->client->dev, |
|---|
| 1356 | | - "init exp fail in hdr mode\n"); |
|---|
| 1357 | + if (!sc530ai->is_thunderboot) { |
|---|
| 1358 | + ret = sc530ai_write_array(sc530ai->client, sc530ai->cur_mode->reg_list); |
|---|
| 1359 | + if (ret) |
|---|
| 1357 | 1360 | return ret; |
|---|
| 1361 | + |
|---|
| 1362 | + /* In case these controls are set before streaming */ |
|---|
| 1363 | + ret = __v4l2_ctrl_handler_setup(&sc530ai->ctrl_handler); |
|---|
| 1364 | + if (ret) |
|---|
| 1365 | + return ret; |
|---|
| 1366 | + if (sc530ai->has_init_exp && sc530ai->cur_mode->hdr_mode != NO_HDR) { |
|---|
| 1367 | + ret = sc530ai_ioctl(&sc530ai->subdev, PREISP_CMD_SET_HDRAE_EXP, |
|---|
| 1368 | + &sc530ai->init_hdrae_exp); |
|---|
| 1369 | + if (ret) { |
|---|
| 1370 | + dev_err(&sc530ai->client->dev, |
|---|
| 1371 | + "init exp fail in hdr mode\n"); |
|---|
| 1372 | + return ret; |
|---|
| 1373 | + } |
|---|
| 1358 | 1374 | } |
|---|
| 1359 | 1375 | } |
|---|
| 1360 | 1376 | return sc530ai_write_reg(sc530ai->client, SC530AI_REG_CTRL_MODE, |
|---|
| .. | .. |
|---|
| 1365 | 1381 | static int __sc530ai_stop_stream(struct sc530ai *sc530ai) |
|---|
| 1366 | 1382 | { |
|---|
| 1367 | 1383 | sc530ai->has_init_exp = false; |
|---|
| 1384 | + if (sc530ai->is_thunderboot) { |
|---|
| 1385 | + sc530ai->is_first_streamoff = true; |
|---|
| 1386 | + pm_runtime_put(&sc530ai->client->dev); |
|---|
| 1387 | + } |
|---|
| 1368 | 1388 | return sc530ai_write_reg(sc530ai->client, SC530AI_REG_CTRL_MODE, |
|---|
| 1369 | 1389 | SC530AI_REG_VALUE_08BIT, |
|---|
| 1370 | 1390 | SC530AI_MODE_SW_STANDBY); |
|---|
| 1371 | 1391 | } |
|---|
| 1372 | 1392 | |
|---|
| 1393 | +static int __sc530ai_power_on(struct sc530ai *sc530ai); |
|---|
| 1373 | 1394 | static int sc530ai_s_stream(struct v4l2_subdev *sd, int on) |
|---|
| 1374 | 1395 | { |
|---|
| 1375 | 1396 | struct sc530ai *sc530ai = to_sc530ai(sd); |
|---|
| .. | .. |
|---|
| 1381 | 1402 | if (on == sc530ai->streaming) |
|---|
| 1382 | 1403 | goto unlock_and_return; |
|---|
| 1383 | 1404 | if (on) { |
|---|
| 1405 | + if (sc530ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { |
|---|
| 1406 | + sc530ai->is_thunderboot = false; |
|---|
| 1407 | + __sc530ai_power_on(sc530ai); |
|---|
| 1408 | + } |
|---|
| 1384 | 1409 | ret = pm_runtime_get_sync(&client->dev); |
|---|
| 1385 | 1410 | if (ret < 0) { |
|---|
| 1386 | 1411 | pm_runtime_put_noidle(&client->dev); |
|---|
| .. | .. |
|---|
| 1423 | 1448 | pm_runtime_put_noidle(&client->dev); |
|---|
| 1424 | 1449 | goto unlock_and_return; |
|---|
| 1425 | 1450 | } |
|---|
| 1426 | | - |
|---|
| 1427 | | - ret |= sc530ai_write_reg(sc530ai->client, |
|---|
| 1428 | | - SC530AI_SOFTWARE_RESET_REG, |
|---|
| 1429 | | - SC530AI_REG_VALUE_08BIT, |
|---|
| 1430 | | - 0x01); |
|---|
| 1431 | | - usleep_range(100, 200); |
|---|
| 1432 | | - |
|---|
| 1451 | + if (!sc530ai->is_thunderboot) { |
|---|
| 1452 | + ret |= sc530ai_write_reg(sc530ai->client, |
|---|
| 1453 | + SC530AI_SOFTWARE_RESET_REG, |
|---|
| 1454 | + SC530AI_REG_VALUE_08BIT, |
|---|
| 1455 | + 0x01); |
|---|
| 1456 | + if (ret) { |
|---|
| 1457 | + v4l2_err(sd, "could not set init registers\n"); |
|---|
| 1458 | + pm_runtime_put_noidle(&client->dev); |
|---|
| 1459 | + goto unlock_and_return; |
|---|
| 1460 | + } |
|---|
| 1461 | + usleep_range(100, 200); |
|---|
| 1462 | + } |
|---|
| 1433 | 1463 | sc530ai->power_on = true; |
|---|
| 1434 | 1464 | } else { |
|---|
| 1435 | 1465 | pm_runtime_put(&client->dev); |
|---|
| .. | .. |
|---|
| 1463 | 1493 | dev_err(dev, "Failed to enable xvclk\n"); |
|---|
| 1464 | 1494 | return ret; |
|---|
| 1465 | 1495 | } |
|---|
| 1496 | + |
|---|
| 1497 | + if (sc530ai->is_thunderboot) |
|---|
| 1498 | + return 0; |
|---|
| 1499 | + |
|---|
| 1466 | 1500 | if (!IS_ERR(sc530ai->reset_gpio)) |
|---|
| 1467 | 1501 | gpiod_set_value_cansleep(sc530ai->reset_gpio, 0); |
|---|
| 1468 | 1502 | |
|---|
| .. | .. |
|---|
| 1492 | 1526 | { |
|---|
| 1493 | 1527 | int ret; |
|---|
| 1494 | 1528 | struct device *dev = &sc530ai->client->dev; |
|---|
| 1529 | + |
|---|
| 1530 | + if (sc530ai->is_thunderboot) { |
|---|
| 1531 | + if (sc530ai->is_first_streamoff) { |
|---|
| 1532 | + sc530ai->is_thunderboot = false; |
|---|
| 1533 | + sc530ai->is_first_streamoff = false; |
|---|
| 1534 | + } else { |
|---|
| 1535 | + return; |
|---|
| 1536 | + } |
|---|
| 1537 | + } |
|---|
| 1495 | 1538 | |
|---|
| 1496 | 1539 | if (!IS_ERR(sc530ai->pwdn_gpio)) |
|---|
| 1497 | 1540 | gpiod_set_value_cansleep(sc530ai->pwdn_gpio, 0); |
|---|
| .. | .. |
|---|
| 1716 | 1759 | vts & 0xff); |
|---|
| 1717 | 1760 | if (!ret) |
|---|
| 1718 | 1761 | sc530ai->cur_vts = vts; |
|---|
| 1719 | | - if (sc530ai->cur_vts != sc530ai->cur_mode->vts_def) |
|---|
| 1720 | | - sc530ai_modify_fps_info(sc530ai); |
|---|
| 1762 | + sc530ai_modify_fps_info(sc530ai); |
|---|
| 1721 | 1763 | dev_dbg(&client->dev, "set vblank 0x%x\n", ctrl->val); |
|---|
| 1722 | 1764 | break; |
|---|
| 1723 | 1765 | case V4L2_CID_HFLIP: |
|---|
| .. | .. |
|---|
| 1893 | 1935 | u32 id = 0; |
|---|
| 1894 | 1936 | int ret; |
|---|
| 1895 | 1937 | |
|---|
| 1938 | + if (sc530ai->is_thunderboot) { |
|---|
| 1939 | + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); |
|---|
| 1940 | + return 0; |
|---|
| 1941 | + } |
|---|
| 1896 | 1942 | ret = sc530ai_read_reg(client, SC530AI_REG_CHIP_ID, |
|---|
| 1897 | 1943 | SC530AI_REG_VALUE_16BIT, &id); |
|---|
| 1898 | 1944 | if (id != SC530AI_CHIP_ID) { |
|---|
| .. | .. |
|---|
| 1951 | 1997 | return -EINVAL; |
|---|
| 1952 | 1998 | } |
|---|
| 1953 | 1999 | |
|---|
| 2000 | + sc530ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); |
|---|
| 1954 | 2001 | sc530ai->client = client; |
|---|
| 1955 | 2002 | |
|---|
| 1956 | 2003 | ret = sc530ai_parse_of(sc530ai); |
|---|
| .. | .. |
|---|
| 1963 | 2010 | return -EINVAL; |
|---|
| 1964 | 2011 | } |
|---|
| 1965 | 2012 | |
|---|
| 1966 | | - sc530ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
|---|
| 2013 | + sc530ai->reset_gpio = devm_gpiod_get(dev, "reset", |
|---|
| 2014 | + sc530ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); |
|---|
| 1967 | 2015 | if (IS_ERR(sc530ai->reset_gpio)) |
|---|
| 1968 | 2016 | dev_warn(dev, "Failed to get reset-gpios\n"); |
|---|
| 1969 | 2017 | |
|---|
| 1970 | | - sc530ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); |
|---|
| 2018 | + sc530ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", |
|---|
| 2019 | + sc530ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); |
|---|
| 1971 | 2020 | if (IS_ERR(sc530ai->pwdn_gpio)) |
|---|
| 1972 | 2021 | dev_warn(dev, "Failed to get pwdn-gpios\n"); |
|---|
| 1973 | 2022 | |
|---|
| .. | .. |
|---|
| 2041 | 2090 | |
|---|
| 2042 | 2091 | pm_runtime_set_active(dev); |
|---|
| 2043 | 2092 | pm_runtime_enable(dev); |
|---|
| 2044 | | - pm_runtime_idle(dev); |
|---|
| 2093 | + if (sc530ai->is_thunderboot) |
|---|
| 2094 | + pm_runtime_get_sync(dev); |
|---|
| 2095 | + else |
|---|
| 2096 | + pm_runtime_idle(dev); |
|---|
| 2045 | 2097 | |
|---|
| 2046 | 2098 | return 0; |
|---|
| 2047 | 2099 | |
|---|