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