1 /*
2 * linux-5.4/drivers/media/platform/sunxi-vin/utility/vin_os.c
3 *
4 * Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16 #include <linux/module.h>
17 #include <linux/ion.h>
18
19 #include "vin_os.h"
20 #include <linux/dma-heap.h>
21
22 unsigned int vin_log_mask;
23 EXPORT_SYMBOL_GPL(vin_log_mask);
24
os_gpio_write(u32 gpio,__u32 out_value,int force_value_flag)25 int os_gpio_write(u32 gpio, __u32 out_value, int force_value_flag)
26 {
27 #ifndef FPGA_VER
28 if (gpio == GPIO_INDEX_INVALID)
29 return 0;
30
31 if (force_value_flag == 1) {
32 gpio_direction_output(gpio, 0);
33 __gpio_set_value(gpio, out_value);
34 } else {
35 if (out_value == 0) {
36 gpio_direction_output(gpio, 0);
37 __gpio_set_value(gpio, out_value);
38 } else {
39 gpio_direction_input(gpio);
40 }
41 }
42 #endif
43 return 0;
44 }
45 EXPORT_SYMBOL_GPL(os_gpio_write);
46
vin_get_ion_phys(struct device * dev,struct vin_mm * mem_man)47 int vin_get_ion_phys(struct device *dev, struct vin_mm *mem_man)
48 {
49 struct dma_buf_attachment *attachment;
50 struct sg_table *sgt;
51 int ret = -1;
52
53 if (IS_ERR(mem_man->buf)) {
54 pr_err("dma_buf is null\n");
55 return ret;
56 }
57
58 attachment = dma_buf_attach(mem_man->buf, get_device(dev));
59 if (IS_ERR(attachment)) {
60 pr_err("dma_buf_attach failed\n");
61 goto err_buf_put;
62 }
63
64 sgt = dma_buf_map_attachment(attachment, DMA_FROM_DEVICE);
65 if (IS_ERR_OR_NULL(sgt)) {
66 pr_err("dma_buf_map_attachment failed\n");
67 goto err_buf_detach;
68 }
69
70 mem_man->phy_addr = (void *)sg_dma_address(sgt->sgl);
71 mem_man->sgt = sgt;
72 mem_man->attachment = attachment;
73 ret = 0;
74 goto exit;
75
76 err_buf_detach:
77 dma_buf_detach(mem_man->buf, attachment);
78 err_buf_put:
79 dma_buf_put(mem_man->buf);
80 exit:
81 return ret;
82
83 }
84
vin_free_ion_phys(struct device * dev,struct vin_mm * mem_man)85 void vin_free_ion_phys(struct device *dev, struct vin_mm *mem_man)
86 {
87 dma_buf_unmap_attachment(mem_man->attachment, mem_man->sgt, DMA_FROM_DEVICE);
88 dma_buf_detach(mem_man->buf, mem_man->attachment);
89 dma_buf_put(mem_man->buf);
90
91 }
os_mem_alloc(struct device * dev,struct vin_mm * mem_man)92 int os_mem_alloc(struct device *dev, struct vin_mm *mem_man)
93 {
94 int ret = -1;
95 __maybe_unused struct ion_buffer *ion_buf;
96
97 if (mem_man == NULL)
98 return -1;
99 ion_buf = (struct ion_buffer *)mem_man->buf->priv;
100
101 #ifdef SUNXI_MEM
102 #if IS_ENABLED(CONFIG_AW_IOMMU) && IS_ENABLED(CONFIG_VIN_IOMMU)
103 /* DMA BUFFER HEAP (after linux 5.10)*/
104 mem_man->dmaHeap = dma_heap_find("system");
105 mem_man->buf = dma_heap_buffer_alloc(mem_man->dmaHeap, mem_man->size, O_RDWR, 0);
106 if (IS_ERR(mem_man->buf)) {
107 vin_err("dma_heap_buffer_alloc failed\n");
108 goto err_alloc;
109 }
110 #else
111 /* CMA or CARVEOUT */
112 mem_man->dmaHeap = dma_heap_find("reserved");
113 mem_man->buf = dma_heap_buffer_alloc(mem_man->dmaHeap, mem_man->size, O_RDWR, 0);
114 if (IS_ERR(mem_man->buf)) {
115 vin_err("dma_heap_buffer alloc failed\n");
116 goto err_alloc;
117 }
118
119 #endif
120 mem_man->vir_addr = dma_buf_vmap(mem_man->buf);
121 if (IS_ERR_OR_NULL(mem_man->vir_addr)) {
122 vin_err("ion_map_kernel failed!!");
123 goto err_map_kernel;
124 }
125
126 /*IOMMU or CMA or CARVEOUT */
127 ret = vin_get_ion_phys(dev, mem_man);
128 if (ret) {
129 vin_err("ion_phys failed!!");
130 goto err_phys;
131 }
132 mem_man->dma_addr = mem_man->phy_addr;
133 return ret;
134
135 err_phys:
136
137 dma_buf_vunmap(mem_man->buf, mem_man->vir_addr);
138
139 err_map_kernel:
140
141 dma_heap_buffer_free(mem_man->buf);
142
143
144 err_alloc:
145 return ret;
146 #else
147 mem_man->vir_addr = dma_alloc_coherent(dev, (size_t) mem_man->size,
148 (dma_addr_t *)&mem_man->phy_addr,
149 GFP_KERNEL);
150 if (!mem_man->vir_addr) {
151 vin_err("dma_alloc_coherent memory alloc failed\n");
152 return -ENOMEM;
153 }
154 mem_man->dma_addr = mem_man->phy_addr;
155 ret = 0;
156 return ret;
157 #endif
158 }
159 EXPORT_SYMBOL_GPL(os_mem_alloc);
160
161
os_mem_free(struct device * dev,struct vin_mm * mem_man)162 void os_mem_free(struct device *dev, struct vin_mm *mem_man)
163 {
164 __maybe_unused struct ion_buffer *ion_buf;
165
166 if (mem_man == NULL)
167 return;
168 ion_buf = (struct ion_buffer *)mem_man->buf->priv;
169
170 #ifdef SUNXI_MEM
171 vin_free_ion_phys(dev, mem_man);
172 //ion_heap_unmap_kernel(mem_man->heap, mem_man->buf->priv);
173 dma_buf_vunmap(mem_man->buf, mem_man->vir_addr);
174 //ion_free(mem_man->buf->priv);
175 dma_heap_buffer_free(mem_man->buf);
176 #else
177 if (mem_man->vir_addr)
178 dma_free_coherent(dev, mem_man->size, mem_man->vir_addr,
179 (dma_addr_t) mem_man->phy_addr);
180 #endif
181 mem_man->phy_addr = NULL;
182 mem_man->dma_addr = NULL;
183 mem_man->vir_addr = NULL;
184 }
185 EXPORT_SYMBOL_GPL(os_mem_free);
186
187 MODULE_AUTHOR("raymonxiu");
188 MODULE_LICENSE("Dual BSD/GPL");
189 MODULE_DESCRIPTION("Video front end OSAL for sunxi");
190