mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
media: i2c: tc35874x: support interlace output
Change-Id: I62025a9fcea726791aeed8a5e993e74f2e748d1c Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user