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(struct saa7164_buffer), GFP_KERNEL); 102 if (!buf) { 103 log_warn("%s() SAA_ERR_NO_RESOURCES\n", __func__); 104 goto ret; 105 } 106 107 buf->idx = -1; 108 buf->port = port; 109 buf->flags = SAA7164_BUFFER_FREE; 110 buf->pos = 0; 111 buf->actual_size = params->pitch * params->numberoflines; 112 buf->crc = 0; 113 /* TODO: arg len is being ignored */ 114 buf->pci_size = SAA7164_PT_ENTRIES * 0x1000; 115 buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000; 116 117 /* Allocate contiguous memory */ 118 buf->cpu = pci_alloc_consistent(port->dev->pci, buf->pci_size, 119 &buf->dma); 120 if (!buf->cpu) 121 goto fail1; 122 123 buf->pt_cpu = pci_alloc_consistent(port->dev->pci, buf->pt_size, 124 &buf->pt_dma); 125 if (!buf->pt_cpu) 126 goto fail2; 127 128 /* init the buffers to a known pattern, easier during debugging */ 129 memset(buf->cpu, 0xff, buf->pci_size); 130 buf->crc = crc32(0, buf->cpu, buf->actual_size); 131 memset(buf->pt_cpu, 0xff, buf->pt_size); 132 133 dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p (%d pageptrs)\n", 134 __func__, buf, params->numpagetables); 135 dprintk(DBGLVL_BUF, " pci_cpu @ 0x%p dma @ 0x%08lx len = 0x%x\n", 136 buf->cpu, (long)buf->dma, buf->pci_size); 137 dprintk(DBGLVL_BUF, " pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n", 138 buf->pt_cpu, (long)buf->pt_dma, buf->pt_size); 139 140 /* Format the Page Table Entries to point into the data buffer */ 141 for (i = 0 ; i < params->numpagetables; i++) { 142 143 *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */ 144 dprintk(DBGLVL_BUF, " pt[%02d] = 0x%p -> 0x%llx\n", 145 i, buf->pt_cpu, (u64)*(buf->pt_cpu)); 146 147 } 148 149 goto ret; 150 151 fail2: 152 pci_free_consistent(port->dev->pci, buf->pci_size, buf->cpu, buf->dma); 153 fail1: 154 kfree(buf); 155 156 buf = NULL; 157 ret: 158 return buf; 159 } 160 161 int saa7164_buffer_dealloc(struct saa7164_buffer *buf) 162 { 163 struct saa7164_dev *dev; 164 165 if (!buf || !buf->port) 166 return SAA_ERR_BAD_PARAMETER; 167 dev = buf->port->dev; 168 169 dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", 170 __func__, buf); 171 172 if (buf->flags != SAA7164_BUFFER_FREE) 173 log_warn(" freeing a non-free buffer\n"); 174 175 pci_free_consistent(dev->pci, buf->pci_size, buf->cpu, buf->dma); 176 pci_free_consistent(dev->pci, buf->pt_size, buf->pt_cpu, buf->pt_dma); 177 178 kfree(buf); 179 180 return SAA_OK; 181 } 182 183 int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i) 184 { 185 struct saa7164_dev *dev = port->dev; 186 187 if ((i < 0) || (i >= port->hwcfg.buffercount)) 188 return -EINVAL; 189 190 dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i); 191 192 saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0); 193 194 return 0; 195 } 196 197 /* Write a buffer into the hardware */ 198 int saa7164_buffer_activate(struct saa7164_buffer *buf, int i) 199 { 200 struct saa7164_port *port = buf->port; 201 struct saa7164_dev *dev = port->dev; 202 203 if ((i < 0) || (i >= port->hwcfg.buffercount)) 204 return -EINVAL; 205 206 dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i); 207 208 buf->idx = i; /* Note of which buffer list index position we occupy */ 209 buf->flags = SAA7164_BUFFER_BUSY; 210 buf->pos = 0; 211 212 /* TODO: Review this in light of 32v64 assignments */ 213 saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0); 214 saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma); 215 saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0); 216 217 dprintk(DBGLVL_BUF, " buf[%d] offset 0x%llx (0x%x) buf 0x%llx/%llx (0x%x/%x) nr=%d\n", 218 buf->idx, 219 (u64)port->bufoffset + (i * sizeof(u32)), 220 saa7164_readl(port->bufoffset + (sizeof(u32) * i)), 221 (u64)port->bufptr32h + ((sizeof(u32) * 2) * i), 222 (u64)port->bufptr32l + ((sizeof(u32) * 2) * i), 223 saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)), 224 saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)), 225 buf->idx); 226 227 return 0; 228 } 229 230 int saa7164_buffer_cfg_port(struct saa7164_port *port) 231 { 232 struct tmHWStreamParameters *params = &port->hw_streamingparams; 233 struct saa7164_dev *dev = port->dev; 234 struct saa7164_buffer *buf; 235 struct list_head *c, *n; 236 int i = 0; 237 238 dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr); 239 240 saa7164_writel(port->bufcounter, 0); 241 saa7164_writel(port->pitch, params->pitch); 242 saa7164_writel(port->bufsize, params->pitch * params->numberoflines); 243 244 dprintk(DBGLVL_BUF, " configured:\n"); 245 dprintk(DBGLVL_BUF, " lmmio 0x%p\n", dev->lmmio); 246 dprintk(DBGLVL_BUF, " bufcounter 0x%x = 0x%x\n", port->bufcounter, 247 saa7164_readl(port->bufcounter)); 248 249 dprintk(DBGLVL_BUF, " pitch 0x%x = %d\n", port->pitch, 250 saa7164_readl(port->pitch)); 251 252 dprintk(DBGLVL_BUF, " bufsize 0x%x = %d\n", port->bufsize, 253 saa7164_readl(port->bufsize)); 254 255 dprintk(DBGLVL_BUF, " buffercount = %d\n", port->hwcfg.buffercount); 256 dprintk(DBGLVL_BUF, " bufoffset = 0x%x\n", port->bufoffset); 257 dprintk(DBGLVL_BUF, " bufptr32h = 0x%x\n", port->bufptr32h); 258 dprintk(DBGLVL_BUF, " bufptr32l = 0x%x\n", port->bufptr32l); 259 260 /* Poke the buffers and offsets into PCI space */ 261 mutex_lock(&port->dmaqueue_lock); 262 list_for_each_safe(c, n, &port->dmaqueue.list) { 263 buf = list_entry(c, struct saa7164_buffer, list); 264 265 if (buf->flags != SAA7164_BUFFER_FREE) 266 BUG(); 267 268 /* Place the buffer in the h/w queue */ 269 saa7164_buffer_activate(buf, i); 270 271 /* Don't exceed the device maximum # bufs */ 272 if (i++ > port->hwcfg.buffercount) 273 BUG(); 274 275 } 276 mutex_unlock(&port->dmaqueue_lock); 277 278 return 0; 279 } 280 281 struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, 282 u32 len) 283 { 284 struct saa7164_user_buffer *buf; 285 286 buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL); 287 if (!buf) 288 return NULL; 289 290 buf->data = kzalloc(len, GFP_KERNEL); 291 292 if (!buf->data) { 293 kfree(buf); 294 return NULL; 295 } 296 297 buf->actual_size = len; 298 buf->pos = 0; 299 buf->crc = 0; 300 301 dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n", 302 __func__, buf); 303 304 return buf; 305 } 306 307 void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf) 308 { 309 if (!buf) 310 return; 311 312 kfree(buf->data); 313 buf->data = NULL; 314 315 kfree(buf); 316 } 317 318