diff options
author | Steven Toth <stoth@kernellabs.com> | 2010-07-31 16:01:00 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 07:55:01 -0200 |
commit | 1b0e8e46297a214336d85c8e278a8a004f97889e (patch) | |
tree | 8bcfe776bfc8926b2636cf8bfe6efb630404e4f6 /drivers/media/video/saa7164/saa7164-encoder.c | |
parent | 7c1618227e6932fcd92597507ee63c01da73e623 (diff) | |
download | lwn-1b0e8e46297a214336d85c8e278a8a004f97889e.tar.gz lwn-1b0e8e46297a214336d85c8e278a8a004f97889e.zip |
[media] saa7164: allow DMA engine buffers to vary in size between analog and digital
Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7164/saa7164-encoder.c')
-rw-r--r-- | drivers/media/video/saa7164/saa7164-encoder.c | 245 |
1 files changed, 144 insertions, 101 deletions
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index 08b62e41c466..0859448bae05 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c @@ -76,15 +76,131 @@ static void saa7164_encoder_configure(struct saa7164_port *port) saa7164_api_set_audio_std(port); } -/* One time configuration at registration time */ -static int saa7164_encoder_initialize(struct saa7164_port *port) +static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port) +{ + struct list_head *c, *n, *p, *q, *l, *v; + struct saa7164_dev *dev = port->dev; + struct saa7164_buffer *buf; + struct saa7164_user_buffer *ubuf; + + /* Remove any allocated buffers */ + mutex_lock(&port->dmaqueue_lock); + + dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); + list_for_each_safe(c, n, &port->dmaqueue.list) { + buf = list_entry(c, struct saa7164_buffer, list); + list_del(c); + saa7164_buffer_dealloc(buf); + } + + dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); + list_for_each_safe(p, q, &port->list_buf_used.list) { + ubuf = list_entry(p, struct saa7164_user_buffer, list); + list_del(p); + saa7164_buffer_dealloc_user(ubuf); + } + + dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); + list_for_each_safe(l, v, &port->list_buf_free.list) { + ubuf = list_entry(l, struct saa7164_user_buffer, list); + list_del(l); + saa7164_buffer_dealloc_user(ubuf); + } + + mutex_unlock(&port->dmaqueue_lock); + dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); + + return 0; +} + +/* Dynamic buffer switch at encoder start time */ +static int saa7164_encoder_buffers_alloc(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; + struct saa7164_buffer *buf; + struct saa7164_user_buffer *ubuf; + tmHWStreamParameters_t *params = &port->hw_streamingparams; + int result = -ENODEV, i; + int len = 0; dprintk(DBGLVL_ENC, "%s()\n", __func__); - saa7164_encoder_configure(port); + if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__); + params->samplesperline = 128; + params->numberoflines = 256; + params->pitch = 128; + params->numpagetables = 2 + + ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); + } else + if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { + dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__); + params->samplesperline = 188; + params->numberoflines = 312; + params->pitch = 188; + params->numpagetables = 2 + + ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE); + } else + BUG(); + + /* Init and establish defaults */ + params->bitspersample = 8; + params->linethreshold = 0; + params->pagetablelistvirt = 0; + params->pagetablelistphys = 0; + params->numpagetableentries = port->hwcfg.buffercount; + + /* Allocate the PCI resources, buffers (hard) */ + for (i = 0; i < port->hwcfg.buffercount; i++) { + buf = saa7164_buffer_alloc(port, + params->numberoflines * + params->pitch); + + if (!buf) { + printk(KERN_ERR "%s() failed " + "(errno = %d), unable to allocate buffer\n", + __func__, result); + result = -ENOMEM; + goto failed; + } else { + + mutex_lock(&port->dmaqueue_lock); + list_add_tail(&buf->list, &port->dmaqueue.list); + mutex_unlock(&port->dmaqueue_lock); + + } + } + + /* Allocate some kenrel kernel buffers for copying + * to userpsace. + */ + len = params->numberoflines * params->pitch; + + if (encoder_buffers < 16) + encoder_buffers = 16; + if (encoder_buffers > 512) + encoder_buffers = 512; + + for (i = 0; i < encoder_buffers; i++) { + + ubuf = saa7164_buffer_alloc_user(dev, len); + if (ubuf) { + mutex_lock(&port->dmaqueue_lock); + list_add_tail(&ubuf->list, &port->list_buf_free.list); + mutex_unlock(&port->dmaqueue_lock); + } + + } + + result = 0; +failed: + return result; +} + +static int saa7164_encoder_initialize(struct saa7164_port *port) +{ + saa7164_encoder_configure(port); return 0; } @@ -835,6 +951,7 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__, port->nr); + /* Reset the state of any allocated buffer resources */ mutex_lock(&port->dmaqueue_lock); /* Reset the hard and soft buffer state */ @@ -851,6 +968,10 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) } mutex_unlock(&port->dmaqueue_lock); + + /* Free any allocated resources */ + saa7164_encoder_buffers_dealloc(port); + dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr); return ret; @@ -863,10 +984,19 @@ static int saa7164_encoder_start_streaming(struct saa7164_port *port) dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); + port->done_first_interrupt = 0; + + /* allocate all of the PCIe DMA buffer resources on the fly, + * allowing switching between TS and PS payloads without + * requiring a complete driver reload. + */ + saa7164_encoder_buffers_alloc(port); + /* Configure the encoder with any cache values */ saa7164_api_set_encoder(port); saa7164_api_get_encoder(port); + /* Place the empty buffers on the hardware */ saa7164_buffer_cfg_port(port); /* Acquire the hardware */ @@ -1005,27 +1135,29 @@ static int fops_release(struct file *file) struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) { - struct saa7164_user_buffer *buf = 0; + struct saa7164_user_buffer *ubuf = 0; struct saa7164_dev *dev = port->dev; u32 crc; mutex_lock(&port->dmaqueue_lock); if (!list_empty(&port->list_buf_used.list)) { - buf = list_first_entry(&port->list_buf_used.list, + ubuf = list_first_entry(&port->list_buf_used.list, struct saa7164_user_buffer, list); - crc = crc32(0, buf->data, buf->actual_size); - if (crc != buf->crc) { - printk(KERN_ERR "%s() buf %p crc became invalid, was 0x%x became 0x%x\n", __func__, - buf, buf->crc, crc); + if (crc_checking) { + crc = crc32(0, ubuf->data, ubuf->actual_size); + if (crc != ubuf->crc) { + printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, + ubuf, ubuf->crc, crc); + } } } mutex_unlock(&port->dmaqueue_lock); - dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, buf); + dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf); - return buf; + return ubuf; } static ssize_t fops_read(struct file *file, char __user *buffer, @@ -1292,10 +1424,7 @@ static struct video_device *saa7164_encoder_alloc( int saa7164_encoder_register(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; - struct saa7164_buffer *buf; - struct saa7164_user_buffer *ubuf; - int result = -ENODEV, i; - int len = 0; + int result = -ENODEV; dprintk(DBGLVL_ENC, "%s()\n", __func__); @@ -1311,64 +1440,6 @@ int saa7164_encoder_register(struct saa7164_port *port) goto failed; } - /* Init and establish defaults */ - /* TODO: Check the umber of lines for PS */ - port->hw_streamingparams.bitspersample = 8; - port->hw_streamingparams.samplesperline = 128; - port->hw_streamingparams.numberoflines = 256; - - port->hw_streamingparams.pitch = 128; - port->hw_streamingparams.linethreshold = 0; - port->hw_streamingparams.pagetablelistvirt = 0; - port->hw_streamingparams.pagetablelistphys = 0; - port->hw_streamingparams.numpagetables = 2 + - ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); - - port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount; - - /* Allocate the PCI resources, buffers (hard) */ - for (i = 0; i < port->hwcfg.buffercount; i++) { - buf = saa7164_buffer_alloc(port, - port->hw_streamingparams.numberoflines * - port->hw_streamingparams.pitch); - - if (!buf) { - printk(KERN_ERR "%s() failed " - "(errno = %d), unable to allocate buffer\n", - __func__, result); - result = -ENOMEM; - goto failed; - } else { - - mutex_lock(&port->dmaqueue_lock); - list_add_tail(&buf->list, &port->dmaqueue.list); - mutex_unlock(&port->dmaqueue_lock); - - } - } - - /* Allocate some kenrel kernel buffers for copying - * to userpsace. - */ - len = port->hw_streamingparams.numberoflines * - port->hw_streamingparams.pitch; - - if (encoder_buffers < 16) - encoder_buffers = 16; - if (encoder_buffers > 512) - encoder_buffers = 512; - - for (i = 0; i < encoder_buffers; i++) { - - ubuf = saa7164_buffer_alloc_user(dev, len); - if (ubuf) { - mutex_lock(&port->dmaqueue_lock); - list_add_tail(&ubuf->list, &port->list_buf_free.list); - mutex_unlock(&port->dmaqueue_lock); - } - - } - /* Establish encoder defaults here */ /* Set default TV standard */ port->encodernorm = saa7164_tvnorms[0]; @@ -1446,9 +1517,6 @@ failed: void saa7164_encoder_unregister(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; - struct saa7164_buffer *buf; - struct saa7164_user_buffer *ubuf; - struct list_head *c, *n, *p, *q, *l, *v; dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); @@ -1464,31 +1532,6 @@ void saa7164_encoder_unregister(struct saa7164_port *port) port->v4l_device = NULL; } - /* Remove any allocated buffers */ - mutex_lock(&port->dmaqueue_lock); - - dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); - list_for_each_safe(c, n, &port->dmaqueue.list) { - buf = list_entry(c, struct saa7164_buffer, list); - list_del(c); - saa7164_buffer_dealloc(buf); - } - - dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); - list_for_each_safe(p, q, &port->list_buf_used.list) { - ubuf = list_entry(p, struct saa7164_user_buffer, list); - list_del(p); - saa7164_buffer_dealloc_user(ubuf); - } - - dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); - list_for_each_safe(l, v, &port->list_buf_free.list) { - ubuf = list_entry(l, struct saa7164_user_buffer, list); - list_del(l); - saa7164_buffer_dealloc_user(ubuf); - } - - mutex_unlock(&port->dmaqueue_lock); dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); } |