|
34 | 34 |
|
35 | 35 | #define OV5640_DEFAULT_SLAVE_ID 0x3c
|
36 | 36 |
|
| 37 | +#define OV5640_REG_SYS_CTRL0 0x3008 |
37 | 38 | #define OV5640_REG_CHIP_ID 0x300a
|
| 39 | +#define OV5640_REG_IO_MIPI_CTRL00 0x300e |
| 40 | +#define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017 |
| 41 | +#define OV5640_REG_PAD_OUTPUT_ENABLE02 0x3018 |
38 | 42 | #define OV5640_REG_PAD_OUTPUT00 0x3019
|
| 43 | +#define OV5640_REG_SYSTEM_CONTROL1 0x302e |
39 | 44 | #define OV5640_REG_SC_PLL_CTRL0 0x3034
|
40 | 45 | #define OV5640_REG_SC_PLL_CTRL1 0x3035
|
41 | 46 | #define OV5640_REG_SC_PLL_CTRL2 0x3036
|
42 | 47 | #define OV5640_REG_SC_PLL_CTRL3 0x3037
|
43 | 48 | #define OV5640_REG_SLAVE_ID 0x3100
|
| 49 | +#define OV5640_REG_SCCB_SYS_CTRL1 0x3103 |
44 | 50 | #define OV5640_REG_SYS_ROOT_DIVIDER 0x3108
|
45 | 51 | #define OV5640_REG_AWB_R_GAIN 0x3400
|
46 | 52 | #define OV5640_REG_AWB_G_GAIN 0x3402
|
|
70 | 76 | #define OV5640_REG_HZ5060_CTRL01 0x3c01
|
71 | 77 | #define OV5640_REG_SIGMADELTA_CTRL0C 0x3c0c
|
72 | 78 | #define OV5640_REG_FRAME_CTRL01 0x4202
|
| 79 | +#define OV5640_REG_POLARITY_CTRL00 0x4740 |
73 | 80 | #define OV5640_REG_MIPI_CTRL00 0x4800
|
74 | 81 | #define OV5640_REG_DEBUG_MODE 0x4814
|
75 | 82 | #define OV5640_REG_PRE_ISP_TEST_SET1 0x503d
|
@@ -982,7 +989,111 @@ static int ov5640_get_gain(struct ov5640_dev *sensor)
|
982 | 989 | return gain & 0x3ff;
|
983 | 990 | }
|
984 | 991 |
|
985 |
| -static int ov5640_set_stream(struct ov5640_dev *sensor, bool on) |
| 992 | +static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on) |
| 993 | +{ |
| 994 | + int ret; |
| 995 | + unsigned int flags = sensor->ep.bus.parallel.flags; |
| 996 | + u8 pclk_pol = 0; |
| 997 | + u8 hsync_pol = 0; |
| 998 | + u8 vsync_pol = 0; |
| 999 | + |
| 1000 | + /* |
| 1001 | + * Note about parallel port configuration. |
| 1002 | + * |
| 1003 | + * When configured in parallel mode, the OV5640 will |
| 1004 | + * output 10 bits data on DVP data lines [9:0]. |
| 1005 | + * If only 8 bits data are wanted, the 8 bits data lines |
| 1006 | + * of the camera interface must be physically connected |
| 1007 | + * on the DVP data lines [9:2]. |
| 1008 | + * |
| 1009 | + * Control lines polarity can be configured through |
| 1010 | + * devicetree endpoint control lines properties. |
| 1011 | + * If no endpoint control lines properties are set, |
| 1012 | + * polarity will be as below: |
| 1013 | + * - VSYNC: active high |
| 1014 | + * - HREF: active low |
| 1015 | + * - PCLK: active low |
| 1016 | + */ |
| 1017 | + |
| 1018 | + if (on) { |
| 1019 | + /* |
| 1020 | + * reset MIPI PCLK/SERCLK divider |
| 1021 | + * |
| 1022 | + * SC PLL CONTRL1 0 |
| 1023 | + * - [3..0]: MIPI PCLK/SERCLK divider |
| 1024 | + */ |
| 1025 | + ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0x0f, 0); |
| 1026 | + if (ret) |
| 1027 | + return ret; |
| 1028 | + |
| 1029 | + /* |
| 1030 | + * configure parallel port control lines polarity |
| 1031 | + * |
| 1032 | + * POLARITY CTRL0 |
| 1033 | + * - [5]: PCLK polarity (0: active low, 1: active high) |
| 1034 | + * - [1]: HREF polarity (0: active low, 1: active high) |
| 1035 | + * - [0]: VSYNC polarity (mismatch here between |
| 1036 | + * datasheet and hardware, 0 is active high |
| 1037 | + * and 1 is active low...) |
| 1038 | + */ |
| 1039 | + if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) |
| 1040 | + pclk_pol = 1; |
| 1041 | + if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) |
| 1042 | + hsync_pol = 1; |
| 1043 | + if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) |
| 1044 | + vsync_pol = 1; |
| 1045 | + |
| 1046 | + ret = ov5640_write_reg(sensor, |
| 1047 | + OV5640_REG_POLARITY_CTRL00, |
| 1048 | + (pclk_pol << 5) | |
| 1049 | + (hsync_pol << 1) | |
| 1050 | + vsync_pol); |
| 1051 | + |
| 1052 | + if (ret) |
| 1053 | + return ret; |
| 1054 | + } |
| 1055 | + |
| 1056 | + /* |
| 1057 | + * powerdown MIPI TX/RX PHY & disable MIPI |
| 1058 | + * |
| 1059 | + * MIPI CONTROL 00 |
| 1060 | + * 4: PWDN PHY TX |
| 1061 | + * 3: PWDN PHY RX |
| 1062 | + * 2: MIPI enable |
| 1063 | + */ |
| 1064 | + ret = ov5640_write_reg(sensor, |
| 1065 | + OV5640_REG_IO_MIPI_CTRL00, on ? 0x18 : 0); |
| 1066 | + if (ret) |
| 1067 | + return ret; |
| 1068 | + |
| 1069 | + /* |
| 1070 | + * enable VSYNC/HREF/PCLK DVP control lines |
| 1071 | + * & D[9:6] DVP data lines |
| 1072 | + * |
| 1073 | + * PAD OUTPUT ENABLE 01 |
| 1074 | + * - 6: VSYNC output enable |
| 1075 | + * - 5: HREF output enable |
| 1076 | + * - 4: PCLK output enable |
| 1077 | + * - [3:0]: D[9:6] output enable |
| 1078 | + */ |
| 1079 | + ret = ov5640_write_reg(sensor, |
| 1080 | + OV5640_REG_PAD_OUTPUT_ENABLE01, |
| 1081 | + on ? 0x7f : 0); |
| 1082 | + if (ret) |
| 1083 | + return ret; |
| 1084 | + |
| 1085 | + /* |
| 1086 | + * enable D[5:0] DVP data lines |
| 1087 | + * |
| 1088 | + * PAD OUTPUT ENABLE 02 |
| 1089 | + * - [7:2]: D[5:0] output enable |
| 1090 | + */ |
| 1091 | + return ov5640_write_reg(sensor, |
| 1092 | + OV5640_REG_PAD_OUTPUT_ENABLE02, |
| 1093 | + on ? 0xfc : 0); |
| 1094 | +} |
| 1095 | + |
| 1096 | +static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on) |
986 | 1097 | {
|
987 | 1098 | int ret;
|
988 | 1099 |
|
@@ -1604,17 +1715,19 @@ static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
|
1604 | 1715 | if (ret)
|
1605 | 1716 | goto power_off;
|
1606 | 1717 |
|
1607 |
| - /* |
1608 |
| - * start streaming briefly followed by stream off in |
1609 |
| - * order to coax the clock lane into LP-11 state. |
1610 |
| - */ |
1611 |
| - ret = ov5640_set_stream(sensor, true); |
1612 |
| - if (ret) |
1613 |
| - goto power_off; |
1614 |
| - usleep_range(1000, 2000); |
1615 |
| - ret = ov5640_set_stream(sensor, false); |
1616 |
| - if (ret) |
1617 |
| - goto power_off; |
| 1718 | + if (sensor->ep.bus_type == V4L2_MBUS_CSI2) { |
| 1719 | + /* |
| 1720 | + * start streaming briefly followed by stream off in |
| 1721 | + * order to coax the clock lane into LP-11 state. |
| 1722 | + */ |
| 1723 | + ret = ov5640_set_stream_mipi(sensor, true); |
| 1724 | + if (ret) |
| 1725 | + goto power_off; |
| 1726 | + usleep_range(1000, 2000); |
| 1727 | + ret = ov5640_set_stream_mipi(sensor, false); |
| 1728 | + if (ret) |
| 1729 | + goto power_off; |
| 1730 | + } |
1618 | 1731 |
|
1619 | 1732 | return 0;
|
1620 | 1733 | }
|
@@ -2188,7 +2301,11 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
|
2188 | 2301 | goto out;
|
2189 | 2302 | }
|
2190 | 2303 |
|
2191 |
| - ret = ov5640_set_stream(sensor, enable); |
| 2304 | + if (sensor->ep.bus_type == V4L2_MBUS_CSI2) |
| 2305 | + ret = ov5640_set_stream_mipi(sensor, enable); |
| 2306 | + else |
| 2307 | + ret = ov5640_set_stream_dvp(sensor, enable); |
| 2308 | + |
2192 | 2309 | if (!ret)
|
2193 | 2310 | sensor->streaming = enable;
|
2194 | 2311 | }
|
@@ -2301,11 +2418,6 @@ static int ov5640_probe(struct i2c_client *client,
|
2301 | 2418 | return ret;
|
2302 | 2419 | }
|
2303 | 2420 |
|
2304 |
| - if (sensor->ep.bus_type != V4L2_MBUS_CSI2) { |
2305 |
| - dev_err(dev, "invalid bus type, must be MIPI CSI2\n"); |
2306 |
| - return -EINVAL; |
2307 |
| - } |
2308 |
| - |
2309 | 2421 | /* get system clock (xclk) */
|
2310 | 2422 | sensor->xclk = devm_clk_get(dev, "xclk");
|
2311 | 2423 | if (IS_ERR(sensor->xclk)) {
|
|
0 commit comments