• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &para->blt.src_image_h;
390 	g2d_image_enh *dst = &para->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