1 /*
2 * drivers/char/sunxi_g2d/g2d_rcq/g2d_rotate.c
3 *
4 * Copyright (c) 2007-2019 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 #include "g2d_rotate.h"
18 #include "g2d_top.h"
19 #include "g2d_driver_i.h"
20
21 /* Rotate register */
22 #define G2D_ROT (0x28000)
23 #define ROT_CTL (0x00 + G2D_ROT)
24 #define ROT_INT (0x04 + G2D_ROT)
25 #define ROT_TIMEOUT (0x08 + G2D_ROT)
26 #define ROT_IFMT (0x20 + G2D_ROT)
27 #define ROT_ISIZE (0x24 + G2D_ROT)
28 #define ROT_IPITCH0 (0x30 + G2D_ROT)
29 #define ROT_IPITCH1 (0x34 + G2D_ROT)
30 #define ROT_IPITCH2 (0x38 + G2D_ROT)
31 #define ROT_ILADD0 (0x40 + G2D_ROT)
32 #define ROT_IHADD0 (0x44 + G2D_ROT)
33 #define ROT_ILADD1 (0x48 + G2D_ROT)
34 #define ROT_IHADD1 (0x4C + G2D_ROT)
35 #define ROT_ILADD2 (0x50 + G2D_ROT)
36 #define ROT_IHADD2 (0x54 + G2D_ROT)
37 #define ROT_OSIZE (0x84 + G2D_ROT)
38 #define ROT_OPITCH0 (0x90 + G2D_ROT)
39 #define ROT_OPITCH1 (0x94 + G2D_ROT)
40 #define ROT_OPITCH2 (0x98 + G2D_ROT)
41 #define ROT_OLADD0 (0xA0 + G2D_ROT)
42 #define ROT_OHADD0 (0xA4 + G2D_ROT)
43 #define ROT_OLADD1 (0xA8 + G2D_ROT)
44 #define ROT_OHADD1 (0xAC + G2D_ROT)
45 #define ROT_OLADD2 (0xB0 + G2D_ROT)
46 #define ROT_OHADD2 (0xB4 + G2D_ROT)
47 #define LBC_ENC_CTL (0xC8 + G2D_ROT)
48 #define LBC_CTL (0xCC + G2D_ROT)
49 #define LBC_DEC_CTL (0xD0 + G2D_ROT)
50 #define G2D_AHB_RESET (0x08)
51
52 static unsigned long base_addr;
53 /* #define write_wvalue(addr, data) m_usbwordwrite32( addr, data ) */
54 /* #define write_wvalue(addr, v) put_wvalue(addr, v) */
55 /* #define read_wvalue(addr) get_wvalue(addr) */
56
57 /* byte input */
58 #define get_bvalue(n) (*((volatile __u8 *)(n)))
59 /* byte output */
60 #define put_bvalue(n, c) (*((volatile __u8 *)(n)) = (c))
61 /* half word input */
62 #define get_hvalue(n) (*((volatile __u16 *)(n)))
63 /* half word output */
64 #define put_hvalue(n, c) (*((volatile __u16 *)(n)) = (c))
65 /* word input */
66 #define get_wvalue(n) (*((volatile __u32 *)(n)))
67 /* word output */
68 #define put_wvalue(n, c) (*((volatile __u32 *)(n)) = (c))
69
70 /* byte input */
71 #define read_bvalue(offset) get_bvalue(base_addr + offset)
72 /* byte output */
73 #define write_bvalue(offset, value) put_bvalue(base_addr + offset, value)
74 /* half word input */
75 #define read_hvalue(offset) get_hvalue(base_addr + offset)
76 /* half word output */
77 #define write_hvalue(offset, value) put_hvalue(base_addr + offset, value)
78 /* word input */
79 #define read_wvalue(offset) get_wvalue(base_addr + offset)
80 /* word output */
81 #define write_wvalue(offset, value) put_wvalue(base_addr + offset, value)
82
g2d_rot_set_base(unsigned long base)83 void g2d_rot_set_base(unsigned long base)
84 {
85 base_addr = base;
86 }
87
88 /**
89 * G2D IRQ query funct
90 * if the mission finish IRQ flag was set to 1, then clear the flag
91 * and return 1
92 * if the IRQ was set to 0, then return 0
93 */
g2d_rot_irq_query(void)94 __s32 g2d_rot_irq_query(void)
95 {
96 __u32 tmp;
97
98 tmp = read_wvalue(ROT_INT);
99 if (tmp & 0x1) {
100 write_wvalue(ROT_INT, tmp);
101 return 1;
102 }
103 return 0;
104 }
105
g2d_rotate_set_para(g2d_image_enh * src,g2d_image_enh * dst,__u32 flag)106 __s32 g2d_rotate_set_para(g2d_image_enh *src, g2d_image_enh *dst, __u32 flag)
107 {
108 __u32 tmp;
109 __u32 ch, cw, cy, cx;
110 __u32 ycnt, ucnt, vcnt;
111 __s32 ret = -1;
112 __u32 pitch0, pitch1, pitch2;
113 __u64 addr0, addr1, addr2;
114 struct dmabuf_item *src_item = NULL;
115 struct dmabuf_item *dst_item = NULL;
116
117 if (!dst || g2d_image_check(dst))
118 goto OUT;
119 if (!src || g2d_image_check(src))
120 goto OUT;
121
122 if (!src->use_phy_addr || !dst->use_phy_addr) {
123 src_item = kmalloc(sizeof(struct dmabuf_item),
124 GFP_KERNEL | __GFP_ZERO);
125 if (src_item == NULL) {
126 G2D_ERR_MSG("malloc memory of size %u fail!\n",
127 (unsigned int)sizeof(struct dmabuf_item));
128 goto OUT;
129 }
130 dst_item = kmalloc(sizeof(struct dmabuf_item),
131 GFP_KERNEL | __GFP_ZERO);
132 if (dst_item == NULL) {
133 G2D_ERR_MSG("malloc memory of size %u fail!\n",
134 (unsigned int)sizeof(struct dmabuf_item));
135 goto FREE_SRC;
136 }
137 ret = g2d_dma_map(src->fd, src_item);
138 if (ret != 0) {
139 G2D_ERR_MSG("map src_item fail!\n");
140 goto FREE_DST;
141 }
142 g2d_set_info(src, src_item);
143
144 ret = g2d_dma_map(dst->fd, dst_item);
145 if (ret != 0) {
146 G2D_ERR_MSG("map dst_item fail!\n");
147 goto SRC_DMA_UNMAP;
148 }
149 g2d_set_info(dst, dst_item);
150 }
151
152 tmp = 1;
153 if (flag & G2D_ROT_H)
154 tmp |= 0x1 << 7;
155 if (flag & G2D_ROT_V)
156 tmp |= 0x1 << 6;
157 if ((flag & 0xf00) == G2D_ROT_90)
158 tmp |= 0x1 << 4;
159 if ((flag & 0xf00) == G2D_ROT_180)
160 tmp |= 0x2 << 4;
161 if ((flag & 0xf00) == G2D_ROT_270)
162 tmp |= 0x3 << 4;
163 if ((flag & 0xf00) == G2D_ROT_0)
164 tmp |= 0x0 << 4;
165
166 write_wvalue(ROT_CTL, tmp);
167 write_wvalue(ROT_IFMT, src->format & 0x3F);
168 write_wvalue(ROT_ISIZE, ((((src->clip_rect.h - 1) & 0x1fff) << 16)) |
169 ((src->clip_rect.w - 1) & 0x1fff));
170
171 if ((src->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) &&
172 (src->format <= G2D_FORMAT_YUV422_PLANAR)) {
173 cw = src->width >> 1;
174 ch = src->height;
175 cx = src->clip_rect.x >> 1;
176 cy = src->clip_rect.y;
177 }
178
179 else if ((src->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) &&
180 (src->format <= G2D_FORMAT_YUV420_PLANAR)) {
181 cw = src->width >> 1;
182 ch = src->height >> 1;
183 cx = src->clip_rect.x >> 1;
184 cy = src->clip_rect.y >> 1;
185 }
186
187 else if ((src->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) &&
188 (src->format <= G2D_FORMAT_YUV411_PLANAR)) {
189 cw = src->width >> 2;
190 ch = src->height;
191 cx = src->clip_rect.x >> 2;
192 cy = src->clip_rect.y;
193 }
194
195 else {
196 cw = 0;
197 ch = 0;
198 cx = 0;
199 cy = 0;
200 }
201
202 g2d_byte_cal(src->format, &ycnt, &ucnt, &vcnt);
203 pitch0 = cal_align(ycnt * src->width, src->align[0]);
204 write_wvalue(ROT_IPITCH0, pitch0);
205 pitch1 = cal_align(ucnt * cw, src->align[1]);
206 write_wvalue(ROT_IPITCH1, pitch1);
207 pitch2 = cal_align(vcnt * cw, src->align[2]);
208 write_wvalue(ROT_IPITCH2, pitch2);
209
210 addr0 = src->laddr[0] + ((__u64)src->haddr[0] << 32) +
211 pitch0 * src->clip_rect.y + ycnt * src->clip_rect.x;
212 write_wvalue(ROT_ILADD0, addr0 & 0xffffffff);
213 write_wvalue(ROT_IHADD0, (addr0 >> 32) & 0xff);
214 addr1 = src->laddr[1] + ((__u64)src->haddr[1] << 32) + pitch1 * cy +
215 ucnt * cx;
216 write_wvalue(ROT_ILADD1, addr1 & 0xffffffff);
217 write_wvalue(ROT_IHADD1, (addr1 >> 32) & 0xff);
218 addr2 = src->laddr[2] + ((__u64)src->haddr[2] << 32) + pitch2 * cy +
219 vcnt * cx;
220 write_wvalue(ROT_ILADD2, addr2 & 0xffffffff);
221 write_wvalue(ROT_IHADD2, (addr2 >> 32) & 0xff);
222
223 if (((flag & 0xf00) == G2D_ROT_90) | ((flag & 0xf00) == G2D_ROT_270)) {
224 dst->clip_rect.w = src->clip_rect.h;
225 dst->clip_rect.h = src->clip_rect.w;
226 }
227
228 else {
229 dst->clip_rect.w = src->clip_rect.w;
230 dst->clip_rect.h = src->clip_rect.h;
231 }
232 write_wvalue(ROT_OSIZE, ((((dst->clip_rect.h - 1) & 0x1fff) << 16)) |
233 ((dst->clip_rect.w - 1) & 0x1fff));
234 /* YUV output fmt only support 420 */
235 if (src->format == G2D_FORMAT_YUV422UVC_V1U1V0U0)
236 dst->format = G2D_FORMAT_YUV420UVC_V1U1V0U0;
237 else if (src->format == G2D_FORMAT_YUV422UVC_U1V1U0V0)
238 dst->format = G2D_FORMAT_YUV420UVC_U1V1U0V0;
239 else if (src->format == G2D_FORMAT_YUV422_PLANAR)
240 dst->format = G2D_FORMAT_YUV420_PLANAR;
241 else
242 dst->format = src->format;
243
244 if ((dst->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) &&
245 (dst->format <= G2D_FORMAT_YUV422_PLANAR)) {
246 cw = dst->width >> 1;
247 ch = dst->height;
248 cx = dst->clip_rect.x >> 1;
249 cy = dst->clip_rect.y;
250 }
251
252 else if ((dst->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) &&
253 (dst->format <= G2D_FORMAT_YUV420_PLANAR)) {
254 cw = dst->width >> 1;
255 ch = dst->height >> 1;
256 cx = dst->clip_rect.x >> 1;
257 cy = dst->clip_rect.y >> 1;
258 }
259
260 else if ((dst->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) &&
261 (dst->format <= G2D_FORMAT_YUV411_PLANAR)) {
262 cw = dst->width >> 2;
263 ch = dst->height;
264 cx = dst->clip_rect.x >> 2;
265 cy = dst->clip_rect.y;
266 }
267
268 else {
269 cw = 0;
270 ch = 0;
271 cx = 0;
272 cy = 0;
273 }
274
275 g2d_byte_cal(dst->format, &ycnt, &ucnt, &vcnt);
276
277 pitch0 = cal_align(ycnt * dst->width, dst->align[0]);
278 write_wvalue(ROT_OPITCH0, pitch0);
279 pitch1 = cal_align(ucnt * cw, dst->align[1]);
280 write_wvalue(ROT_OPITCH1, pitch1);
281 pitch2 = cal_align(vcnt * cw, dst->align[2]);
282 write_wvalue(ROT_OPITCH2, pitch2);
283
284 addr0 = dst->laddr[0] + ((__u64)dst->haddr[0] << 32) +
285 pitch0 * dst->clip_rect.y + ycnt * dst->clip_rect.x;
286 write_wvalue(ROT_OLADD0, addr0 & 0xffffffff);
287 write_wvalue(ROT_OHADD0, (addr0 >> 32) & 0xff);
288 addr1 = dst->laddr[1] + ((__u64)dst->haddr[1] << 32) + pitch1 * cy +
289 ucnt * cx;
290 write_wvalue(ROT_OLADD1, addr1 & 0xffffffff);
291 write_wvalue(ROT_OHADD1, (addr1 >> 32) & 0xff);
292 addr2 = dst->laddr[2] + ((__u64)dst->haddr[2] << 32) + pitch2 * cy +
293 vcnt * cx;
294 write_wvalue(ROT_OLADD2, addr2 & 0xffffffff);
295 write_wvalue(ROT_OHADD2, (addr2 >> 32) & 0xff);
296
297 /* start the module */
298 write_wvalue(ROT_INT, 0x10000);
299 tmp = read_wvalue(ROT_CTL);
300 tmp |= (0x1 << 31);
301 write_wvalue(ROT_CTL, tmp);
302
303 ret = g2d_wait_cmd_finish(WAIT_CMD_TIME_MS);
304
305 if (!src->use_phy_addr || !dst->use_phy_addr)
306 g2d_dma_unmap(dst_item);
307 SRC_DMA_UNMAP:
308 if (!src->use_phy_addr || !dst->use_phy_addr)
309 g2d_dma_unmap(src_item);
310 FREE_DST:
311 kfree(dst_item);
312 FREE_SRC:
313 kfree(src_item);
314 OUT:
315 return ret;
316 }
317
g2d_lbc_calc_ctrl(u32 flag,u32 frm_width,u32 frm_height,u32 cmp_ratio,u32 enc_is_lossy,u32 dec_is_lossy)318 __s32 g2d_lbc_calc_ctrl(u32 flag, u32 frm_width, u32 frm_height,
319 u32 cmp_ratio, u32 enc_is_lossy, u32 dec_is_lossy)
320 {
321 u32 tmp = 0;
322 u32 seg_width = 16, seg_height = 4;
323 u32 bit_depth = 8;
324 u32 enc_c_ratio = 333;
325 u32 ALIGN = 128;
326 u32 seg_tar_bits, seg_tar_bits_y, seg_tar_bits_c, dec_segline_tar_bits, enc_segline_tar_bits;
327 u32 y_mode_bits, c_mode_bits, y_data_bits, c_data_bits;
328
329 if (enc_is_lossy) {
330 seg_tar_bits = ((seg_width * seg_height * bit_depth * cmp_ratio * 3 / 2000) / ALIGN) * ALIGN;
331 seg_tar_bits_y = seg_tar_bits * (1024 - enc_c_ratio) / 1024;
332 seg_tar_bits_c = seg_tar_bits - seg_tar_bits_y;
333 dec_segline_tar_bits = ((frm_width + seg_width - 1) / seg_width) * seg_tar_bits;
334 if (((flag & 0xf00) == G2D_ROT_90) || ((flag & 0xf00) == G2D_ROT_270))
335 enc_segline_tar_bits = ((frm_height + seg_width - 1) / seg_width) * seg_tar_bits;
336 else
337 enc_segline_tar_bits = dec_segline_tar_bits;
338 } else {
339 y_mode_bits = seg_width / 8 * (3 * 2 + 2);
340 c_mode_bits = 2 * (seg_width / 2 / 8 * 2);
341 y_data_bits = seg_width * seg_height * bit_depth;
342 c_data_bits = seg_width * seg_height * bit_depth / 2 + 2 * (seg_width / 2 / 8) * 4;
343 seg_tar_bits = (y_data_bits + c_data_bits + y_mode_bits + c_mode_bits + ALIGN - 1) / ALIGN * ALIGN;
344 seg_tar_bits_y = seg_tar_bits;
345 seg_tar_bits_c = 0;
346 dec_segline_tar_bits = ((frm_width + seg_width - 1) / seg_width) * seg_tar_bits;
347 if (((flag & 0xf00) == G2D_ROT_90) || ((flag & 0xf00) == G2D_ROT_270))
348 enc_segline_tar_bits = ((frm_height + seg_width - 1) / seg_width) * seg_tar_bits;
349 else
350 enc_segline_tar_bits = dec_segline_tar_bits;
351 }
352 tmp |= (enc_is_lossy << 31);
353 /*tmp |= (0x1 << 30);*///fix me
354 tmp |= (0x1 << 29);/*only 1 frame not care use even */
355 tmp |= ((enc_c_ratio & 0x3ff) << 19);
356 tmp |= ((enc_segline_tar_bits & 0x1ffff) << 2);
357 tmp |= (0x1 << 1);
358 write_wvalue(LBC_ENC_CTL, tmp);
359
360 tmp = read_wvalue(LBC_CTL);
361 tmp |= ((seg_tar_bits_y & 0x7ff) << 21);
362 tmp |= ((seg_tar_bits_c & 0x7ff) << 10);
363 write_wvalue(LBC_CTL, tmp);
364
365 tmp = 0;
366 tmp |= ((dec_segline_tar_bits & 0x1ffff) << 2);
367 tmp |= (dec_is_lossy << 31);
368 write_wvalue(LBC_DEC_CTL, tmp);
369
370 return 0;
371 }
g2d_lbc_rot_set_para(g2d_lbc_rot * para)372 __s32 g2d_lbc_rot_set_para(g2d_lbc_rot *para)
373 {
374 __u32 tmp = 0;
375 __u32 lbc = 0;
376 __u32 ch, cw, cy, cx;
377 __u32 ycnt, ucnt, vcnt;
378 __s32 ret = -1;
379 __u32 pitch0, pitch1, pitch2;
380 __u64 addr0, addr1, addr2;
381 struct dmabuf_item *src_item = NULL;
382 struct dmabuf_item *dst_item = NULL;
383 /* lbc para */
384 u32 frm_width = 0, frm_height = 0;
385 u32 cmp_ratio = 500;
386 u32 enc_is_lossy = 1, dec_is_lossy = 1;
387
388 __u32 flag = para->blt.flag_h;
389 g2d_image_enh *src = ¶->blt.src_image_h;
390 g2d_image_enh *dst = ¶->blt.dst_image_h;
391
392 if (!dst || g2d_image_check(dst))
393 goto OUT;
394 if (!src || g2d_image_check(src))
395 goto OUT;
396
397 if ((src->format != G2D_FORMAT_YUV420_PLANAR) ||
398 (dst->format != G2D_FORMAT_YUV420_PLANAR)) {
399 G2D_ERR_MSG("LBC only support YUV420 plannar fmt!\n");
400 goto OUT;
401 }
402
403 if (((flag & 0xf00) == G2D_ROT_180) || ((flag & 0xf00) == G2D_ROT_V)) {
404 G2D_ERR_MSG("LBC not support 180 and V flip!\n");
405 goto OUT;
406 }
407
408 if (!src->use_phy_addr || !dst->use_phy_addr) {
409 src_item = kmalloc(sizeof(struct dmabuf_item),
410 GFP_KERNEL | __GFP_ZERO);
411 if (src_item == NULL) {
412 G2D_ERR_MSG("malloc memory of size %u fail!\n",
413 (unsigned int)sizeof(struct dmabuf_item));
414 goto OUT;
415 }
416 dst_item = kmalloc(sizeof(struct dmabuf_item),
417 GFP_KERNEL | __GFP_ZERO);
418 if (dst_item == NULL) {
419 G2D_ERR_MSG("malloc memory of size %u fail!\n",
420 (unsigned int)sizeof(struct dmabuf_item));
421 goto FREE_SRC;
422 }
423 ret = g2d_dma_map(src->fd, src_item);
424 if (ret != 0) {
425 G2D_ERR_MSG("map src_item fail!\n");
426 goto FREE_DST;
427 }
428 g2d_set_info(src, src_item);
429
430 ret = g2d_dma_map(dst->fd, dst_item);
431 if (ret != 0) {
432 G2D_ERR_MSG("map dst_item fail!\n");
433 goto SRC_DMA_UNMAP;
434 }
435 g2d_set_info(dst, dst_item);
436 }
437
438 /* rotate use same format */
439 dst->format = src->format;
440
441 tmp = 1;
442 write_wvalue(ROT_CTL, tmp);
443
444 if ((flag & 0xf00) == G2D_ROT_0)
445 lbc |= 0x0 << 7;
446 if ((flag & 0xf00) == G2D_ROT_90)
447 lbc |= 0x1 << 7;
448 if ((flag & 0xf00) == G2D_ROT_270)
449 lbc |= 0x2 << 7;
450 if (flag & G2D_ROT_H)
451 lbc |= 0x3 << 7;
452 write_wvalue(LBC_CTL, lbc);
453
454 write_wvalue(ROT_IFMT, src->format & 0x3F);
455 write_wvalue(ROT_ISIZE, ((((src->clip_rect.h - 1) & 0x1fff) << 16)) |
456 ((src->clip_rect.w - 1) & 0x1fff));
457
458 if ((src->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) &&
459 (src->format <= G2D_FORMAT_YUV422_PLANAR)) {
460 cw = src->width >> 1;
461 ch = src->height;
462 cx = src->clip_rect.x >> 1;
463 cy = src->clip_rect.y;
464 }
465
466 else if ((src->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) &&
467 (src->format <= G2D_FORMAT_YUV420_PLANAR)) {
468 cw = src->width >> 1;
469 ch = src->height >> 1;
470 cx = src->clip_rect.x >> 1;
471 cy = src->clip_rect.y >> 1;
472 }
473
474 else if ((src->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) &&
475 (src->format <= G2D_FORMAT_YUV411_PLANAR)) {
476 cw = src->width >> 2;
477 ch = src->height;
478 cx = src->clip_rect.x >> 2;
479 cy = src->clip_rect.y;
480 }
481
482 else {
483 cw = 0;
484 ch = 0;
485 cx = 0;
486 cy = 0;
487 }
488
489 g2d_byte_cal(src->format, &ycnt, &ucnt, &vcnt);
490 pitch0 = cal_align(ycnt * src->width, src->align[0]);
491 write_wvalue(ROT_IPITCH0, pitch0);
492 pitch1 = cal_align(ucnt * cw, src->align[1]);
493 write_wvalue(ROT_IPITCH1, pitch1);
494 pitch2 = cal_align(vcnt * cw, src->align[2]);
495 write_wvalue(ROT_IPITCH2, pitch2);
496
497 addr0 = src->laddr[0] + ((__u64)src->haddr[0] << 32) +
498 pitch0 * src->clip_rect.y + ycnt * src->clip_rect.x;
499 write_wvalue(ROT_ILADD0, addr0 & 0xffffffff);
500 write_wvalue(ROT_IHADD0, (addr0 >> 32) & 0xff);
501 addr1 = src->laddr[1] + ((__u64)src->haddr[1] << 32) + pitch1 * cy +
502 ucnt * cx;
503 write_wvalue(ROT_ILADD1, addr1 & 0xffffffff);
504 write_wvalue(ROT_IHADD1, (addr1 >> 32) & 0xff);
505 addr2 = src->laddr[2] + ((__u64)src->haddr[2] << 32) + pitch2 * cy +
506 vcnt * cx;
507 write_wvalue(ROT_ILADD2, addr2 & 0xffffffff);
508 write_wvalue(ROT_IHADD2, (addr2 >> 32) & 0xff);
509
510 if (((flag & 0xf00) == G2D_ROT_90) || ((flag & 0xf00) == G2D_ROT_270)) {
511 dst->clip_rect.w = src->clip_rect.h;
512 dst->clip_rect.h = src->clip_rect.w;
513 }
514
515 else {
516 dst->clip_rect.w = src->clip_rect.w;
517 dst->clip_rect.h = src->clip_rect.h;
518 }
519 write_wvalue(ROT_OSIZE, ((((dst->clip_rect.h - 1) & 0x1fff) << 16)) |
520 ((dst->clip_rect.w - 1) & 0x1fff));
521
522
523 if ((dst->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) &&
524 (dst->format <= G2D_FORMAT_YUV422_PLANAR)) {
525 cw = dst->width >> 1;
526 ch = dst->height;
527 cx = dst->clip_rect.x >> 1;
528 cy = dst->clip_rect.y;
529 }
530
531 else if ((dst->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) &&
532 (dst->format <= G2D_FORMAT_YUV420_PLANAR)) {
533 cw = dst->width >> 1;
534 ch = dst->height >> 1;
535 cx = dst->clip_rect.x >> 1;
536 cy = dst->clip_rect.y >> 1;
537 }
538
539 else if ((dst->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) &&
540 (dst->format <= G2D_FORMAT_YUV411_PLANAR)) {
541 cw = dst->width >> 2;
542 ch = dst->height;
543 cx = dst->clip_rect.x >> 2;
544 cy = dst->clip_rect.y;
545 }
546
547 else {
548 cw = 0;
549 ch = 0;
550 cx = 0;
551 cy = 0;
552 }
553
554 g2d_byte_cal(dst->format, &ycnt, &ucnt, &vcnt);
555
556 pitch0 = cal_align(ycnt * dst->width, dst->align[0]);
557 write_wvalue(ROT_OPITCH0, pitch0);
558 pitch1 = cal_align(ucnt * cw, dst->align[1]);
559 write_wvalue(ROT_OPITCH1, pitch1);
560 pitch2 = cal_align(vcnt * cw, dst->align[2]);
561 write_wvalue(ROT_OPITCH2, pitch2);
562
563 addr0 = dst->laddr[0] + ((__u64)dst->haddr[0] << 32) +
564 pitch0 * dst->clip_rect.y + ycnt * dst->clip_rect.x;
565 write_wvalue(ROT_OLADD0, addr0 & 0xffffffff);
566 write_wvalue(ROT_OHADD0, (addr0 >> 32) & 0xff);
567 addr1 = dst->laddr[1] + ((__u64)dst->haddr[1] << 32) + pitch1 * cy +
568 ucnt * cx;
569 write_wvalue(ROT_OLADD1, addr1 & 0xffffffff);
570 write_wvalue(ROT_OHADD1, (addr1 >> 32) & 0xff);
571 addr2 = dst->laddr[2] + ((__u64)dst->haddr[2] << 32) + pitch2 * cy +
572 vcnt * cx;
573 write_wvalue(ROT_OLADD2, addr2 & 0xffffffff);
574 write_wvalue(ROT_OHADD2, (addr2 >> 32) & 0xff);
575
576
577 /* lbc */
578
579 frm_width = src->width;
580 frm_height = src->height;
581 cmp_ratio = para->lbc_cmp_ratio;
582 enc_is_lossy = para->enc_is_lossy;
583 dec_is_lossy = para->dec_is_lossy;
584 g2d_lbc_calc_ctrl(flag, frm_width, frm_height, cmp_ratio, enc_is_lossy, dec_is_lossy);
585
586 /* start the module */
587 write_wvalue(ROT_INT, 0x10000);
588 tmp = read_wvalue(ROT_CTL);
589 tmp |= (0x1 << 31);
590 write_wvalue(ROT_CTL, tmp);
591
592 ret = g2d_wait_cmd_finish(WAIT_CMD_TIME_MS);
593
594 if (!src->use_phy_addr || !dst->use_phy_addr)
595 g2d_dma_unmap(dst_item);
596 SRC_DMA_UNMAP:
597 if (!src->use_phy_addr || !dst->use_phy_addr)
598 g2d_dma_unmap(src_item);
599 FREE_DST:
600 kfree(dst_item);
601 FREE_SRC:
602 kfree(src_item);
603 OUT:
604 return ret;
605 }
606