media: i2c: rk628: fix read timing err

Signed-off-by: Chen Shunqing <csq@rock-chips.com>
Change-Id: I86ff4e38dd0ffdd36ae407be6d59dea3048226e8
This commit is contained in:
Chen Shunqing
2025-04-16 10:52:52 +08:00
committed by Tao Huang
parent 3a35a943a2
commit fdca11283f

View File

@@ -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;
}
}
}