• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/msm/
1/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
2 *
3 * Copyright (C) 2007 Google Incorporated
4 * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/time.h>
20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/fb.h>
23#include <msm_mdp.h>
24#include <linux/file.h>
25#include <linux/major.h>
26
27#include "linux/proc_fs.h"
28
29#include <mach/hardware.h>
30#include <linux/io.h>
31
32#include <asm/system.h>
33#include <asm/mach-types.h>
34#include <linux/semaphore.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38
39#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
40				(((x) < MDP_IMGTYPE2_START) || \
41				 ((x) >= MDP_IMGTYPE_LIMIT2)))
42
43static uint32_t bytes_per_pixel[] = {
44	[MDP_RGB_565] = 2,
45	[MDP_RGB_888] = 3,
46	[MDP_XRGB_8888] = 4,
47	[MDP_ARGB_8888] = 4,
48	[MDP_RGBA_8888] = 4,
49	[MDP_BGRA_8888] = 4,
50	[MDP_Y_CBCR_H2V1] = 1,
51	[MDP_Y_CBCR_H2V2] = 1,
52	[MDP_Y_CRCB_H2V1] = 1,
53	[MDP_Y_CRCB_H2V2] = 1,
54	[MDP_YCRYCB_H2V1] = 2,
55	[MDP_BGR_565] = 2
56};
57
58extern uint32 mdp_plv[];
59extern struct semaphore mdp_ppp_mutex;
60
61uint32_t mdp_get_bytes_per_pixel(uint32_t format)
62{
63	uint32_t bpp = 0;
64	if (format < ARRAY_SIZE(bytes_per_pixel))
65		bpp = bytes_per_pixel[format];
66
67	BUG_ON(!bpp);
68	return bpp;
69}
70
71static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
72				    uint16 *matrix_and_bias_vector,
73				    uint32 *clamp_vector,
74				    uint32 *look_up_table)
75{
76	uint8 input_C2, input_C0, input_C1;
77	uint32 output;
78	int32 comp_C2, comp_C1, comp_C0, temp;
79	int32 temp1, temp2, temp3;
80	int32 matrix[9];
81	int32 bias_vector[3];
82	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
83	int32 i;
84	uint32 _is_lookup_table_enabled;
85
86	input_C2 = (input_pixel >> 16) & 0xFF;
87	input_C1 = (input_pixel >> 8) & 0xFF;
88	input_C0 = (input_pixel >> 0) & 0xFF;
89
90	comp_C0 = input_C0;
91	comp_C1 = input_C1;
92	comp_C2 = input_C2;
93
94	for (i = 0; i < 9; i++)
95		matrix[i] =
96		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
97
98	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
99	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
100	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
101
102	Y_low_limit = (int32) clamp_vector[0];
103	Y_high_limit = (int32) clamp_vector[1];
104	C_low_limit = (int32) clamp_vector[2];
105	C_high_limit = (int32) clamp_vector[3];
106
107	if (look_up_table == 0)	/* check for NULL point */
108		_is_lookup_table_enabled = 0;
109	else
110		_is_lookup_table_enabled = 1;
111
112	if (_is_lookup_table_enabled == 1) {
113		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
114		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
115		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
116	}
117	/*
118	 * Color Conversion
119	 * reorder input colors
120	 */
121	temp = comp_C2;
122	comp_C2 = comp_C1;
123	comp_C1 = comp_C0;
124	comp_C0 = temp;
125
126	/* matrix multiplication */
127	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
128	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
129	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
130
131	comp_C0 = temp1 + 0x100;
132	comp_C1 = temp2 + 0x100;
133	comp_C2 = temp3 + 0x100;
134
135	/* take interger part */
136	comp_C0 >>= 9;
137	comp_C1 >>= 9;
138	comp_C2 >>= 9;
139
140	/* post bias (+) */
141	comp_C0 += bias_vector[0];
142	comp_C1 += bias_vector[1];
143	comp_C2 += bias_vector[2];
144
145	/* limit pixel to 8-bit */
146	if (comp_C0 < 0)
147		comp_C0 = 0;
148
149	if (comp_C0 > 255)
150		comp_C0 = 255;
151
152	if (comp_C1 < 0)
153		comp_C1 = 0;
154
155	if (comp_C1 > 255)
156		comp_C1 = 255;
157
158	if (comp_C2 < 0)
159		comp_C2 = 0;
160
161	if (comp_C2 > 255)
162		comp_C2 = 255;
163
164	/* clamp */
165	if (comp_C0 < Y_low_limit)
166		comp_C0 = Y_low_limit;
167
168	if (comp_C0 > Y_high_limit)
169		comp_C0 = Y_high_limit;
170
171	if (comp_C1 < C_low_limit)
172		comp_C1 = C_low_limit;
173
174	if (comp_C1 > C_high_limit)
175		comp_C1 = C_high_limit;
176
177	if (comp_C2 < C_low_limit)
178		comp_C2 = C_low_limit;
179
180	if (comp_C2 > C_high_limit)
181		comp_C2 = C_high_limit;
182
183	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
184	return output;
185}
186
187uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
188			     uint16 *matrix_and_bias_vector,
189			     uint32 *clamp_vector, uint32 *look_up_table)
190{
191	uint8 input_C2, input_C0, input_C1;
192	uint32 output;
193	int32 comp_C2, comp_C1, comp_C0, temp;
194	int32 temp1, temp2, temp3;
195	int32 matrix[9];
196	int32 bias_vector[3];
197	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
198	int32 i;
199	uint32 _is_lookup_table_enabled;
200
201	input_C2 = (input_pixel >> 16) & 0xFF;
202	input_C1 = (input_pixel >> 8) & 0xFF;
203	input_C0 = (input_pixel >> 0) & 0xFF;
204
205	comp_C0 = input_C0;
206	comp_C1 = input_C1;
207	comp_C2 = input_C2;
208
209	for (i = 0; i < 9; i++)
210		matrix[i] =
211		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
212
213	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
214	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
215	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
216
217	Y_low_limit = (int32) clamp_vector[0];
218	Y_high_limit = (int32) clamp_vector[1];
219	C_low_limit = (int32) clamp_vector[2];
220	C_high_limit = (int32) clamp_vector[3];
221
222	if (look_up_table == 0)	/* check for NULL point */
223		_is_lookup_table_enabled = 0;
224	else
225		_is_lookup_table_enabled = 1;
226
227	/* clamp */
228	if (comp_C0 < Y_low_limit)
229		comp_C0 = Y_low_limit;
230
231	if (comp_C0 > Y_high_limit)
232		comp_C0 = Y_high_limit;
233
234	if (comp_C1 < C_low_limit)
235		comp_C1 = C_low_limit;
236
237	if (comp_C1 > C_high_limit)
238		comp_C1 = C_high_limit;
239
240	if (comp_C2 < C_low_limit)
241		comp_C2 = C_low_limit;
242
243	if (comp_C2 > C_high_limit)
244		comp_C2 = C_high_limit;
245
246	/*
247	 * Color Conversion
248	 * pre bias (-)
249	 */
250	comp_C0 -= bias_vector[0];
251	comp_C1 -= bias_vector[1];
252	comp_C2 -= bias_vector[2];
253
254	/* matrix multiplication */
255	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
256	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
257	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
258
259	comp_C0 = temp1 + 0x100;
260	comp_C1 = temp2 + 0x100;
261	comp_C2 = temp3 + 0x100;
262
263	/* take interger part */
264	comp_C0 >>= 9;
265	comp_C1 >>= 9;
266	comp_C2 >>= 9;
267
268	/* reorder output colors */
269	temp = comp_C0;
270	comp_C0 = comp_C1;
271	comp_C1 = comp_C2;
272	comp_C2 = temp;
273
274	/* limit pixel to 8-bit */
275	if (comp_C0 < 0)
276		comp_C0 = 0;
277
278	if (comp_C0 > 255)
279		comp_C0 = 255;
280
281	if (comp_C1 < 0)
282		comp_C1 = 0;
283
284	if (comp_C1 > 255)
285		comp_C1 = 255;
286
287	if (comp_C2 < 0)
288		comp_C2 = 0;
289
290	if (comp_C2 > 255)
291		comp_C2 = 255;
292
293	/* Look-up table */
294	if (_is_lookup_table_enabled == 1) {
295		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
296		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
297		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
298	}
299
300	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
301	return output;
302}
303
304static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
305{
306	uint32 tpVal;
307	uint8 plane_tp;
308
309	tpVal = 0;
310	if ((mdpImg->imgType == MDP_RGB_565)
311	    || (mdpImg->imgType == MDP_BGR_565)) {
312		/*
313		 * transparent color conversion into 24 bpp
314		 *
315		 * C2R_8BIT
316		 * left shift the entire bit and or it with the upper most bits
317		 */
318		plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
319		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
320
321		/* C1B_8BIT */
322		plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
323		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
324
325		/* C0G_8BIT */
326		plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
327		tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
328	} else {
329		/* 24bit RGB to RBG conversion */
330
331		tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
332		tpVal |= (mdpImg->tpVal & 0xFF) << 8;
333		tpVal |= (mdpImg->tpVal & 0xFF0000);
334	}
335
336	return tpVal;
337}
338
339static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
340{
341	uint8 *dest1;
342
343	dest1 = NULL;
344	switch (iBuf->ibuf_type) {
345	case MDP_Y_CBCR_H2V2:
346	case MDP_Y_CRCB_H2V2:
347	case MDP_Y_CBCR_H2V1:
348	case MDP_Y_CRCB_H2V1:
349		dest1 = (uint8 *) iBuf->buf;
350		dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
351		break;
352
353	default:
354		break;
355	}
356
357	return dest1;
358}
359
360static void mdp_ppp_setbg(MDPIBUF *iBuf)
361{
362	uint8 *bg0_addr;
363	uint8 *bg1_addr;
364	uint32 bg0_ystride, bg1_ystride;
365	uint32 ppp_src_cfg_reg, unpack_pattern;
366	int v_slice, h_slice;
367
368	v_slice = h_slice = 1;
369	bg0_addr = (uint8 *) iBuf->buf;
370	bg1_addr = mdp_get_chroma_addr(iBuf);
371
372	bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
373	bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
374
375	switch (iBuf->ibuf_type) {
376	case MDP_BGR_565:
377	case MDP_RGB_565:
378		/* 888 = 3bytes
379		 * RGB = 3Components
380		 * RGB interleaved
381		 */
382		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
383			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
384			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
385			PPP_SRC_UNPACK_ALIGN_LSB |
386			PPP_SRC_FETCH_PLANES_INTERLVD;
387
388		if (iBuf->ibuf_type == MDP_RGB_565)
389			unpack_pattern =
390			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
391		else
392			unpack_pattern =
393			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
394		break;
395
396	case MDP_RGB_888:
397		/*
398		 * 888 = 3bytes
399		 * RGB = 3Components
400		 * RGB interleaved
401		 */
402		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
403		PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
404		PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
405		PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
406
407		unpack_pattern =
408		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
409		break;
410
411	case MDP_BGRA_8888:
412	case MDP_RGBA_8888:
413	case MDP_ARGB_8888:
414	case MDP_XRGB_8888:
415		/*
416		 * 8888 = 4bytes
417		 * ARGB = 4Components
418		 * ARGB interleaved
419		 */
420		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
421		PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
422		PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
423		PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
424		PPP_SRC_FETCH_PLANES_INTERLVD;
425
426		if (iBuf->ibuf_type == MDP_BGRA_8888)
427			unpack_pattern =
428			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
429						 8);
430		else if (iBuf->ibuf_type == MDP_RGBA_8888)
431			unpack_pattern =
432			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
433						 8);
434		else
435			unpack_pattern =
436			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
437						 8);
438		break;
439
440	case MDP_Y_CBCR_H2V2:
441	case MDP_Y_CRCB_H2V2:
442		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
443		    PPP_SRC_C0G_8BITS |
444		    PPP_SRC_C1B_8BITS |
445		    PPP_SRC_C3A_8BITS |
446		    PPP_SRC_BPP_INTERLVD_2BYTES |
447		    PPP_SRC_INTERLVD_2COMPONENTS |
448		    PPP_SRC_UNPACK_TIGHT |
449		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
450
451		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
452			unpack_pattern =
453			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
454		else
455			unpack_pattern =
456			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
457		v_slice = h_slice = 2;
458		break;
459
460	case MDP_YCRYCB_H2V1:
461		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
462		    PPP_SRC_C0G_8BITS |
463		    PPP_SRC_C1B_8BITS |
464		    PPP_SRC_C3A_8BITS |
465		    PPP_SRC_BPP_INTERLVD_2BYTES |
466		    PPP_SRC_INTERLVD_4COMPONENTS |
467		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
468
469		unpack_pattern =
470		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
471		h_slice = 2;
472		break;
473
474	case MDP_Y_CBCR_H2V1:
475	case MDP_Y_CRCB_H2V1:
476		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
477		    PPP_SRC_C0G_8BITS |
478		    PPP_SRC_C1B_8BITS |
479		    PPP_SRC_C3A_8BITS |
480		    PPP_SRC_BPP_INTERLVD_2BYTES |
481		    PPP_SRC_INTERLVD_2COMPONENTS |
482		    PPP_SRC_UNPACK_TIGHT |
483		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
484
485		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
486			unpack_pattern =
487			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
488		else
489			unpack_pattern =
490			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
491		h_slice = 2;
492		break;
493
494	default:
495		return;
496	}
497
498	/* starting input address adjustment */
499	mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
500			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
501			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
502			      iBuf, 1);
503
504	/*
505	 * 0x01c0: background plane 0 addr
506	 * 0x01c4: background plane 1 addr
507	 * 0x01c8: background plane 2 addr
508	 * 0x01cc: bg y stride for plane 0 and 1
509	 * 0x01d0: bg y stride for plane 2
510	 * 0x01d4: bg src PPP config
511	 * 0x01d8: unpack pattern
512	 */
513	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
514	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
515
516	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
517		 (bg1_ystride << 16) | bg0_ystride);
518	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
519
520	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
521}
522
523#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
524				(img == MDP_Y_CBCR_H2V2) | \
525				(img == MDP_Y_CRCB_H2V1) | \
526				(img == MDP_Y_CBCR_H2V1))
527
528#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
529
530#define Y_TO_CRCB_RATIO(format) \
531	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
532	(format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
533
534static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
535			uint32_t *len0, uint32_t *len1)
536{
537	*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
538	if (IS_PSEUDOPLNR(img->format))
539		*len1 = *len0/Y_TO_CRCB_RATIO(img->format);
540	else
541		*len1 = 0;
542}
543
544static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
545			struct file *p_src_file, struct file *p_dst_file)
546{
547#ifdef CONFIG_ANDROID_PMEM
548	uint32_t src0_len, src1_len, dst0_len, dst1_len;
549
550	/* flush src images to memory before dma to mdp */
551	get_len(&req->src, &req->src_rect, src_bpp,
552	&src0_len, &src1_len);
553
554	flush_pmem_file(p_src_file,
555	req->src.offset, src0_len);
556
557	if (IS_PSEUDOPLNR(req->src.format))
558		flush_pmem_file(p_src_file,
559			req->src.offset + src0_len, src1_len);
560
561	get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
562	flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
563
564	if (IS_PSEUDOPLNR(req->dst.format))
565		flush_pmem_file(p_dst_file,
566			req->dst.offset + dst0_len, dst1_len);
567#endif
568}
569
570static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
571struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
572{
573	uint8 *src0, *src1;
574	uint8 *dest0, *dest1;
575	uint16 inpBpp;
576	uint32 dest0_ystride;
577	uint32 src_width;
578	uint32 src_height;
579	uint32 src0_ystride;
580	uint32 dst_roi_width;
581	uint32 dst_roi_height;
582	uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
583	uint32 alpha, tpVal;
584	uint32 packPattern;
585	uint32 dst_packPattern;
586	boolean inputRGB, outputRGB, pseudoplanr_output;
587	int sv_slice, sh_slice;
588	int dv_slice, dh_slice;
589	boolean perPixelAlpha = FALSE;
590	boolean ppp_lookUp_enable = FALSE;
591
592	sv_slice = sh_slice = dv_slice = dh_slice = 1;
593	alpha = tpVal = 0;
594	src_width = iBuf->mdpImg.width;
595	src_height = iBuf->roi.y + iBuf->roi.height;
596	src1 = NULL;
597	dest1 = NULL;
598
599	inputRGB = outputRGB = TRUE;
600	pseudoplanr_output = FALSE;
601	ppp_operation_reg = 0;
602	ppp_dst_cfg_reg = 0;
603	ppp_src_cfg_reg = 0;
604
605	/* Wait for the pipe to clear */
606	do { } while (mdp_ppp_pipe_wait() <= 0);
607
608	/*
609	 * destination config
610	 */
611	switch (iBuf->ibuf_type) {
612	case MDP_RGB_888:
613		dst_packPattern =
614		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
615		ppp_dst_cfg_reg =
616		    PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
617		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
618		    PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
619		    PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
620		break;
621
622	case MDP_XRGB_8888:
623	case MDP_ARGB_8888:
624	case MDP_RGBA_8888:
625		if (iBuf->ibuf_type == MDP_BGRA_8888)
626			dst_packPattern =
627			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
628						 8);
629		else if (iBuf->ibuf_type == MDP_RGBA_8888)
630			dst_packPattern =
631			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
632						 8);
633		else
634			dst_packPattern =
635			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
636						 8);
637
638		ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
639		    PPP_DST_C1B_8BIT |
640		    PPP_DST_C2R_8BIT |
641		    PPP_DST_C3A_8BIT |
642		    PPP_DST_C3ALPHA_EN |
643		    PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
644		    PPP_DST_PACK_TIGHT |
645		    PPP_DST_PACK_ALIGN_LSB |
646		    PPP_DST_OUT_SEL_AXI |
647		    PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
648		break;
649
650	case MDP_Y_CBCR_H2V2:
651	case MDP_Y_CRCB_H2V2:
652		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
653			dst_packPattern =
654			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
655		else
656			dst_packPattern =
657			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
658
659		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
660		    PPP_DST_C0G_8BIT |
661		    PPP_DST_C1B_8BIT |
662		    PPP_DST_C3A_8BIT |
663		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
664		    PPP_DST_PACK_TIGHT |
665		    PPP_DST_PACK_ALIGN_LSB |
666		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
667
668		ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
669		outputRGB = FALSE;
670		pseudoplanr_output = TRUE;
671		/*
672		 * vertically (y direction) and horizontally (x direction)
673		 * sample reduction by 2
674		 */
675
676		/*
677		 * H2V2(YUV420) Cosite
678		 *
679		 * Y    Y    Y    Y
680		 * CbCr      CbCr
681		 * Y    Y    Y    Y
682		 * Y    Y    Y    Y
683		 * CbCr      CbCr
684		 * Y    Y    Y    Y
685		 */
686		dv_slice = dh_slice = 2;
687
688		/* (x,y) and (width,height) must be even numbern */
689		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
690		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
691		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
692		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
693
694		iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
695		iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
696		iBuf->roi.y = (iBuf->roi.y / 2) * 2;
697		iBuf->roi.height = (iBuf->roi.height / 2) * 2;
698		break;
699
700	case MDP_YCRYCB_H2V1:
701		dst_packPattern =
702		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
703		ppp_dst_cfg_reg =
704		    PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
705		    PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
706		    PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
707		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
708		    PPP_DST_PLANE_INTERLVD;
709
710		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
711		outputRGB = FALSE;
712		/*
713		 * horizontally (x direction) sample reduction by 2
714		 *
715		 * H2V1(YUV422) Cosite
716		 *
717		 * YCbCr    Y    YCbCr    Y
718		 * YCbCr    Y    YCbCr    Y
719		 * YCbCr    Y    YCbCr    Y
720		 * YCbCr    Y    YCbCr    Y
721		 */
722		dh_slice = 2;
723
724		/*
725		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
726		 * preloaded gamma setting of 2.2 when the content is
727		 * non-linear ppp_lookUp_enable = TRUE;
728		 */
729
730		/* x and width must be even number */
731		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
732		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
733		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
734		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
735		break;
736
737	case MDP_Y_CBCR_H2V1:
738	case MDP_Y_CRCB_H2V1:
739		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
740			dst_packPattern =
741			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
742		else
743			dst_packPattern =
744			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
745
746		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
747		    PPP_DST_C0G_8BIT |
748		    PPP_DST_C1B_8BIT |
749		    PPP_DST_C3A_8BIT |
750		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
751		    PPP_DST_PACK_TIGHT |
752		    PPP_DST_PACK_ALIGN_LSB |
753		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
754
755		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
756		outputRGB = FALSE;
757		pseudoplanr_output = TRUE;
758		/* horizontally (x direction) sample reduction by 2 */
759		dh_slice = 2;
760
761		/* x and width must be even number */
762		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
763		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
764		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
765		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
766		break;
767
768	case MDP_BGR_565:
769	case MDP_RGB_565:
770	default:
771		if (iBuf->ibuf_type == MDP_RGB_565)
772			dst_packPattern =
773			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
774		else
775			dst_packPattern =
776			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
777
778		ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
779		    PPP_DST_C1B_5BIT |
780		    PPP_DST_C2R_5BIT |
781		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
782		    PPP_DST_PACK_TIGHT |
783		    PPP_DST_PACK_ALIGN_LSB |
784		    PPP_DST_OUT_SEL_AXI |
785		    PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
786		break;
787	}
788
789	/* source config */
790	switch (iBuf->mdpImg.imgType) {
791	case MDP_RGB_888:
792		inpBpp = 3;
793		/*
794		 * 565 = 2bytes
795		 * RGB = 3Components
796		 * RGB interleaved
797		 */
798		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
799			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
800			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
801			PPP_SRC_UNPACK_ALIGN_LSB |
802			PPP_SRC_FETCH_PLANES_INTERLVD;
803
804		packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
805
806		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
807		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
808		break;
809
810	case MDP_BGRA_8888:
811	case MDP_RGBA_8888:
812	case MDP_ARGB_8888:
813		perPixelAlpha = TRUE;
814	case MDP_XRGB_8888:
815		inpBpp = 4;
816		/*
817		 * 8888 = 4bytes
818		 * ARGB = 4Components
819		 * ARGB interleaved
820		 */
821		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
822			PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
823			PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
824			PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
825			PPP_SRC_UNPACK_ALIGN_LSB |
826			PPP_SRC_FETCH_PLANES_INTERLVD;
827
828		if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
829			packPattern =
830			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
831						 8);
832		else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
833			packPattern =
834			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
835						 8);
836		else
837			packPattern =
838			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
839						 8);
840
841		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
842		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
843		break;
844
845	case MDP_Y_CBCR_H2V2:
846	case MDP_Y_CRCB_H2V2:
847		inpBpp = 1;
848		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
849
850		/*
851		 * CbCr = 2bytes
852		 * CbCr = 2Components
853		 * Y+CbCr
854		 */
855		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
856			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
857			PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
858			PPP_SRC_UNPACK_ALIGN_LSB |
859			PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
860
861		if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
862			packPattern =
863			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
864		else
865			packPattern =
866			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
867
868		ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
869		    PPP_OP_SRC_CHROMA_420 |
870		    PPP_OP_SRC_CHROMA_COSITE |
871		    PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
872
873		inputRGB = FALSE;
874		sh_slice = sv_slice = 2;
875		break;
876
877	case MDP_YCRYCB_H2V1:
878		inpBpp = 2;
879		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
880		    PPP_SRC_C0G_8BITS |
881		    PPP_SRC_C1B_8BITS |
882		    PPP_SRC_C3A_8BITS |
883		    PPP_SRC_BPP_INTERLVD_2BYTES |
884		    PPP_SRC_INTERLVD_4COMPONENTS |
885		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
886
887		packPattern =
888		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
889
890		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
891		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
892
893		/*
894		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
895		 * preloaded inverse gamma setting of 2.2 since they're
896		 * symetric when the content is non-linear
897		 * ppp_lookUp_enable = TRUE;
898		 */
899
900		/* x and width must be even number */
901		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
902		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
903		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
904		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
905
906		inputRGB = FALSE;
907		sh_slice = 2;
908		break;
909
910	case MDP_Y_CBCR_H2V1:
911	case MDP_Y_CRCB_H2V1:
912		inpBpp = 1;
913		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
914
915		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
916		    PPP_SRC_C0G_8BITS |
917		    PPP_SRC_C1B_8BITS |
918		    PPP_SRC_C3A_8BITS |
919		    PPP_SRC_BPP_INTERLVD_2BYTES |
920		    PPP_SRC_INTERLVD_2COMPONENTS |
921		    PPP_SRC_UNPACK_TIGHT |
922		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
923
924		if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
925			packPattern =
926			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
927		else
928			packPattern =
929			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
930
931		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
932		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
933		inputRGB = FALSE;
934		sh_slice = 2;
935		break;
936
937	case MDP_BGR_565:
938	case MDP_RGB_565:
939	default:
940		inpBpp = 2;
941		/*
942		 * 565 = 2bytes
943		 * RGB = 3Components
944		 * RGB interleaved
945		 */
946		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
947			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
948			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
949			PPP_SRC_UNPACK_ALIGN_LSB |
950			PPP_SRC_FETCH_PLANES_INTERLVD;
951
952		if (iBuf->mdpImg.imgType == MDP_RGB_565)
953			packPattern =
954			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
955		else
956			packPattern =
957			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
958
959		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
960		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
961		break;
962
963	}
964
965	if (pseudoplanr_output)
966		ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
967
968	/* YCbCr to RGB color conversion flag */
969	if ((!inputRGB) && (outputRGB)) {
970		ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
971		    PPP_OP_CONVERT_ON;
972
973		/*
974		 * primary/secondary is sort of misleading term...but
975		 * in mdp2.2/3.0 we only use primary matrix (forward/rev)
976		 * in mdp3.1 we use set1(prim) and set2(secd)
977		 */
978#ifdef CONFIG_FB_MSM_MDP31
979		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
980					PPP_OP_DST_RGB;
981		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
982#endif
983
984		if (ppp_lookUp_enable) {
985			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
986			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
987		}
988	}
989	/* RGB to YCbCr color conversion flag */
990	if ((inputRGB) && (!outputRGB)) {
991		ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
992		    PPP_OP_CONVERT_ON;
993
994#ifdef CONFIG_FB_MSM_MDP31
995		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
996					PPP_OP_DST_YCBCR;
997		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
998#endif
999
1000		if (ppp_lookUp_enable) {
1001			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
1002			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
1003		}
1004	}
1005	/* YCbCr to YCbCr color conversion flag */
1006	if ((!inputRGB) && (!outputRGB)) {
1007		if ((ppp_lookUp_enable) &&
1008		    (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
1009			ppp_operation_reg |= PPP_OP_LUT_C0_ON;
1010		}
1011	}
1012
1013	ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
1014	ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
1015
1016	if (req->flags & MDP_DEINTERLACE)
1017		ppp_operation_reg |= PPP_OP_DEINT_EN;
1018
1019	/* Dither at DMA side only since iBuf format is RGB888 */
1020	if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
1021		ppp_operation_reg |= PPP_OP_DITHER_EN;
1022
1023	if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
1024		ppp_operation_reg |= PPP_OP_ROT_ON;
1025
1026		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
1027			ppp_operation_reg |= PPP_OP_ROT_90;
1028		}
1029		if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
1030			ppp_operation_reg |= PPP_OP_FLIP_LR;
1031		}
1032		if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
1033			ppp_operation_reg |= PPP_OP_FLIP_UD;
1034		}
1035	}
1036
1037	src0_ystride = src_width * inpBpp;
1038	dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
1039
1040	/* no need to care about rotation since it's the real-XY. */
1041	dst_roi_width = iBuf->roi.dst_width;
1042	dst_roi_height = iBuf->roi.dst_height;
1043
1044	src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
1045	dest0 = (uint8 *) iBuf->buf;
1046
1047	/* Jumping from Y-Plane to Chroma Plane */
1048	dest1 = mdp_get_chroma_addr(iBuf);
1049
1050	/* first pixel addr calculation */
1051	mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
1052			      iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
1053			      0);
1054	mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
1055			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
1056			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
1057			      iBuf, 2);
1058
1059	/* set scale operation */
1060	mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
1061		      inputRGB, outputRGB, &ppp_operation_reg);
1062
1063	/*
1064	 * setting background source for blending
1065	 */
1066	mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
1067			   &ppp_operation_reg);
1068
1069	if (ppp_operation_reg & PPP_OP_BLEND_ON) {
1070		mdp_ppp_setbg(iBuf);
1071
1072		if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
1073			ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
1074
1075			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
1076				tpVal = mdp_conv_matx_rgb2yuv(tpVal,
1077						      (uint16 *) &
1078						      mdp_ccs_rgb2yuv,
1079						      &mdp_plv[0], NULL);
1080			}
1081		}
1082	}
1083
1084	/*
1085	 * 0x0004: enable dbg bus
1086	 * 0x0100: "don't care" Edge Condit until scaling is on
1087	 * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
1088	 * 0x0108: src pixel size
1089	 * 0x010c: component plane 0 starting address
1090	 * 0x011c: component plane 0 ystride
1091	 * 0x0124: PPP source config register
1092	 * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
1093	 */
1094	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
1095						      iBuf->roi.width));
1096	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
1097	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
1098	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
1099		 (src0_ystride << 16 | src0_ystride));
1100
1101	/* setup for rgb 565 */
1102	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
1103	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
1104	/*
1105	 * 0x0138: PPP destination operation register
1106	 * 0x014c: constant_alpha|transparent_color
1107	 * 0x0150: PPP destination config register
1108	 * 0x0154: PPP packing pattern
1109	 */
1110	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
1111	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
1112	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
1113	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
1114
1115	/*
1116	 * 0x0164: ROI height and width
1117	 * 0x0168: Component Plane 0 starting addr
1118	 * 0x016c: Component Plane 1 starting addr
1119	 * 0x0178: Component Plane 1/0 y stride
1120	 */
1121	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
1122		 (dst_roi_height << 16 | dst_roi_width));
1123	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
1124	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
1125	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
1126		 (dest0_ystride << 16 | dest0_ystride));
1127
1128	flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
1129#ifdef CONFIG_MDP_PPP_ASYNC_OP
1130	mdp_ppp_process_curr_djob();
1131#else
1132	mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
1133#endif
1134}
1135
1136static int mdp_ppp_verify_req(struct mdp_blit_req *req)
1137{
1138	u32 src_width, src_height, dst_width, dst_height;
1139
1140	if (req == NULL)
1141		return -1;
1142
1143	if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
1144	    MDP_IS_IMGTYPE_BAD(req->dst.format))
1145		return -1;
1146
1147	if ((req->src.width == 0) || (req->src.height == 0) ||
1148	    (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
1149	    (req->dst.width == 0) || (req->dst.height == 0) ||
1150	    (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
1151
1152		return -1;
1153
1154	if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
1155	    ((req->src_rect.y + req->src_rect.h) > req->src.height))
1156		return -1;
1157
1158	if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
1159	    ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
1160		return -1;
1161
1162	/*
1163	 * scaling range check
1164	 */
1165	src_width = req->src_rect.w;
1166	src_height = req->src_rect.h;
1167
1168	if (req->flags & MDP_ROT_90) {
1169		dst_width = req->dst_rect.h;
1170		dst_height = req->dst_rect.w;
1171	} else {
1172		dst_width = req->dst_rect.w;
1173		dst_height = req->dst_rect.h;
1174	}
1175
1176	switch (req->dst.format) {
1177	case MDP_Y_CRCB_H2V2:
1178	case MDP_Y_CBCR_H2V2:
1179		src_width = (src_width / 2) * 2;
1180		src_height = (src_height / 2) * 2;
1181		dst_width = (src_width / 2) * 2;
1182		dst_height = (src_height / 2) * 2;
1183		break;
1184
1185	case MDP_Y_CRCB_H2V1:
1186	case MDP_Y_CBCR_H2V1:
1187	case MDP_YCRYCB_H2V1:
1188		src_width = (src_width / 2) * 2;
1189		dst_width = (src_width / 2) * 2;
1190		break;
1191
1192	default:
1193		break;
1194	}
1195
1196	if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
1197	     MDP_MAX_X_SCALE_FACTOR)
1198	    || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
1199		MDP_MIN_X_SCALE_FACTOR))
1200		return -1;
1201
1202	if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
1203	     MDP_MAX_Y_SCALE_FACTOR)
1204	    || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
1205		MDP_MIN_Y_SCALE_FACTOR))
1206		return -1;
1207
1208	return 0;
1209}
1210
1211/**
1212 * get_gem_img() - retrieve drm obj's start address and size
1213 * @img:	contains drm file descriptor and gem handle
1214 * @start:	repository of starting address of drm obj allocated memory
1215 * @len:	repository of size of drm obj alloacted memory
1216 *
1217 **/
1218int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
1219{
1220	panic("waaaaaaaah");
1221	//return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
1222}
1223
1224int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
1225	    unsigned long *len, struct file **pp_file)
1226{
1227	int put_needed, ret = 0;
1228	struct file *file;
1229	unsigned long vstart;
1230#ifdef CONFIG_ANDROID_PMEM
1231	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1232		return 0;
1233#endif
1234	file = fget_light(img->memory_id, &put_needed);
1235	if (file == NULL)
1236		return -1;
1237
1238	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1239		*start = info->fix.smem_start;
1240		*len = info->fix.smem_len;
1241		*pp_file = file;
1242	} else {
1243		ret = -1;
1244		fput_light(file, put_needed);
1245	}
1246	return ret;
1247}
1248
1249int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
1250	struct file **pp_src_file, struct file **pp_dst_file)
1251{
1252	unsigned long src_start, dst_start;
1253	unsigned long src_len = 0;
1254	unsigned long dst_len = 0;
1255	MDPIBUF iBuf;
1256	u32 dst_width, dst_height;
1257	struct file *p_src_file = 0 , *p_dst_file = 0;
1258	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1259
1260	if (req->dst.format == MDP_FB_FORMAT)
1261		req->dst.format =  mfd->fb_imgType;
1262	if (req->src.format == MDP_FB_FORMAT)
1263		req->src.format = mfd->fb_imgType;
1264
1265	if (req->flags & MDP_BLIT_SRC_GEM) {
1266		if (get_gem_img(&req->src, &src_start, &src_len) < 0)
1267			return -1;
1268	} else {
1269		get_img(&req->src, info, &src_start, &src_len, &p_src_file);
1270	}
1271	if (src_len == 0) {
1272		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
1273		       "memory\n");
1274		return -1;
1275	}
1276
1277	if (req->flags & MDP_BLIT_DST_GEM) {
1278		if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
1279			return -1;
1280	} else {
1281		get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
1282	}
1283	if (dst_len == 0) {
1284		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
1285		       "memory\n");
1286		return -1;
1287	}
1288	*pp_src_file = p_src_file;
1289	*pp_dst_file = p_dst_file;
1290	if (mdp_ppp_verify_req(req)) {
1291		printk(KERN_ERR "mdp_ppp: invalid image!\n");
1292		return -1;
1293	}
1294
1295	iBuf.ibuf_width = req->dst.width;
1296	iBuf.ibuf_height = req->dst.height;
1297	iBuf.bpp = bytes_per_pixel[req->dst.format];
1298
1299	iBuf.ibuf_type = req->dst.format;
1300	iBuf.buf = (uint8 *) dst_start;
1301	iBuf.buf += req->dst.offset;
1302
1303	iBuf.roi.lcd_x = req->dst_rect.x;
1304	iBuf.roi.lcd_y = req->dst_rect.y;
1305	iBuf.roi.dst_width = req->dst_rect.w;
1306	iBuf.roi.dst_height = req->dst_rect.h;
1307
1308	iBuf.roi.x = req->src_rect.x;
1309	iBuf.roi.width = req->src_rect.w;
1310	iBuf.roi.y = req->src_rect.y;
1311	iBuf.roi.height = req->src_rect.h;
1312
1313	iBuf.mdpImg.width = req->src.width;
1314	iBuf.mdpImg.imgType = req->src.format;
1315
1316	iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
1317	iBuf.mdpImg.cbcr_addr =
1318	    (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
1319			req->src.width * req->src.height);
1320
1321	iBuf.mdpImg.mdpOp = MDPOP_NOP;
1322
1323	/* blending check */
1324	if (req->transp_mask != MDP_TRANSP_NOP) {
1325		iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
1326		iBuf.mdpImg.tpVal = req->transp_mask;
1327		iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
1328	}
1329
1330	req->alpha &= 0xff;
1331	if (req->alpha < MDP_ALPHA_NOP) {
1332		iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
1333		iBuf.mdpImg.alpha = req->alpha;
1334	}
1335
1336	/* rotation check */
1337	if (req->flags & MDP_FLIP_LR)
1338		iBuf.mdpImg.mdpOp |= MDPOP_LR;
1339	if (req->flags & MDP_FLIP_UD)
1340		iBuf.mdpImg.mdpOp |= MDPOP_UD;
1341	if (req->flags & MDP_ROT_90)
1342		iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
1343	if (req->flags & MDP_DITHER)
1344		iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
1345
1346	if (req->flags & MDP_BLEND_FG_PREMULT) {
1347#ifdef CONFIG_FB_MSM_MDP31
1348		iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
1349#else
1350		return -EINVAL;
1351#endif
1352	}
1353
1354	if (req->flags & MDP_DEINTERLACE) {
1355#ifdef CONFIG_FB_MSM_MDP31
1356		if ((req->src.format != MDP_Y_CBCR_H2V2) &&
1357			(req->src.format != MDP_Y_CRCB_H2V2))
1358#endif
1359		return -EINVAL;
1360	}
1361
1362	/* scale check */
1363	if (req->flags & MDP_ROT_90) {
1364		dst_width = req->dst_rect.h;
1365		dst_height = req->dst_rect.w;
1366	} else {
1367		dst_width = req->dst_rect.w;
1368		dst_height = req->dst_rect.h;
1369	}
1370
1371	if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
1372		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
1373
1374	if (req->flags & MDP_BLUR) {
1375#ifdef CONFIG_FB_MSM_MDP31
1376		if (req->flags & MDP_SHARPENING)
1377			printk(KERN_WARNING
1378				"mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
1379		req->flags |= MDP_SHARPENING;
1380		req->sharpening_strength = -127;
1381#else
1382		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
1383
1384#endif
1385	}
1386
1387	if (req->flags & MDP_SHARPENING) {
1388#ifdef CONFIG_FB_MSM_MDP31
1389		if ((req->sharpening_strength > 127) ||
1390			(req->sharpening_strength < -127)) {
1391			printk(KERN_ERR
1392				"%s: sharpening strength out of range\n",
1393				__func__);
1394			return -EINVAL;
1395		}
1396
1397		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
1398		iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
1399#else
1400		return -EINVAL;
1401#endif
1402	}
1403
1404	down(&mdp_ppp_mutex);
1405	/* MDP cmd block enable */
1406	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1407
1408#ifdef CONFIG_FB_MSM_MDP31
1409	mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1410#else
1411	if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
1412	     (req->src.format == MDP_ARGB_8888) ||
1413	     (req->src.format == MDP_BGRA_8888) ||
1414	     (req->src.format == MDP_RGBA_8888)) &&
1415	    (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
1416		int dst_h, src_w, i;
1417
1418		src_w = req->src_rect.w;
1419		dst_h = iBuf.roi.dst_height;
1420
1421		for (i = 0; i < (req->dst_rect.h / 16); i++) {
1422			/* this tile size */
1423			iBuf.roi.dst_height = 16;
1424			iBuf.roi.width =
1425			    (16 * req->src_rect.w) / req->dst_rect.h;
1426
1427			/* if it's out of scale range... */
1428			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1429			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
1430				iBuf.roi.width =
1431				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1432				    MDP_MAX_X_SCALE_FACTOR;
1433			else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1434				  iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
1435				iBuf.roi.width =
1436				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1437				    MDP_MIN_X_SCALE_FACTOR;
1438
1439			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1440
1441			/* next tile location */
1442			iBuf.roi.lcd_y += 16;
1443			iBuf.roi.x += iBuf.roi.width;
1444
1445			/* this is for a remainder update */
1446			dst_h -= 16;
1447			src_w -= iBuf.roi.width;
1448		}
1449
1450		if ((dst_h < 0) || (src_w < 0))
1451			printk
1452			    ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
1453			     __LINE__);
1454
1455		/* remainder update */
1456		if ((dst_h > 0) && (src_w > 0)) {
1457			u32 tmp_v;
1458
1459			iBuf.roi.dst_height = dst_h;
1460			iBuf.roi.width = src_w;
1461
1462			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1463			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
1464				tmp_v =
1465				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1466				    MDP_MAX_X_SCALE_FACTOR +
1467				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1468				    MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
1469
1470				/* move x location as roi width gets bigger */
1471				iBuf.roi.x -= tmp_v - iBuf.roi.width;
1472				iBuf.roi.width = tmp_v;
1473			} else
1474			    if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1475				 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
1476				tmp_v =
1477				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1478				    MDP_MIN_X_SCALE_FACTOR +
1479				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1480				    MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
1481
1482				/*
1483				 * we don't move x location for continuity of
1484				 * source image
1485				 */
1486				iBuf.roi.width = tmp_v;
1487			}
1488
1489			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1490		}
1491	} else {
1492		mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1493	}
1494#endif
1495
1496	/* MDP cmd block disable */
1497	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1498	up(&mdp_ppp_mutex);
1499
1500	return 0;
1501}
1502