• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/video/fbdev/sunxi/disp2/disp/de/disp_rotation_sw/disp_rotation_sw.c
3  *
4  * Copyright (c) 2007-2018 Allwinnertech Co., Ltd.
5  * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17 #ifdef CONFIG_DISP2_SUNXI_NEON_ROTATION
18 #include <asm/neon.h>
19 #endif
20 
21 #include "disp_rotation_sw.h"
22 
23 #define ROTATION_SW_ALIGN 4
24 
25 #define DOUBLE_BUF
26 
27 #define MB_SIZE 32
28 #define MB_SIZE_U8 MB_SIZE
29 #define MB_SIZE_U16 (MB_SIZE >> 1)
30 #define MB_SIZE_U32 (MB_SIZE >> 2)
31 
32 #define MY_BYTE_ALIGN(x) (((x + (4*1024-1)) >> 12) << 12)
33 
34 struct buf_info {
35 	unsigned long long   phy_addr;
36 	unsigned int         vir_addr;
37 	unsigned int         size;
38 	struct disp_rect            update_rect;
39 };
40 
41 struct rotation_buf_info {
42 	struct buf_info *w_buf;
43 	struct buf_info *r_buf;
44 	struct buf_info buf_a;
45 	struct buf_info buf_b;
46 	struct buf_info buf_c;
47 };
48 
49 typedef struct disp_rotation_sw_private_data {
50 	int enable;
51 	int degree;
52 	int bytes_pp;
53 	struct rotation_buf_info tg_buf;
54 	struct disp_layer_config     lyr_bak;
55 #if defined(__LINUX_PLAT__)
56 	spinlock_t data_lock;
57 #else
58 	int data_lock;
59 #endif
60 } prv_data_t;
61 
62 #if defined(__LINUX_PLAT__)
63 	static spinlock_t s_data_lock;
64 #else
65 	static int s_data_lock;
66 #endif
67 
68 struct disp_rotation_sw *g_rot_sw;
69 prv_data_t *rot_sw_p;
70 
Fb_unmap_kernel(void * vaddr)71 static void Fb_unmap_kernel(void *vaddr) { vunmap(vaddr); }
72 
73 #if 0
74 extern int flush_user_range(long start, long end);
75 #else
flush_user_range(long start,long end)76 static int flush_user_range(long start, long end)
77 {
78 	return 0;
79 }
80 #endif
81 
disp_malloc_cache(u32 num_bytes,u32 * phys_addr)82 void *disp_malloc_cache(u32 num_bytes, u32 *phys_addr)
83 {
84 	return disp_malloc(num_bytes, phys_addr);
85 }
86 
map_kernel_cache(unsigned long phys_addr,unsigned long size)87 static void *map_kernel_cache(unsigned long phys_addr, unsigned long size)
88 {
89 	int npages = PAGE_ALIGN(size) / PAGE_SIZE;
90 	struct page **pages = vmalloc(sizeof(struct page *) * npages);
91 	struct page **tmp = pages;
92 	struct page *cur_page = phys_to_page(phys_addr);
93 	pgprot_t pgprot;
94 	void *vaddr;
95 	int i;
96 
97 	if (!pages)
98 		return 0;
99 
100 	for (i = 0; i < npages; i++)
101 		*(tmp++) = cur_page++;
102 
103 	pgprot = pgprot_noncached(PAGE_KERNEL);
104 	vaddr = vmap(pages, npages, VM_MAP, pgprot);
105 
106 	vfree(pages);
107 	return vaddr;
108 }
109 
110 extern void rot_90_u32(
111 	unsigned int *src_addr, const unsigned int src_widthstep,
112 	const unsigned int src_width, const unsigned int src_height,
113 	unsigned int *dst_addr, const unsigned int dst_widthstep);
114 
disp_get_rotation_sw(u32 disp)115 struct disp_rotation_sw *disp_get_rotation_sw(u32 disp)
116 {
117 	u32 num_screens;
118 
119 	num_screens = bsp_disp_feat_get_num_screens();
120 	if (disp >= num_screens || NULL == g_rot_sw) {
121 		DE_WRN("disp %d out of range? g_rot_sw=%d\n",
122 			disp, (int)g_rot_sw);
123 		return NULL;
124 	}
125 	return &g_rot_sw[disp];
126 }
127 
rot_270_u8_buf(unsigned char * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned char * dst_addr,const unsigned int dst_widthstep)128 static void rot_270_u8_buf(
129 	unsigned char *src_addr, const unsigned int src_widthstep,
130 	const unsigned int src_width, const unsigned int src_height,
131 	unsigned char *dst_addr, const unsigned int dst_widthstep)
132 {
133 	unsigned char buf[MB_SIZE_U8][MB_SIZE_U8];
134 
135 	rot_270_u8(src_addr, src_widthstep, src_width,
136 		src_height, (unsigned char *)buf, MB_SIZE);
137 	rot_0_u8((unsigned char *)buf, MB_SIZE, src_height,
138 		src_width, dst_addr, dst_widthstep);
139 }
140 
rot_270_u16_buf(unsigned short * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned short * dst_addr,const unsigned int dst_widthstep)141 static void rot_270_u16_buf(
142 	unsigned short *src_addr, const unsigned int src_widthstep,
143 	const unsigned int src_width, const unsigned int src_height,
144 	unsigned short *dst_addr, const unsigned int dst_widthstep)
145 {
146 	unsigned short buf[MB_SIZE_U16][MB_SIZE_U16];
147 
148 	rot_270_u16(src_addr, src_widthstep, src_width,
149 		src_height, (unsigned short *)buf, MB_SIZE);
150 	rot_0_u16((unsigned short *)buf, MB_SIZE, src_height,
151 		src_width, dst_addr, dst_widthstep);
152 }
153 
rot_270_u32_buf(unsigned int * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned int * dst_addr,const unsigned int dst_widthstep)154 static void rot_270_u32_buf(
155 	unsigned int *src_addr, const unsigned int src_widthstep,
156 	const unsigned int src_width, const unsigned int src_height,
157 	unsigned int *dst_addr, const unsigned int dst_widthstep)
158 {
159 	unsigned int buf[MB_SIZE_U32][MB_SIZE_U32];
160 
161 	rot_270_u32(src_addr, src_widthstep, src_width,
162 		src_height, (unsigned int *)buf, MB_SIZE);
163 	rot_0_u32((unsigned int *)buf, MB_SIZE, src_height,
164 		src_width, dst_addr, dst_widthstep);
165 }
166 
rot_90_u8_buf(unsigned char * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned char * dst_addr,const unsigned int dst_widthstep)167 static void rot_90_u8_buf(
168 	unsigned char *src_addr, const unsigned int src_widthstep,
169 	const unsigned int src_width, const unsigned int src_height,
170 	unsigned char *dst_addr, const unsigned int dst_widthstep)
171 {
172 	unsigned char buf[MB_SIZE_U8][MB_SIZE_U8];
173 
174 	rot_90_u8(src_addr, src_widthstep, src_width,
175 		src_height, (unsigned char *)buf, MB_SIZE);
176 	rot_0_u8((unsigned char *)buf, MB_SIZE, src_height,
177 		src_width, dst_addr, dst_widthstep);
178 }
179 
rot_90_u16_buf(unsigned short * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned short * dst_addr,const unsigned int dst_widthstep)180 static void rot_90_u16_buf(
181 	unsigned short *src_addr, const unsigned int src_widthstep,
182 	const unsigned int src_width, const unsigned int src_height,
183 	unsigned short *dst_addr, const unsigned int dst_widthstep)
184 {
185 	unsigned short buf[MB_SIZE_U16][MB_SIZE_U16];
186 
187 	rot_90_u16(src_addr, src_widthstep, src_width,
188 		src_height, (unsigned short *)buf, MB_SIZE);
189 	rot_0_u16((unsigned short *)buf, MB_SIZE, src_height,
190 		src_width, dst_addr, dst_widthstep);
191 }
192 
rot_90_u32_buf(unsigned int * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned int * dst_addr,const unsigned int dst_widthstep)193 static void rot_90_u32_buf(
194 	unsigned int *src_addr, const unsigned int src_widthstep,
195 	const unsigned int src_width, const unsigned int src_height,
196 	unsigned int *dst_addr, const unsigned int dst_widthstep)
197 {
198 	unsigned int buf[MB_SIZE_U32][MB_SIZE_U32];
199 
200 #ifdef CONFIG_DISP2_SUNXI_NEON_ROTATION
201 kernel_neon_begin();
202 	rot_90_u32(src_addr, src_widthstep, src_width,
203 		src_height, (unsigned int *)buf, MB_SIZE);
204 kernel_neon_end();
205 #else
206 	rot_90_u32(src_addr, src_widthstep, src_width,
207 		src_height, (unsigned int *)buf, MB_SIZE);
208 #endif
209 
210 	rot_0_u32((unsigned int *)buf, MB_SIZE, src_height,
211 		src_width, dst_addr, dst_widthstep);
212 }
213 
rot_270_u8_mb(unsigned char * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned char * dst_addr,const unsigned int dst_widthstep)214 static int rot_270_u8_mb(
215 	unsigned char *src_addr, const unsigned int src_widthstep,
216 	const unsigned int src_width, const unsigned int src_height,
217 	unsigned char *dst_addr, const unsigned int dst_widthstep)
218 
219 {
220 	unsigned int delta_w;
221 	unsigned int delta_h;
222 	unsigned int src_widthstep_buf;
223 	unsigned char *src_addr_end, *p_src;
224 
225 	unsigned int dst_widthstep_buf;
226 	unsigned char *p_dst, *p_dst_end;
227 	const char *dst_vir_addr = (const char *)dst_addr;
228 
229 	delta_w = src_width % MB_SIZE_U8;
230 	delta_h = src_height % MB_SIZE_U8;
231 
232 	src_widthstep_buf = MB_SIZE_U8 * src_widthstep;
233 	dst_widthstep_buf = MB_SIZE_U8 * dst_widthstep;
234 
235 	src_addr = src_addr + src_width - MB_SIZE_U8;
236 	src_addr_end = src_addr - src_width + delta_w;
237 
238 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U8) {
239 		p_src = src_addr;
240 		p_dst = dst_addr;
241 		p_dst_end = p_dst + src_height - delta_h;
242 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U8) {
243 			rot_270_u8_buf(p_src, src_widthstep, MB_SIZE_U8,
244 				MB_SIZE_U8, p_dst, dst_widthstep);
245 			p_src += src_widthstep_buf;
246 		}
247 		dst_addr += dst_widthstep_buf;
248 	}
249 
250 	src_addr += (MB_SIZE_U8 - delta_w);
251 	p_dst_end = dst_addr + src_height - delta_h;
252 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U8) {
253 		rot_270_u8_buf(src_addr, src_widthstep, delta_w,
254 			MB_SIZE_U8, dst_addr, dst_widthstep);
255 		src_addr += src_widthstep_buf;
256 	}
257 
258 	rot_270_u8_buf(src_addr, src_widthstep, delta_w,
259 		delta_h, dst_addr, dst_widthstep);
260 
261 	src_addr = src_addr + src_width - MB_SIZE_U8;
262 	dst_addr -= (dst_widthstep * (src_width - delta_w));
263 	src_addr_end = src_addr - src_width + delta_w;
264 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U8) {
265 		rot_270_u8_buf(src_addr, src_widthstep, MB_SIZE_U8,
266 			delta_h, dst_addr, dst_widthstep);
267 		dst_addr += dst_widthstep_buf;
268 	}
269 
270 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
271 		 + dst_widthstep * (src_width - 1) + src_height));
272 
273 	return 0;
274 }
275 
rot_270_u16_mb(unsigned short * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned short * dst_addr,const unsigned int dst_widthstep)276 static int rot_270_u16_mb(
277 	unsigned short *src_addr, const unsigned int src_widthstep,
278 	const unsigned int src_width, const unsigned int src_height,
279 	unsigned short *dst_addr, const unsigned int dst_widthstep)
280 {
281 	unsigned int delta_w;
282 	unsigned int delta_h;
283 
284 	unsigned int src_widthstep_buf;
285 	unsigned short *src_addr_end, *p_src;
286 
287 	unsigned int dst_widthstep_buf;
288 	unsigned short *p_dst, *p_dst_end;
289 	const char *dst_vir_addr = (const char *)dst_addr;
290 
291 	delta_w = src_width % MB_SIZE_U16;
292 	delta_h = src_height % MB_SIZE_U16;
293 
294 	src_widthstep_buf = MB_SIZE_U16 * src_widthstep;
295 	dst_widthstep_buf = MB_SIZE_U16 * dst_widthstep;
296 
297 	src_addr = src_addr + src_width - MB_SIZE_U16;
298 	src_addr_end = src_addr - src_width + delta_w;
299 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U16) {
300 		p_src = src_addr;
301 		p_dst = dst_addr;
302 		p_dst_end = p_dst + src_height - delta_h;
303 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U16) {
304 			rot_270_u16_buf(p_src, src_widthstep, MB_SIZE_U16,
305 				MB_SIZE_U16, p_dst, dst_widthstep);
306 			p_src = (unsigned short *)((char *)p_src + src_widthstep_buf);
307 		}
308 		dst_addr = (unsigned short *)((char *)dst_addr + dst_widthstep_buf);
309 	}
310 
311 	src_addr += (MB_SIZE_U16 - delta_w);
312 	p_dst_end = dst_addr + src_height - delta_h;
313 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U16) {
314 		rot_270_u16_buf(src_addr, src_widthstep, delta_w,
315 			MB_SIZE_U16, dst_addr, dst_widthstep);
316 		src_addr = (unsigned short *)((char *)src_addr + src_widthstep_buf);
317 	}
318 
319 	rot_270_u16_buf(src_addr, src_widthstep, delta_w,
320 		delta_h, dst_addr, dst_widthstep);
321 
322 	src_addr = src_addr + src_width - MB_SIZE_U16;
323 	dst_addr = (unsigned short *)((char *)dst_addr
324 		 - dst_widthstep * (src_width - delta_w));
325 	src_addr_end = src_addr - src_width + delta_w;
326 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U16) {
327 		rot_270_u16_buf(src_addr, src_widthstep, MB_SIZE_U16,
328 			delta_h, dst_addr, dst_widthstep);
329 		dst_addr = (unsigned short *)((char *)dst_addr + dst_widthstep_buf);
330 	}
331 
332 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
333 		 + dst_widthstep * (src_width - 1) + (src_height << 1)));
334 
335 	return 0;
336 }
337 
rot_270_u32_mb(unsigned int * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned int * dst_addr,const unsigned int dst_widthstep)338 static int rot_270_u32_mb(
339 	unsigned int *src_addr, const unsigned int src_widthstep,
340 	const unsigned int src_width, const unsigned int src_height,
341 	unsigned int *dst_addr, const unsigned int dst_widthstep)
342 
343 {
344 	unsigned int delta_w;
345 	unsigned int delta_h;
346 
347 	unsigned int src_widthstep_buf;
348 	unsigned int *src_addr_end, *p_src;
349 
350 	unsigned int dst_widthstep_buf;
351 	unsigned int *p_dst, *p_dst_end;
352 	const char *dst_vir_addr = (const char *)dst_addr;
353 
354 	delta_w = src_width % MB_SIZE_U32;
355 	delta_h = src_height % MB_SIZE_U32;
356 
357 	src_widthstep_buf = MB_SIZE_U32 * src_widthstep;
358 	dst_widthstep_buf = MB_SIZE_U32 * dst_widthstep;
359 
360 	src_addr = src_addr + src_width - MB_SIZE_U32;
361 	src_addr_end = src_addr - src_width + delta_w;
362 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U32) {
363 		p_src = src_addr;
364 		p_dst = dst_addr;
365 		p_dst_end = p_dst + src_height - delta_h;
366 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U32) {
367 			rot_270_u32_buf(p_src, src_widthstep, MB_SIZE_U32,
368 				MB_SIZE_U32, p_dst, dst_widthstep);
369 			p_src = (unsigned int *)((char *)p_src + src_widthstep_buf);
370 		}
371 		dst_addr = (unsigned int *)((char *)dst_addr + dst_widthstep_buf);
372 	}
373 
374 	src_addr += (MB_SIZE_U32 - delta_w);
375 	p_dst_end = dst_addr + src_height - delta_h;
376 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U32) {
377 		rot_270_u32_buf(src_addr, src_widthstep, delta_w,
378 			MB_SIZE_U32, dst_addr, dst_widthstep);
379 		src_addr = (unsigned int *)((char *)src_addr + src_widthstep_buf);
380 	}
381 
382 	rot_270_u32_buf(src_addr, src_widthstep, delta_w,
383 		delta_h, dst_addr, dst_widthstep);
384 
385 	src_addr = src_addr + src_width - MB_SIZE_U32;
386 	dst_addr = (unsigned int *)((char *)dst_addr
387 		 - dst_widthstep * (src_width - delta_w));
388 
389 	src_addr_end = src_addr - src_width + delta_w;
390 	for (; src_addr != src_addr_end; src_addr -= MB_SIZE_U32) {
391 		rot_270_u32_buf(src_addr, src_widthstep, MB_SIZE_U32,
392 			delta_h, dst_addr, dst_widthstep);
393 		dst_addr = (unsigned int *)((char *)dst_addr + dst_widthstep_buf);
394 	}
395 
396 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
397 		 + dst_widthstep * (src_width - 1) + (src_height << 2)));
398 
399 	return 0;
400 }
401 
rot_90_u8_mb(unsigned char * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned char * dst_addr,const unsigned int dst_widthstep)402 static int rot_90_u8_mb(
403 	unsigned char *src_addr, const unsigned int src_widthstep,
404 	const unsigned int src_width, const unsigned int src_height,
405 	unsigned char *dst_addr, const unsigned int dst_widthstep)
406 {
407 	unsigned int delta_w;
408 	unsigned int delta_h;
409 
410 	unsigned int src_widthstep_buf;
411 	unsigned char *src_addr_end, *p_src;
412 
413 	unsigned int dst_widthstep_buf;
414 	unsigned char *p_dst, *p_dst_end;
415 	const char *dst_vir_addr = (const char *)dst_addr;
416 
417 	delta_w = src_width % MB_SIZE_U8;
418 	delta_h = src_height % MB_SIZE_U8;
419 
420 	src_widthstep_buf = MB_SIZE_U8 * src_widthstep;
421 	dst_widthstep_buf = MB_SIZE_U8 * dst_widthstep;
422 
423 	src_addr += (src_widthstep * ((signed int)src_height - delta_h - MB_SIZE_U8));
424 	src_addr_end = src_addr + src_width - delta_w;
425 	dst_addr += delta_h;
426 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U8) {
427 		p_src = src_addr;
428 		p_dst = dst_addr;
429 		p_dst_end = p_dst + src_height - delta_h;
430 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U8) {
431 			rot_90_u8_buf(p_src, src_widthstep, MB_SIZE_U8,
432 				MB_SIZE_U8, p_dst, dst_widthstep);
433 			p_src -= src_widthstep_buf;
434 		}
435 		dst_addr += dst_widthstep_buf;
436 	}
437 
438 	p_dst_end = dst_addr + src_height - delta_h;
439 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U8) {
440 		rot_90_u8_buf(src_addr, src_widthstep, delta_w,
441 			MB_SIZE_U8, dst_addr, dst_widthstep);
442 		src_addr -= src_widthstep_buf;
443 	}
444 
445 	src_addr = src_addr - src_width + delta_w
446 		 + src_widthstep * (src_height + MB_SIZE_U8 - delta_h);
447 	dst_addr = (unsigned char *)dst_vir_addr;
448 	src_addr_end = src_addr + src_width - delta_w;
449 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U8) {
450 		rot_90_u8_buf(src_addr, src_widthstep, MB_SIZE_U8,
451 			delta_h, dst_addr, dst_widthstep);
452 		dst_addr += dst_widthstep_buf;
453 	}
454 
455 	rot_90_u8_buf(src_addr, src_widthstep, delta_w,
456 		delta_h, dst_addr, dst_widthstep);
457 
458 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
459 		 + dst_widthstep * (src_width - 1) + src_height));
460 
461 	return 0;
462 }
463 
rot_90_u16_mb(unsigned short * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned short * dst_addr,const unsigned int dst_widthstep)464 static int rot_90_u16_mb(
465 	unsigned short *src_addr, const unsigned int src_widthstep,
466 	const unsigned int src_width, const unsigned int src_height,
467 	unsigned short *dst_addr, const unsigned int dst_widthstep)
468 {
469 	unsigned int delta_w;
470 	unsigned int delta_h;
471 
472 	unsigned int src_widthstep_buf;
473 	unsigned short *src_addr_end, *p_src;
474 
475 	unsigned int dst_widthstep_buf;
476 	unsigned short *p_dst, *p_dst_end;
477 	const char *dst_vir_addr = (const char *)dst_addr;
478 
479 	delta_w = src_width % MB_SIZE_U16;
480 	delta_h = src_height % MB_SIZE_U16;
481 
482 	src_widthstep_buf = MB_SIZE_U16 * src_widthstep;
483 	dst_widthstep_buf = MB_SIZE_U16 * dst_widthstep;
484 
485 	src_addr = (unsigned short *)((char *)src_addr + src_widthstep
486 		 * ((signed int)src_height - delta_h - MB_SIZE_U16));
487 	src_addr_end = src_addr + src_width - delta_w;
488 	dst_addr += delta_h;
489 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U16) {
490 		p_src = src_addr;
491 		p_dst = dst_addr;
492 		p_dst_end = p_dst + src_height - delta_h;
493 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U16) {
494 			rot_90_u16_buf(p_src, src_widthstep, MB_SIZE_U16,
495 				MB_SIZE_U16, p_dst, dst_widthstep);
496 			p_src = (unsigned short *)((char *)p_src -
497 							src_widthstep_buf);
498 		}
499 		dst_addr = (unsigned short *)((char *)dst_addr +
500 							dst_widthstep_buf);
501 	}
502 
503 	p_dst_end = dst_addr + src_height - delta_h;
504 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U16) {
505 		rot_90_u16_buf(src_addr, src_widthstep, delta_w,
506 			MB_SIZE_U16, dst_addr, dst_widthstep);
507 		src_addr = (unsigned short *)((char *)src_addr -
508 							src_widthstep_buf);
509 	}
510 
511 	src_addr = (unsigned short *)((char *)src_addr
512 		 + src_widthstep * (src_height + MB_SIZE_U16 - delta_h)
513 		 - ((src_width - delta_w) << 1));
514 	dst_addr = (unsigned short *)dst_vir_addr;
515 	src_addr_end = src_addr + src_width - delta_w;
516 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U16) {
517 		rot_90_u16_buf(src_addr, src_widthstep, MB_SIZE_U16,
518 			delta_h, dst_addr, dst_widthstep);
519 		dst_addr = (unsigned short *)((char *)dst_addr +
520 							dst_widthstep_buf);
521 	}
522 
523 	rot_90_u16_buf(src_addr, src_widthstep, delta_w,
524 		delta_h, dst_addr, dst_widthstep);
525 
526 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
527 		 + dst_widthstep * (src_width - 1) + (src_height << 1)));
528 
529 	return 0;
530 }
531 
rot_90_u32_mb(unsigned int * src_addr,const unsigned int src_widthstep,const unsigned int src_width,const unsigned int src_height,unsigned int * dst_addr,const unsigned int dst_widthstep)532 static int rot_90_u32_mb(
533 	unsigned int *src_addr, const unsigned int src_widthstep,
534 	const unsigned int src_width, const unsigned int src_height,
535 	unsigned int *dst_addr, const unsigned int dst_widthstep)
536 {
537 	unsigned int delta_w;
538 	unsigned int delta_h;
539 
540 	unsigned int src_widthstep_buf;
541 	unsigned int *src_addr_end, *p_src;
542 
543 	unsigned int dst_widthstep_buf;
544 	unsigned int *p_dst, *p_dst_end;
545 	const char *dst_vir_addr = (const char *)dst_addr;
546 
547 	delta_w = src_width % MB_SIZE_U32;
548 	delta_h = src_height % MB_SIZE_U32;
549 
550 	src_widthstep_buf = MB_SIZE_U32 * src_widthstep;
551 	dst_widthstep_buf = MB_SIZE_U32 * dst_widthstep;
552 
553 	src_addr = (unsigned int *)((char *)src_addr
554 		 + src_widthstep * ((signed int)src_height - delta_h - MB_SIZE_U32));
555 	src_addr_end = src_addr + src_width - delta_w;
556 	dst_addr += delta_h;
557 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U32) {
558 		p_src = src_addr;
559 		p_dst = dst_addr;
560 		p_dst_end = p_dst + src_height - delta_h;
561 		for (; p_dst != p_dst_end; p_dst += MB_SIZE_U32) {
562 			rot_90_u32_buf(p_src, src_widthstep, MB_SIZE_U32,
563 				MB_SIZE_U32, p_dst, dst_widthstep);
564 			p_src = (unsigned int *)((char *)p_src - src_widthstep_buf);
565 		}
566 		dst_addr = (unsigned int *)((char *)dst_addr + dst_widthstep_buf);
567 	}
568 
569 	p_dst_end = dst_addr + src_height - delta_h;
570 	for (; dst_addr != p_dst_end; dst_addr += MB_SIZE_U32) {
571 		rot_90_u32_buf(src_addr, src_widthstep, delta_w,
572 			MB_SIZE_U32, dst_addr, dst_widthstep);
573 		src_addr = (unsigned int *)((char *)src_addr - src_widthstep_buf);
574 	}
575 
576 	src_addr = (unsigned int *)((char *)src_addr
577 		 + src_widthstep * (src_height + MB_SIZE_U32 - delta_h)
578 		 - ((src_width - delta_w) << 2));
579 	dst_addr = (unsigned int *)dst_vir_addr;
580 	src_addr_end = src_addr + src_width - delta_w;
581 	for (; src_addr != src_addr_end; src_addr += MB_SIZE_U32) {
582 		rot_90_u32_buf(src_addr, src_widthstep, MB_SIZE_U32,
583 			delta_h, dst_addr, dst_widthstep);
584 		dst_addr = (unsigned int *)((char *)dst_addr + dst_widthstep_buf);
585 	}
586 
587 	rot_90_u32_buf(src_addr, src_widthstep, delta_w,
588 		delta_h, dst_addr, dst_widthstep);
589 
590 	flush_user_range((long)dst_vir_addr, (long)(dst_vir_addr
591 		 + dst_widthstep * (src_width - 1) + (src_height << 2)));
592 
593 	return 0;
594 }
595 
rotate_fb(struct disp_fb_info * src_fb,struct disp_rect * src_dirty,struct disp_fb_info * dst_fb,struct disp_rect * dst_dirty,void * dst_vir_addr,int deg)596 static int rotate_fb(struct disp_fb_info *src_fb, struct disp_rect *src_dirty,
597 	struct disp_fb_info *dst_fb, struct disp_rect *dst_dirty, void *dst_vir_addr, int deg)
598 {
599 	unsigned long map_size;
600 	void *src_vir_addr;
601 	int src_widthstep, src_offset;
602 	int dst_widthstep, dst_offset;
603 	int Bpp[3];
604 	int dirty_fac1, dirty_fac2;
605 
606 	switch (src_fb->format) {
607 	case DISP_FORMAT_ARGB_8888:
608 	case DISP_FORMAT_ABGR_8888:
609 	case DISP_FORMAT_RGBA_8888:
610 	case DISP_FORMAT_BGRA_8888:
611 		map_size = src_fb->size[0].width * src_fb->size[0].height << 2;
612 		Bpp[0] = 4;
613 		Bpp[1] = Bpp[2] = 0;
614 		break;
615 	case DISP_FORMAT_YUV420_SP_UVUV:
616 	case DISP_FORMAT_YUV420_SP_VUVU:
617 		map_size = src_fb->size[0].width * src_fb->size[0].height * 3 >> 1;
618 		Bpp[0] = 1;
619 		Bpp[1] = 2;
620 		Bpp[2] = 0;
621 		dirty_fac1 = 1;
622 		break;
623 	case DISP_FORMAT_YUV420_P:
624 		map_size = src_fb->size[0].width * src_fb->size[0].height * 3 >> 1;
625 		Bpp[0] = Bpp[1] = Bpp[2] = 1;
626 		dirty_fac1 = dirty_fac2 = 1;
627 	default:
628 		DE_WRN("fixme");
629 		return -1;
630 	}
631 
632 	src_vir_addr = map_kernel_cache((unsigned long)src_fb->addr[0], map_size);
633 	if (NULL == src_vir_addr) {
634 		DE_WRN("map_kernel_cache failed!\n");
635 		return -1;
636 	}
637 
638 	switch (Bpp[0]) {
639 	case 4:
640 		src_widthstep = src_fb->size[0].width << 2;
641 		src_offset = src_widthstep * src_dirty->y + (src_dirty->x << 2);
642 		dst_widthstep = dst_fb->size[0].width << 2;
643 		dst_offset = dst_widthstep * dst_dirty->y + (dst_dirty->x << 2);
644 		switch (deg) {
645 		case ROTATION_SW_90:
646 
647 #ifdef CONFIG_DISP2_SUNXI_NEON_ROTATION
648 		    kernel_neon_begin();
649 			rot_90_u32((unsigned int *)((char *)src_vir_addr + src_offset),
650 				src_widthstep, src_dirty->width, src_dirty->height,
651 				(unsigned int *)((char *)dst_vir_addr + dst_offset), dst_widthstep);
652 			kernel_neon_end();
653 #else
654 			rot_90_u32_mb((unsigned int *)((char *)src_vir_addr + src_offset),
655 				src_widthstep, src_dirty->width, src_dirty->height,
656 				(unsigned int *)((char *)dst_vir_addr + dst_offset), dst_widthstep);
657 #endif
658 			break;
659 		case ROTATION_SW_270:
660 			rot_270_u32_mb((unsigned int *)((char *)src_vir_addr + src_offset),
661 				src_widthstep, src_dirty->width, src_dirty->height,
662 				(unsigned int *)((char *)dst_vir_addr + dst_offset), dst_widthstep);
663 			break;
664 		default:
665 			DE_WRN("fixme: deg=%d", deg);
666 			goto go_out;
667 		}
668 		break;
669 	case 1:
670 		src_widthstep = src_fb->size[0].width;
671 		src_offset = src_widthstep * src_dirty->y + src_dirty->x;
672 		dst_widthstep = dst_fb->size[0].width;
673 		dst_offset = dst_widthstep * dst_dirty->y + dst_dirty->x;
674 		switch (deg) {
675 		case ROTATION_SW_90:
676 			rot_90_u8_mb((char *)src_vir_addr + src_offset,
677 				src_widthstep, src_dirty->width, src_dirty->height,
678 				(char *)dst_vir_addr + dst_offset, dst_widthstep);
679 			break;
680 		case ROTATION_SW_270:
681 			rot_270_u8_mb((char *)src_vir_addr + src_offset,
682 				src_widthstep, src_dirty->width, src_dirty->height,
683 				(char *)dst_vir_addr + dst_offset, dst_widthstep);
684 			break;
685 		default:
686 			DE_WRN("fixme: deg=%d", deg);
687 			goto go_out;
688 		}
689 		break;
690 	case 2:
691 	default:
692 		DE_WRN("fixme");
693 		goto go_out;
694 	}
695 
696 	src_offset = src_widthstep * src_fb->size[0].height;
697 	dst_offset = dst_widthstep * dst_fb->size[0].height;
698 
699 	switch (Bpp[1]) {
700 	case 2:
701 		src_widthstep = src_fb->size[0].width << 1;
702 		src_offset += src_widthstep * (src_dirty->y >> dirty_fac1)
703 			 + (src_dirty->x << 1 >> dirty_fac1);
704 		dst_widthstep = dst_fb->size[0].width << 1;
705 		dst_offset += dst_widthstep * (dst_dirty->y >> dirty_fac1)
706 			 + (dst_dirty->x << 1 >> dirty_fac1);
707 		switch (deg) {
708 		case ROTATION_SW_90:
709 			rot_90_u16_mb((unsigned short *)((char *)src_vir_addr + src_offset),
710 				src_widthstep, src_dirty->width >> dirty_fac1, src_dirty->height >> dirty_fac1,
711 				(unsigned short *)((char *)dst_vir_addr + dst_offset), dst_widthstep);
712 			break;
713 		case ROTATION_SW_270:
714 			rot_270_u16_mb((unsigned short *)((char *)src_vir_addr + src_offset),
715 				src_widthstep, src_dirty->width >> dirty_fac1, src_dirty->height >> dirty_fac1,
716 				(unsigned short *)((char *)dst_vir_addr + dst_offset), dst_widthstep);
717 			break;
718 		default:
719 			DE_WRN("fixme: deg=%d", deg);
720 			goto go_out;
721 		}
722 		break;
723 	case 0:
724 		break;
725 	case 4:
726 	case 1:
727 	default:
728 		DE_WRN("fixme: Bpp[1]=%d", Bpp[1]);
729 	}
730 
731 go_out:
732 	Fb_unmap_kernel(src_vir_addr);
733 	return 0;
734 }
735 
update_rotate_fb(struct buf_info * src,struct buf_info * dst,int Bpp,int widthstep,struct disp_rect * dst_dirty_rect,struct disp_rectsz * scn_win)736 static int update_rotate_fb(struct buf_info *src, struct buf_info *dst,
737 	int Bpp, int widthstep, struct disp_rect *dst_dirty_rect, struct disp_rectsz *scn_win)
738 {
739 
740 #if 0
741 	printk("update_rect[%d,%d,%d,%d], dst_dirty_rect[%d,%d,%d,%d],scn_win[%d,%d]\n",
742 		src->update_rect.x, src->update_rect.y, src->update_rect.width,
743 		src->update_rect.height, dst_dirty_rect->x, dst_dirty_rect->y,
744 		dst_dirty_rect->width, dst_dirty_rect->height, scn_win->width, scn_win->height);
745 #endif
746 
747 #if defined(DOUBLE_BUF)
748 	if ((0 != src->vir_addr) && (0 != dst->vir_addr)
749 		&& ((dst_dirty_rect->width != scn_win->height)
750 		|| (dst_dirty_rect->height != scn_win->width))
751 		&& ((src->update_rect.x != dst_dirty_rect->x)
752 		|| (src->update_rect.y != dst_dirty_rect->y)
753 		|| (src->update_rect.width != dst_dirty_rect->width)
754 		|| (src->update_rect.height != dst_dirty_rect->height))) {
755 		int offset = widthstep * src->update_rect.y + Bpp * src->update_rect.x;
756 		void *src_addr = (void *)((char *)src->vir_addr + offset);
757 		void *dst_addr = (void *)((char *)dst->vir_addr + offset);
758 		rot_0_u32(src_addr, widthstep, src->update_rect.width,
759 			src->update_rect.height, dst_addr, widthstep);
760 	}
761 	memcpy((void *)&dst->update_rect, (void *)dst_dirty_rect, sizeof(struct disp_rect));
762 #endif
763 	return 0;
764 }
765 
manager_rotate_buffer(struct disp_fb_info * ask_fb,struct rotation_buf_info * tg_buf)766 static int manager_rotate_buffer(struct disp_fb_info *ask_fb, struct rotation_buf_info *tg_buf)
767 {
768 	unsigned int ask_total_size = 0;
769 	unsigned int phy_addr = 0;
770 	unsigned int offset0 = 0;
771 	struct buf_info *buf = NULL;
772 
773 	switch (ask_fb->format) {
774 	case DISP_FORMAT_ARGB_8888:
775 	case DISP_FORMAT_ABGR_8888:
776 	case DISP_FORMAT_RGBA_8888:
777 	case DISP_FORMAT_BGRA_8888:
778 		ask_total_size = (ask_fb->size[0].width * ask_fb->size[0].height) << 2;
779 
780 #if defined(ONE_BUF)
781 		tg_buf->w_buf = &tg_buf->buf_a;
782 #elif defined(DOUBLE_BUF)
783 		if (tg_buf->w_buf == &tg_buf->buf_a) {
784 			tg_buf->w_buf = &tg_buf->buf_b;
785 			tg_buf->r_buf = &tg_buf->buf_a;
786 		} else {
787 			tg_buf->w_buf = &tg_buf->buf_a;
788 			tg_buf->r_buf = &tg_buf->buf_b;
789 		}
790 #elif defined(TRIPLE_BUF)
791 		if (tg_buf->w_buf == &tg_buf->buf_a) {
792 			tg_buf->w_buf = &tg_buf->buf_b;
793 			tg_buf->r_buf = &tg_buf->buf_a;
794 		} else if (tg_buf->w_buf == &tg_buf->buf_b) {
795 			tg_buf->w_buf = &tg_buf->buf_c;
796 			tg_buf->r_buf = &tg_buf->buf_b;
797 		} else {
798 			tg_buf->w_buf = &tg_buf->buf_a;
799 			tg_buf->r_buf = &tg_buf->buf_c;
800 		}
801 #endif
802 		break;
803 	case DISP_FORMAT_YUV420_SP_UVUV:
804 	case DISP_FORMAT_YUV420_SP_VUVU:
805 		ask_total_size = ask_fb->size[1].width * ask_fb->size[1].height * 6;
806 		offset0 = (unsigned int)(ask_fb->addr[1] - ask_fb->addr[0]);
807 		if (tg_buf->w_buf == &tg_buf->buf_b) {
808 			tg_buf->w_buf = &tg_buf->buf_a;
809 		} else {
810 			tg_buf->w_buf = &tg_buf->buf_b;
811 		}
812 		break;
813 	case DISP_FORMAT_YUV420_P:
814 	default:
815 		DE_WRN("not support this mode[%d]\n",
816 			ask_fb->format);
817 		return -1;
818 	}
819 
820 	buf = tg_buf->w_buf;
821 	if (ask_total_size != buf->size) {
822 		if (0 != buf->size) {
823 			phy_addr = (unsigned int)buf->phy_addr;
824 			disp_free((void *)buf->vir_addr, (void *)phy_addr, buf->size);
825 			memset((void *)buf, 0, sizeof(struct buf_info));
826 		}
827 		buf->vir_addr = (unsigned int)disp_malloc_cache(ask_total_size, &phy_addr);
828 		if (0 == buf->vir_addr) {
829 			DE_WRN("malloc failed! size=%x\n", ask_total_size);
830 			return -1;
831 		}
832 		buf->phy_addr = (unsigned long long)phy_addr;
833 		buf->size = ask_total_size;
834 	}
835 
836 	ask_fb->addr[0] = buf->phy_addr;
837 	switch (ask_fb->format) {
838 	case DISP_FORMAT_ARGB_8888:
839 	case DISP_FORMAT_ABGR_8888:
840 	case DISP_FORMAT_RGBA_8888:
841 	case DISP_FORMAT_BGRA_8888:
842 		break;
843 	case DISP_FORMAT_YUV420_SP_UVUV:
844 	case DISP_FORMAT_YUV420_SP_VUVU:
845 		ask_fb->addr[1] = ask_fb->addr[0] + offset0;
846 		break;
847 	case DISP_FORMAT_YUV420_P:
848 	default:
849 		DE_WRN("not support this mode[%d]\n",
850 			ask_fb->format);
851 		return -1;
852 	}
853 
854 	return 0;
855 }
856 
update_layer_info(int rot,struct disp_rectsz scn_size,struct disp_rect * src_dirty_rect,struct disp_rect * dst_dirty_rect,struct disp_layer_config * lyr_bak,struct disp_layer_config * lyr)857 static int update_layer_info(int rot, struct disp_rectsz scn_size,
858 	struct disp_rect *src_dirty_rect, struct disp_rect *dst_dirty_rect,
859 	struct disp_layer_config *lyr_bak, struct disp_layer_config *lyr)
860 {
861 	switch (rot) {
862 	case ROTATION_SW_90:
863 		lyr->info.screen_win.x = scn_size.height
864 			 - lyr_bak->info.screen_win.y
865 			 - lyr_bak->info.screen_win.height;
866 		lyr->info.screen_win.y = lyr_bak->info.screen_win.x;
867 		lyr->info.screen_win.width = lyr_bak->info.screen_win.height;
868 		lyr->info.screen_win.height = lyr_bak->info.screen_win.width;
869 		lyr->info.fb.crop.x = 0;
870 		lyr->info.fb.crop.y = 0;
871 		lyr->info.fb.crop.width = lyr_bak->info.fb.crop.height;
872 		lyr->info.fb.crop.height = lyr_bak->info.fb.crop.width;
873 		lyr->info.fb.size[0].width = DISPALIGN(
874 			lyr_bak->info.fb.size[0].height, ROTATION_SW_ALIGN);
875 		lyr->info.fb.size[0].height = lyr_bak->info.fb.size[0].width;
876 		lyr->info.fb.size[1].width = DISPALIGN(
877 			lyr_bak->info.fb.size[1].height, ROTATION_SW_ALIGN);
878 		lyr->info.fb.size[1].height = lyr_bak->info.fb.size[1].width;
879 		lyr->info.fb.size[2].width = DISPALIGN(
880 			lyr_bak->info.fb.size[2].height, ROTATION_SW_ALIGN);
881 		lyr->info.fb.size[2].height = lyr_bak->info.fb.size[2].width;
882 		dst_dirty_rect->x = (lyr_bak->info.fb.crop.height >> 32)
883 			- src_dirty_rect->y - src_dirty_rect->height;
884 		dst_dirty_rect->y = src_dirty_rect->x;
885 		dst_dirty_rect->width = src_dirty_rect->height;
886 		dst_dirty_rect->height = src_dirty_rect->width;
887 		break;
888 	case ROTATION_SW_270:
889 		lyr->info.screen_win.x = lyr_bak->info.screen_win.y;
890 		lyr->info.screen_win.y = scn_size.width
891 			 - lyr_bak->info.screen_win.x
892 			 - lyr_bak->info.screen_win.width;
893 		lyr->info.screen_win.width = lyr_bak->info.screen_win.height;
894 		lyr->info.screen_win.height = lyr_bak->info.screen_win.width;
895 		lyr->info.fb.crop.x = 0;
896 		lyr->info.fb.crop.y = 0;
897 		lyr->info.fb.crop.width = lyr_bak->info.fb.crop.height;
898 		lyr->info.fb.crop.height = lyr_bak->info.fb.crop.width;
899 		lyr->info.fb.size[0].width = DISPALIGN(
900 			lyr_bak->info.fb.size[0].height, ROTATION_SW_ALIGN);
901 		lyr->info.fb.size[0].height = lyr_bak->info.fb.size[0].width;
902 		lyr->info.fb.size[1].width = DISPALIGN(
903 			lyr_bak->info.fb.size[1].height, ROTATION_SW_ALIGN);
904 		lyr->info.fb.size[1].height = lyr_bak->info.fb.size[1].width;
905 		lyr->info.fb.size[2].width = DISPALIGN(
906 			lyr_bak->info.fb.size[2].height, ROTATION_SW_ALIGN);
907 		lyr->info.fb.size[2].height = lyr_bak->info.fb.size[2].width;
908 		dst_dirty_rect->x = src_dirty_rect->y;
909 		dst_dirty_rect->y = (lyr_bak->info.fb.crop.width >> 32)
910 			- src_dirty_rect->x - src_dirty_rect->width;
911 		dst_dirty_rect->width = src_dirty_rect->height;
912 		dst_dirty_rect->height = src_dirty_rect->width;
913 		break;
914 	case ROTATION_SW_180:
915 	case ROTATION_SW_0:
916 	default:
917 		DE_WRN("fixme: rot=%d\n", rot);
918 		return -1;
919 	}
920 
921 	return 0;
922 }
923 
check_dirty_rect(struct disp_rect * dirty,struct disp_rect64 * crop)924 static int check_dirty_rect(struct disp_rect *dirty, struct disp_rect64 *crop)
925 {
926 	int fixed = 0;
927 	int dirty_end, crop_end;
928 	int crop_x = (int)(crop->x >> 32);
929 	int crop_y = (int)(crop->y >> 32);
930 	unsigned int crop_w = (unsigned int)(crop->width >> 32);
931 	unsigned int crop_h = (unsigned int)(crop->height >> 32);
932 
933 #ifdef CONFIG_DISP2_SUNXI_NEON_ROTATION
934 	if (dirty->width & 0x01)
935 		dirty->width += 1;
936 
937 	if (dirty->height & 0x01)
938 		dirty->height += 1;
939 #endif
940 
941 	dirty_end = dirty->x + dirty->width;
942 	crop_end = crop_x + crop_w;
943 	if (crop_x > dirty->x) {
944 		dirty->x = crop_x;
945 		fixed = 1;
946 	}
947 	if (dirty_end > crop_end) {
948 		dirty_end = crop_end;
949 		fixed = 1;
950 	}
951 	if (1 == fixed) {
952 		if (dirty_end > dirty->x) {
953 			dirty->width = dirty_end - dirty->x;
954 			fixed = 0;
955 		} else {
956 			fixed = -1;
957 			goto fix_fail;
958 		}
959 	}
960 
961 	dirty_end = dirty->y + dirty->height;
962 	crop_end = crop_y + crop_h;
963 	if (crop_y > dirty->y) {
964 		dirty->y = crop_y;
965 		fixed = 1;
966 	}
967 	if (dirty_end > crop_end) {
968 		dirty_end = crop_end;
969 		fixed = 1;
970 	}
971 	if (1 == fixed) {
972 		if (dirty_end > dirty->y) {
973 			dirty->height = dirty_end - dirty->y;
974 			fixed = 0;
975 		} else {
976 			fixed = -1;
977 			goto fix_fail;
978 		}
979 	}
980 
981 fix_fail:
982 	if (fixed) {
983 		DE_WRN("dirty[%d,%d,%d,%d],crop[%d,%d,%d,%d]\n",
984 			dirty->x, dirty->y, dirty->width,
985 			dirty->height, crop_h, crop_h, crop_w, crop_h);
986 	}
987 
988 	return fixed;
989 }
990 
991 static prv_data_t *
disp_rotation_sw_get_priv(struct disp_rotation_sw * rot_sw,unsigned int chn,unsigned int layer_id)992 disp_rotation_sw_get_priv(struct disp_rotation_sw *rot_sw,
993 	unsigned int chn, unsigned int layer_id)
994 {
995 	int i;
996 	prv_data_t *p_rot_sw_p = rot_sw_p;
997 
998 	if (NULL == rot_sw) {
999 		DE_WRN("NULL hdl!\n");
1000 		return NULL;
1001 	}
1002 	for (i = 0; i < rot_sw->disp; i++) {
1003 		p_rot_sw_p += bsp_disp_feat_get_num_layers(i);
1004 	}
1005 	for (i = 0; i < chn; i++) {
1006 		p_rot_sw_p += bsp_disp_feat_get_num_layers_by_chn(
1007 			rot_sw->disp, i);
1008 	}
1009 	p_rot_sw_p += layer_id;
1010 
1011 	return p_rot_sw_p;
1012 }
1013 
disp_rot_sw_apply(struct disp_rotation_sw * rot_sw,struct disp_layer_config * lyr_config,struct disp_rect src_dirty_rect)1014 static s32 disp_rot_sw_apply(struct disp_rotation_sw *rot_sw,
1015 	struct disp_layer_config *lyr_config, struct disp_rect src_dirty_rect)
1016 {
1017 	int ret = 0;
1018 	struct disp_rect dst_dirty_rect;
1019 	prv_data_t *p_rot_sw_p = NULL;
1020 	unsigned int degree;
1021 	unsigned int Bpp[3] = {0, 0, 0};
1022 
1023 	if ((NULL == rot_sw) || (NULL == lyr_config)) {
1024 		DE_INF("NULL hdl![%d,%d]\n", (int)rot_sw, (int)lyr_config);
1025 		return -1;
1026 	}
1027 
1028 	if (DISP_FORMAT_BGRA_8888 < lyr_config->info.fb.format)
1029 		return 0;
1030 
1031 	p_rot_sw_p = disp_rotation_sw_get_priv(rot_sw,
1032 		lyr_config->channel, lyr_config->layer_id);
1033 	if (NULL == p_rot_sw_p) {
1034 		DE_WRN("p_rot_sw_p is null !\n");
1035 		return -1;
1036 	}
1037 
1038 	memcpy((void *)&p_rot_sw_p->lyr_bak, (void *)lyr_config,
1039 		sizeof(struct disp_layer_config));
1040 
1041 	degree = p_rot_sw_p->degree;
1042 	switch (degree) {
1043 	case ROTATION_SW_90:
1044 	case ROTATION_SW_270:
1045 		break;
1046 	case ROTATION_SW_0:
1047 		goto out;
1048 	default:
1049 		DE_WRN("not support this degree[%d]\n", degree);
1050 		ret = -1;
1051 		goto out;
1052 	}
1053 	switch (lyr_config->info.fb.format) {
1054 	case DISP_FORMAT_ARGB_8888:
1055 	case DISP_FORMAT_ABGR_8888:
1056 	case DISP_FORMAT_RGBA_8888:
1057 	case DISP_FORMAT_BGRA_8888:
1058 		Bpp[0] = 4;
1059 		break;
1060 	case DISP_FORMAT_YUV420_SP_UVUV:
1061 	case DISP_FORMAT_YUV420_SP_VUVU:
1062 		Bpp[0] = 1;
1063 		Bpp[1] = 2;
1064 		break;
1065 	case DISP_FORMAT_YUV420_P:
1066 		Bpp[0] = Bpp[1] = Bpp[2] = 1;
1067 		break;
1068 	default:
1069 		DE_WRN("not support this mode[%d]\n",
1070 			lyr_config->info.fb.format);
1071 		ret = -1;
1072 		goto out;
1073 	}
1074 	ret = check_dirty_rect(&src_dirty_rect, &lyr_config->info.fb.crop);
1075 	if (ret)
1076 		goto out;
1077 	ret = update_layer_info(degree, rot_sw->screen_size,
1078 		&src_dirty_rect, &dst_dirty_rect,
1079 		&p_rot_sw_p->lyr_bak, lyr_config);
1080 	if (ret)
1081 		goto out;
1082 	ret = manager_rotate_buffer(&lyr_config->info.fb, &p_rot_sw_p->tg_buf);
1083 	if (ret) {
1084 		goto out;
1085 	}
1086 	if (1 == lyr_config->enable) {
1087 		update_rotate_fb(p_rot_sw_p->tg_buf.r_buf, p_rot_sw_p->tg_buf.w_buf,
1088 			Bpp[0], lyr_config->info.fb.size[0].width * Bpp[0],
1089 			&dst_dirty_rect, &rot_sw->screen_size);
1090 		rotate_fb(&(p_rot_sw_p->lyr_bak.info.fb),
1091 			&src_dirty_rect, &(lyr_config->info.fb), &dst_dirty_rect,
1092 			(void *)p_rot_sw_p->tg_buf.w_buf->vir_addr, degree);
1093 		flush_user_range((long)p_rot_sw_p->tg_buf.w_buf->vir_addr,
1094 			(long)((char *)p_rot_sw_p->tg_buf.w_buf->vir_addr + p_rot_sw_p->tg_buf.w_buf->size));
1095 	}
1096 
1097 out:
1098 	return ret;
1099 }
1100 
disp_rot_sw_checkout(struct disp_rotation_sw * rot_sw,struct disp_layer_config * lyr_config)1101 static s32 disp_rot_sw_checkout(struct disp_rotation_sw *rot_sw,
1102 	struct disp_layer_config *lyr_config)
1103 {
1104 	prv_data_t *p_rot_sw_p = NULL;
1105 	unsigned long flags;
1106 	s32 type;
1107 	static unsigned int need_clear_flag;
1108 	int ret = 0;
1109 
1110 	if ((NULL == rot_sw) || (NULL == lyr_config)) {
1111 		DE_WRN("NULL hdl[%d,%d]!\n", (int)rot_sw, (int)lyr_config);
1112 		return -1;
1113 	}
1114 
1115 	if (DISP_FORMAT_BGRA_8888 < lyr_config->info.fb.format) {
1116 		return 0;
1117 	}
1118 
1119 	p_rot_sw_p = disp_rotation_sw_get_priv(rot_sw,
1120 		lyr_config->channel, lyr_config->layer_id);
1121 	if (NULL == p_rot_sw_p) {
1122 		DE_WRN("null pointer\n");
1123 		return -1;
1124 	}
1125 
1126 	type = bsp_disp_get_output_type(0);
1127 	spin_lock_irqsave(&p_rot_sw_p->data_lock, flags);
1128 	if (type == DISP_OUTPUT_TYPE_HDMI) {
1129 		need_clear_flag = 1;
1130 		memcpy((void *)&(lyr_config->info.fb.crop),
1131 			(void *)&(p_rot_sw_p->lyr_bak.info.fb.crop), sizeof(struct disp_rect64));
1132 		memcpy((void *)lyr_config->info.fb.size,
1133 			(void *)p_rot_sw_p->lyr_bak.info.fb.size,
1134 			sizeof(p_rot_sw_p->lyr_bak.info.fb.size));
1135 		memcpy((void *)lyr_config->info.fb.addr,
1136 			(void *)p_rot_sw_p->lyr_bak.info.fb.addr,
1137 			sizeof(p_rot_sw_p->lyr_bak.info.fb.addr));
1138 		spin_unlock_irqrestore(&p_rot_sw_p->data_lock, flags);
1139 		return 0;
1140 	} else {
1141 		if (need_clear_flag == 1) {
1142 			ret = 1;
1143 			need_clear_flag = 0;
1144 		}
1145 		 if (p_rot_sw_p->degree == ROTATION_SW_90 ||
1146 			p_rot_sw_p->degree == ROTATION_SW_270) {
1147 			unsigned int x, y, width, height;
1148 
1149 			x = lyr_config->info.screen_win.x;
1150 			y = lyr_config->info.screen_win.y;
1151 			width = lyr_config->info.screen_win.width;
1152 			height = lyr_config->info.screen_win.height;
1153 			lyr_config->info.screen_win.x = y;
1154 			lyr_config->info.screen_win.y = x;
1155 			lyr_config->info.screen_win.width = height;
1156 			lyr_config->info.screen_win.height = width;
1157 		}
1158 		memcpy((void *)&(lyr_config->info.fb.crop),
1159 			(void *)&(p_rot_sw_p->lyr_bak.info.fb.crop), sizeof(struct disp_rect64));
1160 		memcpy((void *)lyr_config->info.fb.size,
1161 			(void *)p_rot_sw_p->lyr_bak.info.fb.size,
1162 			sizeof(p_rot_sw_p->lyr_bak.info.fb.size));
1163 		memcpy((void *)lyr_config->info.fb.addr,
1164 			(void *)p_rot_sw_p->lyr_bak.info.fb.addr,
1165 			sizeof(p_rot_sw_p->lyr_bak.info.fb.addr));
1166 	}
1167 	spin_unlock_irqrestore(&p_rot_sw_p->data_lock, flags);
1168 	return ret;
1169 }
1170 
disp_rot_sw_set_layer_degree(struct disp_rotation_sw * rot_sw,u32 chn,u32 lyr_id,u32 degree)1171 static s32 disp_rot_sw_set_layer_degree(struct disp_rotation_sw *rot_sw,
1172 	u32 chn, u32 lyr_id, u32 degree)
1173 {
1174 	prv_data_t *p_rot_sw_p = NULL;
1175 	p_rot_sw_p = disp_rotation_sw_get_priv(rot_sw, chn, lyr_id);
1176 	if (NULL != p_rot_sw_p) {
1177 		p_rot_sw_p->degree = degree;
1178 		printk("set layer degree[%d] ok\n", degree);
1179 		return 0;
1180 	}
1181 	DE_WRN("p_rot_sw_p is null !\n");
1182 	return -1;
1183 }
1184 
disp_rot_sw_get_layer_degree(struct disp_rotation_sw * rot_sw,u32 chn,u32 lyr_id)1185 static s32 disp_rot_sw_get_layer_degree(struct disp_rotation_sw *rot_sw,
1186 	u32 chn, u32 lyr_id)
1187 {
1188 	prv_data_t *p_rot_sw_p = NULL;
1189 	p_rot_sw_p = disp_rotation_sw_get_priv(rot_sw, chn, lyr_id);
1190 	if (NULL != p_rot_sw_p) {
1191 		printk("get layer degree[%d] ok\n", p_rot_sw_p->degree);
1192 		return p_rot_sw_p->degree;
1193 	}
1194 	DE_WRN("p_rot_sw_p is null !\n");
1195 	return -1;
1196 }
1197 
disp_rot_sw_set_manager(struct disp_rotation_sw * rot_sw,struct disp_manager * mgr)1198 static s32 disp_rot_sw_set_manager(struct disp_rotation_sw *rot_sw,
1199 	struct disp_manager *mgr)
1200 {
1201 	unsigned long flags;
1202 
1203 	if ((NULL == rot_sw) || (NULL == mgr)) {
1204 		DE_INF("NULL hdl!\n");
1205 		return -1;
1206 	}
1207 	printk("%s,%d\n", __func__, __LINE__);
1208 	spin_lock_irqsave(&s_data_lock, flags);
1209 	rot_sw->manager = mgr;
1210 	mgr->rot_sw = rot_sw;
1211 	spin_unlock_irqrestore(&s_data_lock, flags);
1212 
1213 	return 0;
1214 }
1215 
disp_rot_sw_unset_manager(struct disp_rotation_sw * rot_sw)1216 static s32 disp_rot_sw_unset_manager(struct disp_rotation_sw *rot_sw)
1217 {
1218 	unsigned long flags;
1219 
1220 	if ((NULL == rot_sw)) {
1221 		DE_INF("NULL hdl!\n");
1222 		return -1;
1223 	}
1224 	spin_lock_irqsave(&s_data_lock, flags);
1225 	if (rot_sw->manager)
1226 		rot_sw->manager->enhance = NULL;
1227 	rot_sw->manager = NULL;
1228 	spin_unlock_irqrestore(&s_data_lock, flags);
1229 
1230 	return 0;
1231 }
1232 
disp_rot_sw_init(struct disp_rotation_sw * rot_sw)1233 static s32 disp_rot_sw_init(struct disp_rotation_sw *rot_sw)
1234 {
1235 	char primary_key[32] = {0};
1236 	char sub_name[32] = {0};
1237 	int ret, i;
1238 	int value = 0;
1239 	int layer_num = 0;
1240 	prv_data_t *p_rot_sw_p = NULL;
1241 
1242 	if (NULL == rot_sw) {
1243 		DE_WRN("NULL hdl!\n");
1244 		return DIS_FAIL;
1245 	}
1246 
1247 	p_rot_sw_p = disp_rotation_sw_get_priv(rot_sw, 0, 0);
1248 	if (NULL == p_rot_sw_p) {
1249 		return -1;
1250 	}
1251 
1252 	strncpy(primary_key, "disp", 32);
1253 	sprintf(sub_name, "degree%d", rot_sw->disp);
1254 	ret = disp_sys_script_get_item(primary_key, sub_name, &value, 1);
1255 	if (ret != 1) {
1256 		value = ROTATION_SW_0;
1257 	}
1258 
1259 	switch (value) {
1260 	case ROTATION_SW_0:
1261 	case ROTATION_SW_90:
1262 	case ROTATION_SW_180:
1263 	case ROTATION_SW_270:
1264 		rot_sw->degree = value;
1265 		break;
1266 	default:
1267 		rot_sw->degree = ROTATION_SW_0;
1268 	}
1269 
1270 	value = DISP_OUTPUT_TYPE_LCD;
1271 	if (DISP_OUTPUT_TYPE_LCD == value) {
1272 		sprintf(primary_key, "lcd%d", rot_sw->disp);
1273 		strncpy(sub_name, "lcd_x", 32);
1274 		ret = disp_sys_script_get_item(primary_key, sub_name, &value, 1);
1275 		if (1 != ret) {
1276 			DE_WRN("check me!");
1277 			value = 0;
1278 		}
1279 		rot_sw->screen_size.width = value;
1280 		strncpy(sub_name, "lcd_y", 32);
1281 		ret = disp_sys_script_get_item(primary_key, sub_name, &value, 1);
1282 		if (1 != ret) {
1283 			DE_WRN("check me!");
1284 			value = 0;
1285 		}
1286 		rot_sw->screen_size.height = value;
1287 	} else {
1288 		DE_WRN("fixme!");
1289 		rot_sw->screen_size.width = bsp_disp_get_screen_width_from_output_type(
1290 			rot_sw->disp, (u32)value, 0);
1291 		rot_sw->screen_size.height = bsp_disp_get_screen_height_from_output_type(
1292 			rot_sw->disp, (u32)value, 0);
1293 	}
1294 	if ((ROTATION_SW_90 == rot_sw->degree)
1295 		|| (ROTATION_SW_270 == rot_sw->degree)) {
1296 		rot_sw->screen_size.width ^= rot_sw->screen_size.height;
1297 		rot_sw->screen_size.height ^= rot_sw->screen_size.width;
1298 		rot_sw->screen_size.width ^= rot_sw->screen_size.height;
1299 	}
1300 	printk("***** disp_rot_sw_init:rot-degree=%d, frame[%d,%d] *****\n", rot_sw->degree,
1301 		rot_sw->screen_size.width, rot_sw->screen_size.height);
1302 
1303 	layer_num = bsp_disp_feat_get_num_layers(rot_sw->disp);
1304 	strncpy(primary_key, "disp", 32);
1305 	for (i = 0; i < layer_num; i++) {
1306 		sprintf(sub_name, "degree%d_%d", rot_sw->disp, i);
1307 		ret = disp_sys_script_get_item(primary_key, sub_name, &value, 1);
1308 		if (ret != 1) {
1309 			value = rot_sw->degree;
1310 		}
1311 		switch (value) {
1312 		case ROTATION_SW_0:
1313 		case ROTATION_SW_90:
1314 		case ROTATION_SW_180:
1315 		case ROTATION_SW_270:
1316 			p_rot_sw_p->degree = value;
1317 			break;
1318 		default:
1319 			p_rot_sw_p->degree = rot_sw->degree;
1320 		}
1321 
1322 	  #if defined(__LINUX_PLAT__)
1323 		spin_lock_init(&p_rot_sw_p->data_lock);
1324 	  #endif
1325 		p_rot_sw_p++;
1326 	}
1327 
1328 	return 0;
1329 }
1330 
disp_rot_sw_exit(struct disp_rotation_sw * rot_sw)1331 static s32 disp_rot_sw_exit(struct disp_rotation_sw *rot_sw)
1332 {
1333 	return 0;
1334 }
1335 
disp_init_rotation_sw(struct disp_bsp_init_para * para)1336 s32 disp_init_rotation_sw(struct disp_bsp_init_para *para)
1337 {
1338 	u32 num_screens = 0;
1339 	u32 max_num_layers = 0;
1340 	u32 disp;
1341 	u32 used = 0;
1342 	int ret;
1343 	struct disp_rotation_sw *p_rot_sw = NULL;
1344 
1345 	ret = disp_sys_script_get_item("disp", "disp_rotation_used", &used, 1);
1346 	if (ret != 1) {
1347 		used = 0;
1348 	}
1349 	if (!used) {
1350 		printk("rotation_sw module is config as no used\n");
1351 		return 0;
1352 	}
1353 	printk("disp_init_rotation_sw\n");
1354 
1355 
1356 #if defined(__LINUX_PLAT__)
1357 	spin_lock_init(&s_data_lock);
1358 #endif
1359 	num_screens = bsp_disp_feat_get_num_screens();
1360 	g_rot_sw = (struct disp_rotation_sw *)kmalloc(
1361 		sizeof(struct disp_rotation_sw) * num_screens, GFP_KERNEL | __GFP_ZERO);
1362 	if (NULL == g_rot_sw) {
1363 		DE_WRN("malloc memory fail for rotation_sw! size=0x%x\n",
1364 			sizeof(struct disp_rotation_sw) * num_screens);
1365 		return DIS_FAIL;
1366 	}
1367 	for (disp = 0; disp < num_screens; disp++) {
1368 		max_num_layers += bsp_disp_feat_get_num_layers(disp);
1369 	}
1370 	rot_sw_p = (prv_data_t *)kmalloc(
1371 		sizeof(prv_data_t) * max_num_layers, GFP_KERNEL | __GFP_ZERO);
1372 	if (NULL == rot_sw_p) {
1373 		DE_WRN("malloc memory fail! size=0x%x\n",
1374 			sizeof(prv_data_t) * max_num_layers);
1375 		return DIS_FAIL;
1376 	}
1377 
1378 	p_rot_sw = g_rot_sw;
1379 	for (disp = 0; disp < num_screens; disp++) {
1380 		p_rot_sw->disp = disp;
1381 		p_rot_sw->init = disp_rot_sw_init;
1382 		p_rot_sw->exit = disp_rot_sw_exit;
1383 		p_rot_sw->set_layer_degree = disp_rot_sw_set_layer_degree;
1384 		p_rot_sw->get_layer_degree = disp_rot_sw_get_layer_degree;
1385 		p_rot_sw->set_manager = disp_rot_sw_set_manager;
1386 		p_rot_sw->unset_manager = disp_rot_sw_unset_manager;
1387 		p_rot_sw->apply = disp_rot_sw_apply;
1388 		p_rot_sw->checkout = disp_rot_sw_checkout;
1389 
1390 		disp_rot_sw_init(p_rot_sw);
1391 		p_rot_sw++;
1392 	}
1393 
1394 	return 0;
1395 }
1396 
1397