block: fix warning with calling smp_processor_id() in preemptible section
[pandora-kernel.git] / drivers / staging / msm / mdp4_overlay.c
1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/time.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/spinlock.h>
25 #include <linux/hrtimer.h>
26 #include <linux/clk.h>
27 #include <mach/hardware.h>
28 #include <linux/io.h>
29 #include <linux/debugfs.h>
30 #include <linux/fb.h>
31 #include <msm_mdp.h>
32 #include <linux/file.h>
33 #include "android_pmem.h"
34 #include <linux/major.h>
35 #include <asm/system.h>
36 #include <asm/mach-types.h>
37 #include <linux/semaphore.h>
38 #include <linux/uaccess.h>
39 #include <linux/mutex.h>
40
41 #include "mdp.h"
42 #include "msm_fb.h"
43 #include "mdp4.h"
44
45
46 struct mdp4_overlay_ctrl {
47         struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
48         struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
49 } mdp4_overlay_db;
50
51 static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
52
53
54 void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
55 {
56         uint32  dma2_cfg_reg;
57
58         dma2_cfg_reg = DMA_DITHER_EN;
59
60         if (mfd->fb_imgType == MDP_BGR_565)
61                 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
62         else
63                 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
64
65
66         if (mfd->panel_info.bpp == 18) {
67                 dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 666 18BPP */
68                     DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
69         } else if (mfd->panel_info.bpp == 16) {
70                 dma2_cfg_reg |= DMA_DSTC0G_6BITS |      /* 565 16BPP */
71                     DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
72         } else {
73                 dma2_cfg_reg |= DMA_DSTC0G_8BITS |      /* 888 16BPP */
74                     DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
75         }
76
77         if (lcdc)
78                 dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
79
80         /* dma2 config register */
81         MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
82
83 }
84
85 void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
86 {
87
88         /* dma_p source */
89         MDP_OUTP(MDP_BASE + 0x90004,
90                         (pipe->src_height << 16 | pipe->src_width));
91         MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
92         MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
93
94         /* dma_p dest */
95         MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
96 }
97
98 #define MDP4_VG_PHASE_STEP_DEFAULT      0x20000000
99 #define MDP4_VG_PHASE_STEP_SHIFT        29
100
101 static int mdp4_leading_0(uint32 num)
102 {
103         uint32 bit = 0x80000000;
104         int i;
105
106         for (i = 0; i < 32; i++) {
107                 if (bit & num)
108                         return i;
109                 bit >>= 1;
110         }
111
112         return i;
113 }
114
115 static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
116 {
117         uint32 val;
118         int     n;
119
120         n = mdp4_leading_0(src);
121         if (n > f_num)
122                 n = f_num;
123         val = src << n; /* maximum to reduce lose of resolution */
124         val /= dst;
125         if (n < f_num) {
126                 n = f_num - n;
127                 val <<= n;
128         }
129
130         return val;
131 }
132
133 static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
134 {
135
136         pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
137         pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
138
139         if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
140                 if (pipe->dst_h >= pipe->src_h * 8)     /* too much */
141                         return;
142                 pipe->op_mode |= MDP4_OP_SCALEY_EN;
143
144                 if (pipe->pipe_type == OVERLAY_TYPE_VG) {
145                         if (pipe->dst_h <= (pipe->src_h / 4))
146                                 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
147                         else
148                                 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
149                 }
150
151                 pipe->phasey_step = mdp4_scale_phase_step(29,
152                                         pipe->src_h, pipe->dst_h);
153         }
154
155         if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
156                 if (pipe->dst_w >= pipe->src_w * 8)     /* too much */
157                         return;
158                 pipe->op_mode |= MDP4_OP_SCALEX_EN;
159
160                 if (pipe->pipe_type == OVERLAY_TYPE_VG) {
161                         if (pipe->dst_w <= (pipe->src_w / 4))
162                                 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
163                         else
164                                 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
165                 }
166
167                 pipe->phasex_step = mdp4_scale_phase_step(29,
168                                         pipe->src_w, pipe->dst_w);
169         }
170 }
171
172 void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
173 {
174         char *rgb_base;
175         uint32 src_size, src_xy, dst_size, dst_xy;
176         uint32 format, pattern;
177
178         rgb_base = MDP_BASE + MDP4_RGB_BASE;
179         rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
180
181         src_size = ((pipe->src_h << 16) | pipe->src_w);
182         src_xy = ((pipe->src_y << 16) | pipe->src_x);
183         dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
184         dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
185
186         format = mdp4_overlay_format(pipe);
187         pattern = mdp4_overlay_unpack_pattern(pipe);
188
189         pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
190
191         mdp4_scale_setup(pipe);
192
193         outpdw(rgb_base + 0x0000, src_size);    /* MDP_RGB_SRC_SIZE */
194         outpdw(rgb_base + 0x0004, src_xy);      /* MDP_RGB_SRC_XY */
195         outpdw(rgb_base + 0x0008, dst_size);    /* MDP_RGB_DST_SIZE */
196         outpdw(rgb_base + 0x000c, dst_xy);      /* MDP_RGB_DST_XY */
197
198         outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
199         outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
200
201         outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
202         outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
203         outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
204         outpdw(rgb_base + 0x005c, pipe->phasex_step);
205         outpdw(rgb_base + 0x0060, pipe->phasey_step);
206
207         /* 16 bytes-burst x 3 req <= 48 bytes */
208         outpdw(rgb_base + 0x1004, 0xc2);        /* MDP_RGB_FETCH_CFG */
209 }
210
211 void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
212 {
213         char *vg_base;
214         uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
215         uint32 format, pattern;
216
217         vg_base = MDP_BASE + MDP4_VIDEO_BASE;
218         vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
219
220         frame_size = ((pipe->src_height << 16) | pipe->src_width);
221         src_size = ((pipe->src_h << 16) | pipe->src_w);
222         src_xy = ((pipe->src_y << 16) | pipe->src_x);
223         dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
224         dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
225
226         format = mdp4_overlay_format(pipe);
227         pattern = mdp4_overlay_unpack_pattern(pipe);
228
229         pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
230                                 MDP4_OP_IGC_LUT_EN);
231
232         mdp4_scale_setup(pipe);
233
234         outpdw(vg_base + 0x0000, src_size);     /* MDP_RGB_SRC_SIZE */
235         outpdw(vg_base + 0x0004, src_xy);       /* MDP_RGB_SRC_XY */
236         outpdw(vg_base + 0x0008, dst_size);     /* MDP_RGB_DST_SIZE */
237         outpdw(vg_base + 0x000c, dst_xy);       /* MDP_RGB_DST_XY */
238         outpdw(vg_base + 0x0048, frame_size);   /* TILE frame size */
239
240         /* luma component plane */
241         outpdw(vg_base + 0x0010, pipe->srcp0_addr);
242
243         /* chroma component plane */
244         outpdw(vg_base + 0x0014, pipe->srcp1_addr);
245
246         outpdw(vg_base + 0x0040,
247                         pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
248
249         outpdw(vg_base + 0x0050, format);       /* MDP_RGB_SRC_FORMAT */
250         outpdw(vg_base + 0x0054, pattern);      /* MDP_RGB_SRC_UNPACK_PATTERN */
251         outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
252         outpdw(vg_base + 0x005c, pipe->phasex_step);
253         outpdw(vg_base + 0x0060, pipe->phasey_step);
254
255         if (pipe->op_mode & MDP4_OP_DITHER_EN) {
256                 outpdw(vg_base + 0x0068,
257                         pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
258         }
259
260         /* 16 bytes-burst x 3 req <= 48 bytes */
261         outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */
262 }
263
264 int mdp4_overlay_format2type(uint32 format)
265 {
266         switch (format) {
267         case MDP_RGB_565:
268         case MDP_RGB_888:
269         case MDP_BGR_565:
270         case MDP_ARGB_8888:
271         case MDP_RGBA_8888:
272         case MDP_BGRA_8888:
273                 return OVERLAY_TYPE_RGB;
274         case MDP_YCRYCB_H2V1:
275         case MDP_Y_CRCB_H2V1:
276         case MDP_Y_CBCR_H2V1:
277         case MDP_Y_CRCB_H2V2:
278         case MDP_Y_CBCR_H2V2:
279         case MDP_Y_CBCR_H2V2_TILE:
280         case MDP_Y_CRCB_H2V2_TILE:
281                 return OVERLAY_TYPE_VG;
282         default:
283                 return -ERANGE;
284         }
285
286 }
287
288 #define C3_ALPHA        3       /* alpha */
289 #define C2_R_Cr         2       /* R/Cr */
290 #define C1_B_Cb         1       /* B/Cb */
291 #define C0_G_Y          0       /* G/luma */
292
293 int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
294 {
295         switch (pipe->src_format) {
296         case MDP_RGB_565:
297                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
298                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
299                 pipe->a_bit = 0;
300                 pipe->r_bit = 1;        /* R, 5 bits */
301                 pipe->b_bit = 1;        /* B, 5 bits */
302                 pipe->g_bit = 2;        /* G, 6 bits */
303                 pipe->alpha_enable = 0;
304                 pipe->unpack_tight = 1;
305                 pipe->unpack_align_msb = 0;
306                 pipe->unpack_count = 2;
307                 pipe->element2 = C2_R_Cr;       /* R */
308                 pipe->element1 = C0_G_Y;        /* G */
309                 pipe->element0 = C1_B_Cb;       /* B */
310                 pipe->bpp = 2;  /* 2 bpp */
311                 break;
312         case MDP_RGB_888:
313                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
314                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
315                 pipe->a_bit = 0;
316                 pipe->r_bit = 3;        /* R, 8 bits */
317                 pipe->b_bit = 3;        /* B, 8 bits */
318                 pipe->g_bit = 3;        /* G, 8 bits */
319                 pipe->alpha_enable = 0;
320                 pipe->unpack_tight = 1;
321                 pipe->unpack_align_msb = 0;
322                 pipe->unpack_count = 2;
323                 pipe->element2 = C2_R_Cr;       /* R */
324                 pipe->element1 = C0_G_Y;        /* G */
325                 pipe->element0 = C1_B_Cb;       /* B */
326                 pipe->bpp = 3;  /* 3 bpp */
327                 break;
328         case MDP_BGR_565:
329                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
330                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
331                 pipe->a_bit = 0;
332                 pipe->r_bit = 1;        /* R, 5 bits */
333                 pipe->b_bit = 1;        /* B, 5 bits */
334                 pipe->g_bit = 2;        /* G, 6 bits */
335                 pipe->alpha_enable = 0;
336                 pipe->unpack_tight = 1;
337                 pipe->unpack_align_msb = 0;
338                 pipe->unpack_count = 2;
339                 pipe->element2 = C1_B_Cb;       /* B */
340                 pipe->element1 = C0_G_Y;        /* G */
341                 pipe->element0 = C2_R_Cr;       /* R */
342                 pipe->bpp = 2;  /* 2 bpp */
343                 break;
344         case MDP_ARGB_8888:
345                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
346                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
347                 pipe->a_bit = 3;        /* alpha, 4 bits */
348                 pipe->r_bit = 3;        /* R, 8 bits */
349                 pipe->b_bit = 3;        /* B, 8 bits */
350                 pipe->g_bit = 3;        /* G, 8 bits */
351                 pipe->alpha_enable = 1;
352                 pipe->unpack_tight = 1;
353                 pipe->unpack_align_msb = 0;
354                 pipe->unpack_count = 3;
355                 pipe->element3 = C3_ALPHA;      /* alpha */
356                 pipe->element2 = C2_R_Cr;       /* R */
357                 pipe->element1 = C0_G_Y;        /* G */
358                 pipe->element0 = C1_B_Cb;       /* B */
359                 pipe->bpp = 4;          /* 4 bpp */
360                 break;
361         case MDP_RGBA_8888:
362                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
363                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
364                 pipe->a_bit = 3;        /* alpha, 4 bits */
365                 pipe->r_bit = 3;        /* R, 8 bits */
366                 pipe->b_bit = 3;        /* B, 8 bits */
367                 pipe->g_bit = 3;        /* G, 8 bits */
368                 pipe->alpha_enable = 1;
369                 pipe->unpack_tight = 1;
370                 pipe->unpack_align_msb = 0;
371                 pipe->unpack_count = 3;
372                 pipe->element3 = C2_R_Cr;       /* R */
373                 pipe->element2 = C0_G_Y;        /* G */
374                 pipe->element1 = C1_B_Cb;       /* B */
375                 pipe->element0 = C3_ALPHA;      /* alpha */
376                 pipe->bpp = 4;          /* 4 bpp */
377                 break;
378         case MDP_BGRA_8888:
379                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
380                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
381                 pipe->a_bit = 3;        /* alpha, 4 bits */
382                 pipe->r_bit = 3;        /* R, 8 bits */
383                 pipe->b_bit = 3;        /* B, 8 bits */
384                 pipe->g_bit = 3;        /* G, 8 bits */
385                 pipe->alpha_enable = 1;
386                 pipe->unpack_tight = 1;
387                 pipe->unpack_align_msb = 0;
388                 pipe->unpack_count = 3;
389                 pipe->element3 = C1_B_Cb;       /* B */
390                 pipe->element2 = C0_G_Y;        /* G */
391                 pipe->element1 = C2_R_Cr;       /* R */
392                 pipe->element0 = C3_ALPHA;      /* alpha */
393                 pipe->bpp = 4;          /* 4 bpp */
394                 break;
395         case MDP_YCRYCB_H2V1:
396                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
397                 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
398                 pipe->a_bit = 0;        /* alpha, 4 bits */
399                 pipe->r_bit = 3;        /* R, 8 bits */
400                 pipe->b_bit = 3;        /* B, 8 bits */
401                 pipe->g_bit = 3;        /* G, 8 bits */
402                 pipe->alpha_enable = 0;
403                 pipe->unpack_tight = 1;
404                 pipe->unpack_align_msb = 0;
405                 pipe->unpack_count = 3;
406                 pipe->element3 = C0_G_Y;        /* G */
407                 pipe->element2 = C2_R_Cr;       /* R */
408                 pipe->element1 = C0_G_Y;        /* G */
409                 pipe->element0 = C1_B_Cb;       /* B */
410                 pipe->bpp = 2;          /* 2 bpp */
411                 pipe->chroma_sample = MDP4_CHROMA_H2V1;
412                 break;
413         case MDP_Y_CRCB_H2V1:
414         case MDP_Y_CBCR_H2V1:
415         case MDP_Y_CRCB_H2V2:
416         case MDP_Y_CBCR_H2V2:
417                 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
418                 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
419                 pipe->a_bit = 0;
420                 pipe->r_bit = 3;        /* R, 8 bits */
421                 pipe->b_bit = 3;        /* B, 8 bits */
422                 pipe->g_bit = 3;        /* G, 8 bits */
423                 pipe->alpha_enable = 0;
424                 pipe->unpack_tight = 1;
425                 pipe->unpack_align_msb = 0;
426                 pipe->unpack_count = 1;         /* 2 */
427                 pipe->element3 = C0_G_Y;        /* not used */
428                 pipe->element2 = C0_G_Y;        /* not used */
429                 if (pipe->src_format == MDP_Y_CRCB_H2V1) {
430                         pipe->element1 = C2_R_Cr;       /* R */
431                         pipe->element0 = C1_B_Cb;       /* B */
432                         pipe->chroma_sample = MDP4_CHROMA_H2V1;
433                 } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
434                         pipe->element1 = C1_B_Cb;       /* B */
435                         pipe->element0 = C2_R_Cr;       /* R */
436                         pipe->chroma_sample = MDP4_CHROMA_H2V1;
437                 } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
438                         pipe->element1 = C2_R_Cr;       /* R */
439                         pipe->element0 = C1_B_Cb;       /* B */
440                         pipe->chroma_sample = MDP4_CHROMA_420;
441                 } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
442                         pipe->element1 = C1_B_Cb;       /* B */
443                         pipe->element0 = C2_R_Cr;       /* R */
444                         pipe->chroma_sample = MDP4_CHROMA_420;
445                 }
446                 pipe->bpp = 2;  /* 2 bpp */
447                 break;
448         case MDP_Y_CBCR_H2V2_TILE:
449         case MDP_Y_CRCB_H2V2_TILE:
450                 pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
451                 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
452                 pipe->a_bit = 0;
453                 pipe->r_bit = 3;        /* R, 8 bits */
454                 pipe->b_bit = 3;        /* B, 8 bits */
455                 pipe->g_bit = 3;        /* G, 8 bits */
456                 pipe->alpha_enable = 0;
457                 pipe->unpack_tight = 1;
458                 pipe->unpack_align_msb = 0;
459                 pipe->unpack_count = 1;         /* 2 */
460                 pipe->element3 = C0_G_Y;        /* not used */
461                 pipe->element2 = C0_G_Y;        /* not used */
462                 if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
463                         pipe->element1 = C2_R_Cr;       /* R */
464                         pipe->element0 = C1_B_Cb;       /* B */
465                         pipe->chroma_sample = MDP4_CHROMA_420;
466                 } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
467                         pipe->element1 = C1_B_Cb;       /* B */
468                         pipe->element0 = C2_R_Cr;       /* R */
469                         pipe->chroma_sample = MDP4_CHROMA_420;
470                 }
471                 pipe->bpp = 2;  /* 2 bpp */
472                 break;
473         default:
474                 /* not likely */
475                 return -ERANGE;
476         }
477
478         return 0;
479 }
480
481 /*
482  * color_key_convert: output with 12 bits color key
483  */
484 static uint32 color_key_convert(int start, int num, uint32 color)
485 {
486
487         uint32 data;
488
489         data = (color >> start) & ((1 << num) - 1);
490
491         if (num == 5)
492                 data = (data << 7) + (data << 2) + (data >> 3);
493         else if (num == 6)
494                 data = (data << 6) + data;
495         else    /* 8 bits */
496                 data = (data << 4) + (data >> 4);
497
498         return data;
499
500 }
501
502 void transp_color_key(int format, uint32 transp,
503                         uint32 *c0, uint32 *c1, uint32 *c2)
504 {
505         int b_start, g_start, r_start;
506         int b_num, g_num, r_num;
507
508         switch (format) {
509         case MDP_RGB_565:
510                 b_start = 0;
511                 g_start = 5;
512                 r_start = 11;
513                 r_num = 5;
514                 g_num = 6;
515                 b_num = 5;
516                 break;
517         case MDP_RGB_888:
518         case MDP_XRGB_8888:
519         case MDP_ARGB_8888:
520                 b_start = 0;
521                 g_start = 8;
522                 r_start = 16;
523                 r_num = 8;
524                 g_num = 8;
525                 b_num = 8;
526                 break;
527         case MDP_BGR_565:
528                 b_start = 11;
529                 g_start = 5;
530                 r_start = 0;
531                 r_num = 5;
532                 g_num = 6;
533                 b_num = 5;
534                 break;
535         case MDP_Y_CBCR_H2V2:
536         case MDP_Y_CBCR_H2V1:
537                 b_start = 8;
538                 g_start = 16;
539                 r_start = 0;
540                 r_num = 8;
541                 g_num = 8;
542                 b_num = 8;
543                 break;
544         case MDP_Y_CRCB_H2V2:
545         case MDP_Y_CRCB_H2V1:
546                 b_start = 0;
547                 g_start = 16;
548                 r_start = 8;
549                 r_num = 8;
550                 g_num = 8;
551                 b_num = 8;
552                 break;
553         default:
554                 b_start = 0;
555                 g_start = 8;
556                 r_start = 16;
557                 r_num = 8;
558                 g_num = 8;
559                 b_num = 8;
560                 break;
561         }
562
563         *c0 = color_key_convert(g_start, g_num, transp);
564         *c1 = color_key_convert(b_start, b_num, transp);
565         *c2 = color_key_convert(r_start, r_num, transp);
566 }
567
568 uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
569 {
570         uint32  format;
571
572         format = 0;
573
574         if (pipe->solid_fill)
575                 format |= MDP4_FORMAT_SOLID_FILL;
576
577         if (pipe->unpack_align_msb)
578                 format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
579
580         if (pipe->unpack_tight)
581                 format |= MDP4_FORMAT_UNPACK_TIGHT;
582
583         if (pipe->alpha_enable)
584                 format |= MDP4_FORMAT_ALPHA_ENABLE;
585
586         format |= (pipe->unpack_count << 13);
587         format |= ((pipe->bpp - 1) << 9);
588         format |= (pipe->a_bit << 6);
589         format |= (pipe->r_bit << 4);
590         format |= (pipe->b_bit << 2);
591         format |= pipe->g_bit;
592
593         format |= (pipe->frame_format << 29);
594
595         if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
596                 /* video/graphic */
597                 format |= (pipe->fetch_plane << 19);
598                 format |= (pipe->chroma_site << 28);
599                 format |= (pipe->chroma_sample << 26);
600         }
601
602         return format;
603 }
604
605 uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
606 {
607         return (pipe->element3 << 24) | (pipe->element2 << 16) |
608                         (pipe->element1 << 8) | pipe->element0;
609 }
610
611 void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
612 {
613         uint32 data;
614         char *overlay_base;
615
616         if (pipe->mixer_num == MDP4_MIXER1)
617                 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
618         else
619                 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
620
621         /* MDP_OVERLAYPROC_CFG */
622         outpdw(overlay_base + 0x0004, 0x01); /* directout */
623         data = pipe->src_height;
624         data <<= 16;
625         data |= pipe->src_width;
626         outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
627         outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
628         outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
629         outpdw(overlay_base + 0x0014, 0x4);     /* GC_LUT_EN, 888 */
630 }
631
632 int mdp4_overlay_active(int mixer)
633 {
634         uint32 data, mask, i;
635         int p1, p2;
636
637         data = inpdw(MDP_BASE + 0x10100);
638         p1 = 0;
639         p2 = 0;
640         for (i = 0; i < 8; i++) {
641                 mask = data & 0x0f;
642                 if (mask) {
643                         if (mask <= 4)
644                                 p1++;
645                         else
646                                 p2++;
647                 }
648                 data >>= 4;
649         }
650
651         if (mixer)
652                 return p2;
653         else
654                 return p1;
655 }
656
657 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
658 {
659         uint32 data, mask, snum, stage, mixer;
660
661         stage = pipe->mixer_stage;
662         mixer = pipe->mixer_num;
663
664         /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
665         data = inpdw(MDP_BASE + 0x10100);
666
667         if (mixer == MDP4_MIXER1)
668                 stage += 8;
669
670         if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
671                 snum = 0;
672                 snum += (4 * pipe->pipe_num);
673         } else {
674                 snum = 8;
675                 snum += (4 * pipe->pipe_num);   /* RGB1 and RGB2 */
676         }
677
678         mask = 0x0f;
679         mask <<= snum;
680         stage <<= snum;
681         data &= ~mask;  /* clear old bits */
682
683         data |= stage;
684
685         outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
686
687         data = inpdw(MDP_BASE + 0x10100);
688
689         ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
690 }
691
692 void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
693 {
694         uint32 data, mask, snum, stage, mixer;
695
696         stage = pipe->mixer_stage;
697         mixer = pipe->mixer_num;
698
699         if (pipe != ctrl->stage[mixer][stage])  /* not running */
700                 return;
701
702         /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
703         data = inpdw(MDP_BASE + 0x10100);
704
705         if (mixer == MDP4_MIXER1)
706                 stage += 8;
707
708         if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
709                 snum = 0;
710                 snum += (4 * pipe->pipe_num);
711         } else {
712                 snum = 8;
713                 snum += (4 * pipe->pipe_num);   /* RGB1 and RGB2 */
714         }
715
716         mask = 0x0f;
717         mask <<= snum;
718         data &= ~mask;  /* clear old bits */
719
720         outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
721
722         data = inpdw(MDP_BASE + 0x10100);
723
724         ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
725 }
726
727 void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
728 {
729         unsigned char *overlay_base;
730         uint32 c0, c1, c2, blend_op;
731         int off;
732
733         if (pipe->mixer_num)    /* mixer number, /dev/fb0, /dev/fb1 */
734                 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
735         else
736                 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
737
738         /* stage 0 to stage 2 */
739         off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
740
741         blend_op = 0;
742         if (pipe->alpha_enable)         /* ARGB */
743                 blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
744                                 MDP4_BLEND_BG_ALPHA_FG_PIXEL;
745         else
746                 blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
747                                 MDP4_BLEND_FG_ALPHA_FG_CONST);
748
749
750         if (pipe->alpha_enable == 0) {  /* not ARGB */
751                 if (pipe->is_fg) {
752                         outpdw(overlay_base + off + 0x108, pipe->alpha);
753                         outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
754                 } else {
755                         outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
756                         outpdw(overlay_base + off + 0x10c, pipe->alpha);
757                 }
758         }
759
760         if (pipe->transp != MDP_TRANSP_NOP) {
761                 transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
762                 if (pipe->is_fg) {
763                         blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
764                         /* lower limit */
765                         if (c0 > 0x10)
766                                 c0 -= 0x10;
767                         if (c1 > 0x10)
768                                 c1 -= 0x10;
769                         if (c2 > 0x10)
770                                 c2 -= 0x10;
771                         outpdw(overlay_base + off + 0x110,
772                                                 (c1 << 16 | c0));/* low */
773                         outpdw(overlay_base + off + 0x114, c2);/* low */
774                         /* upper limit */
775                         if ((c0 + 0x20) < 0x0fff)
776                                 c0 += 0x20;
777                         else
778                                 c0 = 0x0fff;
779                         if ((c1 + 0x20) < 0x0fff)
780                                 c1 += 0x20;
781                         else
782                                 c1 = 0x0fff;
783                         if ((c2 + 0x20) < 0x0fff)
784                                 c2 += 0x20;
785                         else
786                                 c2 = 0x0fff;
787                         outpdw(overlay_base + off + 0x118,
788                                         (c1 << 16 | c0));/* high */
789                         outpdw(overlay_base + off + 0x11c, c2);/* high */
790                 } else {
791                         blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
792                         /* lower limit */
793                         if (c0 > 0x10)
794                                 c0 -= 0x10;
795                         if (c1 > 0x10)
796                                 c1 -= 0x10;
797                         if (c2 > 0x10)
798                                 c2 -= 0x10;
799                         outpdw(overlay_base + 0x180,
800                                                 (c1 << 16 | c0));/* low */
801                         outpdw(overlay_base + 0x184, c2);/* low */
802                         /* upper limit */
803                         if ((c0 + 0x20) < 0x0fff)
804                                 c0 += 0x20;
805                         else
806                                 c0 = 0x0fff;
807                         if ((c1 + 0x20) < 0x0fff)
808                                 c1 += 0x20;
809                         else
810                                 c1 = 0x0fff;
811                         if ((c2 + 0x20) < 0x0fff)
812                                 c2 += 0x20;
813                         else
814                                 c2 = 0x0fff;
815                         outpdw(overlay_base + 0x188,
816                                                 (c1 << 16 | c0));/* high */
817                         outpdw(overlay_base + 0x18c, c2);/* high */
818                 }
819         }
820         outpdw(overlay_base + off + 0x104, blend_op);
821 }
822
823 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
824 {
825         uint32 bits = 0;
826
827         if (pipe->mixer_num == MDP4_MIXER1)
828                 bits |= 0x02;
829         else
830                 bits |= 0x01;
831
832         if (all) {
833                 if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
834                         if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
835                                 bits |= 0x20;
836                         else
837                                 bits |= 0x10;
838                 } else {
839                         if (pipe->pipe_num == OVERLAY_PIPE_VG2)
840                                 bits |= 0x08;
841                         else
842                                 bits |= 0x04;
843                 }
844         }
845
846         outpdw(MDP_BASE + 0x18000, bits);       /* MDP_OVERLAY_REG_FLUSH */
847
848         while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
849                 ;
850 }
851
852 struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
853 {
854         struct mdp4_overlay_pipe *pipe;
855
856         if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
857                 return NULL;
858
859         pipe = &ctrl->plist[ndx - 1];   /* ndx start from 1 */
860
861         if (pipe->pipe_ndx == 0)
862                 return NULL;
863
864         return pipe;
865 }
866
867 struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
868 {
869         int i;
870         struct mdp4_overlay_pipe *pipe;
871
872         pipe = &ctrl->plist[0];
873         for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
874                 if (pipe->pipe_ndx == 0) {
875                         pipe->pipe_ndx = i + 1; /* start from 1 */
876                         init_completion(&pipe->comp);
877         printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%p ndx=%d\n",
878                                         pipe, pipe->pipe_ndx);
879                         return pipe;
880                 }
881                 pipe++;
882         }
883
884         return NULL;
885 }
886
887
888 void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
889 {
890         printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%p ndx=%d\n",
891                                         pipe, pipe->pipe_ndx);
892         memset(pipe, 0, sizeof(*pipe));
893 }
894
895 static int get_pipe_num(int ptype, int stage)
896 {
897         if (ptype == OVERLAY_TYPE_RGB) {
898                 if (stage == MDP4_MIXER_STAGE_BASE)
899                         return OVERLAY_PIPE_RGB1;
900                 else
901                         return OVERLAY_PIPE_RGB2;
902         } else {
903                 if (stage == MDP4_MIXER_STAGE0)
904                         return OVERLAY_PIPE_VG1;
905                 else
906                         return OVERLAY_PIPE_VG2;
907         }
908 }
909
910 int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
911 {
912         struct mdp4_overlay_pipe *pipe;
913
914         pipe = ctrl->stage[mixer][z_order];
915
916         if (pipe == NULL)
917                 return 0;
918
919         if (pipe->pipe_ndx == id)       /* same req, recycle */
920                 return 0;
921
922         return -EPERM;
923 }
924
925 static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
926                         struct mdp4_overlay_pipe **ppipe)
927 {
928         struct mdp4_overlay_pipe *pipe;
929         int ret, ptype;
930
931         if (mixer >= MDP4_MAX_MIXER) {
932                 printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
933                 return -ERANGE;
934         }
935
936         if (req->z_order < 0 || req->z_order > 2) {
937                 printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
938                                 req->z_order);
939                 return -ERANGE;
940         }
941
942         if (req->src_rect.h == 0 || req->src_rect.w == 0) {
943                 printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
944                 return -EINVAL;
945         }
946
947         ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
948         if (ret < 0)
949                 return ret;
950
951         ptype = mdp4_overlay_format2type(req->src.format);
952         if (ptype < 0)
953                 return ptype;
954
955         if (req->id == MSMFB_NEW_REQUEST)  /* new request */
956                 pipe = mdp4_overlay_pipe_alloc();
957         else
958                 pipe = mdp4_overlay_ndx2pipe(req->id);
959
960         if (pipe == NULL)
961                 return -ENOMEM;
962
963         pipe->src_format = req->src.format;
964         ret = mdp4_overlay_format2pipe(pipe);
965
966         if (ret < 0)
967                 return ret;
968
969         /*
970          * base layer == 1, reserved for frame buffer
971          * zorder 0 == stage 0 == 2
972          * zorder 1 == stage 1 == 3
973          * zorder 2 == stage 2 == 4
974          */
975         if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
976                 pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
977                 pipe->pipe_type = ptype;
978                 pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
979                 printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
980                                 req->z_order, pipe->pipe_num);
981         }
982
983         pipe->src_width = req->src.width & 0x07ff;      /* source img width */
984         pipe->src_height = req->src.height & 0x07ff;    /* source img height */
985         pipe->src_h = req->src_rect.h & 0x07ff;
986         pipe->src_w = req->src_rect.w & 0x07ff;
987         pipe->src_y = req->src_rect.y & 0x07ff;
988         pipe->src_x = req->src_rect.x & 0x07ff;
989         pipe->dst_h = req->dst_rect.h & 0x07ff;
990         pipe->dst_w = req->dst_rect.w & 0x07ff;
991         pipe->dst_y = req->dst_rect.y & 0x07ff;
992         pipe->dst_x = req->dst_rect.x & 0x07ff;
993
994         if (req->flags & MDP_FLIP_LR)
995                 pipe->op_mode |= MDP4_OP_FLIP_LR;
996
997         if (req->flags & MDP_FLIP_UD)
998                 pipe->op_mode |= MDP4_OP_FLIP_UD;
999
1000         if (req->flags & MDP_DITHER)
1001                 pipe->op_mode |= MDP4_OP_DITHER_EN;
1002
1003         if (req->flags & MDP_DEINTERLACE)
1004                 pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
1005
1006         pipe->is_fg = req->is_fg;/* control alpha and color key */
1007
1008         pipe->alpha = req->alpha & 0x0ff;
1009
1010         pipe->transp = req->transp_mask;
1011
1012         *ppipe = pipe;
1013
1014         return 0;
1015 }
1016
1017 int get_img(struct msmfb_data *img, struct fb_info *info,
1018         unsigned long *start, unsigned long *len, struct file **pp_file)
1019 {
1020         int put_needed, ret = 0;
1021         struct file *file;
1022 #ifdef CONFIG_ANDROID_PMEM
1023         unsigned long vstart;
1024 #endif
1025
1026 #ifdef CONFIG_ANDROID_PMEM
1027         if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1028                 return 0;
1029 #endif
1030         file = fget_light(img->memory_id, &put_needed);
1031         if (file == NULL)
1032                 return -1;
1033
1034         if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1035                 *start = info->fix.smem_start;
1036                 *len = info->fix.smem_len;
1037                 *pp_file = file;
1038         } else {
1039                 ret = -1;
1040                 fput_light(file, put_needed);
1041         }
1042         return ret;
1043 }
1044 int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
1045 {
1046         struct mdp4_overlay_pipe *pipe;
1047
1048         pipe = mdp4_overlay_ndx2pipe(req->id);
1049         if (pipe == NULL)
1050                 return -ENODEV;
1051
1052         *req = pipe->req_data;
1053
1054         return 0;
1055 }
1056
1057 int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
1058 {
1059         struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1060         int ret, mixer;
1061         struct mdp4_overlay_pipe *pipe;
1062         int lcdc;
1063
1064         if (mfd == NULL)
1065                 return -ENODEV;
1066
1067         if (req->src.format == MDP_FB_FORMAT)
1068                 req->src.format = mfd->fb_imgType;
1069
1070         if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1071                 return -EINTR;
1072
1073         mixer = info->node; /* minor number of char device */
1074
1075         ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
1076         if (ret < 0) {
1077                 mutex_unlock(&mfd->dma->ov_mutex);
1078                 return ret;
1079         }
1080
1081         lcdc = inpdw(MDP_BASE + 0xc0000);
1082
1083         if (lcdc == 0) { /* mddi */
1084                 /* MDP cmd block enable */
1085                 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1086         }
1087
1088         /* return id back to user */
1089         req->id = pipe->pipe_ndx;       /* pipe_ndx start from 1 */
1090         pipe->req_data = *req;          /* keep original req */
1091
1092         mutex_unlock(&mfd->dma->ov_mutex);
1093
1094         return 0;
1095 }
1096
1097 int mdp4_overlay_unset(struct fb_info *info, int ndx)
1098 {
1099         struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1100         struct mdp4_overlay_pipe *pipe;
1101         int lcdc;
1102
1103         if (mfd == NULL)
1104                 return -ENODEV;
1105
1106         if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1107                 return -EINTR;
1108
1109         pipe = mdp4_overlay_ndx2pipe(ndx);
1110
1111         if (pipe == NULL) {
1112                 mutex_unlock(&mfd->dma->ov_mutex);
1113                 return -ENODEV;
1114         }
1115
1116         lcdc = inpdw(MDP_BASE + 0xc0000);
1117
1118         mdp4_mixer_stage_down(pipe);
1119
1120         if (lcdc == 0) { /* mddi */
1121                 /* MDP cmd block disable */
1122                 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1123         }
1124
1125         if (lcdc) /* LCDC mode */
1126                 mdp4_overlay_reg_flush(pipe, 0);
1127
1128         mdp4_overlay_pipe_free(pipe);
1129
1130         if (lcdc == 0) { /* mddi */
1131                 mdp4_mddi_overlay_restore();
1132         }
1133
1134         mutex_unlock(&mfd->dma->ov_mutex);
1135
1136         return 0;
1137 }
1138
1139 struct tile_desc {
1140         uint32 width;  /* tile's width */
1141         uint32 height; /* tile's height */
1142         uint32 row_tile_w; /* tiles per row's width */
1143         uint32 row_tile_h; /* tiles per row's height */
1144 };
1145
1146 void tile_samsung(struct tile_desc *tp)
1147 {
1148         /*
1149          * each row of samsung tile consists of two tiles in height
1150          * and two tiles in width which means width should align to
1151          * 64 x 2 bytes and height should align to 32 x 2 bytes.
1152          * video decoder generate two tiles in width and one tile
1153          * in height which ends up height align to 32 X 1 bytes.
1154          */
1155         tp->width = 64;         /* 64 bytes */
1156         tp->row_tile_w = 2;     /* 2 tiles per row's width */
1157         tp->height = 32;        /* 32 bytes */
1158         tp->row_tile_h = 1;     /* 1 tiles per row's height */
1159 }
1160
1161 uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
1162 {
1163         uint32 tile_w, tile_h;
1164         uint32 row_num_w, row_num_h;
1165
1166
1167         tile_w = tp->width * tp->row_tile_w;
1168         tile_h = tp->height * tp->row_tile_h;
1169
1170         row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
1171         row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
1172
1173         return row_num_w * row_num_h * tile_w * tile_h;
1174 }
1175
1176 int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
1177                 struct file **pp_src_file)
1178 {
1179         struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1180         struct msmfb_data *img;
1181         struct mdp4_overlay_pipe *pipe;
1182         ulong start, addr;
1183         ulong len = 0;
1184         struct file *p_src_file = 0;
1185         int lcdc;
1186
1187         if (mfd == NULL)
1188                 return -ENODEV;
1189
1190         pipe = mdp4_overlay_ndx2pipe(req->id);
1191         if (pipe == NULL)
1192                 return -ENODEV;
1193
1194         if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1195                 return -EINTR;
1196
1197         img = &req->data;
1198         get_img(img, info, &start, &len, &p_src_file);
1199         if (len == 0) {
1200                 mutex_unlock(&mfd->dma->ov_mutex);
1201                 printk(KERN_ERR "mdp_overlay_play: could not retrieve"
1202                                        " image from memory\n");
1203                 return -1;
1204         }
1205         *pp_src_file = p_src_file;
1206
1207         addr = start + img->offset;
1208         pipe->srcp0_addr = addr;
1209         pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
1210
1211         if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
1212                 if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
1213                         struct tile_desc tile;
1214
1215                         tile_samsung(&tile);
1216                         pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
1217                 } else
1218                         pipe->srcp1_addr = addr +
1219                                         pipe->src_width * pipe->src_height;
1220
1221                 pipe->srcp0_ystride = pipe->src_width;
1222                 pipe->srcp1_ystride = pipe->src_width;
1223         }
1224
1225         lcdc = inpdw(MDP_BASE + 0xc0000);
1226         lcdc &= 0x01; /* LCDC mode */
1227
1228         if (pipe->pipe_type == OVERLAY_TYPE_VG)
1229                 mdp4_overlay_vg_setup(pipe);    /* video/graphic pipe */
1230         else
1231                 mdp4_overlay_rgb_setup(pipe);   /* rgb pipe */
1232
1233         mdp4_mixer_blend_setup(pipe);
1234         mdp4_mixer_stage_up(pipe);
1235
1236         if (lcdc) { /* LCDC mode */
1237                 mdp4_overlay_reg_flush(pipe, 1);
1238         }
1239
1240         if (lcdc) { /* LCDC mode */
1241                 if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
1242                         mutex_unlock(&mfd->dma->ov_mutex);
1243                         return 0;
1244                 }
1245         }
1246
1247         if (lcdc == 0) { /* MDDI mode */
1248 #ifdef MDP4_NONBLOCKING
1249                 if (mfd->panel_power_on)
1250 #else
1251                 if (!mfd->dma->busy && mfd->panel_power_on)
1252 #endif
1253                         mdp4_mddi_overlay_kickoff(mfd, pipe);
1254         }
1255
1256         mutex_unlock(&mfd->dma->ov_mutex);
1257
1258         return 0;
1259 }