[media] saa7164: allow DMA engine buffers to vary in size between analog and digital
[deliverable/linux.git] / drivers / media / video / saa7164 / saa7164-encoder.c
index 08b62e41c466690a91c5ffe139feb1e2bfeacea0..0859448bae050b6187b96fa86696272787d77999 100644 (file)
@@ -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);
 }
 
This page took 0.039273 seconds and 5 git commands to generate.