aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2010-03-13 18:22:34 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-17 23:47:15 -0400
commit2443baeaa01388f56824c55c087510312b8d8197 (patch)
treee23643dce16babebfad3087dbb103249a28dec2d /drivers/media
parentf978ac90b2cfa79cb075f74fd5c403e9f9ec4246 (diff)
V4L/DVB: ivtv: Avoid hard system lock on decoder output mode change
Changing the decoder video standard just prior to, or during, the output of the lower field may result in a hard system lock. To avoid this, try to ensure the firmware call occurs only during the first 100 lines of the top field. (Minor comment addition and a line break added Andy Walls <awalls@radix.net>.) Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c5
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c21
2 files changed, 25 insertions, 1 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 9a250548be4d..1b79475ca134 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1293,7 +1293,6 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1293 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); 1293 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
1294 ivtv_init_mpeg_decoder(itv); 1294 ivtv_init_mpeg_decoder(itv);
1295 } 1295 }
1296 ivtv_s_std(NULL, &fh, &itv->tuner_std);
1297 1296
1298 /* On a cx23416 this seems to be able to enable DMA to the chip? */ 1297 /* On a cx23416 this seems to be able to enable DMA to the chip? */
1299 if (!itv->has_cx23415) 1298 if (!itv->has_cx23415)
@@ -1310,6 +1309,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1310 } 1309 }
1311 else 1310 else
1312 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); 1311 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
1312
1313 /* For cards with video out, this call needs interrupts enabled */
1314 ivtv_s_std(NULL, &fh, &itv->tuner_std);
1315
1313 return 0; 1316 return 0;
1314} 1317}
1315 1318
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 99f3c39a118b..2192bc42c6b6 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1087,8 +1087,10 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1087 1087
1088int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) 1088int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1089{ 1089{
1090 DEFINE_WAIT(wait);
1090 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; 1091 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1091 struct yuv_playback_info *yi = &itv->yuv_info; 1092 struct yuv_playback_info *yi = &itv->yuv_info;
1093 int f;
1092 1094
1093 if ((*std & V4L2_STD_ALL) == 0) 1095 if ((*std & V4L2_STD_ALL) == 0)
1094 return -EINVAL; 1096 return -EINVAL;
@@ -1128,6 +1130,25 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1128 itv->is_out_60hz = itv->is_60hz; 1130 itv->is_out_60hz = itv->is_60hz;
1129 itv->is_out_50hz = itv->is_50hz; 1131 itv->is_out_50hz = itv->is_50hz;
1130 ivtv_call_all(itv, video, s_std_output, itv->std_out); 1132 ivtv_call_all(itv, video, s_std_output, itv->std_out);
1133
1134 /*
1135 * The next firmware call is time sensitive. Time it to
1136 * avoid risk of a hard lock, by trying to ensure the call
1137 * happens within the first 100 lines of the top field.
1138 * Make 4 attempts to sync to the decoder before giving up.
1139 */
1140 for (f = 0; f < 4; f++) {
1141 prepare_to_wait(&itv->vsync_waitq, &wait,
1142 TASK_UNINTERRUPTIBLE);
1143 if ((read_reg(0x28c0) >> 16) < 100)
1144 break;
1145 schedule_timeout(msecs_to_jiffies(25));
1146 }
1147 finish_wait(&itv->vsync_waitq, &wait);
1148
1149 if (f == 4)
1150 IVTV_WARN("Mode change failed to sync to decoder\n");
1151
1131 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); 1152 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1132 itv->main_rect.left = itv->main_rect.top = 0; 1153 itv->main_rect.left = itv->main_rect.top = 0;
1133 itv->main_rect.width = 720; 1154 itv->main_rect.width = 720;