.. | .. |
---|
5 | 5 | * Copyright (C) 2020 Rockchip Electronics Co., Ltd. |
---|
6 | 6 | * |
---|
7 | 7 | * V0.0X01.0X00 first version. |
---|
| 8 | + * V0.0X01.0X01 fix power on & off sequence |
---|
8 | 9 | */ |
---|
9 | 10 | |
---|
10 | 11 | #include <linux/clk.h> |
---|
.. | .. |
---|
27 | 28 | #include <linux/rk-preisp.h> |
---|
28 | 29 | #include "../platform/rockchip/isp/rkisp_tb_helper.h" |
---|
29 | 30 | |
---|
30 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00) |
---|
| 31 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) |
---|
31 | 32 | |
---|
32 | 33 | #ifndef V4L2_CID_DIGITAL_GAIN |
---|
33 | 34 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
---|
.. | .. |
---|
91 | 92 | #define SENSOR_ID(_msb, _lsb) ((_msb) << 8 | (_lsb)) |
---|
92 | 93 | |
---|
93 | 94 | static const char * const OV02B10_supply_names[] = { |
---|
94 | | - "avdd", /* Analog power */ |
---|
95 | 95 | "dovdd", /* Digital I/O power */ |
---|
96 | | - "dvdd", /* Digital core power */ |
---|
| 96 | + "avdd", /* Analog power */ |
---|
97 | 97 | }; |
---|
98 | 98 | |
---|
99 | 99 | #define OV02B10_NUM_SUPPLIES ARRAY_SIZE(OV02B10_supply_names) |
---|
100 | | - |
---|
101 | | -enum ov02b10_max_pad { |
---|
102 | | - PAD0, |
---|
103 | | - PAD1, |
---|
104 | | - PAD2, |
---|
105 | | - PAD3, |
---|
106 | | - PAD_MAX, |
---|
107 | | -}; |
---|
108 | 100 | |
---|
109 | 101 | struct regval { |
---|
110 | 102 | u8 addr; |
---|
.. | .. |
---|
534 | 526 | struct ov02b10 *ov02b10 = to_ov02b10(sd); |
---|
535 | 527 | const struct ov02b10_mode *mode = ov02b10->cur_mode; |
---|
536 | 528 | |
---|
537 | | - mutex_lock(&ov02b10->mutex); |
---|
538 | 529 | fi->interval = mode->max_fps; |
---|
539 | | - mutex_unlock(&ov02b10->mutex); |
---|
540 | 530 | |
---|
541 | 531 | return 0; |
---|
542 | 532 | } |
---|
543 | 533 | |
---|
544 | | -static int ov02b10_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 534 | +static int ov02b10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
545 | 535 | struct v4l2_mbus_config *config) |
---|
546 | 536 | { |
---|
547 | 537 | struct ov02b10 *ov02b10 = to_ov02b10(sd); |
---|
.. | .. |
---|
558 | 548 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | |
---|
559 | 549 | V4L2_MBUS_CSI2_CHANNEL_1; |
---|
560 | 550 | |
---|
561 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 551 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
562 | 552 | config->flags = val; |
---|
563 | 553 | |
---|
564 | 554 | return 0; |
---|
.. | .. |
---|
639 | 629 | } |
---|
640 | 630 | |
---|
641 | 631 | ret = ov02b10_ioctl(sd, cmd, inf); |
---|
642 | | - if (!ret) |
---|
| 632 | + if (!ret) { |
---|
643 | 633 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 634 | + if (ret) |
---|
| 635 | + ret = -EFAULT; |
---|
| 636 | + } |
---|
644 | 637 | kfree(inf); |
---|
645 | 638 | break; |
---|
646 | 639 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
653 | 646 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
654 | 647 | if (!ret) |
---|
655 | 648 | ret = ov02b10_ioctl(sd, cmd, cfg); |
---|
| 649 | + else |
---|
| 650 | + ret = -EFAULT; |
---|
656 | 651 | kfree(cfg); |
---|
657 | 652 | break; |
---|
658 | 653 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
663 | 658 | } |
---|
664 | 659 | |
---|
665 | 660 | ret = ov02b10_ioctl(sd, cmd, hdr); |
---|
666 | | - if (!ret) |
---|
| 661 | + if (!ret) { |
---|
667 | 662 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 663 | + if (ret) |
---|
| 664 | + ret = -EFAULT; |
---|
| 665 | + } |
---|
668 | 666 | kfree(hdr); |
---|
669 | 667 | break; |
---|
670 | 668 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
677 | 675 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
678 | 676 | if (!ret) |
---|
679 | 677 | ret = ov02b10_ioctl(sd, cmd, hdr); |
---|
| 678 | + else |
---|
| 679 | + ret = -EFAULT; |
---|
680 | 680 | kfree(hdr); |
---|
681 | 681 | break; |
---|
682 | 682 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
689 | 689 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
690 | 690 | if (!ret) |
---|
691 | 691 | ret = ov02b10_ioctl(sd, cmd, hdrae); |
---|
| 692 | + else |
---|
| 693 | + ret = -EFAULT; |
---|
692 | 694 | kfree(hdrae); |
---|
693 | 695 | break; |
---|
694 | 696 | case RKMODULE_SET_CONVERSION_GAIN: |
---|
695 | 697 | ret = copy_from_user(&cg, up, sizeof(cg)); |
---|
696 | 698 | if (!ret) |
---|
697 | 699 | ret = ov02b10_ioctl(sd, cmd, &cg); |
---|
| 700 | + else |
---|
| 701 | + ret = -EFAULT; |
---|
698 | 702 | break; |
---|
699 | 703 | case RKMODULE_SET_QUICK_STREAM: |
---|
700 | 704 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
701 | 705 | if (!ret) |
---|
702 | 706 | ret = ov02b10_ioctl(sd, cmd, &stream); |
---|
| 707 | + else |
---|
| 708 | + ret = -EFAULT; |
---|
703 | 709 | break; |
---|
704 | 710 | default: |
---|
705 | 711 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
813 | 819 | return ret; |
---|
814 | 820 | } |
---|
815 | 821 | |
---|
| 822 | +static int ov02b10_enable_regulators(struct ov02b10 *ov02b10, |
---|
| 823 | + struct regulator_bulk_data *consumers) |
---|
| 824 | +{ |
---|
| 825 | + int i, j; |
---|
| 826 | + int ret = 0; |
---|
| 827 | + struct device *dev = &ov02b10->client->dev; |
---|
| 828 | + int num_consumers = OV02B10_NUM_SUPPLIES; |
---|
| 829 | + |
---|
| 830 | + for (i = 0; i < num_consumers; i++) { |
---|
| 831 | + |
---|
| 832 | + ret = regulator_enable(consumers[i].consumer); |
---|
| 833 | + if (ret < 0) { |
---|
| 834 | + dev_err(dev, "Failed to enable regulator: %s\n", |
---|
| 835 | + consumers[i].supply); |
---|
| 836 | + goto err; |
---|
| 837 | + } |
---|
| 838 | + } |
---|
| 839 | + return 0; |
---|
| 840 | +err: |
---|
| 841 | + for (j = 0; j < i; j++) |
---|
| 842 | + regulator_disable(consumers[j].consumer); |
---|
| 843 | + |
---|
| 844 | + return ret; |
---|
| 845 | +} |
---|
| 846 | + |
---|
816 | 847 | static int __ov02b10_power_on(struct ov02b10 *ov02b10) |
---|
817 | 848 | { |
---|
818 | 849 | int ret; |
---|
.. | .. |
---|
829 | 860 | dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); |
---|
830 | 861 | if (clk_get_rate(ov02b10->xvclk) != OV02B10_XVCLK_FREQ) |
---|
831 | 862 | dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); |
---|
832 | | - ret = clk_prepare_enable(ov02b10->xvclk); |
---|
833 | | - if (ret < 0) { |
---|
834 | | - dev_err(dev, "Failed to enable xvclk\n"); |
---|
835 | | - return ret; |
---|
836 | | - } |
---|
837 | 863 | |
---|
838 | 864 | if (!IS_ERR(ov02b10->pwdn_gpio)) |
---|
839 | 865 | gpiod_direction_output(ov02b10->pwdn_gpio, 1); |
---|
.. | .. |
---|
841 | 867 | if (!IS_ERR(ov02b10->reset_gpio)) |
---|
842 | 868 | gpiod_direction_output(ov02b10->reset_gpio, 1); |
---|
843 | 869 | |
---|
844 | | - ret = regulator_bulk_enable(OV02B10_NUM_SUPPLIES, ov02b10->supplies); |
---|
| 870 | + ret = ov02b10_enable_regulators(ov02b10, ov02b10->supplies); |
---|
845 | 871 | if (ret < 0) { |
---|
846 | 872 | dev_err(dev, "Failed to enable regulators\n"); |
---|
847 | 873 | goto disable_clk; |
---|
| 874 | + } |
---|
| 875 | + usleep_range(100, 110); |
---|
| 876 | + ret = clk_prepare_enable(ov02b10->xvclk); |
---|
| 877 | + if (ret < 0) { |
---|
| 878 | + dev_err(dev, "Failed to enable xvclk\n"); |
---|
| 879 | + return ret; |
---|
848 | 880 | } |
---|
849 | 881 | |
---|
850 | 882 | /* From spec: delay from power stable to pwdn off: 5ms */ |
---|
.. | .. |
---|
872 | 904 | int ret; |
---|
873 | 905 | struct device *dev = &ov02b10->client->dev; |
---|
874 | 906 | |
---|
875 | | - if (!IS_ERR(ov02b10->pwdn_gpio)) |
---|
876 | | - gpiod_direction_output(ov02b10->pwdn_gpio, 1); |
---|
| 907 | + if (!IS_ERR(ov02b10->reset_gpio)) |
---|
| 908 | + gpiod_direction_output(ov02b10->reset_gpio, 1); |
---|
877 | 909 | |
---|
878 | 910 | clk_disable_unprepare(ov02b10->xvclk); |
---|
879 | 911 | |
---|
880 | | - if (!IS_ERR(ov02b10->reset_gpio)) |
---|
881 | | - gpiod_direction_output(ov02b10->reset_gpio, 1); |
---|
| 912 | + if (!IS_ERR(ov02b10->pwdn_gpio)) |
---|
| 913 | + gpiod_direction_output(ov02b10->pwdn_gpio, 1); |
---|
| 914 | + |
---|
882 | 915 | if (!IS_ERR_OR_NULL(ov02b10->pins_sleep)) { |
---|
883 | 916 | ret = pinctrl_select_state(ov02b10->pinctrl, |
---|
884 | 917 | ov02b10->pins_sleep); |
---|
.. | .. |
---|
888 | 921 | regulator_bulk_disable(OV02B10_NUM_SUPPLIES, ov02b10->supplies); |
---|
889 | 922 | } |
---|
890 | 923 | |
---|
891 | | -static int ov02b10_runtime_resume(struct device *dev) |
---|
| 924 | +static int __maybe_unused ov02b10_runtime_resume(struct device *dev) |
---|
892 | 925 | { |
---|
893 | 926 | struct i2c_client *client = to_i2c_client(dev); |
---|
894 | 927 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
897 | 930 | return __ov02b10_power_on(ov02b10); |
---|
898 | 931 | } |
---|
899 | 932 | |
---|
900 | | -static int ov02b10_runtime_suspend(struct device *dev) |
---|
| 933 | +static int __maybe_unused ov02b10_runtime_suspend(struct device *dev) |
---|
901 | 934 | { |
---|
902 | 935 | struct i2c_client *client = to_i2c_client(dev); |
---|
903 | 936 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
969 | 1002 | static const struct v4l2_subdev_video_ops ov02b10_video_ops = { |
---|
970 | 1003 | .s_stream = ov02b10_s_stream, |
---|
971 | 1004 | .g_frame_interval = ov02b10_g_frame_interval, |
---|
972 | | - .g_mbus_config = ov02b10_g_mbus_config, |
---|
973 | 1005 | }; |
---|
974 | 1006 | |
---|
975 | 1007 | static const struct v4l2_subdev_pad_ops ov02b10_pad_ops = { |
---|
.. | .. |
---|
978 | 1010 | .enum_frame_interval = ov02b10_enum_frame_interval, |
---|
979 | 1011 | .get_fmt = ov02b10_get_fmt, |
---|
980 | 1012 | .set_fmt = ov02b10_set_fmt, |
---|
| 1013 | + .get_mbus_config = ov02b10_g_mbus_config, |
---|
981 | 1014 | }; |
---|
982 | 1015 | |
---|
983 | 1016 | static const struct v4l2_subdev_ops ov02b10_subdev_ops = { |
---|