[COMMON] fimc-is2: Add dual sync settings for 5E9 & OV12A10
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / media / m2m1shot-helper.c
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>
25 #include <linux/ion_exynos.h>
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 }
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 {
50 if (plane->dmabuf)
51 dma_buf_unmap_attachment(plane->attachment, plane->sgt, dir);
52 }
53 EXPORT_SYMBOL(m2m1shot_unmap_dma_buf);
54
55 static inline bool is_dma_coherent(struct device *dev)
56 {
57 return device_get_dma_attr(dev) == DEV_DMA_COHERENT;
58 }
59
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;
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;
72
73 if (plane->dmabuf) {
74 iova = ion_iovmm_map(plane->attachment, 0,
75 plane->bytes_used, dir, prot);
76 } else {
77 down_read(&current->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(&current->mm->mmap_sem);
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
101 exynos_iovmm_unmap_userptr(dev, dma_addr);
102
103 plane->dma_addr = 0;
104 }
105
106 void m2m1shot_sync_for_device(struct device *dev,
107 struct m2m1shot_buffer_plane_dma *plane,
108 enum dma_data_direction dir)
109 {
110 if (is_dma_coherent(dev))
111 return;
112
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 {
126 if (is_dma_coherent(dev))
127 return;
128
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);