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