V4L/DVB (9166): ivtv - Fix potential race condition in yuv handler

Modified yuv register update handling to remove a potential race condition
which could occur with the first video frame.

Also removed a forced yuv position update, since changing the source video
dimensions or interlace settings doesn't affect the frame already being
displayed.

Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Ian Armstrong 2008-10-09 12:04:23 -03:00 committed by Mauro Carvalho Chehab
parent ec9faa1cfa
commit 2bd7ac55c3
4 changed files with 9 additions and 5 deletions

View file

@ -506,6 +506,8 @@ struct yuv_playback_info
struct v4l2_rect main_rect;
u32 v4l2_src_w;
u32 v4l2_src_h;
u8 running; /* Have any frames been displayed */
};
#define IVTV_VBI_FRAMES 32

View file

@ -644,8 +644,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
itv->dma_data_req_size =
1080 * ((yi->v4l2_src_h + 31) & ~31);
/* Force update of yuv registers */
yi->yuv_forced_update = 1;
return 0;
}

View file

@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
*/
unsigned int frame = read_reg(0x28c0) & 1;
struct yuv_playback_info *yi = &itv->yuv_info;
int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame);
int last_dma_frame = atomic_read(&yi->next_dma_frame);
struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
@ -772,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
atomic_set(&yi->next_dma_frame, next_dma_frame);
yi->fields_lapsed = -1;
yi->running = 1;
}
}
}
@ -804,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
/* Check if we need to update the yuv registers */
if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) {
if (yi->running && (yi->yuv_forced_update || f->update)) {
if (!f->update) {
last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS;
last_dma_frame =
(u8)(atomic_read(&yi->next_dma_frame) -
1) % IVTV_YUV_BUFFERS;
f = &yi->new_frame_info[last_dma_frame];
}

View file

@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv)
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
ivtv_waitq(&itv->vsync_waitq);
yi->running = 0;
atomic_set(&yi->next_dma_frame, -1);
atomic_set(&yi->next_fill_frame, 0);