V4L/DVB (5404): Merges VBI & YUV handling into a single work queue.
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>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
037c86c533
commit
1e13f9e3f1
@@ -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,
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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);
|
||||||
|
@@ -386,7 +386,6 @@ struct ivtv_mailbox_data {
|
|||||||
#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 */
|
||||||
@@ -399,6 +398,8 @@ struct ivtv_mailbox_data {
|
|||||||
#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 */
|
||||||
@@ -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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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)
|
|||||||
(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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 @@
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user