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:
parent
ec9faa1cfa
commit
2bd7ac55c3
drivers/media/video/ivtv
@ -506,6 +506,8 @@ struct yuv_playback_info
|
|||||||
struct v4l2_rect main_rect;
|
struct v4l2_rect main_rect;
|
||||||
u32 v4l2_src_w;
|
u32 v4l2_src_w;
|
||||||
u32 v4l2_src_h;
|
u32 v4l2_src_h;
|
||||||
|
|
||||||
|
u8 running; /* Have any frames been displayed */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IVTV_VBI_FRAMES 32
|
#define IVTV_VBI_FRAMES 32
|
||||||
|
@ -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 =
|
itv->dma_data_req_size =
|
||||||
1080 * ((yi->v4l2_src_h + 31) & ~31);
|
1080 * ((yi->v4l2_src_h + 31) & ~31);
|
||||||
|
|
||||||
/* Force update of yuv registers */
|
|
||||||
yi->yuv_forced_update = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
|
|||||||
*/
|
*/
|
||||||
unsigned int frame = read_reg(0x28c0) & 1;
|
unsigned int frame = read_reg(0x28c0) & 1;
|
||||||
struct yuv_playback_info *yi = &itv->yuv_info;
|
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];
|
struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
|
||||||
|
|
||||||
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
|
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;
|
next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
|
||||||
atomic_set(&yi->next_dma_frame, next_dma_frame);
|
atomic_set(&yi->next_dma_frame, next_dma_frame);
|
||||||
yi->fields_lapsed = -1;
|
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 */
|
/* 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) {
|
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];
|
f = &yi->new_frame_info[last_dma_frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv)
|
|||||||
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
|
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
|
||||||
ivtv_waitq(&itv->vsync_waitq);
|
ivtv_waitq(&itv->vsync_waitq);
|
||||||
|
|
||||||
|
yi->running = 0;
|
||||||
atomic_set(&yi->next_dma_frame, -1);
|
atomic_set(&yi->next_dma_frame, -1);
|
||||||
atomic_set(&yi->next_fill_frame, 0);
|
atomic_set(&yi->next_fill_frame, 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user