Skip to content

Commit f22996d

Browse files
hfr72mchehab
authored andcommitted
media: ov5640: add support of DVP parallel interface
Add support of DVP parallel mode in addition of existing MIPI CSI mode. The choice between two modes and configuration is made through device tree. Signed-off-by: Hugues Fruchet <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 495f014 commit f22996d

File tree

1 file changed

+130
-18
lines changed

1 file changed

+130
-18
lines changed

drivers/media/i2c/ov5640.c

+130-18
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,19 @@
3434

3535
#define OV5640_DEFAULT_SLAVE_ID 0x3c
3636

37+
#define OV5640_REG_SYS_CTRL0 0x3008
3738
#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
3842
#define OV5640_REG_PAD_OUTPUT00 0x3019
43+
#define OV5640_REG_SYSTEM_CONTROL1 0x302e
3944
#define OV5640_REG_SC_PLL_CTRL0 0x3034
4045
#define OV5640_REG_SC_PLL_CTRL1 0x3035
4146
#define OV5640_REG_SC_PLL_CTRL2 0x3036
4247
#define OV5640_REG_SC_PLL_CTRL3 0x3037
4348
#define OV5640_REG_SLAVE_ID 0x3100
49+
#define OV5640_REG_SCCB_SYS_CTRL1 0x3103
4450
#define OV5640_REG_SYS_ROOT_DIVIDER 0x3108
4551
#define OV5640_REG_AWB_R_GAIN 0x3400
4652
#define OV5640_REG_AWB_G_GAIN 0x3402
@@ -70,6 +76,7 @@
7076
#define OV5640_REG_HZ5060_CTRL01 0x3c01
7177
#define OV5640_REG_SIGMADELTA_CTRL0C 0x3c0c
7278
#define OV5640_REG_FRAME_CTRL01 0x4202
79+
#define OV5640_REG_POLARITY_CTRL00 0x4740
7380
#define OV5640_REG_MIPI_CTRL00 0x4800
7481
#define OV5640_REG_DEBUG_MODE 0x4814
7582
#define OV5640_REG_PRE_ISP_TEST_SET1 0x503d
@@ -982,7 +989,111 @@ static int ov5640_get_gain(struct ov5640_dev *sensor)
982989
return gain & 0x3ff;
983990
}
984991

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)
9861097
{
9871098
int ret;
9881099

@@ -1604,17 +1715,19 @@ static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
16041715
if (ret)
16051716
goto power_off;
16061717

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+
}
16181731

16191732
return 0;
16201733
}
@@ -2188,7 +2301,11 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
21882301
goto out;
21892302
}
21902303

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+
21922309
if (!ret)
21932310
sensor->streaming = enable;
21942311
}
@@ -2301,11 +2418,6 @@ static int ov5640_probe(struct i2c_client *client,
23012418
return ret;
23022419
}
23032420

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-
23092421
/* get system clock (xclk) */
23102422
sensor->xclk = devm_clk_get(dev, "xclk");
23112423
if (IS_ERR(sensor->xclk)) {

0 commit comments

Comments
 (0)