diff options
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/adv7604.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 88b7984a4188..05f8950f6f91 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
@@ -76,6 +76,7 @@ struct adv7604_state { | |||
76 | struct workqueue_struct *work_queues; | 76 | struct workqueue_struct *work_queues; |
77 | struct delayed_work delayed_work_enable_hotplug; | 77 | struct delayed_work delayed_work_enable_hotplug; |
78 | bool connector_hdmi; | 78 | bool connector_hdmi; |
79 | bool restart_stdi_once; | ||
79 | 80 | ||
80 | /* i2c clients */ | 81 | /* i2c clients */ |
81 | struct i2c_client *i2c_avlink; | 82 | struct i2c_client *i2c_avlink; |
@@ -1297,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | |||
1297 | stdi.lcvs -= 2; | 1298 | stdi.lcvs -= 2; |
1298 | v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs); | 1299 | v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs); |
1299 | if (stdi2dv_timings(sd, &stdi, timings)) { | 1300 | if (stdi2dv_timings(sd, &stdi, timings)) { |
1301 | /* | ||
1302 | * The STDI block may measure wrong values, especially | ||
1303 | * for lcvs and lcf. If the driver can not find any | ||
1304 | * valid timing, the STDI block is restarted to measure | ||
1305 | * the video timings again. The function will return an | ||
1306 | * error, but the restart of STDI will generate a new | ||
1307 | * STDI interrupt and the format detection process will | ||
1308 | * restart. | ||
1309 | */ | ||
1310 | if (state->restart_stdi_once) { | ||
1311 | v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__); | ||
1312 | /* TODO restart STDI for Sync Channel 2 */ | ||
1313 | /* enter one-shot mode */ | ||
1314 | cp_write_and_or(sd, 0x86, 0xf9, 0x00); | ||
1315 | /* trigger STDI restart */ | ||
1316 | cp_write_and_or(sd, 0x86, 0xf9, 0x04); | ||
1317 | /* reset to continuous mode */ | ||
1318 | cp_write_and_or(sd, 0x86, 0xf9, 0x02); | ||
1319 | state->restart_stdi_once = false; | ||
1320 | return -ENOLINK; | ||
1321 | } | ||
1300 | v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); | 1322 | v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); |
1301 | return -ERANGE; | 1323 | return -ERANGE; |
1302 | } | 1324 | } |
1325 | state->restart_stdi_once = true; | ||
1303 | } | 1326 | } |
1304 | found: | 1327 | found: |
1305 | 1328 | ||
@@ -2026,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client, | |||
2026 | v4l2_err(sd, "failed to create all i2c clients\n"); | 2049 | v4l2_err(sd, "failed to create all i2c clients\n"); |
2027 | goto err_i2c; | 2050 | goto err_i2c; |
2028 | } | 2051 | } |
2052 | state->restart_stdi_once = true; | ||
2029 | 2053 | ||
2030 | /* work queues */ | 2054 | /* work queues */ |
2031 | state->work_queues = create_singlethread_workqueue(client->name); | 2055 | state->work_queues = create_singlethread_workqueue(client->name); |