Skip to content

Commit

Permalink
V4L/DVB: ivtv: Avoid hard system lock on decoder output mode change
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ian Armstrong authored and Mauro Carvalho Chehab committed May 18, 2010
1 parent f978ac9 commit 2443bae
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
5 changes: 4 additions & 1 deletion drivers/media/video/ivtv/ivtv-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,6 @@ int ivtv_init_on_first_open(struct ivtv *itv)
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
ivtv_init_mpeg_decoder(itv);
}
ivtv_s_std(NULL, &fh, &itv->tuner_std);

/* On a cx23416 this seems to be able to enable DMA to the chip? */
if (!itv->has_cx23415)
Expand All @@ -1310,6 +1309,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
}
else
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);

/* For cards with video out, this call needs interrupts enabled */
ivtv_s_std(NULL, &fh, &itv->tuner_std);

return 0;
}

Expand Down
21 changes: 21 additions & 0 deletions drivers/media/video/ivtv/ivtv-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,8 +1087,10 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)

int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
{
DEFINE_WAIT(wait);
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
struct yuv_playback_info *yi = &itv->yuv_info;
int f;

if ((*std & V4L2_STD_ALL) == 0)
return -EINVAL;
Expand Down Expand Up @@ -1128,6 +1130,25 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
itv->is_out_60hz = itv->is_60hz;
itv->is_out_50hz = itv->is_50hz;
ivtv_call_all(itv, video, s_std_output, itv->std_out);

/*
* The next firmware call is time sensitive. Time it to
* avoid risk of a hard lock, by trying to ensure the call
* happens within the first 100 lines of the top field.
* Make 4 attempts to sync to the decoder before giving up.
*/
for (f = 0; f < 4; f++) {
prepare_to_wait(&itv->vsync_waitq, &wait,
TASK_UNINTERRUPTIBLE);
if ((read_reg(0x28c0) >> 16) < 100)
break;
schedule_timeout(msecs_to_jiffies(25));
}
finish_wait(&itv->vsync_waitq, &wait);

if (f == 4)
IVTV_WARN("Mode change failed to sync to decoder\n");

ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
itv->main_rect.left = itv->main_rect.top = 0;
itv->main_rect.width = 720;
Expand Down

0 comments on commit 2443bae

Please sign in to comment.