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