summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorCai YiWei <cyw@rock-chips.com>2018-12-29 17:47:03 +0800
committerTao Huang <huangtao@rock-chips.com>2019-01-03 19:04:50 +0800
commitb25f7aefe04509ea4dd00d818b197fa15bea161d (patch)
treec79d4a7579f6aea0308d4887e780d90b1eccc61d /drivers/media
parent70f89eed1a95f4681ca1d7e294459a83252ae30d (diff)
media: i2c: tc35874x: support interlace output
Change-Id: I62025a9fcea726791aeed8a5e993e74f2e748d1c Signed-off-by: Cai YiWei <cyw@rock-chips.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/i2c/tc35874x.c67
-rw-r--r--drivers/media/i2c/tc35874x_regs.h7
2 files changed, 54 insertions, 20 deletions
diff --git a/drivers/media/i2c/tc35874x.c b/drivers/media/i2c/tc35874x.c
index 9c7f4270567d..1932bad41602 100644
--- a/drivers/media/i2c/tc35874x.c
+++ b/drivers/media/i2c/tc35874x.c
@@ -80,14 +80,14 @@ static const struct v4l2_dv_timings_cap tc35874x_timings_cap = {
V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 165000000,
V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
- V4L2_DV_BT_CAP_PROGRESSIVE |
+ V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED |
V4L2_DV_BT_CAP_REDUCED_BLANKING |
V4L2_DV_BT_CAP_CUSTOM)
};
static u8 EDID_1920x1080_60[] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
- 0x52, 0x62, 0x88, 0x88, 0x00, 0x88, 0x88, 0x88,
+ 0x52, 0x62, 0x01, 0x88, 0x00, 0x88, 0x88, 0x88,
0x1C, 0x15, 0x01, 0x03, 0x80, 0x00, 0x00, 0x78,
0x0A, 0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27,
0x12, 0x48, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x01,
@@ -98,10 +98,29 @@ static u8 EDID_1920x1080_60[] = {
0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20,
0x6E, 0x28, 0x55, 0x00, 0xC4, 0x8E, 0x21, 0x00,
0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x54,
- 0x6F, 0x73, 0x68, 0x69, 0x62, 0x61, 0x2D, 0x48,
- 0x32, 0x44, 0x0A, 0x20, 0x00, 0x00, 0x00, 0xFD,
- 0x00, 0x17, 0x3D, 0x0F, 0x8C, 0x17, 0x00, 0x0A,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x92,
+ 0x37, 0x34, 0x39, 0x2D, 0x66, 0x48, 0x44, 0x37,
+ 0x32, 0x30, 0x0A, 0x20, 0x00, 0x00, 0x00, 0xFD,
+ 0x00, 0x14, 0x78, 0x01, 0xFF, 0x1D, 0x00, 0x0A,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x7B,
+};
+
+static u8 EDID_extend[] = {
+ 0x02, 0x03, 0x1A, 0x71, 0x47, 0x90, 0x04, 0x02,
+ 0x01, 0x11, 0x22, 0x05, 0x23, 0x09, 0x07, 0x01,
+ 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0C, 0x00,
+ 0x10, 0x00, 0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0,
+ 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0x13, 0x8E,
+ 0x21, 0x00, 0x00, 0x1E, 0xD8, 0x09, 0x80, 0xA0,
+ 0x20, 0xE0, 0x2D, 0x10, 0x10, 0x60, 0xA2, 0x00,
+ 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x18, 0x8C, 0x0A,
+ 0xD0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0C, 0x40,
+ 0x55, 0x00, 0x48, 0x39, 0x00, 0x00, 0x00, 0x18,
+ 0x01, 0x1D, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40,
+ 0x58, 0x2C, 0x45, 0x00, 0xC0, 0x6C, 0x00, 0x00,
+ 0x00, 0x18, 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C,
+ 0x16, 0x20, 0x58, 0x2C, 0x25, 0x00, 0xC0, 0x6C,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
};
struct tc35874x_state {
@@ -589,22 +608,24 @@ static void tc35874x_set_pll(struct v4l2_subdev *sd)
u16 pllctl0_new = SET_PLL_PRD(pdata->pll_prd) |
SET_PLL_FBD(pdata->pll_fbd);
u32 hsck = (pdata->refclk_hz / pdata->pll_prd) * pdata->pll_fbd;
+ u16 pll_frs;
v4l2_dbg(2, debug, sd, "%s:\n", __func__);
+ if (state->timings.bt.interlaced)
+ hsck /= 2;
+ if (hsck > 500000000)
+ pll_frs = 0x0;
+ else if (hsck > 250000000)
+ pll_frs = 0x1;
+ else if (hsck > 125000000)
+ pll_frs = 0x2;
+ else
+ pll_frs = 0x3;
/* Only rewrite when needed (new value or disabled), since rewriting
* triggers another format change event. */
- if ((pllctl0 != pllctl0_new) || ((pllctl1 & MASK_PLL_EN) == 0)) {
- u16 pll_frs;
-
- if (hsck > 500000000)
- pll_frs = 0x0;
- else if (hsck > 250000000)
- pll_frs = 0x1;
- else if (hsck > 125000000)
- pll_frs = 0x2;
- else
- pll_frs = 0x3;
+ if (pllctl0 != pllctl0_new || (pllctl1 & MASK_PLL_EN) == 0 ||
+ SET_PLL_FRS(pll_frs) != (pllctl1 & MASK_PLL_FRS)) {
v4l2_dbg(1, debug, sd, "%s: updating PLL clock\n", __func__);
tc35874x_sleep_mode(sd, true);
@@ -1535,7 +1556,9 @@ static int tc35874x_get_fmt(struct v4l2_subdev *sd,
format->format.code = state->mbus_fmt_code;
format->format.width = state->timings.bt.width;
format->format.height = state->timings.bt.height;
- format->format.field = V4L2_FIELD_NONE;
+ format->format.field =
+ state->timings.bt.interlaced ?
+ V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
switch (vi_rep & MASK_VOUT_COLOR_SEL) {
case MASK_VOUT_COLOR_RGB_FULL:
@@ -1657,11 +1680,17 @@ static int tc35874x_s_edid(struct v4l2_subdev *sd,
return 0;
}
- for (i = 0; i < edid_len; i += EDID_BLOCK_SIZE)
+ for (i = 0; i < edid_len; i += EDID_BLOCK_SIZE) {
i2c_wr(sd, EDID_RAM + i, edid->edid + i, EDID_BLOCK_SIZE);
+ i2c_wr(sd, EDID_EXT_RAM + i, EDID_extend + i, EDID_BLOCK_SIZE);
+ }
state->edid_blocks_written = edid->blocks;
+ /* frame count number: FS = FE 1,2,1,2... */
+ i2c_wr16(sd, FCCTL, 0x0002);
+ /* packet id for interlace mode only */
+ i2c_wr16(sd, PACKETID1, 0x1e1e);
if (tx_5v_power_present(sd))
tc35874x_enable_edid(sd);
diff --git a/drivers/media/i2c/tc35874x_regs.h b/drivers/media/i2c/tc35874x_regs.h
index b441d2dcfc46..4a21f0d5e0df 100644
--- a/drivers/media/i2c/tc35874x_regs.h
+++ b/drivers/media/i2c/tc35874x_regs.h
@@ -67,6 +67,10 @@
#define FIFOCTL 0x0006
+#define PACKETID1 0x000C
+
+#define FCCTL 0x0012
+
#define INTSTATUS 0x0014
#define MASK_AMUTE_INT 0x0400
#define MASK_HDMI_INT 0x0200
@@ -678,6 +682,7 @@
#define MASK_MAX_EXCED 0x08
#define EDID_RAM 0x8C00
+#define EDID_EXT_RAM 0x8c80
#define NO_GDB_LIMIT 0x9007
-#endif \ No newline at end of file
+#endif