diff options
author | Andy Walls <awalls@md.metrocast.net> | 2012-09-03 19:50:49 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-09-18 18:29:07 +0200 |
commit | 4313902ebe33155209472215c62d2f29d117be29 (patch) | |
tree | 74bdcb1474e9275359c50e3c58e6636fbc0e0fdd | |
parent | [media] ivtv, ivtv-alsa: Add initial ivtv-alsa interface driver for ivtv (diff) | |
download | linux-4313902ebe33155209472215c62d2f29d117be29.tar.xz linux-4313902ebe33155209472215c62d2f29d117be29.zip |
[media] ivtv-alsa, ivtv: Connect ivtv PCM capture stream to ivtv-alsa interface driver
This change hooks up the ivtv PCM capture stream to the ivtv-alsa interface
driver. This is all that should be needed for basic CX23415/CX23416 PCM
audio capture to be available via ALSA device nodes.
Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-driver.h | 1 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-irq.c | 50 |
2 files changed, 51 insertions, 0 deletions
diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index 1918e7326795..bc309f42c8ed 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -259,6 +259,7 @@ struct ivtv_mailbox_data { #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ #define IVTV_F_I_INITED 21 /* set after first open */ #define IVTV_F_I_FAILED 22 /* set if first open failed */ +#define IVTV_F_I_WORK_HANDLER_PCM 23 /* there is work to be done for PCM */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index 1b3b9578bf47..19a7c9b990a3 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c @@ -38,6 +38,34 @@ static const int ivtv_stream_map[] = { IVTV_ENC_STREAM_TYPE_VBI, }; +static void ivtv_pcm_work_handler(struct ivtv *itv) +{ + struct ivtv_stream *s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; + struct ivtv_buffer *buf; + + /* Pass the PCM data to ivtv-alsa */ + + while (1) { + /* + * Users should not be using both the ALSA and V4L2 PCM audio + * capture interfaces at the same time. If the user is doing + * this, there maybe a buffer in q_io to grab, use, and put + * back in rotation. + */ + buf = ivtv_dequeue(s, &s->q_io); + if (buf == NULL) + buf = ivtv_dequeue(s, &s->q_full); + if (buf == NULL) + break; + + if (buf->readpos < buf->bytesused) + itv->pcm_announce_callback(itv->alsa, + (u8 *)(buf->buf + buf->readpos), + (size_t)(buf->bytesused - buf->readpos)); + + ivtv_enqueue(s, buf, &s->q_free); + } +} static void ivtv_pio_work_handler(struct ivtv *itv) { @@ -83,6 +111,9 @@ void ivtv_irq_work_handler(struct kthread_work *work) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) ivtv_yuv_work_handler(itv); + + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags)) + ivtv_pcm_work_handler(itv); } /* Determine the required DMA size, setup enough buffers in the predma queue and @@ -293,7 +324,26 @@ static void dma_post(struct ivtv_stream *s) return; } } + ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); + + if (s->type == IVTV_ENC_STREAM_TYPE_PCM && + itv->pcm_announce_callback != NULL) { + /* + * Set up the work handler to pass the data to ivtv-alsa. + * + * We just use q_full and let the work handler race with users + * making ivtv-fileops.c calls on the PCM device node. + * + * Users should not be using both the ALSA and V4L2 PCM audio + * capture interfaces at the same time. If the user does this, + * fragments of data will just go out each interface as they + * race for PCM data. + */ + set_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags); + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); + } + if (s->fh) wake_up(&s->waitq); } |