diff options
Diffstat (limited to 'drivers/misc/carma/carma-fpga.c')
| -rw-r--r-- | drivers/misc/carma/carma-fpga.c | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 55e913b7eb11..68cdfe151bdb 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
| 99 | #include <linux/highmem.h> | 99 | #include <linux/highmem.h> |
| 100 | #include <linux/debugfs.h> | 100 | #include <linux/debugfs.h> |
| 101 | #include <linux/vmalloc.h> | ||
| 101 | #include <linux/kernel.h> | 102 | #include <linux/kernel.h> |
| 102 | #include <linux/module.h> | 103 | #include <linux/module.h> |
| 103 | #include <linux/poll.h> | 104 | #include <linux/poll.h> |
| @@ -105,8 +106,6 @@ | |||
| 105 | #include <linux/kref.h> | 106 | #include <linux/kref.h> |
| 106 | #include <linux/io.h> | 107 | #include <linux/io.h> |
| 107 | 108 | ||
| 108 | #include <media/videobuf-dma-sg.h> | ||
| 109 | |||
| 110 | /* system controller registers */ | 109 | /* system controller registers */ |
| 111 | #define SYS_IRQ_SOURCE_CTL 0x24 | 110 | #define SYS_IRQ_SOURCE_CTL 0x24 |
| 112 | #define SYS_IRQ_OUTPUT_EN 0x28 | 111 | #define SYS_IRQ_OUTPUT_EN 0x28 |
| @@ -142,7 +141,10 @@ struct fpga_info { | |||
| 142 | 141 | ||
| 143 | struct data_buf { | 142 | struct data_buf { |
| 144 | struct list_head entry; | 143 | struct list_head entry; |
| 145 | struct videobuf_dmabuf vb; | 144 | void *vaddr; |
| 145 | struct scatterlist *sglist; | ||
| 146 | int sglen; | ||
| 147 | int nr_pages; | ||
| 146 | size_t size; | 148 | size_t size; |
| 147 | }; | 149 | }; |
| 148 | 150 | ||
| @@ -207,6 +209,68 @@ static void fpga_device_release(struct kref *ref) | |||
| 207 | * Data Buffer Allocation Helpers | 209 | * Data Buffer Allocation Helpers |
| 208 | */ | 210 | */ |
| 209 | 211 | ||
| 212 | static int carma_dma_init(struct data_buf *buf, int nr_pages) | ||
| 213 | { | ||
| 214 | struct page *pg; | ||
| 215 | int i; | ||
| 216 | |||
| 217 | buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); | ||
| 218 | if (NULL == buf->vaddr) { | ||
| 219 | pr_debug("vmalloc_32(%d pages) failed\n", nr_pages); | ||
| 220 | return -ENOMEM; | ||
| 221 | } | ||
| 222 | |||
| 223 | pr_debug("vmalloc is at addr 0x%08lx, size=%d\n", | ||
| 224 | (unsigned long)buf->vaddr, | ||
| 225 | nr_pages << PAGE_SHIFT); | ||
| 226 | |||
| 227 | memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); | ||
| 228 | buf->nr_pages = nr_pages; | ||
| 229 | |||
| 230 | buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); | ||
| 231 | if (NULL == buf->sglist) | ||
| 232 | goto vzalloc_err; | ||
| 233 | |||
| 234 | sg_init_table(buf->sglist, buf->nr_pages); | ||
| 235 | for (i = 0; i < buf->nr_pages; i++) { | ||
| 236 | pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); | ||
| 237 | if (NULL == pg) | ||
| 238 | goto vmalloc_to_page_err; | ||
| 239 | sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); | ||
| 240 | } | ||
| 241 | return 0; | ||
| 242 | |||
| 243 | vmalloc_to_page_err: | ||
| 244 | vfree(buf->sglist); | ||
| 245 | buf->sglist = NULL; | ||
| 246 | vzalloc_err: | ||
| 247 | vfree(buf->vaddr); | ||
| 248 | buf->vaddr = NULL; | ||
| 249 | return -ENOMEM; | ||
| 250 | } | ||
| 251 | |||
| 252 | static int carma_dma_map(struct device *dev, struct data_buf *buf) | ||
| 253 | { | ||
| 254 | buf->sglen = dma_map_sg(dev, buf->sglist, | ||
| 255 | buf->nr_pages, DMA_FROM_DEVICE); | ||
| 256 | |||
| 257 | if (0 == buf->sglen) { | ||
| 258 | pr_warn("%s: dma_map_sg failed\n", __func__); | ||
| 259 | return -ENOMEM; | ||
| 260 | } | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int carma_dma_unmap(struct device *dev, struct data_buf *buf) | ||
| 265 | { | ||
| 266 | if (!buf->sglen) | ||
| 267 | return 0; | ||
| 268 | |||
| 269 | dma_unmap_sg(dev, buf->sglist, buf->sglen, DMA_FROM_DEVICE); | ||
| 270 | buf->sglen = 0; | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 210 | /** | 274 | /** |
| 211 | * data_free_buffer() - free a single data buffer and all allocated memory | 275 | * data_free_buffer() - free a single data buffer and all allocated memory |
| 212 | * @buf: the buffer to free | 276 | * @buf: the buffer to free |
| @@ -221,7 +285,8 @@ static void data_free_buffer(struct data_buf *buf) | |||
| 221 | return; | 285 | return; |
| 222 | 286 | ||
| 223 | /* free all memory */ | 287 | /* free all memory */ |
| 224 | videobuf_dma_free(&buf->vb); | 288 | vfree(buf->sglist); |
| 289 | vfree(buf->vaddr); | ||
| 225 | kfree(buf); | 290 | kfree(buf); |
| 226 | } | 291 | } |
| 227 | 292 | ||
| @@ -230,7 +295,7 @@ static void data_free_buffer(struct data_buf *buf) | |||
| 230 | * @bytes: the number of bytes required | 295 | * @bytes: the number of bytes required |
| 231 | * | 296 | * |
| 232 | * This allocates all space needed for a data buffer. It must be mapped before | 297 | * This allocates all space needed for a data buffer. It must be mapped before |
| 233 | * use in a DMA transaction using videobuf_dma_map(). | 298 | * use in a DMA transaction using carma_dma_map(). |
| 234 | * | 299 | * |
| 235 | * Returns NULL on failure | 300 | * Returns NULL on failure |
| 236 | */ | 301 | */ |
| @@ -252,9 +317,8 @@ static struct data_buf *data_alloc_buffer(const size_t bytes) | |||
| 252 | INIT_LIST_HEAD(&buf->entry); | 317 | INIT_LIST_HEAD(&buf->entry); |
| 253 | buf->size = bytes; | 318 | buf->size = bytes; |
| 254 | 319 | ||
| 255 | /* allocate the videobuf */ | 320 | /* allocate the buffer */ |
| 256 | videobuf_dma_init(&buf->vb); | 321 | ret = carma_dma_init(buf, nr_pages); |
| 257 | ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages); | ||
| 258 | if (ret) | 322 | if (ret) |
| 259 | goto out_free_buf; | 323 | goto out_free_buf; |
| 260 | 324 | ||
| @@ -285,13 +349,13 @@ static void data_free_buffers(struct fpga_device *priv) | |||
| 285 | 349 | ||
| 286 | list_for_each_entry_safe(buf, tmp, &priv->free, entry) { | 350 | list_for_each_entry_safe(buf, tmp, &priv->free, entry) { |
| 287 | list_del_init(&buf->entry); | 351 | list_del_init(&buf->entry); |
| 288 | videobuf_dma_unmap(priv->dev, &buf->vb); | 352 | carma_dma_unmap(priv->dev, buf); |
| 289 | data_free_buffer(buf); | 353 | data_free_buffer(buf); |
| 290 | } | 354 | } |
| 291 | 355 | ||
| 292 | list_for_each_entry_safe(buf, tmp, &priv->used, entry) { | 356 | list_for_each_entry_safe(buf, tmp, &priv->used, entry) { |
| 293 | list_del_init(&buf->entry); | 357 | list_del_init(&buf->entry); |
| 294 | videobuf_dma_unmap(priv->dev, &buf->vb); | 358 | carma_dma_unmap(priv->dev, buf); |
| 295 | data_free_buffer(buf); | 359 | data_free_buffer(buf); |
| 296 | } | 360 | } |
| 297 | 361 | ||
| @@ -330,7 +394,7 @@ static int data_alloc_buffers(struct fpga_device *priv) | |||
| 330 | break; | 394 | break; |
| 331 | 395 | ||
| 332 | /* map it for DMA */ | 396 | /* map it for DMA */ |
| 333 | ret = videobuf_dma_map(priv->dev, &buf->vb); | 397 | ret = carma_dma_map(priv->dev, buf); |
| 334 | if (ret) { | 398 | if (ret) { |
| 335 | data_free_buffer(buf); | 399 | data_free_buffer(buf); |
| 336 | break; | 400 | break; |
| @@ -634,8 +698,8 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) | |||
| 634 | dma_addr_t dst, src; | 698 | dma_addr_t dst, src; |
| 635 | unsigned long dma_flags = 0; | 699 | unsigned long dma_flags = 0; |
| 636 | 700 | ||
| 637 | dst_sg = buf->vb.sglist; | 701 | dst_sg = buf->sglist; |
| 638 | dst_nents = buf->vb.sglen; | 702 | dst_nents = buf->sglen; |
| 639 | 703 | ||
| 640 | src_sg = priv->corl_table.sgl; | 704 | src_sg = priv->corl_table.sgl; |
| 641 | src_nents = priv->corl_nents; | 705 | src_nents = priv->corl_nents; |
| @@ -1134,7 +1198,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count, | |||
| 1134 | spin_unlock_irq(&priv->lock); | 1198 | spin_unlock_irq(&priv->lock); |
| 1135 | 1199 | ||
| 1136 | /* Buffers are always mapped: unmap it */ | 1200 | /* Buffers are always mapped: unmap it */ |
| 1137 | videobuf_dma_unmap(priv->dev, &dbuf->vb); | 1201 | carma_dma_unmap(priv->dev, dbuf); |
| 1138 | 1202 | ||
| 1139 | /* save the buffer for later */ | 1203 | /* save the buffer for later */ |
| 1140 | reader->buf = dbuf; | 1204 | reader->buf = dbuf; |
| @@ -1143,7 +1207,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count, | |||
| 1143 | have_buffer: | 1207 | have_buffer: |
| 1144 | /* Get the number of bytes available */ | 1208 | /* Get the number of bytes available */ |
| 1145 | avail = dbuf->size - reader->buf_start; | 1209 | avail = dbuf->size - reader->buf_start; |
| 1146 | data = dbuf->vb.vaddr + reader->buf_start; | 1210 | data = dbuf->vaddr + reader->buf_start; |
| 1147 | 1211 | ||
| 1148 | /* Get the number of bytes we can transfer */ | 1212 | /* Get the number of bytes we can transfer */ |
| 1149 | count = min(count, avail); | 1213 | count = min(count, avail); |
| @@ -1171,7 +1235,7 @@ have_buffer: | |||
| 1171 | * If it fails, we pretend that the read never happed and return | 1235 | * If it fails, we pretend that the read never happed and return |
| 1172 | * -EFAULT to userspace. The read will be retried. | 1236 | * -EFAULT to userspace. The read will be retried. |
| 1173 | */ | 1237 | */ |
| 1174 | ret = videobuf_dma_map(priv->dev, &dbuf->vb); | 1238 | ret = carma_dma_map(priv->dev, dbuf); |
| 1175 | if (ret) { | 1239 | if (ret) { |
| 1176 | dev_err(priv->dev, "unable to remap buffer for DMA\n"); | 1240 | dev_err(priv->dev, "unable to remap buffer for DMA\n"); |
| 1177 | return -EFAULT; | 1241 | return -EFAULT; |
| @@ -1203,7 +1267,7 @@ out_unlock: | |||
| 1203 | spin_unlock_irq(&priv->lock); | 1267 | spin_unlock_irq(&priv->lock); |
| 1204 | 1268 | ||
| 1205 | if (drop_buffer) { | 1269 | if (drop_buffer) { |
| 1206 | videobuf_dma_unmap(priv->dev, &dbuf->vb); | 1270 | carma_dma_unmap(priv->dev, dbuf); |
| 1207 | data_free_buffer(dbuf); | 1271 | data_free_buffer(dbuf); |
| 1208 | } | 1272 | } |
| 1209 | 1273 | ||
| @@ -1433,7 +1497,6 @@ static struct platform_driver data_of_driver = { | |||
| 1433 | .driver = { | 1497 | .driver = { |
| 1434 | .name = drv_name, | 1498 | .name = drv_name, |
| 1435 | .of_match_table = data_of_match, | 1499 | .of_match_table = data_of_match, |
| 1436 | .owner = THIS_MODULE, | ||
| 1437 | }, | 1500 | }, |
| 1438 | }; | 1501 | }; |
| 1439 | 1502 | ||
