.. | .. |
---|
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 | |
---|