• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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