mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
media: i2c: rk628: fix read timing err
Signed-off-by: Chen Shunqing <csq@rock-chips.com> Change-Id: I86ff4e38dd0ffdd36ae407be6d59dea3048226e8
This commit is contained in:
@@ -1552,6 +1552,44 @@ u32 rk628_hdmirx_get_tmdsclk_cnt(struct rk628 *rk628)
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_tmdsclk_cnt);
|
||||
|
||||
struct rk628_timings {
|
||||
int vic;
|
||||
int hactive;
|
||||
int hfp;
|
||||
int hsync;
|
||||
int hbp;
|
||||
int htotal;
|
||||
int vactive;
|
||||
int vfp;
|
||||
int vsync;
|
||||
int vbp;
|
||||
int vtotal;
|
||||
int clock;
|
||||
};
|
||||
|
||||
static const struct rk628_timings pre_timing[] = {
|
||||
{ 2, 720, 16, 62, 60, 858, 480, 9, 6, 30, 525, 27000000 },
|
||||
{ 3, 720, 16, 62, 60, 858, 480, 9, 6, 30, 525, 27000000 },
|
||||
{ 4, 1280, 110, 40, 220, 1650, 720, 5, 5, 20, 750, 74250000},
|
||||
{ 16, 1920, 88, 44, 148, 2200, 1080, 4, 5, 36, 1125, 148500000 },
|
||||
{ 19, 1280, 440, 40, 220, 1980, 720, 5, 5, 20, 750, 74250000},
|
||||
{ 31, 1920, 528, 44, 148, 2640, 1080, 4, 5, 36, 1125, 148500000},
|
||||
{ 32, 1920, 638, 44, 148, 2750, 1080, 4, 5, 36, 1125, 74250000},
|
||||
{ 33, 1920, 528, 44, 148, 2640, 1080, 4, 5, 36, 1125, 74250000},
|
||||
{ 34, 1920, 88, 44, 148, 2200, 1080, 4, 5, 36, 1125, 74250000},
|
||||
{ 62, 1280, 1760, 40, 220, 3300, 720, 5, 5, 20, 750, 74250000},
|
||||
{ 93, 3840, 1276, 88, 296, 5500, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 94, 3840, 1056, 88, 296, 5280, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 95, 3840, 176, 88, 296, 4400, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 96, 3840, 1056, 88, 296, 5280, 2160, 8, 10, 72, 2250, 594000000 },
|
||||
{ 97, 3840, 176, 88, 296, 4400, 2160, 8, 10, 72, 2250, 594000000 },
|
||||
{ 103, 3840, 1276, 88, 296, 5500, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 104, 3840, 1056, 88, 296, 5280, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 105, 3840, 176, 88, 296, 4400, 2160, 8, 10, 72, 2250, 297000000 },
|
||||
{ 106, 3840, 1056, 88, 296, 5280, 2160, 8, 10, 72, 2250, 594000000 },
|
||||
{ 107, 3840, 176, 88, 296, 4400, 2160, 8, 10, 72, 2250, 594000000 },
|
||||
};
|
||||
|
||||
static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
@@ -1564,6 +1602,7 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
u64 tmp_data;
|
||||
u8 video_fmt, vic, color_range, color_space;
|
||||
u32 format;
|
||||
int i, match = 0;
|
||||
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
timings->type = V4L2_DV_BT_656_1120;
|
||||
@@ -1574,55 +1613,6 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
bt->interlaced = val & ILACE_STS ?
|
||||
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HACT_PX, &val);
|
||||
hact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VAL, &val);
|
||||
vact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
htotal = (val >> 16) & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VTL, &val);
|
||||
vtotal = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
hofs_pix = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VOL, &val);
|
||||
vbp = (val & 0xffff) + 1;
|
||||
|
||||
tmdsclk_cnt = rk628_hdmirx_get_tmdsclk_cnt(rk628);
|
||||
tmp_data = tmdsclk_cnt;
|
||||
tmp_data = ((tmp_data * HDMIRX_MODETCLK_HZ) + HDMIRX_MODETCLK_CNT_NUM / 2);
|
||||
do_div(tmp_data, HDMIRX_MODETCLK_CNT_NUM);
|
||||
tmds_clk = tmp_data;
|
||||
if (!htotal || !vtotal || bt->interlaced || vtotal > 3000) {
|
||||
dev_err(rk628->dev, "timing err, %s htotal:%d, vtotal:%d\n",
|
||||
bt->interlaced ? "interlaced is not supported," : "",
|
||||
htotal, vtotal);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
fps = tmds_clk / (htotal * vtotal);
|
||||
else
|
||||
fps = (tmds_clk + (htotal * vtotal) / 2) / (htotal * vtotal);
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT0, &val);
|
||||
modetclk_cnt_hs = val & 0xffff;
|
||||
hs = (tmdsclk_cnt * modetclk_cnt_hs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VSC, &val);
|
||||
modetclk_cnt_vs = val & 0xffff;
|
||||
vs = (tmdsclk_cnt * modetclk_cnt_vs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
vs = (vs + htotal / 2) / htotal;
|
||||
|
||||
if ((hofs_pix < hs) || (htotal < (hact + hofs_pix)) ||
|
||||
(vtotal < (vact + vs + vbp)) || !vs) {
|
||||
dev_err(rk628->dev, "timing err, total:%dx%d, act:%dx%d, hofs:%d, hs:%d, vs:%d, vbp:%d\n",
|
||||
htotal, vtotal, hact, vact, hofs_pix, hs, vs, vbp);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
hbp = hofs_pix - hs;
|
||||
hfp = htotal - hact - hofs_pix;
|
||||
vfp = vtotal - vact - vs - vbp;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
vic = (val & VID_IDENT_CODE_MASK) >> 24;
|
||||
@@ -1637,28 +1627,101 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
rk628->color_space = color_space;
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_STS, &val);
|
||||
rk628->dvi_mode = val & DVI_DET;
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
//format:color depth, 5: 10bit, 4: 8bit
|
||||
if (format == 5) {
|
||||
htotal = htotal * 2 * 8 / 10;
|
||||
hact = hact * 2 * 8 / 10;
|
||||
hfp = hfp * 2 * 8 / 10;
|
||||
hbp = hbp * 2 * 8 / 10;
|
||||
hs = hs * 2 * 8 / 10;
|
||||
} else {
|
||||
htotal *= 2;
|
||||
hact *= 2;
|
||||
hfp *= 2;
|
||||
hbp *= 2;
|
||||
hs *= 2;
|
||||
|
||||
for (i = 0; vic && i < ARRAY_SIZE(pre_timing); i++) {
|
||||
if (vic == pre_timing[i].vic) {
|
||||
hact = pre_timing[i].hactive;
|
||||
hfp = pre_timing[i].hfp;
|
||||
hs = pre_timing[i].hsync;
|
||||
hbp = pre_timing[i].hbp;
|
||||
htotal = pre_timing[i].htotal;
|
||||
vact = pre_timing[i].vactive;
|
||||
vfp = pre_timing[i].vfp;
|
||||
vs = pre_timing[i].vsync;
|
||||
vbp = pre_timing[i].vbp;
|
||||
vtotal = pre_timing[i].vtotal;
|
||||
tmds_clk = pre_timing[i].clock;
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rk628_dbg(rk628, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
|
||||
HDMIRX_MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs, modetclk_cnt_vs, hofs_pix);
|
||||
if (!match) {
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HACT_PX, &val);
|
||||
hact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VAL, &val);
|
||||
vact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
htotal = (val >> 16) & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VTL, &val);
|
||||
vtotal = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
hofs_pix = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VOL, &val);
|
||||
vbp = (val & 0xffff) + 1;
|
||||
|
||||
tmdsclk_cnt = rk628_hdmirx_get_tmdsclk_cnt(rk628);
|
||||
tmp_data = tmdsclk_cnt;
|
||||
tmp_data = ((tmp_data * HDMIRX_MODETCLK_HZ) + HDMIRX_MODETCLK_CNT_NUM / 2);
|
||||
do_div(tmp_data, HDMIRX_MODETCLK_CNT_NUM);
|
||||
tmds_clk = tmp_data;
|
||||
if (!htotal || !vtotal || bt->interlaced || vtotal > 3000) {
|
||||
dev_err(rk628->dev, "timing err, %s htotal:%d, vtotal:%d\n",
|
||||
bt->interlaced ? "interlaced is not supported," : "",
|
||||
htotal, vtotal);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT0, &val);
|
||||
modetclk_cnt_hs = val & 0xffff;
|
||||
hs = (tmdsclk_cnt * modetclk_cnt_hs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VSC, &val);
|
||||
modetclk_cnt_vs = val & 0xffff;
|
||||
vs = (tmdsclk_cnt * modetclk_cnt_vs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
vs = (vs + htotal / 2) / htotal;
|
||||
|
||||
if ((hofs_pix < hs) || (htotal < (hact + hofs_pix)) ||
|
||||
(vtotal < (vact + vs + vbp)) || !vs) {
|
||||
dev_err(rk628->dev, "timing err, total:%dx%d, act:%dx%d, hofs:%d, hs:%d, vs:%d, vbp:%d\n",
|
||||
htotal, vtotal, hact, vact, hofs_pix, hs, vs, vbp);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
hbp = hofs_pix - hs;
|
||||
hfp = htotal - hact - hofs_pix;
|
||||
vfp = vtotal - vact - vs - vbp;
|
||||
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
//format:color depth, 5: 10bit, 4: 8bit
|
||||
if (format == 5) {
|
||||
htotal = htotal * 2 * 8 / 10;
|
||||
hact = hact * 2 * 8 / 10;
|
||||
hfp = hfp * 2 * 8 / 10;
|
||||
hbp = hbp * 2 * 8 / 10;
|
||||
hs = hs * 2 * 8 / 10;
|
||||
} else {
|
||||
htotal *= 2;
|
||||
hact *= 2;
|
||||
hfp *= 2;
|
||||
hbp *= 2;
|
||||
hs *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
rk628_dbg(rk628, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
|
||||
HDMIRX_MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs,
|
||||
modetclk_cnt_vs, hofs_pix);
|
||||
}
|
||||
|
||||
rk628_dbg(rk628, "get current aviif: vic:%d, color_range: %s, color_space %s",
|
||||
vic, bus_color_range_str[color_range], bus_color_space_str[color_space]);
|
||||
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
fps = tmds_clk / (htotal * vtotal);
|
||||
else
|
||||
fps = (tmds_clk + (htotal * vtotal) / 2) / (htotal * vtotal);
|
||||
bt->width = hact;
|
||||
bt->height = vact;
|
||||
bt->hfrontporch = hfp;
|
||||
@@ -1677,12 +1740,14 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
bt->il_vsync = bt->vsync + 1;
|
||||
bt->pixelclock /= 2;
|
||||
}
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
if (format == 5) {
|
||||
bt->pixelclock = bt->pixelclock * 8 * 2;
|
||||
do_div(bt->pixelclock, 10);
|
||||
} else {
|
||||
bt->pixelclock *= 2;
|
||||
if (!match) {
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
if (format == 5) {
|
||||
bt->pixelclock = bt->pixelclock * 8 * 2;
|
||||
do_div(bt->pixelclock, 10);
|
||||
} else {
|
||||
bt->pixelclock *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user