Commit 1e13f9e3 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (5404): Merges VBI & YUV handling into a single work queue.

Signed-off-by: default avatarIan Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 037c86c5
...@@ -628,21 +628,13 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) ...@@ -628,21 +628,13 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->lock = SPIN_LOCK_UNLOCKED; itv->lock = SPIN_LOCK_UNLOCKED;
itv->dma_reg_lock = SPIN_LOCK_UNLOCKED; itv->dma_reg_lock = SPIN_LOCK_UNLOCKED;
itv->vbi.work_queues = create_workqueue("ivtv_vbi"); itv->irq_work_queues = create_workqueue(itv->name);
if (itv->vbi.work_queues == NULL) { if (itv->irq_work_queues == NULL) {
IVTV_ERR("Could not create VBI workqueue\n"); IVTV_ERR("Could not create ivtv workqueue\n");
return -1; return -1;
} }
itv->yuv_info.work_queues = create_workqueue("ivtv_yuv"); INIT_WORK(&itv->irq_work_queue, ivtv_irq_work_handler);
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);
/* start counting open_id at 1 */ /* start counting open_id at 1 */
itv->open_id = 1; itv->open_id = 1;
...@@ -1241,8 +1233,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -1241,8 +1233,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
if (itv->has_cx23415) if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
free_workqueue: free_workqueue:
destroy_workqueue(itv->vbi.work_queues); destroy_workqueue(itv->irq_work_queues);
destroy_workqueue(itv->yuv_info.work_queues);
err: err:
if (retval == 0) if (retval == 0)
retval = -ENODEV; retval = -ENODEV;
...@@ -1284,10 +1275,8 @@ static void ivtv_remove(struct pci_dev *pci_dev) ...@@ -1284,10 +1275,8 @@ static void ivtv_remove(struct pci_dev *pci_dev)
/* Stop all Work Queues */ /* Stop all Work Queues */
IVTV_DEBUG_INFO(" Stop Work Queues.\n"); IVTV_DEBUG_INFO(" Stop Work Queues.\n");
flush_workqueue(itv->vbi.work_queues); flush_workqueue(itv->irq_work_queues);
flush_workqueue(itv->yuv_info.work_queues); destroy_workqueue(itv->irq_work_queues);
destroy_workqueue(itv->vbi.work_queues);
destroy_workqueue(itv->yuv_info.work_queues);
IVTV_DEBUG_INFO(" Stopping Firmware.\n"); IVTV_DEBUG_INFO(" Stopping Firmware.\n");
ivtv_halt_firmware(itv); ivtv_halt_firmware(itv);
......
...@@ -383,28 +383,29 @@ struct ivtv_mailbox_data { ...@@ -383,28 +383,29 @@ struct ivtv_mailbox_data {
#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */
/* per-ivtv, i_flags */ /* per-ivtv, i_flags */
#define IVTV_F_I_DMA 0 /* DMA in progress */ #define IVTV_F_I_DMA 0 /* DMA in progress */
#define IVTV_F_I_UDMA 1 /* UDMA in progress */ #define IVTV_F_I_UDMA 1 /* UDMA in progress */
#define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ #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_SPEED_CHANGE 3 /* A speed change is in progress */ #define IVTV_F_I_EOS 4 /* End of encoder stream reached */
#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_RADIO_USER 5 /* The radio tuner is selected */ #define IVTV_F_I_DIG_RST 6 /* Reset digitizer */
#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_DEC_YUV 7 /* YUV instead of MPG is being decoded */ #define IVTV_F_I_ENC_VBI 8 /* VBI DMA */
#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_CC 9 /* CC should be updated */ #define IVTV_F_I_UPDATE_WSS 10 /* WSS 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_UPDATE_VPS 11 /* VPS should be updated */ #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */
#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_ENC_PAUSED 13 /* the encoder is paused */
#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ #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 */ /* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ #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 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_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_VSYNC_ENABLED 31 /* VSYNC event enabled */
/* Scatter-Gather array element, used in DMA transfers */ /* Scatter-Gather array element, used in DMA transfers */
struct ivtv_SG_element { struct ivtv_SG_element {
...@@ -612,8 +613,6 @@ struct yuv_playback_info ...@@ -612,8 +613,6 @@ struct yuv_playback_info
u32 yuv_forced_update; u32 yuv_forced_update;
int update_frame; 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 new_frame_info[4];
struct yuv_frame_info old_frame_info; struct yuv_frame_info old_frame_info;
struct yuv_frame_info old_frame_info_args; struct yuv_frame_info old_frame_info_args;
...@@ -676,8 +675,6 @@ struct vbi_info { ...@@ -676,8 +675,6 @@ struct vbi_info {
struct ivtv_buffer sliced_mpeg_buf; struct ivtv_buffer sliced_mpeg_buf;
u32 inserted_frame; u32 inserted_frame;
struct workqueue_struct *work_queues;
struct work_struct work_queue;
u32 start[2], count; u32 start[2], count;
u32 raw_size; u32 raw_size;
u32 sliced_size; u32 sliced_size;
...@@ -734,6 +731,9 @@ struct ivtv { ...@@ -734,6 +731,9 @@ struct ivtv {
u32 base_addr; u32 base_addr;
u32 irqmask; 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 timer_list dma_timer; /* Timer used to catch unfinished DMAs */
struct vbi_info vbi; struct vbi_info vbi;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "ivtv-ioctl.h" #include "ivtv-ioctl.h"
#include "ivtv-mailbox.h" #include "ivtv-mailbox.h"
#include "ivtv-vbi.h" #include "ivtv-vbi.h"
#include "ivtv-yuv.h"
#define DMA_MAGIC_COOKIE 0x000001fe #define DMA_MAGIC_COOKIE 0x000001fe
...@@ -49,6 +50,19 @@ static inline int ivtv_use_pio(struct ivtv_stream *s) ...@@ -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); (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 /* 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 actually copy the data from the card to the buffers in case a PIO transfer is
required for this stream. required for this stream.
...@@ -643,6 +657,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) ...@@ -643,6 +657,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
} }
if (frame != (itv->lastVsyncFrame & 1)) { if (frame != (itv->lastVsyncFrame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv); struct ivtv_stream *s = ivtv_get_output_stream(itv);
int work = 0;
itv->lastVsyncFrame += 1; itv->lastVsyncFrame += 1;
if (frame == 0) { if (frame == 0) {
...@@ -661,8 +676,10 @@ static void ivtv_irq_vsync(struct ivtv *itv) ...@@ -661,8 +676,10 @@ static void ivtv_irq_vsync(struct ivtv *itv)
wake_up(&s->waitq); wake_up(&s->waitq);
/* Send VBI to saa7127 */ /* Send VBI to saa7127 */
if (frame) if (frame) {
vbi_schedule_work(itv); set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
work = 1;
}
/* Check if we need to update the yuv registers */ /* 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) { 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) ...@@ -673,9 +690,12 @@ static void ivtv_irq_vsync(struct ivtv *itv)
itv->yuv_info.update_frame = last_dma_frame; itv->yuv_info.update_frame = last_dma_frame;
itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
itv->yuv_info.yuv_forced_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);
} }
} }
......
...@@ -20,5 +20,7 @@ ...@@ -20,5 +20,7 @@
*/ */
irqreturn_t ivtv_irq_handler(int irq, void *dev_id); 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_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
void ivtv_unfinished_dma(unsigned long arg); void ivtv_unfinished_dma(unsigned long arg);
...@@ -32,11 +32,6 @@ static int odd_parity(u8 c) ...@@ -32,11 +32,6 @@ static int odd_parity(u8 c)
return c & 1; 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) static void passthrough_vbi_data(struct ivtv *itv, int cnt)
{ {
int wss = 0; int wss = 0;
...@@ -454,12 +449,10 @@ void ivtv_disable_vbi(struct ivtv *itv) ...@@ -454,12 +449,10 @@ void ivtv_disable_vbi(struct ivtv *itv)
itv->vbi.cc_pos = 0; 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; struct v4l2_sliced_vbi_data data;
DEFINE_WAIT(wait);
/* Lock */ /* Lock */
if (itv->output_mode == OUT_PASSTHROUGH) { if (itv->output_mode == OUT_PASSTHROUGH) {
......
...@@ -23,5 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, ...@@ -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); int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv); void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg); void ivtv_set_vbi(unsigned long arg);
void vbi_work_handler(struct work_struct *work); void vbi_work_handler(struct ivtv *itv);
void vbi_schedule_work(struct ivtv *itv);
...@@ -804,12 +804,8 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo ...@@ -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 */ /* 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; struct yuv_frame_info window;
u32 yuv_update; u32 yuv_update;
......
...@@ -21,4 +21,4 @@ ...@@ -21,4 +21,4 @@
int ivtv_yuv_filter_check(struct ivtv *itv); int ivtv_yuv_filter_check(struct ivtv *itv);
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
void ivtv_yuv_close(struct ivtv *itv); void ivtv_yuv_close(struct ivtv *itv);
void ivtv_yuv_work_handler (struct work_struct *work); void ivtv_yuv_work_handler (struct ivtv *itv);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment