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
mdp4_overlay_dmap_cfg(struct msm_fb_data_type * mfd,int lcdc)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
mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe * pipe)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
mdp4_leading_0(uint32 num)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
mdp4_scale_phase_step(int f_num,uint32 src,uint32 dst)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
mdp4_scale_setup(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_vg_setup(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_format2type(uint32 format)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
mdp4_overlay_format2pipe(struct mdp4_overlay_pipe * pipe)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 */
color_key_convert(int start,int num,uint32 color)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
transp_color_key(int format,uint32 transp,uint32 * c0,uint32 * c1,uint32 * c2)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
mdp4_overlay_format(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe * pipe)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
mdp4_overlayproc_cfg(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_active(int mixer)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
mdp4_mixer_stage_up(struct mdp4_overlay_pipe * pipe)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
mdp4_mixer_stage_down(struct mdp4_overlay_pipe * pipe)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
mdp4_mixer_blend_setup(struct mdp4_overlay_pipe * pipe)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
mdp4_overlay_reg_flush(struct mdp4_overlay_pipe * pipe,int all)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
mdp4_overlay_ndx2pipe(int ndx)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
mdp4_overlay_pipe_alloc(void)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
mdp4_overlay_pipe_free(struct mdp4_overlay_pipe * pipe)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
get_pipe_num(int ptype,int stage)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
mdp4_overlay_req_check(uint32 id,uint32 z_order,uint32 mixer)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
mdp4_overlay_req2pipe(struct mdp_overlay * req,int mixer,struct mdp4_overlay_pipe ** ppipe)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
get_img(struct msmfb_data * img,struct fb_info * info,unsigned long * start,unsigned long * len,struct file ** pp_file)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 }
mdp4_overlay_get(struct fb_info * info,struct mdp_overlay * req)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
mdp4_overlay_set(struct fb_info * info,struct mdp_overlay * req)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
mdp4_overlay_unset(struct fb_info * info,int ndx)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
tile_samsung(struct tile_desc * tp)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
tile_mem_size(struct mdp4_overlay_pipe * pipe,struct tile_desc * tp)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
mdp4_overlay_play(struct fb_info * info,struct msmfb_overlay_data * req,struct file ** pp_src_file)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 }
1260