Commit 6e9071f2 authored by Martin Bugge's avatar Martin Bugge Committed by Mauro Carvalho Chehab

[media] adv7842: restart STDI once if format is not found

The STDI block may measure wrong values, especially for lcvs and lcf.
If the driver can not find any valid timing, the STDI block is restarted
to measure the video timings again. The function will return an error,
but the restart of STDI will generate a new STDI interrupt and the format
detection process will restart.

Copied from adv7604.
Signed-off-by: default avatarMartin Bugge <marbugge@cisco.com>
Cc: Mats Randgaard <matrandg@cisco.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent fc2e991e
...@@ -85,6 +85,7 @@ struct adv7842_state { ...@@ -85,6 +85,7 @@ struct adv7842_state {
bool is_cea_format; bool is_cea_format;
struct workqueue_struct *work_queues; struct workqueue_struct *work_queues;
struct delayed_work delayed_work_enable_hotplug; struct delayed_work delayed_work_enable_hotplug;
bool restart_stdi_once;
bool hdmi_port_a; bool hdmi_port_a;
/* i2c clients */ /* i2c clients */
...@@ -1345,6 +1346,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, ...@@ -1345,6 +1346,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
/* read STDI */ /* read STDI */
if (read_stdi(sd, &stdi)) { if (read_stdi(sd, &stdi)) {
state->restart_stdi_once = true;
v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__);
return -ENOLINK; return -ENOLINK;
} }
...@@ -1355,6 +1357,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, ...@@ -1355,6 +1357,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
uint32_t freq; uint32_t freq;
timings->type = V4L2_DV_BT_656_1120; timings->type = V4L2_DV_BT_656_1120;
bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
freq = (hdmi_read(sd, 0x06) * 1000000) + freq = (hdmi_read(sd, 0x06) * 1000000) +
...@@ -1391,21 +1394,50 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, ...@@ -1391,21 +1394,50 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
} }
adv7842_fill_optional_dv_timings_fields(sd, timings); adv7842_fill_optional_dv_timings_fields(sd, timings);
} else { } else {
/* Interlaced? */ /* find format
if (stdi.interlaced) { * Since LCVS values are inaccurate [REF_03, p. 339-340],
v4l2_dbg(1, debug, sd, "%s: interlaced video not supported\n", __func__); * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
return -ERANGE; */
} if (!stdi2dv_timings(sd, &stdi, timings))
goto found;
stdi.lcvs += 1;
v4l2_dbg(1, debug, sd, "%s: lcvs + 1 = %d\n", __func__, stdi.lcvs);
if (!stdi2dv_timings(sd, &stdi, timings))
goto found;
stdi.lcvs -= 2;
v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
if (stdi2dv_timings(sd, &stdi, timings)) { if (stdi2dv_timings(sd, &stdi, timings)) {
/*
* The STDI block may measure wrong values, especially
* for lcvs and lcf. If the driver can not find any
* valid timing, the STDI block is restarted to measure
* the video timings again. The function will return an
* error, but the restart of STDI will generate a new
* STDI interrupt and the format detection process will
* restart.
*/
if (state->restart_stdi_once) {
v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
/* TODO restart STDI for Sync Channel 2 */
/* enter one-shot mode */
cp_write_and_or(sd, 0x86, 0xf9, 0x00);
/* trigger STDI restart */
cp_write_and_or(sd, 0x86, 0xf9, 0x04);
/* reset to continuous mode */
cp_write_and_or(sd, 0x86, 0xf9, 0x02);
state->restart_stdi_once = false;
return -ENOLINK;
}
v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
return -ERANGE; return -ERANGE;
} }
state->restart_stdi_once = true;
} }
found:
if (debug > 1) if (debug > 1)
v4l2_print_dv_timings(sd->name, "adv7842_query_dv_timings: ", v4l2_print_dv_timings(sd->name, "adv7842_query_dv_timings:",
timings, true); timings, true);
return 0; return 0;
} }
...@@ -2804,6 +2836,7 @@ static int adv7842_probe(struct i2c_client *client, ...@@ -2804,6 +2836,7 @@ static int adv7842_probe(struct i2c_client *client,
state->mode = pdata->mode; state->mode = pdata->mode;
state->hdmi_port_a = pdata->input == ADV7842_SELECT_HDMI_PORT_A; state->hdmi_port_a = pdata->input == ADV7842_SELECT_HDMI_PORT_A;
state->restart_stdi_once = true;
/* i2c access to adv7842? */ /* i2c access to adv7842? */
rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 | rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment