From 1e13f9e3f1501cc167e40a2adf07e6e4705cb331 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 10 Mar 2007 06:52:02 -0300 Subject: [PATCH] V4L/DVB (5404): Merges VBI & YUV handling into a single work queue. Signed-off-by: Ian Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 25 ++++---------- drivers/media/video/ivtv/ivtv-driver.h | 46 +++++++++++++------------- drivers/media/video/ivtv/ivtv-irq.c | 26 +++++++++++++-- drivers/media/video/ivtv/ivtv-irq.h | 2 ++ drivers/media/video/ivtv/ivtv-vbi.c | 11 ++---- drivers/media/video/ivtv/ivtv-vbi.h | 3 +- drivers/media/video/ivtv/ivtv-yuv.c | 6 +--- drivers/media/video/ivtv/ivtv-yuv.h | 2 +- 8 files changed, 60 insertions(+), 61 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 162a1e8fcdc8..ad0c1628ef96 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -628,21 +628,13 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->lock = SPIN_LOCK_UNLOCKED; itv->dma_reg_lock = SPIN_LOCK_UNLOCKED; - itv->vbi.work_queues = create_workqueue("ivtv_vbi"); - if (itv->vbi.work_queues == NULL) { - IVTV_ERR("Could not create VBI workqueue\n"); + itv->irq_work_queues = create_workqueue(itv->name); + if (itv->irq_work_queues == NULL) { + IVTV_ERR("Could not create ivtv workqueue\n"); return -1; } - itv->yuv_info.work_queues = create_workqueue("ivtv_yuv"); - if (itv->yuv_info.work_queues == NULL) { - IVTV_ERR("Could not create YUV workqueue\n"); - destroy_workqueue(itv->vbi.work_queues); - return -1; - } - - INIT_WORK(&itv->vbi.work_queue, vbi_work_handler); - INIT_WORK(&itv->yuv_info.work_queue, ivtv_yuv_work_handler); + INIT_WORK(&itv->irq_work_queue, ivtv_irq_work_handler); /* start counting open_id at 1 */ itv->open_id = 1; @@ -1241,8 +1233,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, if (itv->has_cx23415) release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); free_workqueue: - destroy_workqueue(itv->vbi.work_queues); - destroy_workqueue(itv->yuv_info.work_queues); + destroy_workqueue(itv->irq_work_queues); err: if (retval == 0) retval = -ENODEV; @@ -1284,10 +1275,8 @@ static void ivtv_remove(struct pci_dev *pci_dev) /* Stop all Work Queues */ IVTV_DEBUG_INFO(" Stop Work Queues.\n"); - flush_workqueue(itv->vbi.work_queues); - flush_workqueue(itv->yuv_info.work_queues); - destroy_workqueue(itv->vbi.work_queues); - destroy_workqueue(itv->yuv_info.work_queues); + flush_workqueue(itv->irq_work_queues); + destroy_workqueue(itv->irq_work_queues); IVTV_DEBUG_INFO(" Stopping Firmware.\n"); ivtv_halt_firmware(itv); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 236e3532f569..1b2f7a6d311e 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -383,28 +383,29 @@ struct ivtv_mailbox_data { #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ /* per-ivtv, i_flags */ -#define IVTV_F_I_DMA 0 /* DMA in progress */ -#define IVTV_F_I_UDMA 1 /* UDMA in progress */ -#define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ - -#define IVTV_F_I_SPEED_CHANGE 3 /* A speed change is in progress */ -#define IVTV_F_I_EOS 4 /* End of encoder stream reached */ -#define IVTV_F_I_RADIO_USER 5 /* The radio tuner is selected */ -#define IVTV_F_I_DIG_RST 6 /* Reset digitizer */ -#define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ -#define IVTV_F_I_ENC_VBI 8 /* VBI DMA */ -#define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ -#define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ -#define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ -#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ -#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ +#define IVTV_F_I_DMA 0 /* DMA in progress */ +#define IVTV_F_I_UDMA 1 /* UDMA in progress */ +#define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ +#define IVTV_F_I_SPEED_CHANGE 3 /* A speed change is in progress */ +#define IVTV_F_I_EOS 4 /* End of encoder stream reached */ +#define IVTV_F_I_RADIO_USER 5 /* The radio tuner is selected */ +#define IVTV_F_I_DIG_RST 6 /* Reset digitizer */ +#define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ +#define IVTV_F_I_ENC_VBI 8 /* VBI DMA */ +#define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ +#define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ +#define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ +#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ +#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ +#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */ +#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */ /* Event notifications */ -#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ -#define IVTV_F_I_EV_VSYNC 29 /* VSYNC event */ -#define IVTV_F_I_EV_VSYNC_FIELD 30 /* VSYNC event field (0 = first, 1 = second field) */ -#define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ +#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ +#define IVTV_F_I_EV_VSYNC 29 /* VSYNC event */ +#define IVTV_F_I_EV_VSYNC_FIELD 30 /* VSYNC event field (0 = first, 1 = second field) */ +#define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ /* Scatter-Gather array element, used in DMA transfers */ struct ivtv_SG_element { @@ -612,8 +613,6 @@ struct yuv_playback_info u32 yuv_forced_update; int update_frame; - struct workqueue_struct *work_queues; - struct work_struct work_queue; struct yuv_frame_info new_frame_info[4]; struct yuv_frame_info old_frame_info; struct yuv_frame_info old_frame_info_args; @@ -676,8 +675,6 @@ struct vbi_info { struct ivtv_buffer sliced_mpeg_buf; u32 inserted_frame; - struct workqueue_struct *work_queues; - struct work_struct work_queue; u32 start[2], count; u32 raw_size; u32 sliced_size; @@ -734,6 +731,9 @@ struct ivtv { u32 base_addr; u32 irqmask; + + struct workqueue_struct *irq_work_queues; + struct work_struct irq_work_queue; struct timer_list dma_timer; /* Timer used to catch unfinished DMAs */ struct vbi_info vbi; diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 0656e18b7c7e..c3a047b381b3 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -27,6 +27,7 @@ #include "ivtv-ioctl.h" #include "ivtv-mailbox.h" #include "ivtv-vbi.h" +#include "ivtv-yuv.h" #define DMA_MAGIC_COOKIE 0x000001fe @@ -49,6 +50,19 @@ static inline int ivtv_use_pio(struct ivtv_stream *s) (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); } +void ivtv_irq_work_handler(struct work_struct *work) +{ + struct ivtv *itv = container_of(work, struct ivtv, irq_work_queue); + + DEFINE_WAIT(wait); + + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) + vbi_work_handler(itv); + + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) + ivtv_yuv_work_handler(itv); +} + /* Determine the required DMA size, setup enough buffers in the predma queue and actually copy the data from the card to the buffers in case a PIO transfer is required for this stream. @@ -643,6 +657,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) } if (frame != (itv->lastVsyncFrame & 1)) { struct ivtv_stream *s = ivtv_get_output_stream(itv); + int work = 0; itv->lastVsyncFrame += 1; if (frame == 0) { @@ -661,8 +676,10 @@ static void ivtv_irq_vsync(struct ivtv *itv) wake_up(&s->waitq); /* Send VBI to saa7127 */ - if (frame) - vbi_schedule_work(itv); + if (frame) { + set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); + work = 1; + } /* Check if we need to update the yuv registers */ if ((itv->yuv_info.yuv_forced_update || itv->yuv_info.new_frame_info[last_dma_frame].update) && last_dma_frame != -1) { @@ -673,9 +690,12 @@ static void ivtv_irq_vsync(struct ivtv *itv) itv->yuv_info.update_frame = last_dma_frame; itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.yuv_forced_update = 0; - queue_work(itv->yuv_info.work_queues, &itv->yuv_info.work_queue); + set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); + work = 1; } } + if (work) + queue_work(itv->irq_work_queues, &itv->irq_work_queue); } } diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h index ed96205e87a2..a43348a30309 100644 --- a/drivers/media/video/ivtv/ivtv-irq.h +++ b/drivers/media/video/ivtv/ivtv-irq.h @@ -20,5 +20,7 @@ */ irqreturn_t ivtv_irq_handler(int irq, void *dev_id); + +void ivtv_irq_work_handler(struct work_struct *work); void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); void ivtv_unfinished_dma(unsigned long arg); diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index b53ca508dacc..5efa5a867818 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -32,11 +32,6 @@ static int odd_parity(u8 c) return c & 1; } -void vbi_schedule_work(struct ivtv *itv) -{ - queue_work(itv->vbi.work_queues, &itv->vbi.work_queue); -} - static void passthrough_vbi_data(struct ivtv *itv, int cnt) { int wss = 0; @@ -454,12 +449,10 @@ void ivtv_disable_vbi(struct ivtv *itv) itv->vbi.cc_pos = 0; } -void vbi_work_handler(struct work_struct *work) + +void vbi_work_handler(struct ivtv *itv) { - struct vbi_info *info = container_of(work, struct vbi_info, work_queue); - struct ivtv *itv = container_of(info, struct ivtv, vbi); struct v4l2_sliced_vbi_data data; - DEFINE_WAIT(wait); /* Lock */ if (itv->output_mode == OUT_PASSTHROUGH) { diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index c897e9bd4f92..cdaea697b3ec 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -23,5 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, int ivtv_used_line(struct ivtv *itv, int line, int field); void ivtv_disable_vbi(struct ivtv *itv); void ivtv_set_vbi(unsigned long arg); -void vbi_work_handler(struct work_struct *work); -void vbi_schedule_work(struct ivtv *itv); +void vbi_work_handler(struct ivtv *itv); diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index e49ecef93046..c962303e891c 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -804,12 +804,8 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo } /* Update the scaling register to the requested value */ -void ivtv_yuv_work_handler (struct work_struct *work) +void ivtv_yuv_work_handler (struct ivtv *itv) { - struct yuv_playback_info *info = container_of(work, struct yuv_playback_info, work_queue); - struct ivtv *itv = container_of(info, struct ivtv, yuv_info); - DEFINE_WAIT(wait); - struct yuv_frame_info window; u32 yuv_update; diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index 31128733e784..88972d3f77c4 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/video/ivtv/ivtv-yuv.h @@ -21,4 +21,4 @@ int ivtv_yuv_filter_check(struct ivtv *itv); int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); void ivtv_yuv_close(struct ivtv *itv); -void ivtv_yuv_work_handler (struct work_struct *work); +void ivtv_yuv_work_handler (struct ivtv *itv); -- 2.34.1