xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/rga3/rga_dma_buf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) Rockchip Electronics Co., Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Huang Lee <Putin.li@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define pr_fmt(fmt) "rga_dma_buf: " fmt
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "rga_dma_buf.h"
11*4882a593Smuzhiyun #include "rga.h"
12*4882a593Smuzhiyun #include "rga_common.h"
13*4882a593Smuzhiyun #include "rga_job.h"
14*4882a593Smuzhiyun #include "rga_debugger.h"
15*4882a593Smuzhiyun 
rga_dma_info_to_prot(enum dma_data_direction dir)16*4882a593Smuzhiyun static int rga_dma_info_to_prot(enum dma_data_direction dir)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun 	switch (dir) {
19*4882a593Smuzhiyun 	case DMA_BIDIRECTIONAL:
20*4882a593Smuzhiyun 		return IOMMU_READ | IOMMU_WRITE;
21*4882a593Smuzhiyun 	case DMA_TO_DEVICE:
22*4882a593Smuzhiyun 		return IOMMU_READ;
23*4882a593Smuzhiyun 	case DMA_FROM_DEVICE:
24*4882a593Smuzhiyun 		return IOMMU_WRITE;
25*4882a593Smuzhiyun 	default:
26*4882a593Smuzhiyun 		return 0;
27*4882a593Smuzhiyun 	}
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun 
rga_buf_size_cal(unsigned long yrgb_addr,unsigned long uv_addr,unsigned long v_addr,int format,uint32_t w,uint32_t h,unsigned long * StartAddr,unsigned long * size)30*4882a593Smuzhiyun int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
31*4882a593Smuzhiyun 		      unsigned long v_addr, int format, uint32_t w,
32*4882a593Smuzhiyun 		      uint32_t h, unsigned long *StartAddr, unsigned long *size)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	uint32_t size_yrgb = 0;
35*4882a593Smuzhiyun 	uint32_t size_uv = 0;
36*4882a593Smuzhiyun 	uint32_t size_v = 0;
37*4882a593Smuzhiyun 	uint32_t stride = 0;
38*4882a593Smuzhiyun 	unsigned long start, end;
39*4882a593Smuzhiyun 	uint32_t pageCount;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	switch (format) {
42*4882a593Smuzhiyun 	case RGA_FORMAT_RGBA_8888:
43*4882a593Smuzhiyun 	case RGA_FORMAT_RGBX_8888:
44*4882a593Smuzhiyun 	case RGA_FORMAT_BGRA_8888:
45*4882a593Smuzhiyun 	case RGA_FORMAT_BGRX_8888:
46*4882a593Smuzhiyun 	case RGA_FORMAT_ARGB_8888:
47*4882a593Smuzhiyun 	case RGA_FORMAT_XRGB_8888:
48*4882a593Smuzhiyun 	case RGA_FORMAT_ABGR_8888:
49*4882a593Smuzhiyun 	case RGA_FORMAT_XBGR_8888:
50*4882a593Smuzhiyun 		stride = (w * 4 + 3) & (~3);
51*4882a593Smuzhiyun 		size_yrgb = stride * h;
52*4882a593Smuzhiyun 		start = yrgb_addr >> PAGE_SHIFT;
53*4882a593Smuzhiyun 		end = yrgb_addr + size_yrgb;
54*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
55*4882a593Smuzhiyun 		pageCount = end - start;
56*4882a593Smuzhiyun 		break;
57*4882a593Smuzhiyun 	case RGA_FORMAT_RGB_888:
58*4882a593Smuzhiyun 	case RGA_FORMAT_BGR_888:
59*4882a593Smuzhiyun 		stride = (w * 3 + 3) & (~3);
60*4882a593Smuzhiyun 		size_yrgb = stride * h;
61*4882a593Smuzhiyun 		start = yrgb_addr >> PAGE_SHIFT;
62*4882a593Smuzhiyun 		end = yrgb_addr + size_yrgb;
63*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
64*4882a593Smuzhiyun 		pageCount = end - start;
65*4882a593Smuzhiyun 		break;
66*4882a593Smuzhiyun 	case RGA_FORMAT_RGB_565:
67*4882a593Smuzhiyun 	case RGA_FORMAT_RGBA_5551:
68*4882a593Smuzhiyun 	case RGA_FORMAT_RGBA_4444:
69*4882a593Smuzhiyun 	case RGA_FORMAT_BGR_565:
70*4882a593Smuzhiyun 	case RGA_FORMAT_BGRA_5551:
71*4882a593Smuzhiyun 	case RGA_FORMAT_BGRA_4444:
72*4882a593Smuzhiyun 	case RGA_FORMAT_ARGB_5551:
73*4882a593Smuzhiyun 	case RGA_FORMAT_ARGB_4444:
74*4882a593Smuzhiyun 	case RGA_FORMAT_ABGR_5551:
75*4882a593Smuzhiyun 	case RGA_FORMAT_ABGR_4444:
76*4882a593Smuzhiyun 		stride = (w * 2 + 3) & (~3);
77*4882a593Smuzhiyun 		size_yrgb = stride * h;
78*4882a593Smuzhiyun 		start = yrgb_addr >> PAGE_SHIFT;
79*4882a593Smuzhiyun 		end = yrgb_addr + size_yrgb;
80*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
81*4882a593Smuzhiyun 		pageCount = end - start;
82*4882a593Smuzhiyun 		break;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 		/* YUV FORMAT */
85*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_422_SP:
86*4882a593Smuzhiyun 	case RGA_FORMAT_YCrCb_422_SP:
87*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
88*4882a593Smuzhiyun 		size_yrgb = stride * h;
89*4882a593Smuzhiyun 		size_uv = stride * h;
90*4882a593Smuzhiyun 		start = min(yrgb_addr, uv_addr);
91*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
92*4882a593Smuzhiyun 		end = max((yrgb_addr + size_yrgb), (uv_addr + size_uv));
93*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
94*4882a593Smuzhiyun 		pageCount = end - start;
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_422_P:
97*4882a593Smuzhiyun 	case RGA_FORMAT_YCrCb_422_P:
98*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
99*4882a593Smuzhiyun 		size_yrgb = stride * h;
100*4882a593Smuzhiyun 		size_uv = ((stride >> 1) * h);
101*4882a593Smuzhiyun 		size_v = ((stride >> 1) * h);
102*4882a593Smuzhiyun 		start = min3(yrgb_addr, uv_addr, v_addr);
103*4882a593Smuzhiyun 		start = start >> PAGE_SHIFT;
104*4882a593Smuzhiyun 		end =
105*4882a593Smuzhiyun 			max3((yrgb_addr + size_yrgb), (uv_addr + size_uv),
106*4882a593Smuzhiyun 			(v_addr + size_v));
107*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
108*4882a593Smuzhiyun 		pageCount = end - start;
109*4882a593Smuzhiyun 		break;
110*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_420_SP:
111*4882a593Smuzhiyun 	case RGA_FORMAT_YCrCb_420_SP:
112*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
113*4882a593Smuzhiyun 		size_yrgb = stride * h;
114*4882a593Smuzhiyun 		size_uv = (stride * (h >> 1));
115*4882a593Smuzhiyun 		start = min(yrgb_addr, uv_addr);
116*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
117*4882a593Smuzhiyun 		end = max((yrgb_addr + size_yrgb), (uv_addr + size_uv));
118*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
119*4882a593Smuzhiyun 		pageCount = end - start;
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_420_P:
122*4882a593Smuzhiyun 	case RGA_FORMAT_YCrCb_420_P:
123*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
124*4882a593Smuzhiyun 		size_yrgb = stride * h;
125*4882a593Smuzhiyun 		size_uv = ((stride >> 1) * (h >> 1));
126*4882a593Smuzhiyun 		size_v = ((stride >> 1) * (h >> 1));
127*4882a593Smuzhiyun 		start = min3(yrgb_addr, uv_addr, v_addr);
128*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
129*4882a593Smuzhiyun 		end =
130*4882a593Smuzhiyun 			max3((yrgb_addr + size_yrgb), (uv_addr + size_uv),
131*4882a593Smuzhiyun 			(v_addr + size_v));
132*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
133*4882a593Smuzhiyun 		pageCount = end - start;
134*4882a593Smuzhiyun 		break;
135*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_400:
136*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
137*4882a593Smuzhiyun 		size_yrgb = stride * h;
138*4882a593Smuzhiyun 		start = yrgb_addr >> PAGE_SHIFT;
139*4882a593Smuzhiyun 		end = yrgb_addr + size_yrgb;
140*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
141*4882a593Smuzhiyun 		pageCount = end - start;
142*4882a593Smuzhiyun 		break;
143*4882a593Smuzhiyun 	case RGA_FORMAT_Y4:
144*4882a593Smuzhiyun 		stride = ((w + 3) & (~3)) >> 1;
145*4882a593Smuzhiyun 		size_yrgb = stride * h;
146*4882a593Smuzhiyun 		start = yrgb_addr >> PAGE_SHIFT;
147*4882a593Smuzhiyun 		end = yrgb_addr + size_yrgb;
148*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
149*4882a593Smuzhiyun 		pageCount = end - start;
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	case RGA_FORMAT_YVYU_422:
152*4882a593Smuzhiyun 	case RGA_FORMAT_VYUY_422:
153*4882a593Smuzhiyun 	case RGA_FORMAT_YUYV_422:
154*4882a593Smuzhiyun 	case RGA_FORMAT_UYVY_422:
155*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
156*4882a593Smuzhiyun 		size_yrgb = stride * h;
157*4882a593Smuzhiyun 		size_uv = stride * h;
158*4882a593Smuzhiyun 		start = min(yrgb_addr, uv_addr);
159*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
160*4882a593Smuzhiyun 		end = max((yrgb_addr + size_yrgb), (uv_addr + size_uv));
161*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
162*4882a593Smuzhiyun 		pageCount = end - start;
163*4882a593Smuzhiyun 		break;
164*4882a593Smuzhiyun 	case RGA_FORMAT_YVYU_420:
165*4882a593Smuzhiyun 	case RGA_FORMAT_VYUY_420:
166*4882a593Smuzhiyun 	case RGA_FORMAT_YUYV_420:
167*4882a593Smuzhiyun 	case RGA_FORMAT_UYVY_420:
168*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
169*4882a593Smuzhiyun 		size_yrgb = stride * h;
170*4882a593Smuzhiyun 		size_uv = (stride * (h >> 1));
171*4882a593Smuzhiyun 		start = min(yrgb_addr, uv_addr);
172*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
173*4882a593Smuzhiyun 		end = max((yrgb_addr + size_yrgb), (uv_addr + size_uv));
174*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
175*4882a593Smuzhiyun 		pageCount = end - start;
176*4882a593Smuzhiyun 		break;
177*4882a593Smuzhiyun 	case RGA_FORMAT_YCbCr_420_SP_10B:
178*4882a593Smuzhiyun 	case RGA_FORMAT_YCrCb_420_SP_10B:
179*4882a593Smuzhiyun 		stride = (w + 3) & (~3);
180*4882a593Smuzhiyun 		size_yrgb = stride * h;
181*4882a593Smuzhiyun 		size_uv = (stride * (h >> 1));
182*4882a593Smuzhiyun 		start = min(yrgb_addr, uv_addr);
183*4882a593Smuzhiyun 		start >>= PAGE_SHIFT;
184*4882a593Smuzhiyun 		end = max((yrgb_addr + size_yrgb), (uv_addr + size_uv));
185*4882a593Smuzhiyun 		end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
186*4882a593Smuzhiyun 		pageCount = end - start;
187*4882a593Smuzhiyun 		break;
188*4882a593Smuzhiyun 	default:
189*4882a593Smuzhiyun 		pageCount = 0;
190*4882a593Smuzhiyun 		start = 0;
191*4882a593Smuzhiyun 		break;
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	*StartAddr = start;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (size != NULL)
197*4882a593Smuzhiyun 		*size = size_yrgb + size_uv + size_v;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	return pageCount;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
rga_iommu_dma_alloc_iova(struct iommu_domain * domain,size_t size,u64 dma_limit,struct device * dev)202*4882a593Smuzhiyun static dma_addr_t rga_iommu_dma_alloc_iova(struct iommu_domain *domain,
203*4882a593Smuzhiyun 					    size_t size, u64 dma_limit,
204*4882a593Smuzhiyun 					    struct device *dev)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie;
207*4882a593Smuzhiyun 	struct iova_domain *iovad = &cookie->iovad;
208*4882a593Smuzhiyun 	unsigned long shift, iova_len, iova = 0;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	shift = iova_shift(iovad);
211*4882a593Smuzhiyun 	iova_len = size >> shift;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
214*4882a593Smuzhiyun 	/*
215*4882a593Smuzhiyun 	 * Freeing non-power-of-two-sized allocations back into the IOVA caches
216*4882a593Smuzhiyun 	 * will come back to bite us badly, so we have to waste a bit of space
217*4882a593Smuzhiyun 	 * rounding up anything cacheable to make sure that can't happen. The
218*4882a593Smuzhiyun 	 * order of the unadjusted size will still match upon freeing.
219*4882a593Smuzhiyun 	 */
220*4882a593Smuzhiyun 	if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
221*4882a593Smuzhiyun 		iova_len = roundup_pow_of_two(iova_len);
222*4882a593Smuzhiyun #endif
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
225*4882a593Smuzhiyun 	dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
226*4882a593Smuzhiyun #else
227*4882a593Smuzhiyun 	if (dev->bus_dma_mask)
228*4882a593Smuzhiyun 		dma_limit &= dev->bus_dma_mask;
229*4882a593Smuzhiyun #endif
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	if (domain->geometry.force_aperture)
232*4882a593Smuzhiyun 		dma_limit = min(dma_limit, (u64)domain->geometry.aperture_end);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun #if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 111) && \
235*4882a593Smuzhiyun      LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
236*4882a593Smuzhiyun 	iova = alloc_iova_fast(iovad, iova_len,
237*4882a593Smuzhiyun 			       min_t(dma_addr_t, dma_limit >> shift, iovad->end_pfn),
238*4882a593Smuzhiyun 			       true);
239*4882a593Smuzhiyun #else
240*4882a593Smuzhiyun 	iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift, true);
241*4882a593Smuzhiyun #endif
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	return (dma_addr_t)iova << shift;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
rga_iommu_dma_free_iova(struct iommu_domain * domain,dma_addr_t iova,size_t size)246*4882a593Smuzhiyun static void rga_iommu_dma_free_iova(struct iommu_domain *domain,
247*4882a593Smuzhiyun 				    dma_addr_t iova, size_t size)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie;
250*4882a593Smuzhiyun 	struct iova_domain *iovad = &cookie->iovad;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	free_iova_fast(iovad, iova_pfn(iovad, iova), size >> iova_shift(iovad));
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
rga_iommu_get_dma_domain(struct device * dev)255*4882a593Smuzhiyun static inline struct iommu_domain *rga_iommu_get_dma_domain(struct device *dev)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	return iommu_get_domain_for_dev(dev);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
rga_iommu_unmap(struct rga_dma_buffer * buffer)260*4882a593Smuzhiyun void rga_iommu_unmap(struct rga_dma_buffer *buffer)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	if (buffer == NULL)
263*4882a593Smuzhiyun 		return;
264*4882a593Smuzhiyun 	if (buffer->iova == 0)
265*4882a593Smuzhiyun 		return;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	iommu_unmap(buffer->domain, buffer->iova, buffer->size);
268*4882a593Smuzhiyun 	rga_iommu_dma_free_iova(buffer->domain, buffer->iova, buffer->size);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
rga_iommu_map_sgt(struct sg_table * sgt,size_t size,struct rga_dma_buffer * buffer,struct device * rga_dev)271*4882a593Smuzhiyun int rga_iommu_map_sgt(struct sg_table *sgt, size_t size,
272*4882a593Smuzhiyun 		      struct rga_dma_buffer *buffer,
273*4882a593Smuzhiyun 		      struct device *rga_dev)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	struct iommu_domain *domain = NULL;
276*4882a593Smuzhiyun 	struct rga_iommu_dma_cookie *cookie;
277*4882a593Smuzhiyun 	struct iova_domain *iovad;
278*4882a593Smuzhiyun 	dma_addr_t iova;
279*4882a593Smuzhiyun 	size_t map_size;
280*4882a593Smuzhiyun 	unsigned long align_size;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	if (sgt == NULL) {
283*4882a593Smuzhiyun 		pr_err("can not map iommu, because sgt is null!\n");
284*4882a593Smuzhiyun 		return -EINVAL;
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	domain = rga_iommu_get_dma_domain(rga_dev);
288*4882a593Smuzhiyun 	cookie = (void *)domain->iova_cookie;
289*4882a593Smuzhiyun 	iovad = &cookie->iovad;
290*4882a593Smuzhiyun 	align_size = iova_align(iovad, size);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	if (DEBUGGER_EN(MSG))
293*4882a593Smuzhiyun 		pr_info("iova_align size = %ld", align_size);
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev);
296*4882a593Smuzhiyun 	if (!iova) {
297*4882a593Smuzhiyun 		pr_err("rga_iommu_dma_alloc_iova failed");
298*4882a593Smuzhiyun 		return -ENOMEM;
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	map_size = iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents,
302*4882a593Smuzhiyun 				rga_dma_info_to_prot(DMA_BIDIRECTIONAL));
303*4882a593Smuzhiyun 	if (map_size < align_size) {
304*4882a593Smuzhiyun 		pr_err("iommu can not map sgt to iova");
305*4882a593Smuzhiyun 		rga_iommu_dma_free_iova(domain, iova, align_size);
306*4882a593Smuzhiyun 		return -EINVAL;
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	buffer->domain = domain;
310*4882a593Smuzhiyun 	buffer->iova = iova;
311*4882a593Smuzhiyun 	buffer->size = align_size;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
rga_iommu_map(phys_addr_t paddr,size_t size,struct rga_dma_buffer * buffer,struct device * rga_dev)316*4882a593Smuzhiyun int rga_iommu_map(phys_addr_t paddr, size_t size,
317*4882a593Smuzhiyun 		  struct rga_dma_buffer *buffer,
318*4882a593Smuzhiyun 		  struct device *rga_dev)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	int ret;
321*4882a593Smuzhiyun 	struct iommu_domain *domain = NULL;
322*4882a593Smuzhiyun 	struct rga_iommu_dma_cookie *cookie;
323*4882a593Smuzhiyun 	struct iova_domain *iovad;
324*4882a593Smuzhiyun 	dma_addr_t iova;
325*4882a593Smuzhiyun 	unsigned long align_size;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (paddr == 0) {
328*4882a593Smuzhiyun 		pr_err("can not map iommu, because phys_addr is 0!\n");
329*4882a593Smuzhiyun 		return -EINVAL;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	domain = rga_iommu_get_dma_domain(rga_dev);
333*4882a593Smuzhiyun 	cookie = (void *)domain->iova_cookie;
334*4882a593Smuzhiyun 	iovad = &cookie->iovad;
335*4882a593Smuzhiyun 	align_size = iova_align(iovad, size);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (DEBUGGER_EN(MSG))
338*4882a593Smuzhiyun 		pr_info("iova_align size = %ld", align_size);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev);
341*4882a593Smuzhiyun 	if (!iova) {
342*4882a593Smuzhiyun 		pr_err("rga_iommu_dma_alloc_iova failed");
343*4882a593Smuzhiyun 		return -ENOMEM;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	ret = iommu_map(domain, iova, paddr, align_size,
347*4882a593Smuzhiyun 			rga_dma_info_to_prot(DMA_BIDIRECTIONAL));
348*4882a593Smuzhiyun 	if (ret) {
349*4882a593Smuzhiyun 		pr_err("iommu can not map phys_addr to iova");
350*4882a593Smuzhiyun 		rga_iommu_dma_free_iova(domain, iova, align_size);
351*4882a593Smuzhiyun 		return ret;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	buffer->domain = domain;
355*4882a593Smuzhiyun 	buffer->iova = iova;
356*4882a593Smuzhiyun 	buffer->size = align_size;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	return 0;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
rga_virtual_memory_check(void * vaddr,u32 w,u32 h,u32 format,int fd)361*4882a593Smuzhiyun int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	int bits = 32;
364*4882a593Smuzhiyun 	int temp_data = 0;
365*4882a593Smuzhiyun 	void *one_line = NULL;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	bits = rga_get_format_bits(format);
368*4882a593Smuzhiyun 	if (bits < 0)
369*4882a593Smuzhiyun 		return -1;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	one_line = kzalloc(w * 4, GFP_KERNEL);
372*4882a593Smuzhiyun 	if (!one_line) {
373*4882a593Smuzhiyun 		pr_err("kzalloc fail %s[%d]\n", __func__, __LINE__);
374*4882a593Smuzhiyun 		return 0;
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	temp_data = w * (h - 1) * bits >> 3;
378*4882a593Smuzhiyun 	if (fd > 0) {
379*4882a593Smuzhiyun 		pr_info("vaddr is%p, bits is %d, fd check\n", vaddr, bits);
380*4882a593Smuzhiyun 		memcpy(one_line, (char *)vaddr + temp_data, w * bits >> 3);
381*4882a593Smuzhiyun 		pr_info("fd check ok\n");
382*4882a593Smuzhiyun 	} else {
383*4882a593Smuzhiyun 		pr_info("vir addr memory check.\n");
384*4882a593Smuzhiyun 		memcpy((void *)((char *)vaddr + temp_data), one_line,
385*4882a593Smuzhiyun 			 w * bits >> 3);
386*4882a593Smuzhiyun 		pr_info("vir addr check ok.\n");
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	kfree(one_line);
390*4882a593Smuzhiyun 	return 0;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
rga_dma_memory_check(struct rga_dma_buffer * rga_dma_buffer,struct rga_img_info_t * img)393*4882a593Smuzhiyun int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_info_t *img)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	int ret = 0;
396*4882a593Smuzhiyun 	void *vaddr;
397*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
398*4882a593Smuzhiyun 	struct iosys_map map;
399*4882a593Smuzhiyun #endif
400*4882a593Smuzhiyun 	struct dma_buf *dma_buf;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	dma_buf = rga_dma_buffer->dma_buf;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(dma_buf)) {
405*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
406*4882a593Smuzhiyun 		ret = dma_buf_vmap(dma_buf, &map);
407*4882a593Smuzhiyun 		vaddr = ret ? NULL : map.vaddr;
408*4882a593Smuzhiyun #else
409*4882a593Smuzhiyun 		vaddr = dma_buf_vmap(dma_buf);
410*4882a593Smuzhiyun #endif
411*4882a593Smuzhiyun 		if (vaddr) {
412*4882a593Smuzhiyun 			ret = rga_virtual_memory_check(vaddr, img->vir_w,
413*4882a593Smuzhiyun 				img->vir_h, img->format, img->yrgb_addr);
414*4882a593Smuzhiyun 		} else {
415*4882a593Smuzhiyun 			pr_err("can't vmap the dma buffer!\n");
416*4882a593Smuzhiyun 			return -EINVAL;
417*4882a593Smuzhiyun 		}
418*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
419*4882a593Smuzhiyun 		dma_buf_vunmap(dma_buf, &map);
420*4882a593Smuzhiyun #else
421*4882a593Smuzhiyun 		dma_buf_vunmap(dma_buf, vaddr);
422*4882a593Smuzhiyun #endif
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	return ret;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun 
rga_dma_map_buf(struct dma_buf * dma_buf,struct rga_dma_buffer * rga_dma_buffer,enum dma_data_direction dir,struct device * rga_dev)428*4882a593Smuzhiyun int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer,
429*4882a593Smuzhiyun 		    enum dma_data_direction dir, struct device *rga_dev)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct dma_buf_attachment *attach = NULL;
432*4882a593Smuzhiyun 	struct sg_table *sgt = NULL;
433*4882a593Smuzhiyun 	struct scatterlist *sg = NULL;
434*4882a593Smuzhiyun 	int i, ret = 0;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	if (dma_buf != NULL) {
437*4882a593Smuzhiyun 		get_dma_buf(dma_buf);
438*4882a593Smuzhiyun 	} else {
439*4882a593Smuzhiyun 		pr_err("dma_buf is invalid[%p]\n", dma_buf);
440*4882a593Smuzhiyun 		return -EINVAL;
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	attach = dma_buf_attach(dma_buf, rga_dev);
444*4882a593Smuzhiyun 	if (IS_ERR(attach)) {
445*4882a593Smuzhiyun 		ret = PTR_ERR(attach);
446*4882a593Smuzhiyun 		pr_err("Failed to attach dma_buf, ret[%d]\n", ret);
447*4882a593Smuzhiyun 		goto err_get_attach;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	sgt = dma_buf_map_attachment(attach, dir);
451*4882a593Smuzhiyun 	if (IS_ERR(sgt)) {
452*4882a593Smuzhiyun 		ret = PTR_ERR(sgt);
453*4882a593Smuzhiyun 		pr_err("Failed to map attachment, ret[%d]\n", ret);
454*4882a593Smuzhiyun 		goto err_get_sgt;
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	rga_dma_buffer->dma_buf = dma_buf;
458*4882a593Smuzhiyun 	rga_dma_buffer->attach = attach;
459*4882a593Smuzhiyun 	rga_dma_buffer->sgt = sgt;
460*4882a593Smuzhiyun 	rga_dma_buffer->iova = sg_dma_address(sgt->sgl);
461*4882a593Smuzhiyun 	rga_dma_buffer->dir = dir;
462*4882a593Smuzhiyun 	rga_dma_buffer->size = 0;
463*4882a593Smuzhiyun 	for_each_sgtable_sg(sgt, sg, i)
464*4882a593Smuzhiyun 		rga_dma_buffer->size += sg_dma_len(sg);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return ret;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun err_get_sgt:
469*4882a593Smuzhiyun 	if (attach)
470*4882a593Smuzhiyun 		dma_buf_detach(dma_buf, attach);
471*4882a593Smuzhiyun err_get_attach:
472*4882a593Smuzhiyun 	if (dma_buf)
473*4882a593Smuzhiyun 		dma_buf_put(dma_buf);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	return ret;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
rga_dma_map_fd(int fd,struct rga_dma_buffer * rga_dma_buffer,enum dma_data_direction dir,struct device * rga_dev)478*4882a593Smuzhiyun int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
479*4882a593Smuzhiyun 		   enum dma_data_direction dir, struct device *rga_dev)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	struct dma_buf *dma_buf = NULL;
482*4882a593Smuzhiyun 	struct dma_buf_attachment *attach = NULL;
483*4882a593Smuzhiyun 	struct sg_table *sgt = NULL;
484*4882a593Smuzhiyun 	struct scatterlist *sg = NULL;
485*4882a593Smuzhiyun 	int i, ret = 0;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	dma_buf = dma_buf_get(fd);
488*4882a593Smuzhiyun 	if (IS_ERR(dma_buf)) {
489*4882a593Smuzhiyun 		ret = PTR_ERR(dma_buf);
490*4882a593Smuzhiyun 		pr_err("Fail to get dma_buf from fd[%d], ret[%d]\n", fd, ret);
491*4882a593Smuzhiyun 		return ret;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	attach = dma_buf_attach(dma_buf, rga_dev);
495*4882a593Smuzhiyun 	if (IS_ERR(attach)) {
496*4882a593Smuzhiyun 		ret = PTR_ERR(attach);
497*4882a593Smuzhiyun 		pr_err("Failed to attach dma_buf, ret[%d]\n", ret);
498*4882a593Smuzhiyun 		goto err_get_attach;
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	sgt = dma_buf_map_attachment(attach, dir);
502*4882a593Smuzhiyun 	if (IS_ERR(sgt)) {
503*4882a593Smuzhiyun 		ret = PTR_ERR(sgt);
504*4882a593Smuzhiyun 		pr_err("Failed to map attachment, ret[%d]\n", ret);
505*4882a593Smuzhiyun 		goto err_get_sgt;
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	rga_dma_buffer->dma_buf = dma_buf;
509*4882a593Smuzhiyun 	rga_dma_buffer->attach = attach;
510*4882a593Smuzhiyun 	rga_dma_buffer->sgt = sgt;
511*4882a593Smuzhiyun 	rga_dma_buffer->iova = sg_dma_address(sgt->sgl);
512*4882a593Smuzhiyun 	rga_dma_buffer->dir = dir;
513*4882a593Smuzhiyun 	rga_dma_buffer->size = 0;
514*4882a593Smuzhiyun 	for_each_sgtable_sg(sgt, sg, i)
515*4882a593Smuzhiyun 		rga_dma_buffer->size += sg_dma_len(sg);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	return ret;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun err_get_sgt:
520*4882a593Smuzhiyun 	if (attach)
521*4882a593Smuzhiyun 		dma_buf_detach(dma_buf, attach);
522*4882a593Smuzhiyun err_get_attach:
523*4882a593Smuzhiyun 	if (dma_buf)
524*4882a593Smuzhiyun 		dma_buf_put(dma_buf);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	return ret;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
rga_dma_unmap_buf(struct rga_dma_buffer * rga_dma_buffer)529*4882a593Smuzhiyun void rga_dma_unmap_buf(struct rga_dma_buffer *rga_dma_buffer)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	if (rga_dma_buffer->attach && rga_dma_buffer->sgt)
532*4882a593Smuzhiyun 		dma_buf_unmap_attachment(rga_dma_buffer->attach,
533*4882a593Smuzhiyun 					 rga_dma_buffer->sgt,
534*4882a593Smuzhiyun 					 rga_dma_buffer->dir);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	if (rga_dma_buffer->attach) {
537*4882a593Smuzhiyun 		dma_buf_detach(rga_dma_buffer->dma_buf, rga_dma_buffer->attach);
538*4882a593Smuzhiyun 		dma_buf_put(rga_dma_buffer->dma_buf);
539*4882a593Smuzhiyun 	}
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun 
rga_dma_sync_flush_range(void * pstart,void * pend,struct rga_scheduler_t * scheduler)542*4882a593Smuzhiyun void rga_dma_sync_flush_range(void *pstart, void *pend, struct rga_scheduler_t *scheduler)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	dma_sync_single_for_device(scheduler->dev, virt_to_phys(pstart),
545*4882a593Smuzhiyun 				   pend - pstart, DMA_TO_DEVICE);
546*4882a593Smuzhiyun }
547