Commit | Line | Data |
---|---|---|
40d0b6e1 | 1 | /* |
2 | * drivers/media/m2m1shot-helper.c | |
3 | * | |
4 | * Copyright (C) 2014 Samsung Electronics Co., Ltd. | |
5 | * | |
6 | * Contact: Cho KyongHo <pullip.cho@samsung.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License | |
10 | * version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
20 | * 02110-1301 USA | |
21 | * | |
22 | */ | |
23 | #include <linux/kernel.h> | |
24 | #include <linux/exynos_iovmm.h> | |
be5b8a22 | 25 | #include <linux/ion_exynos.h> |
40d0b6e1 | 26 | |
27 | #include <media/m2m1shot-helper.h> | |
28 | ||
29 | int m2m1shot_map_dma_buf(struct device *dev, | |
30 | struct m2m1shot_buffer_plane_dma *plane, | |
31 | enum dma_data_direction dir) | |
32 | { | |
33 | if (plane->dmabuf) { | |
34 | plane->sgt = dma_buf_map_attachment(plane->attachment, dir); | |
35 | if (IS_ERR(plane->sgt)) { | |
36 | dev_err(dev, "%s: failed to map attacment of dma_buf\n", | |
37 | __func__); | |
38 | return PTR_ERR(plane->sgt); | |
39 | } | |
40d0b6e1 | 40 | } |
41 | ||
42 | return 0; | |
43 | } | |
44 | EXPORT_SYMBOL(m2m1shot_map_dma_buf); | |
45 | ||
46 | void m2m1shot_unmap_dma_buf(struct device *dev, | |
47 | struct m2m1shot_buffer_plane_dma *plane, | |
48 | enum dma_data_direction dir) | |
49 | { | |
07e82f1a | 50 | if (plane->dmabuf) |
40d0b6e1 | 51 | dma_buf_unmap_attachment(plane->attachment, plane->sgt, dir); |
40d0b6e1 | 52 | } |
53 | EXPORT_SYMBOL(m2m1shot_unmap_dma_buf); | |
54 | ||
bf4c54a4 JK |
55 | static inline bool is_dma_coherent(struct device *dev) |
56 | { | |
57 | return device_get_dma_attr(dev) == DEV_DMA_COHERENT; | |
58 | } | |
59 | ||
40d0b6e1 | 60 | int m2m1shot_dma_addr_map(struct device *dev, |
61 | struct m2m1shot_buffer_dma *buf, | |
62 | int plane_idx, enum dma_data_direction dir) | |
63 | { | |
64 | struct m2m1shot_buffer_plane_dma *plane = &buf->plane[plane_idx]; | |
65 | dma_addr_t iova; | |
bf4c54a4 JK |
66 | int prot = IOMMU_READ; |
67 | ||
68 | if (dir == DMA_FROM_DEVICE) | |
69 | prot |= IOMMU_WRITE; | |
70 | if (is_dma_coherent(dev)) | |
71 | prot |= IOMMU_CACHE; | |
40d0b6e1 | 72 | |
73 | if (plane->dmabuf) { | |
74 | iova = ion_iovmm_map(plane->attachment, 0, | |
bf4c54a4 | 75 | plane->bytes_used, dir, prot); |
40d0b6e1 | 76 | } else { |
07e82f1a CK |
77 | down_read(¤t->mm->mmap_sem); |
78 | iova = exynos_iovmm_map_userptr(dev, | |
79 | buf->buffer->plane[plane_idx].userptr, | |
80 | plane->bytes_used, prot); | |
81 | up_read(¤t->mm->mmap_sem); | |
40d0b6e1 | 82 | } |
83 | ||
84 | if (IS_ERR_VALUE(iova)) | |
85 | return (int)iova; | |
86 | ||
87 | buf->plane[plane_idx].dma_addr = iova + plane->offset; | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
92 | void m2m1shot_dma_addr_unmap(struct device *dev, | |
93 | struct m2m1shot_buffer_dma *buf, int plane_idx) | |
94 | { | |
95 | struct m2m1shot_buffer_plane_dma *plane = &buf->plane[plane_idx]; | |
96 | dma_addr_t dma_addr = plane->dma_addr - plane->offset; | |
97 | ||
98 | if (plane->dmabuf) | |
99 | ion_iovmm_unmap(plane->attachment, dma_addr); | |
100 | else | |
07e82f1a | 101 | exynos_iovmm_unmap_userptr(dev, dma_addr); |
40d0b6e1 | 102 | |
103 | plane->dma_addr = 0; | |
104 | } | |
07e82f1a CK |
105 | |
106 | void m2m1shot_sync_for_device(struct device *dev, | |
107 | struct m2m1shot_buffer_plane_dma *plane, | |
108 | enum dma_data_direction dir) | |
109 | { | |
bf4c54a4 JK |
110 | if (is_dma_coherent(dev)) |
111 | return; | |
112 | ||
07e82f1a CK |
113 | if (plane->dmabuf) |
114 | dma_sync_sg_for_device(dev, plane->sgt->sgl, | |
115 | plane->sgt->orig_nents, dir); | |
116 | else | |
117 | exynos_iommu_sync_for_device(dev, plane->dma_addr, | |
118 | plane->bytes_used, dir); | |
119 | } | |
120 | EXPORT_SYMBOL(m2m1shot_sync_for_device); | |
121 | ||
122 | void m2m1shot_sync_for_cpu(struct device *dev, | |
123 | struct m2m1shot_buffer_plane_dma *plane, | |
124 | enum dma_data_direction dir) | |
125 | { | |
bf4c54a4 JK |
126 | if (is_dma_coherent(dev)) |
127 | return; | |
128 | ||
07e82f1a CK |
129 | if (plane->dmabuf) |
130 | dma_sync_sg_for_cpu(dev, plane->sgt->sgl, | |
131 | plane->sgt->orig_nents, dir); | |
132 | else | |
133 | exynos_iommu_sync_for_cpu(dev, plane->dma_addr, | |
134 | plane->bytes_used, dir); | |
135 | } | |
136 | EXPORT_SYMBOL(m2m1shot_sync_for_cpu); |