Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[pandora-kernel.git] / drivers / staging / msm / mdp_ppp.c
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
43 static 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
58 extern uint32 mdp_plv[];
59 extern struct semaphore mdp_ppp_mutex;
60
61 uint32_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
71 static 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
187 uint32 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
304 static 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
339 static 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
360 static 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
534 static 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
544 static 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
570 static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
571 struct 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
1136 static 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  **/
1218 int 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
1224 int 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
1249 int 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         /* bg tile fetching HW workaround */
1412         if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
1413              (req->src.format == MDP_ARGB_8888) ||
1414              (req->src.format == MDP_BGRA_8888) ||
1415              (req->src.format == MDP_RGBA_8888)) &&
1416             (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
1417                 int dst_h, src_w, i;
1418
1419                 src_w = req->src_rect.w;
1420                 dst_h = iBuf.roi.dst_height;
1421
1422                 for (i = 0; i < (req->dst_rect.h / 16); i++) {
1423                         /* this tile size */
1424                         iBuf.roi.dst_height = 16;
1425                         iBuf.roi.width =
1426                             (16 * req->src_rect.w) / req->dst_rect.h;
1427
1428                         /* if it's out of scale range... */
1429                         if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1430                              iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
1431                                 iBuf.roi.width =
1432                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1433                                     MDP_MAX_X_SCALE_FACTOR;
1434                         else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1435                                   iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
1436                                 iBuf.roi.width =
1437                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1438                                     MDP_MIN_X_SCALE_FACTOR;
1439
1440                         mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1441
1442                         /* next tile location */
1443                         iBuf.roi.lcd_y += 16;
1444                         iBuf.roi.x += iBuf.roi.width;
1445
1446                         /* this is for a remainder update */
1447                         dst_h -= 16;
1448                         src_w -= iBuf.roi.width;
1449                 }
1450
1451                 if ((dst_h < 0) || (src_w < 0))
1452                         printk
1453                             ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
1454                              __LINE__);
1455
1456                 /* remainder update */
1457                 if ((dst_h > 0) && (src_w > 0)) {
1458                         u32 tmp_v;
1459
1460                         iBuf.roi.dst_height = dst_h;
1461                         iBuf.roi.width = src_w;
1462
1463                         if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1464                              iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
1465                                 tmp_v =
1466                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1467                                     MDP_MAX_X_SCALE_FACTOR +
1468                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1469                                     MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
1470
1471                                 /* move x location as roi width gets bigger */
1472                                 iBuf.roi.x -= tmp_v - iBuf.roi.width;
1473                                 iBuf.roi.width = tmp_v;
1474                         } else
1475                             if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1476                                  iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
1477                                 tmp_v =
1478                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1479                                     MDP_MIN_X_SCALE_FACTOR +
1480                                     (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1481                                     MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
1482
1483                                 /*
1484                                  * we don't move x location for continuity of
1485                                  * source image
1486                                  */
1487                                 iBuf.roi.width = tmp_v;
1488                         }
1489
1490                         mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1491                 }
1492         } else {
1493                 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1494         }
1495 #endif
1496
1497         /* MDP cmd block disable */
1498         mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1499         up(&mdp_ppp_mutex);
1500
1501         return 0;
1502 }