V4L/DVB (5404): Merges VBI & YUV handling into a single work queue.
authorHans Verkuil <hverkuil@xs4all.nl>
Sat, 10 Mar 2007 09:52:02 +0000 (06:52 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 27 Apr 2007 18:44:24 +0000 (15:44 -0300)
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@infradead.org>
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-irq.h
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtv-vbi.h
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/ivtv/ivtv-yuv.h

index 162a1e8..ad0c162 100644 (file)
@@ -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);
index 236e353..1b2f7a6 100644 (file)
@@ -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;
index 0656e18..c3a047b 100644 (file)
@@ -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);
        }
 }
 
index ed96205..a43348a 100644 (file)
@@ -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);
index b53ca50..5efa5a8 100644 (file)
@@ -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) {
index c897e9b..cdaea69 100644 (file)
@@ -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);
index e49ecef..c962303 100644 (file)
@@ -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;
 
index 3112873..88972d3 100644 (file)
@@ -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);