root/drivers/media/pci/saa7164/saa7164-buffer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. saa7164_buffer_display
  2. saa7164_buffer_alloc
  3. saa7164_buffer_dealloc
  4. saa7164_buffer_zero_offsets
  5. saa7164_buffer_activate
  6. saa7164_buffer_cfg_port
  7. saa7164_buffer_alloc_user
  8. saa7164_buffer_dealloc_user

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Driver for the NXP SAA7164 PCIe bridge
   4  *
   5  *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
   6  */
   7 
   8 #include <linux/slab.h>
   9 
  10 #include "saa7164.h"
  11 
  12 /* The PCI address space for buffer handling looks like this:
  13  *
  14  * +-u32 wide-------------+
  15  * |                      +
  16  * +-u64 wide------------------------------------+
  17  * +                                             +
  18  * +----------------------+
  19  * | CurrentBufferPtr     + Pointer to current PCI buffer >-+
  20  * +----------------------+                                 |
  21  * | Unused               +                                 |
  22  * +----------------------+                                 |
  23  * | Pitch                + = 188 (bytes)                   |
  24  * +----------------------+                                 |
  25  * | PCI buffer size      + = pitch * number of lines (312) |
  26  * +----------------------+                                 |
  27  * |0| Buf0 Write Offset  +                                 |
  28  * +----------------------+                                 v
  29  * |1| Buf1 Write Offset  +                                 |
  30  * +----------------------+                                 |
  31  * |2| Buf2 Write Offset  +                                 |
  32  * +----------------------+                                 |
  33  * |3| Buf3 Write Offset  +                                 |
  34  * +----------------------+                                 |
  35  * ... More write offsets                                   |
  36  * +---------------------------------------------+          |
  37  * +0| set of ptrs to PCI pagetables             +          |
  38  * +---------------------------------------------+          |
  39  * +1| set of ptrs to PCI pagetables             + <--------+
  40  * +---------------------------------------------+
  41  * +2| set of ptrs to PCI pagetables             +
  42  * +---------------------------------------------+
  43  * +3| set of ptrs to PCI pagetables             + >--+
  44  * +---------------------------------------------+    |
  45  * ... More buffer pointers                           |  +----------------+
  46  *                                                  +->| pt[0] TS data  |
  47  *                                                  |  +----------------+
  48  *                                                  |
  49  *                                                  |  +----------------+
  50  *                                                  +->| pt[1] TS data  |
  51  *                                                  |  +----------------+
  52  *                                                  | etc
  53  */
  54 
  55 void saa7164_buffer_display(struct saa7164_buffer *buf)
  56 {
  57         struct saa7164_dev *dev = buf->port->dev;
  58         int i;
  59 
  60         dprintk(DBGLVL_BUF, "%s()   buffer @ 0x%p nr=%d\n",
  61                 __func__, buf, buf->idx);
  62         dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08llx len = 0x%x\n",
  63                 buf->cpu, (long long)buf->dma, buf->pci_size);
  64         dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n",
  65                 buf->pt_cpu, (long long)buf->pt_dma, buf->pt_size);
  66 
  67         /* Format the Page Table Entries to point into the data buffer */
  68         for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) {
  69 
  70                 dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
  71                         i, buf->pt_cpu, (u64)*(buf->pt_cpu));
  72 
  73         }
  74 }
  75 /* Allocate a new buffer structure and associated PCI space in bytes.
  76  * len must be a multiple of sizeof(u64)
  77  */
  78 struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
  79         u32 len)
  80 {
  81         struct tmHWStreamParameters *params = &port->hw_streamingparams;
  82         struct saa7164_buffer *buf = NULL;
  83         struct saa7164_dev *dev = port->dev;
  84         int i;
  85 
  86         if ((len == 0) || (len >= 65536) || (len % sizeof(u64))) {
  87                 log_warn("%s() SAA_ERR_BAD_PARAMETER\n", __func__);
  88                 goto ret;
  89         }
  90 
  91         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
  92         if (!buf)
  93                 goto ret;
  94 
  95         buf->idx = -1;
  96         buf->port = port;
  97         buf->flags = SAA7164_BUFFER_FREE;
  98         buf->pos = 0;
  99         buf->actual_size = params->pitch * params->numberoflines;
 100         buf->crc = 0;
 101         /* TODO: arg len is being ignored */
 102         buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
 103         buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
 104 
 105         /* Allocate contiguous memory */
 106         buf->cpu = pci_alloc_consistent(port->dev->pci, buf->pci_size,
 107                 &buf->dma);
 108         if (!buf->cpu)
 109                 goto fail1;
 110 
 111         buf->pt_cpu = pci_alloc_consistent(port->dev->pci, buf->pt_size,
 112                 &buf->pt_dma);
 113         if (!buf->pt_cpu)
 114                 goto fail2;
 115 
 116         /* init the buffers to a known pattern, easier during debugging */
 117         memset(buf->cpu, 0xff, buf->pci_size);
 118         buf->crc = crc32(0, buf->cpu, buf->actual_size);
 119         memset(buf->pt_cpu, 0xff, buf->pt_size);
 120 
 121         dprintk(DBGLVL_BUF, "%s()   allocated buffer @ 0x%p (%d pageptrs)\n",
 122                 __func__, buf, params->numpagetables);
 123         dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08lx len = 0x%x\n",
 124                 buf->cpu, (long)buf->dma, buf->pci_size);
 125         dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n",
 126                 buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
 127 
 128         /* Format the Page Table Entries to point into the data buffer */
 129         for (i = 0 ; i < params->numpagetables; i++) {
 130 
 131                 *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */
 132                 dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
 133                         i, buf->pt_cpu, (u64)*(buf->pt_cpu));
 134 
 135         }
 136 
 137         goto ret;
 138 
 139 fail2:
 140         pci_free_consistent(port->dev->pci, buf->pci_size, buf->cpu, buf->dma);
 141 fail1:
 142         kfree(buf);
 143 
 144         buf = NULL;
 145 ret:
 146         return buf;
 147 }
 148 
 149 int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
 150 {
 151         struct saa7164_dev *dev;
 152 
 153         if (!buf || !buf->port)
 154                 return SAA_ERR_BAD_PARAMETER;
 155         dev = buf->port->dev;
 156 
 157         dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
 158                 __func__, buf);
 159 
 160         if (buf->flags != SAA7164_BUFFER_FREE)
 161                 log_warn(" freeing a non-free buffer\n");
 162 
 163         pci_free_consistent(dev->pci, buf->pci_size, buf->cpu, buf->dma);
 164         pci_free_consistent(dev->pci, buf->pt_size, buf->pt_cpu, buf->pt_dma);
 165 
 166         kfree(buf);
 167 
 168         return SAA_OK;
 169 }
 170 
 171 int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i)
 172 {
 173         struct saa7164_dev *dev = port->dev;
 174 
 175         if ((i < 0) || (i >= port->hwcfg.buffercount))
 176                 return -EINVAL;
 177 
 178         dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
 179 
 180         saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
 181 
 182         return 0;
 183 }
 184 
 185 /* Write a buffer into the hardware */
 186 int saa7164_buffer_activate(struct saa7164_buffer *buf, int i)
 187 {
 188         struct saa7164_port *port = buf->port;
 189         struct saa7164_dev *dev = port->dev;
 190 
 191         if ((i < 0) || (i >= port->hwcfg.buffercount))
 192                 return -EINVAL;
 193 
 194         dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
 195 
 196         buf->idx = i; /* Note of which buffer list index position we occupy */
 197         buf->flags = SAA7164_BUFFER_BUSY;
 198         buf->pos = 0;
 199 
 200         /* TODO: Review this in light of 32v64 assignments */
 201         saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
 202         saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
 203         saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
 204 
 205         dprintk(DBGLVL_BUF, "   buf[%d] offset 0x%llx (0x%x) buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
 206                 buf->idx,
 207                 (u64)port->bufoffset + (i * sizeof(u32)),
 208                 saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
 209                 (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
 210                 (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
 211                 saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)),
 212                 saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)),
 213                 buf->idx);
 214 
 215         return 0;
 216 }
 217 
 218 int saa7164_buffer_cfg_port(struct saa7164_port *port)
 219 {
 220         struct tmHWStreamParameters *params = &port->hw_streamingparams;
 221         struct saa7164_dev *dev = port->dev;
 222         struct saa7164_buffer *buf;
 223         struct list_head *c, *n;
 224         int i = 0;
 225 
 226         dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr);
 227 
 228         saa7164_writel(port->bufcounter, 0);
 229         saa7164_writel(port->pitch, params->pitch);
 230         saa7164_writel(port->bufsize, params->pitch * params->numberoflines);
 231 
 232         dprintk(DBGLVL_BUF, " configured:\n");
 233         dprintk(DBGLVL_BUF, "   lmmio       0x%p\n", dev->lmmio);
 234         dprintk(DBGLVL_BUF, "   bufcounter  0x%x = 0x%x\n", port->bufcounter,
 235                 saa7164_readl(port->bufcounter));
 236 
 237         dprintk(DBGLVL_BUF, "   pitch       0x%x = %d\n", port->pitch,
 238                 saa7164_readl(port->pitch));
 239 
 240         dprintk(DBGLVL_BUF, "   bufsize     0x%x = %d\n", port->bufsize,
 241                 saa7164_readl(port->bufsize));
 242 
 243         dprintk(DBGLVL_BUF, "   buffercount = %d\n", port->hwcfg.buffercount);
 244         dprintk(DBGLVL_BUF, "   bufoffset = 0x%x\n", port->bufoffset);
 245         dprintk(DBGLVL_BUF, "   bufptr32h = 0x%x\n", port->bufptr32h);
 246         dprintk(DBGLVL_BUF, "   bufptr32l = 0x%x\n", port->bufptr32l);
 247 
 248         /* Poke the buffers and offsets into PCI space */
 249         mutex_lock(&port->dmaqueue_lock);
 250         list_for_each_safe(c, n, &port->dmaqueue.list) {
 251                 buf = list_entry(c, struct saa7164_buffer, list);
 252 
 253                 if (buf->flags != SAA7164_BUFFER_FREE)
 254                         BUG();
 255 
 256                 /* Place the buffer in the h/w queue */
 257                 saa7164_buffer_activate(buf, i);
 258 
 259                 /* Don't exceed the device maximum # bufs */
 260                 if (i++ > port->hwcfg.buffercount)
 261                         BUG();
 262 
 263         }
 264         mutex_unlock(&port->dmaqueue_lock);
 265 
 266         return 0;
 267 }
 268 
 269 struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
 270         u32 len)
 271 {
 272         struct saa7164_user_buffer *buf;
 273 
 274         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 275         if (!buf)
 276                 return NULL;
 277 
 278         buf->data = kzalloc(len, GFP_KERNEL);
 279 
 280         if (!buf->data) {
 281                 kfree(buf);
 282                 return NULL;
 283         }
 284 
 285         buf->actual_size = len;
 286         buf->pos = 0;
 287         buf->crc = 0;
 288 
 289         dprintk(DBGLVL_BUF, "%s()   allocated user buffer @ 0x%p\n",
 290                 __func__, buf);
 291 
 292         return buf;
 293 }
 294 
 295 void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
 296 {
 297         if (!buf)
 298                 return;
 299 
 300         kfree(buf->data);
 301         buf->data = NULL;
 302 
 303         kfree(buf);
 304 }
 305 

/* [<][>][^][v][top][bottom][index][help] */