2 * videobuf2-dma-contig.c - DMA contig memory allocator for videobuf2
4 * Copyright (C) 2010 Samsung Electronics
6 * Author: Pawel Osciak <pawel@osciak.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/dma-mapping.h>
17 #include <media/videobuf2-core.h>
18 #include <media/videobuf2-memops.h>
25 struct vb2_dc_conf
*conf
;
29 struct vm_area_struct
*vma
;
31 struct vb2_vmarea_handler handler
;
34 static void vb2_dma_contig_put(void *buf_priv
);
36 static void *vb2_dma_contig_alloc(void *alloc_ctx
, unsigned long size
)
38 struct vb2_dc_conf
*conf
= alloc_ctx
;
39 struct vb2_dc_buf
*buf
;
41 buf
= kzalloc(sizeof *buf
, GFP_KERNEL
);
43 return ERR_PTR(-ENOMEM
);
45 buf
->vaddr
= dma_alloc_coherent(conf
->dev
, size
, &buf
->dma_addr
,
48 dev_err(conf
->dev
, "dma_alloc_coherent of size %ld failed\n",
51 return ERR_PTR(-ENOMEM
);
57 buf
->handler
.refcount
= &buf
->refcount
;
58 buf
->handler
.put
= vb2_dma_contig_put
;
59 buf
->handler
.arg
= buf
;
61 atomic_inc(&buf
->refcount
);
66 static void vb2_dma_contig_put(void *buf_priv
)
68 struct vb2_dc_buf
*buf
= buf_priv
;
70 if (atomic_dec_and_test(&buf
->refcount
)) {
71 dma_free_coherent(buf
->conf
->dev
, buf
->size
, buf
->vaddr
,
77 static void *vb2_dma_contig_cookie(void *buf_priv
)
79 struct vb2_dc_buf
*buf
= buf_priv
;
81 return &buf
->dma_addr
;
84 static void *vb2_dma_contig_vaddr(void *buf_priv
)
86 struct vb2_dc_buf
*buf
= buf_priv
;
93 static unsigned int vb2_dma_contig_num_users(void *buf_priv
)
95 struct vb2_dc_buf
*buf
= buf_priv
;
97 return atomic_read(&buf
->refcount
);
100 static int vb2_dma_contig_mmap(void *buf_priv
, struct vm_area_struct
*vma
)
102 struct vb2_dc_buf
*buf
= buf_priv
;
105 printk(KERN_ERR
"No buffer to map\n");
109 return vb2_mmap_pfn_range(vma
, buf
->dma_addr
, buf
->size
,
110 &vb2_common_vm_ops
, &buf
->handler
);
113 static void *vb2_dma_contig_get_userptr(void *alloc_ctx
, unsigned long vaddr
,
114 unsigned long size
, int write
)
116 struct vb2_dc_buf
*buf
;
117 struct vm_area_struct
*vma
;
118 dma_addr_t dma_addr
= 0;
121 buf
= kzalloc(sizeof *buf
, GFP_KERNEL
);
123 return ERR_PTR(-ENOMEM
);
125 ret
= vb2_get_contig_userptr(vaddr
, size
, &vma
, &dma_addr
);
127 printk(KERN_ERR
"Failed acquiring VMA for vaddr 0x%08lx\n",
134 buf
->dma_addr
= dma_addr
;
140 static void vb2_dma_contig_put_userptr(void *mem_priv
)
142 struct vb2_dc_buf
*buf
= mem_priv
;
147 vb2_put_vma(buf
->vma
);
151 const struct vb2_mem_ops vb2_dma_contig_memops
= {
152 .alloc
= vb2_dma_contig_alloc
,
153 .put
= vb2_dma_contig_put
,
154 .cookie
= vb2_dma_contig_cookie
,
155 .vaddr
= vb2_dma_contig_vaddr
,
156 .mmap
= vb2_dma_contig_mmap
,
157 .get_userptr
= vb2_dma_contig_get_userptr
,
158 .put_userptr
= vb2_dma_contig_put_userptr
,
159 .num_users
= vb2_dma_contig_num_users
,
161 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops
);
163 void *vb2_dma_contig_init_ctx(struct device
*dev
)
165 struct vb2_dc_conf
*conf
;
167 conf
= kzalloc(sizeof *conf
, GFP_KERNEL
);
169 return ERR_PTR(-ENOMEM
);
175 EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx
);
177 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx
)
181 EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx
);
183 MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
184 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
185 MODULE_LICENSE("GPL");