blob: c5bac33282cfa234c53b81326caff1c316e47d3c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2011, 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 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/time.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/spinlock.h>
21#include <linux/hrtimer.h>
22#include <linux/clk.h>
23#include <mach/hardware.h>
24#include <linux/io.h>
25#include <linux/debugfs.h>
26#include <linux/fb.h>
27#include <linux/msm_mdp.h>
28#include <linux/file.h>
29#include <linux/android_pmem.h>
30#include <linux/major.h>
31#include <asm/system.h>
32#include <asm/mach-types.h>
33#include <linux/semaphore.h>
34#include <linux/uaccess.h>
35#include <linux/mutex.h>
36#include <linux/msm_kgsl.h>
37#include "mdp.h"
38#include "msm_fb.h"
39#include "mdp4.h"
40
41#define VERSION_KEY_MASK 0xFFFFFF00
42
43struct mdp4_overlay_ctrl {
44 struct mdp4_pipe_desc ov_pipe[OVERLAY_PIPE_MAX];/* 4 */
45 struct mdp4_overlay_pipe plist[MDP4_MAX_PIPE]; /* 4 + 2 */
kuogee hsieh405dc302011-07-21 15:06:59 -070046 struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MIXER_STAGE_MAX];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047 uint32 panel_3d;
48 uint32 panel_mode;
49 uint32 mixer0_played;
50 uint32 mixer1_played;
51} mdp4_overlay_db = {
52 .ov_pipe = {
53 {
54 .share = 0, /* RGB 1 */
55 },
56 {
57 .share = 0, /* RGB 2 */
58 },
59 {
60 .share = 1, /* VG 1 */
61 },
62 {
63 .share = 1, /* VG 2 */
64 },
65 },
66 .plist = {
67 {
68 .pipe_type = OVERLAY_TYPE_RGB,
69 .pipe_num = OVERLAY_PIPE_RGB1,
70 .pipe_ndx = 1,
71 },
72 {
73 .pipe_type = OVERLAY_TYPE_RGB,
74 .pipe_num = OVERLAY_PIPE_RGB2,
75 .pipe_ndx = 2,
76 },
77 {
78 .pipe_type = OVERLAY_TYPE_RGB, /* shared */
79 .pipe_num = OVERLAY_PIPE_VG1,
80 .pipe_ndx = 3,
81 },
82 {
83 .pipe_type = OVERLAY_TYPE_RGB, /* shared */
84 .pipe_num = OVERLAY_PIPE_VG2,
85 .pipe_ndx = 4,
86 },
87 {
88 .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
89 .pipe_num = OVERLAY_PIPE_VG1,
90 .pipe_ndx = 5,
91 },
92 {
93 .pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
94 .pipe_num = OVERLAY_PIPE_VG2,
95 .pipe_ndx = 6,
96 },
97 },
98};
99
100static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -0700101static uint32 new_perf_level;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102static uint32 mdp4_del_res_rel;
103/* static array with index 0 for unset status and 1 for set status */
104static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
105
106void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val)
107{
108 overlay_status[type] = val;
109}
110
111bool mdp4_overlay_status_read(enum mdp4_overlay_status type)
112{
113 return overlay_status[type];
114}
115
116int mdp4_overlay_mixer_play(int mixer_num)
117{
118 if (mixer_num == MDP4_MIXER1)
119 return ctrl->mixer1_played;
120 else
121 return ctrl->mixer0_played;
122}
123
124void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d)
125{
126 ctrl->panel_3d = panel_3d;
127}
128
129void mdp4_overlay_panel_mode(int mixer_num, uint32 mode)
130{
131 ctrl->panel_mode |= mode;
132}
133
134uint32 mdp4_overlay_panel_list(void)
135{
136 return ctrl->panel_mode;
137}
138
139void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv)
140{
141 uint32 dmae_cfg_reg;
142
143 if (atv)
144 dmae_cfg_reg = DMA_DEFLKR_EN;
145 else
146 dmae_cfg_reg = 0;
147
148 if (mfd->fb_imgType == MDP_BGR_565)
149 dmae_cfg_reg |= DMA_PACK_PATTERN_BGR;
150 else
151 dmae_cfg_reg |= DMA_PACK_PATTERN_RGB;
152
153
154 if (mfd->panel_info.bpp == 18) {
155 dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
156 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
157 } else if (mfd->panel_info.bpp == 16) {
158 dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
159 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
160 } else {
161 dmae_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
162 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
163 }
164
165 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
166
167 /* dma2 config register */
168 MDP_OUTP(MDP_BASE + 0xb0000, dmae_cfg_reg);
169 if (atv) {
170 MDP_OUTP(MDP_BASE + 0xb0070, 0xeb0010);
171 MDP_OUTP(MDP_BASE + 0xb0074, 0xf00010);
172 MDP_OUTP(MDP_BASE + 0xb0078, 0xf00010);
173 MDP_OUTP(MDP_BASE + 0xb3000, 0x80);
174 MDP_OUTP(MDP_BASE + 0xb3010, 0x1800040);
175 MDP_OUTP(MDP_BASE + 0xb3014, 0x1000080);
176 MDP_OUTP(MDP_BASE + 0xb4004, 0x67686970);
177 } else {
178 MDP_OUTP(MDP_BASE + 0xb0070, 0xff0000);
179 MDP_OUTP(MDP_BASE + 0xb0074, 0xff0000);
180 MDP_OUTP(MDP_BASE + 0xb0078, 0xff0000);
181 }
182
183 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
184}
185
186void unfill_black_screen(void)
187{
188 uint32 temp_src_format;
189
190 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
191 /*
192 * VG2 Constant Color
193 */
194 temp_src_format = inpdw(MDP_BASE + 0x30050);
195 MDP_OUTP(MDP_BASE + 0x30050, temp_src_format&(~BIT(22)));
196 /*
197 * MDP_OVERLAY_REG_FLUSH
198 */
199 MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
200 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
201}
202
203void fill_black_screen(void)
204{
205 /*Black color*/
206 uint32 color = 0x00000000;
207 uint32 temp_src_format;
208 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
209 /*
210 * VG2 Constant Color
211 */
212 MDP_OUTP(MDP_BASE + 0x31008, color);
213 /*
214 * MDP_VG2_SRC_FORMAT
215 */
216 temp_src_format = inpdw(MDP_BASE + 0x30050);
217 MDP_OUTP(MDP_BASE + 0x30050, temp_src_format | BIT(22));
218 /*
219 * MDP_OVERLAY_REG_FLUSH
220 */
221 MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
222 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
223}
224
225void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
226{
227
228 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
229
230 /* dma_p source */
231 MDP_OUTP(MDP_BASE + 0xb0004,
232 (pipe->src_height << 16 | pipe->src_width));
233 MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
234 MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
235
236 /* dma_p dest */
237 MDP_OUTP(MDP_BASE + 0xb0010, (pipe->dst_y << 16 | pipe->dst_x));
238
239 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
240}
241
242void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
243{
244 uint32 dma2_cfg_reg;
245
246 dma2_cfg_reg = DMA_DITHER_EN;
247#ifdef BLT_RGB565
248 /* RGB888 is 0 */
249 dma2_cfg_reg |= DMA_BUF_FORMAT_RGB565; /* blt only */
250#endif
251
252 if (mfd->fb_imgType == MDP_BGR_565)
253 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
254 else
255 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
256
257
258 if (mfd->panel_info.bpp == 18) {
259 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
260 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
261 } else if (mfd->panel_info.bpp == 16) {
262 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
263 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
264 } else {
265 dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
266 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
267 }
268
269 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
270
271#ifndef CONFIG_FB_MSM_LCDC_CHIMEI_WXGA_PANEL
272 if (lcdc)
273 dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
274#endif
275
276 /* dma2 config register */
277 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
278
279 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
280}
281
282/*
283 * mdp4_overlay_dmap_xy: called form baselayer only
284 */
285void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
286{
287 uint32 off, bpp;
288
289 if (mdp_is_in_isr == FALSE)
290 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
291
292 /* dma_p source */
293 MDP_OUTP(MDP_BASE + 0x90004,
294 (pipe->src_height << 16 | pipe->src_width));
295 if (pipe->blt_addr) {
296#ifdef BLT_RGB565
297 bpp = 2; /* overlay ouput is RGB565 */
298#else
299 bpp = 3; /* overlay ouput is RGB888 */
300#endif
301 off = 0;
302 if (pipe->dmap_cnt & 0x01)
303 off = pipe->src_height * pipe->src_width * bpp;
304 MDP_OUTP(MDP_BASE + 0x90008, pipe->blt_addr + off);
305 /* RGB888, output of overlay blending */
306 MDP_OUTP(MDP_BASE + 0x9000c, pipe->src_width * bpp);
307 } else {
308 MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
309 MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
310 }
311
312 /* dma_p dest */
313 MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
314
315 if (mdp_is_in_isr == FALSE)
316 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
317}
318
319#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
320#define MDP4_VG_PHASE_STEP_SHIFT 29
321
322static int mdp4_leading_0(uint32 num)
323{
324 uint32 bit = 0x80000000;
325 int i;
326
327 for (i = 0; i < 32; i++) {
328 if (bit & num)
329 return i;
330 bit >>= 1;
331 }
332
333 return i;
334}
335
336static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
337{
338 uint32 val;
339 int n;
340
341 n = mdp4_leading_0(src);
342 if (n > f_num)
343 n = f_num;
344 val = src << n; /* maximum to reduce lose of resolution */
345 val /= dst;
346 if (n < f_num) {
347 n = f_num - n;
348 val <<= n;
349 }
350
351 return val;
352}
353
354static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
355{
356 int ptype;
357
358 pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
359 pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
360 ptype = mdp4_overlay_format2type(pipe->src_format);
361
362 if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
363 if (pipe->dst_h > pipe->src_h * 8) /* too much */
364 return;
365 pipe->op_mode |= MDP4_OP_SCALEY_EN;
366
367 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
368 if (pipe->dst_h <= (pipe->src_h / 4))
369 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
370 else
371 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
372 }
373
374 pipe->phasey_step = mdp4_scale_phase_step(29,
375 pipe->src_h, pipe->dst_h);
376 }
377
378 if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
379 if (pipe->dst_w > pipe->src_w * 8) /* too much */
380 return;
381 pipe->op_mode |= MDP4_OP_SCALEX_EN;
382
383 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
384 if (pipe->dst_w <= (pipe->src_w / 4))
385 pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
386 else
387 pipe->op_mode |= MDP4_OP_SCALEX_FIR;
388 }
389
390 pipe->phasex_step = mdp4_scale_phase_step(29,
391 pipe->src_w, pipe->dst_w);
392 }
393}
394
395void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
396{
397 char *rgb_base;
398 uint32 src_size, src_xy, dst_size, dst_xy;
399 uint32 format, pattern;
400
401 rgb_base = MDP_BASE + MDP4_RGB_BASE;
402 rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
403
404 src_size = ((pipe->src_h << 16) | pipe->src_w);
405 src_xy = ((pipe->src_y << 16) | pipe->src_x);
406 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
407 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
408
409 format = mdp4_overlay_format(pipe);
410 pattern = mdp4_overlay_unpack_pattern(pipe);
411
412#ifdef MDP4_IGC_LUT_ENABLE
413 pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
414#endif
415
416 mdp4_scale_setup(pipe);
417
418 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
419
420 outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
421 outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
422 outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
423 outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
424
425 outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
426 outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
427
428 outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
429 outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
430 outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
431 outpdw(rgb_base + 0x005c, pipe->phasex_step);
432 outpdw(rgb_base + 0x0060, pipe->phasey_step);
433
434 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
435
436 mdp4_stat.pipe[pipe->pipe_num]++;
437}
438
439void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
440{
441 char *vg_base;
442 uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
443 uint32 format, pattern;
444 int pnum;
445
446 pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
447 vg_base = MDP_BASE + MDP4_VIDEO_BASE;
448 vg_base += (MDP4_VIDEO_OFF * pnum);
449
450 frame_size = ((pipe->src_height << 16) | pipe->src_width);
451 src_size = ((pipe->src_h << 16) | pipe->src_w);
452 src_xy = ((pipe->src_y << 16) | pipe->src_x);
453 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
454 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
455
456 format = mdp4_overlay_format(pipe);
457 pattern = mdp4_overlay_unpack_pattern(pipe);
458
459 /* not RGB use VG pipe, pure VG pipe */
460 if (pipe->pipe_type != OVERLAY_TYPE_RGB)
461#ifdef MDP4_IGC_LUT_ENABLE
462 pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
463 MDP4_OP_IGC_LUT_EN);
464#else
465 pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR);
466#endif
467
468 mdp4_scale_setup(pipe);
469
470 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
471
472 outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
473 outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
474 outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
475 outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
476 outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
477
478 /* luma component plane */
479 outpdw(vg_base + 0x0010, pipe->srcp0_addr);
480
481 /* chroma component plane or planar color 1 */
482 outpdw(vg_base + 0x0014, pipe->srcp1_addr);
483
484 /* planar color 2 */
485 outpdw(vg_base + 0x0018, pipe->srcp2_addr);
486
487 outpdw(vg_base + 0x0040,
488 pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
489
490 outpdw(vg_base + 0x0044,
491 pipe->srcp3_ystride << 16 | pipe->srcp2_ystride);
492
493 outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */
494 outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */
495 outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
496 outpdw(vg_base + 0x005c, pipe->phasex_step);
497 outpdw(vg_base + 0x0060, pipe->phasey_step);
498
499 if (pipe->op_mode & MDP4_OP_DITHER_EN) {
500 outpdw(vg_base + 0x0068,
501 pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
502 }
503
504 if (pipe->flags & MDP_SHARPENING) {
505 outpdw(vg_base + 0x8200,
506 mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
507 0));
508 outpdw(vg_base + 0x8204,
509 mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
510 1));
511 }
512
513 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
514
515 mdp4_stat.pipe[pipe->pipe_num]++;
516}
517
518int mdp4_overlay_format2type(uint32 format)
519{
520 switch (format) {
521 case MDP_RGB_565:
522 case MDP_RGB_888:
523 case MDP_BGR_565:
524 case MDP_XRGB_8888:
525 case MDP_ARGB_8888:
526 case MDP_RGBA_8888:
527 case MDP_BGRA_8888:
528 case MDP_RGBX_8888:
529 return OVERLAY_TYPE_RGB;
530 case MDP_YCRYCB_H2V1:
531 case MDP_Y_CRCB_H2V1:
532 case MDP_Y_CBCR_H2V1:
533 case MDP_Y_CRCB_H2V2:
534 case MDP_Y_CBCR_H2V2:
535 case MDP_Y_CBCR_H2V2_TILE:
536 case MDP_Y_CRCB_H2V2_TILE:
537 case MDP_Y_CR_CB_H2V2:
538 case MDP_Y_CB_CR_H2V2:
539 case MDP_Y_CRCB_H1V1:
540 case MDP_Y_CBCR_H1V1:
541 return OVERLAY_TYPE_VIDEO;
542 default:
543 mdp4_stat.err_format++;
544 return -ERANGE;
545 }
546
547}
548
549#define C3_ALPHA 3 /* alpha */
550#define C2_R_Cr 2 /* R/Cr */
551#define C1_B_Cb 1 /* B/Cb */
552#define C0_G_Y 0 /* G/luma */
553#define YUV_444_MAX_WIDTH 1280 /* Max width for YUV 444*/
554
555int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
556{
557 switch (pipe->src_format) {
558 case MDP_RGB_565:
559 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
560 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
561 pipe->a_bit = 0;
562 pipe->r_bit = 1; /* R, 5 bits */
563 pipe->b_bit = 1; /* B, 5 bits */
564 pipe->g_bit = 2; /* G, 6 bits */
565 pipe->alpha_enable = 0;
566 pipe->unpack_tight = 1;
567 pipe->unpack_align_msb = 0;
568 pipe->unpack_count = 2;
569 pipe->element2 = C2_R_Cr; /* R */
570 pipe->element1 = C0_G_Y; /* G */
571 pipe->element0 = C1_B_Cb; /* B */
572 pipe->bpp = 2; /* 2 bpp */
573 break;
574 case MDP_RGB_888:
575 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
576 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
577 pipe->a_bit = 0;
578 pipe->r_bit = 3; /* R, 8 bits */
579 pipe->b_bit = 3; /* B, 8 bits */
580 pipe->g_bit = 3; /* G, 8 bits */
581 pipe->alpha_enable = 0;
582 pipe->unpack_tight = 1;
583 pipe->unpack_align_msb = 0;
584 pipe->unpack_count = 2;
585 pipe->element2 = C2_R_Cr; /* R */
586 pipe->element1 = C0_G_Y; /* G */
587 pipe->element0 = C1_B_Cb; /* B */
588 pipe->bpp = 3; /* 3 bpp */
589 break;
590 case MDP_BGR_565:
591 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
592 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
593 pipe->a_bit = 0;
594 pipe->r_bit = 1; /* R, 5 bits */
595 pipe->b_bit = 1; /* B, 5 bits */
596 pipe->g_bit = 2; /* G, 6 bits */
597 pipe->alpha_enable = 0;
598 pipe->unpack_tight = 1;
599 pipe->unpack_align_msb = 0;
600 pipe->unpack_count = 2;
601 pipe->element2 = C1_B_Cb; /* B */
602 pipe->element1 = C0_G_Y; /* G */
603 pipe->element0 = C2_R_Cr; /* R */
604 pipe->bpp = 2; /* 2 bpp */
605 break;
606 case MDP_XRGB_8888:
607 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
608 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
609 pipe->a_bit = 3; /* alpha, 4 bits */
610 pipe->r_bit = 3; /* R, 8 bits */
611 pipe->b_bit = 3; /* B, 8 bits */
612 pipe->g_bit = 3; /* G, 8 bits */
613 pipe->alpha_enable = 0;
614 pipe->unpack_tight = 1;
615 pipe->unpack_align_msb = 0;
616 pipe->unpack_count = 3;
617 pipe->element3 = C3_ALPHA; /* alpha */
618 pipe->element2 = C2_R_Cr; /* R */
619 pipe->element1 = C0_G_Y; /* G */
620 pipe->element0 = C1_B_Cb; /* B */
621 pipe->bpp = 4; /* 4 bpp */
622 break;
623 case MDP_ARGB_8888:
624 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
625 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
626 pipe->a_bit = 3; /* alpha, 4 bits */
627 pipe->r_bit = 3; /* R, 8 bits */
628 pipe->b_bit = 3; /* B, 8 bits */
629 pipe->g_bit = 3; /* G, 8 bits */
630 pipe->alpha_enable = 1;
631 pipe->unpack_tight = 1;
632 pipe->unpack_align_msb = 0;
633 pipe->unpack_count = 3;
634 pipe->element3 = C3_ALPHA; /* alpha */
635 pipe->element2 = C2_R_Cr; /* R */
636 pipe->element1 = C0_G_Y; /* G */
637 pipe->element0 = C1_B_Cb; /* B */
638 pipe->bpp = 4; /* 4 bpp */
639 break;
640 case MDP_RGBA_8888:
641 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
642 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
643 pipe->a_bit = 3; /* alpha, 4 bits */
644 pipe->r_bit = 3; /* R, 8 bits */
645 pipe->b_bit = 3; /* B, 8 bits */
646 pipe->g_bit = 3; /* G, 8 bits */
647 pipe->alpha_enable = 1;
648 pipe->unpack_tight = 1;
649 pipe->unpack_align_msb = 0;
650 pipe->unpack_count = 3;
651 pipe->element3 = C3_ALPHA; /* alpha */
652 pipe->element2 = C1_B_Cb; /* B */
653 pipe->element1 = C0_G_Y; /* G */
654 pipe->element0 = C2_R_Cr; /* R */
655 pipe->bpp = 4; /* 4 bpp */
656 break;
657 case MDP_RGBX_8888:
658 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
659 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
660 pipe->a_bit = 3;
661 pipe->r_bit = 3; /* R, 8 bits */
662 pipe->b_bit = 3; /* B, 8 bits */
663 pipe->g_bit = 3; /* G, 8 bits */
664 pipe->alpha_enable = 0;
665 pipe->unpack_tight = 1;
666 pipe->unpack_align_msb = 0;
667 pipe->unpack_count = 3;
668 pipe->element3 = C3_ALPHA; /* alpha */
669 pipe->element2 = C1_B_Cb; /* B */
670 pipe->element1 = C0_G_Y; /* G */
671 pipe->element0 = C2_R_Cr; /* R */
672 pipe->bpp = 4; /* 4 bpp */
673 break;
674 case MDP_BGRA_8888:
675 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
676 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
677 pipe->a_bit = 3; /* alpha, 4 bits */
678 pipe->r_bit = 3; /* R, 8 bits */
679 pipe->b_bit = 3; /* B, 8 bits */
680 pipe->g_bit = 3; /* G, 8 bits */
681 pipe->alpha_enable = 1;
682 pipe->unpack_tight = 1;
683 pipe->unpack_align_msb = 0;
684 pipe->unpack_count = 3;
685 pipe->element3 = C3_ALPHA; /* alpha */
686 pipe->element2 = C2_R_Cr; /* R */
687 pipe->element1 = C0_G_Y; /* G */
688 pipe->element0 = C1_B_Cb; /* B */
689 pipe->bpp = 4; /* 4 bpp */
690 break;
691 case MDP_YCRYCB_H2V1:
692 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
693 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
694 pipe->a_bit = 0; /* alpha, 4 bits */
695 pipe->r_bit = 3; /* R, 8 bits */
696 pipe->b_bit = 3; /* B, 8 bits */
697 pipe->g_bit = 3; /* G, 8 bits */
698 pipe->alpha_enable = 0;
699 pipe->unpack_tight = 1;
700 pipe->unpack_align_msb = 0;
701 pipe->unpack_count = 3;
702 pipe->element3 = C0_G_Y; /* G */
703 pipe->element2 = C2_R_Cr; /* R */
704 pipe->element1 = C0_G_Y; /* G */
705 pipe->element0 = C1_B_Cb; /* B */
706 pipe->bpp = 2; /* 2 bpp */
707 pipe->chroma_sample = MDP4_CHROMA_H2V1;
708 break;
709 case MDP_Y_CRCB_H2V1:
710 case MDP_Y_CBCR_H2V1:
711 case MDP_Y_CRCB_H2V2:
712 case MDP_Y_CBCR_H2V2:
713 case MDP_Y_CRCB_H1V1:
714 case MDP_Y_CBCR_H1V1:
715 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
716 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
717 pipe->a_bit = 0;
718 pipe->r_bit = 3; /* R, 8 bits */
719 pipe->b_bit = 3; /* B, 8 bits */
720 pipe->g_bit = 3; /* G, 8 bits */
721 pipe->alpha_enable = 0;
722 pipe->unpack_tight = 1;
723 pipe->unpack_align_msb = 0;
724 pipe->unpack_count = 1; /* 2 */
725 pipe->element3 = C0_G_Y; /* not used */
726 pipe->element2 = C0_G_Y; /* not used */
727 if (pipe->src_format == MDP_Y_CRCB_H2V1) {
728 pipe->element1 = C2_R_Cr; /* R */
729 pipe->element0 = C1_B_Cb; /* B */
730 pipe->chroma_sample = MDP4_CHROMA_H2V1;
731 } else if (pipe->src_format == MDP_Y_CRCB_H1V1) {
732 pipe->element1 = C2_R_Cr; /* R */
733 pipe->element0 = C1_B_Cb; /* B */
734 if (pipe->src_width > YUV_444_MAX_WIDTH)
735 pipe->chroma_sample = MDP4_CHROMA_H1V2;
736 else
737 pipe->chroma_sample = MDP4_CHROMA_RGB;
738 } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
739 pipe->element1 = C1_B_Cb; /* B */
740 pipe->element0 = C2_R_Cr; /* R */
741 pipe->chroma_sample = MDP4_CHROMA_H2V1;
742 } else if (pipe->src_format == MDP_Y_CBCR_H1V1) {
743 pipe->element1 = C1_B_Cb; /* B */
744 pipe->element0 = C2_R_Cr; /* R */
745 if (pipe->src_width > YUV_444_MAX_WIDTH)
746 pipe->chroma_sample = MDP4_CHROMA_H1V2;
747 else
748 pipe->chroma_sample = MDP4_CHROMA_RGB;
749 } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
750 pipe->element1 = C2_R_Cr; /* R */
751 pipe->element0 = C1_B_Cb; /* B */
752 pipe->chroma_sample = MDP4_CHROMA_420;
753 } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
754 pipe->element1 = C1_B_Cb; /* B */
755 pipe->element0 = C2_R_Cr; /* R */
756 pipe->chroma_sample = MDP4_CHROMA_420;
757 }
758 pipe->bpp = 2; /* 2 bpp */
759 break;
760 case MDP_Y_CBCR_H2V2_TILE:
761 case MDP_Y_CRCB_H2V2_TILE:
762 pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
763 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
764 pipe->a_bit = 0;
765 pipe->r_bit = 3; /* R, 8 bits */
766 pipe->b_bit = 3; /* B, 8 bits */
767 pipe->g_bit = 3; /* G, 8 bits */
768 pipe->alpha_enable = 0;
769 pipe->unpack_tight = 1;
770 pipe->unpack_align_msb = 0;
771 pipe->unpack_count = 1; /* 2 */
772 pipe->element3 = C0_G_Y; /* not used */
773 pipe->element2 = C0_G_Y; /* not used */
774 if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
775 pipe->element1 = C2_R_Cr; /* R */
776 pipe->element0 = C1_B_Cb; /* B */
777 pipe->chroma_sample = MDP4_CHROMA_420;
778 } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
779 pipe->element1 = C1_B_Cb; /* B */
780 pipe->element0 = C2_R_Cr; /* R */
781 pipe->chroma_sample = MDP4_CHROMA_420;
782 }
783 pipe->bpp = 2; /* 2 bpp */
784 break;
785 case MDP_Y_CR_CB_H2V2:
786 case MDP_Y_CB_CR_H2V2:
787 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
788 pipe->fetch_plane = OVERLAY_PLANE_PLANAR;
789 pipe->a_bit = 0;
790 pipe->r_bit = 3; /* R, 8 bits */
791 pipe->b_bit = 3; /* B, 8 bits */
792 pipe->g_bit = 3; /* G, 8 bits */
793 pipe->alpha_enable = 0;
794 pipe->unpack_tight = 1;
795 pipe->unpack_align_msb = 0;
796 pipe->unpack_count = 1; /* 2 */
797 pipe->element3 = C0_G_Y; /* not used */
798 pipe->element2 = C0_G_Y; /* not used */
799 if (pipe->src_format == MDP_Y_CR_CB_H2V2) {
800 pipe->element1 = C2_R_Cr; /* R */
801 pipe->element0 = C1_B_Cb; /* B */
802 pipe->chroma_sample = MDP4_CHROMA_420;
803 } else if (pipe->src_format == MDP_Y_CB_CR_H2V2) {
804 pipe->element1 = C1_B_Cb; /* B */
805 pipe->element0 = C2_R_Cr; /* R */
806 pipe->chroma_sample = MDP4_CHROMA_420;
807 }
808 pipe->bpp = 2; /* 2 bpp */
809 break;
810 default:
811 /* not likely */
812 mdp4_stat.err_format++;
813 return -ERANGE;
814 }
815
816 return 0;
817}
818
819/*
820 * color_key_convert: output with 12 bits color key
821 */
822static uint32 color_key_convert(int start, int num, uint32 color)
823{
824 uint32 data;
825
826 data = (color >> start) & ((1 << num) - 1);
827
828 /* convert to 8 bits */
829 if (num == 5)
830 data = ((data << 3) | (data >> 2));
831 else if (num == 6)
832 data = ((data << 2) | (data >> 4));
833
834 /* convert 8 bits to 12 bits */
835 data = (data << 4) | (data >> 4);
836
837 return data;
838}
839
840void transp_color_key(int format, uint32 transp,
841 uint32 *c0, uint32 *c1, uint32 *c2)
842{
843 int b_start, g_start, r_start;
844 int b_num, g_num, r_num;
845
846 switch (format) {
847 case MDP_RGB_565:
848 b_start = 0;
849 g_start = 5;
850 r_start = 11;
851 r_num = 5;
852 g_num = 6;
853 b_num = 5;
854 break;
855 case MDP_RGB_888:
856 case MDP_XRGB_8888:
857 case MDP_ARGB_8888:
858 case MDP_BGRA_8888:
859 b_start = 0;
860 g_start = 8;
861 r_start = 16;
862 r_num = 8;
863 g_num = 8;
864 b_num = 8;
865 break;
866 case MDP_RGBA_8888:
867 case MDP_RGBX_8888:
868 b_start = 16;
869 g_start = 8;
870 r_start = 0;
871 r_num = 8;
872 g_num = 8;
873 b_num = 8;
874 break;
875 case MDP_BGR_565:
876 b_start = 11;
877 g_start = 5;
878 r_start = 0;
879 r_num = 5;
880 g_num = 6;
881 b_num = 5;
882 break;
883 case MDP_Y_CB_CR_H2V2:
884 case MDP_Y_CBCR_H2V2:
885 case MDP_Y_CBCR_H2V1:
886 b_start = 8;
887 g_start = 16;
888 r_start = 0;
889 r_num = 8;
890 g_num = 8;
891 b_num = 8;
892 break;
893 case MDP_Y_CR_CB_H2V2:
894 case MDP_Y_CRCB_H2V2:
895 case MDP_Y_CRCB_H2V1:
896 case MDP_Y_CRCB_H1V1:
897 case MDP_Y_CBCR_H1V1:
898 b_start = 0;
899 g_start = 16;
900 r_start = 8;
901 r_num = 8;
902 g_num = 8;
903 b_num = 8;
904 break;
905 default:
906 b_start = 0;
907 g_start = 8;
908 r_start = 16;
909 r_num = 8;
910 g_num = 8;
911 b_num = 8;
912 break;
913 }
914
915 *c0 = color_key_convert(g_start, g_num, transp);
916 *c1 = color_key_convert(b_start, b_num, transp);
917 *c2 = color_key_convert(r_start, r_num, transp);
918}
919
920uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
921{
922 uint32 format;
923
924 format = 0;
925
926 if (pipe->solid_fill)
927 format |= MDP4_FORMAT_SOLID_FILL;
928
929 if (pipe->unpack_align_msb)
930 format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
931
932 if (pipe->unpack_tight)
933 format |= MDP4_FORMAT_UNPACK_TIGHT;
934
935 if (pipe->alpha_enable)
936 format |= MDP4_FORMAT_ALPHA_ENABLE;
937
938 if (pipe->flags & MDP_SOURCE_ROTATED_90)
939 format |= MDP4_FORMAT_90_ROTATED;
940 format |= (pipe->unpack_count << 13);
941 format |= ((pipe->bpp - 1) << 9);
942 format |= (pipe->a_bit << 6);
943 format |= (pipe->r_bit << 4);
944 format |= (pipe->b_bit << 2);
945 format |= pipe->g_bit;
946
947 format |= (pipe->frame_format << 29);
948
949 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR ||
950 pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
951 /* video/graphic */
952 format |= (pipe->fetch_plane << 19);
953 format |= (pipe->chroma_site << 28);
954 format |= (pipe->chroma_sample << 26);
955 }
956
957 return format;
958}
959
960uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
961{
962 return (pipe->element3 << 24) | (pipe->element2 << 16) |
963 (pipe->element1 << 8) | pipe->element0;
964}
965
966/*
967 * mdp4_overlayproc_cfg: only be called from base layer
968 */
969void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
970{
971 uint32 data, intf;
972 char *overlay_base;
973
974 intf = 0;
975 if (pipe->mixer_num == MDP4_MIXER1) {
976 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
977 intf = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
978 intf >>= 4;
979 intf &= 0x03;
980 } else
981 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
982
983 if (mdp_is_in_isr == FALSE)
984 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
985
986 /*
987 * BLT only siupport at primary display
988 */
989 if (pipe->mixer_num == MDP4_MIXER0 && pipe->blt_addr) {
990 int off, bpp;
991#ifdef BLT_RGB565
992 bpp = 2; /* overlay ouput is RGB565 */
993#else
994 bpp = 3; /* overlay ouput is RGB888 */
995#endif
996 data = pipe->src_height;
997 data <<= 16;
998 data |= pipe->src_width;
999 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
1000 if (ctrl->panel_mode & MDP4_PANEL_LCDC ||
1001 ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
1002 outpdw(overlay_base + 0x000c, pipe->blt_addr);
1003 outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
1004 off = pipe->src_height * pipe->src_width * bpp;
1005 outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
1006 /* LCDC - FRAME BUFFER + vsync rate */
1007 outpdw(overlay_base + 0x0004, 0x02);
1008 } else { /* MDDI */
1009 off = 0;
1010 if (pipe->ov_cnt & 0x01)
1011 off = pipe->src_height * pipe->src_width * bpp;
1012
1013 outpdw(overlay_base + 0x000c, pipe->blt_addr + off);
1014 /* overlay ouput is RGB888 */
1015 outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
1016 outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
1017 /* MDDI - BLT + on demand */
1018 outpdw(overlay_base + 0x0004, 0x08);
1019 }
1020#ifdef BLT_RGB565
1021 outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
1022#else
1023 outpdw(overlay_base + 0x0014, 0x0); /* RGB888 */
1024#endif
1025 } else {
1026 data = pipe->src_height;
1027 data <<= 16;
1028 data |= pipe->src_width;
1029 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
1030 outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
1031 outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
1032 outpdw(overlay_base + 0x0004, 0x01); /* directout */
1033 }
1034
1035 if (pipe->mixer_num == MDP4_MIXER1) {
1036 if (intf == TV_INTF) {
1037 outpdw(overlay_base + 0x0014, 0x02); /* yuv422 */
1038 /* overlay1 CSC config */
1039 outpdw(overlay_base + 0x0200, 0x05); /* rgb->yuv */
1040 }
1041 }
1042
1043#ifdef MDP4_IGC_LUT_ENABLE
1044 outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
1045#endif
1046
1047 if (mdp_is_in_isr == FALSE)
1048 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1049}
1050
1051int mdp4_overlay_pipe_staged(int mixer)
1052{
1053 uint32 data, mask, i;
1054 int p1, p2;
1055
1056 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1057 data = inpdw(MDP_BASE + 0x10100);
1058 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1059 p1 = 0;
1060 p2 = 0;
1061 for (i = 0; i < 8; i++) {
1062 mask = data & 0x0f;
1063 if (mask) {
1064 if (mask <= 4)
1065 p1++;
1066 else
1067 p2++;
1068 }
1069 data >>= 4;
1070 }
1071
1072 if (mixer)
1073 return p2;
1074 else
1075 return p1;
1076}
1077
kuogee hsieh405dc302011-07-21 15:06:59 -07001078int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info)
1079{
1080
1081 int ndx, cnt;
1082 struct mdp4_overlay_pipe *pipe;
1083
1084 if (mixer_num > MDP4_MIXER_MAX)
1085 return -ENODEV;
1086
1087 cnt = 0;
1088 ndx = 1; /* ndx 0 if not used */
1089
1090 for ( ; ndx < MDP4_MIXER_STAGE_MAX; ndx++) {
1091 pipe = ctrl->stage[mixer_num][ndx];
1092 if (pipe == NULL)
1093 continue;
1094 info->z_order = pipe->mixer_stage - MDP4_MIXER_STAGE0;
1095 info->ptype = pipe->pipe_type;
1096 info->pnum = pipe->pipe_num;
1097 info->pndx = pipe->pipe_ndx;
1098 info->mixer_num = pipe->mixer_num;
1099 info++;
1100 cnt++;
1101 }
1102 return cnt;
1103}
1104
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
1106{
1107 uint32 data, mask, snum, stage, mixer, pnum;
1108
1109 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1110
1111 stage = pipe->mixer_stage;
1112 mixer = pipe->mixer_num;
1113 pnum = pipe->pipe_num;
1114
1115 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
1116 data = inpdw(MDP_BASE + 0x10100);
1117
1118 if (mixer == MDP4_MIXER1)
1119 stage += 8;
1120
1121 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
1122 pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
1123 snum = 0;
1124 snum += (4 * pnum);
1125 } else {
1126 snum = 8;
1127 snum += (4 * pnum); /* RGB1 and RGB2 */
1128 }
1129
1130 mask = 0x0f;
1131 mask <<= snum;
1132 stage <<= snum;
1133 data &= ~mask; /* clear old bits */
1134
1135 data |= stage;
1136
1137 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
1138
1139 data = inpdw(MDP_BASE + 0x10100);
1140
1141 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1142
1143 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
1144}
1145
1146void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
1147{
1148 uint32 data, mask, snum, stage, mixer, pnum;
1149
1150 stage = pipe->mixer_stage;
1151 mixer = pipe->mixer_num;
1152 pnum = pipe->pipe_num;
1153
1154 if (pipe != ctrl->stage[mixer][stage]) /* not runing */
1155 return;
1156
1157 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1158
1159 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
1160 data = inpdw(MDP_BASE + 0x10100);
1161
1162 if (mixer == MDP4_MIXER1)
1163 stage += 8;
1164
1165 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
1166 pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
1167 snum = 0;
1168 snum += (4 * pnum);
1169 } else {
1170 snum = 8;
1171 snum += (4 * pnum); /* RGB1 and RGB2 */
1172 }
1173
1174 mask = 0x0f;
1175 mask <<= snum;
1176 data &= ~mask; /* clear old bits */
1177
1178 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
1179
1180 data = inpdw(MDP_BASE + 0x10100);
1181
1182 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1183
1184 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
1185}
1186
1187void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
1188{
1189 struct mdp4_overlay_pipe *bg_pipe;
1190 unsigned char *overlay_base, *rgb_base;
1191 uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
1192 int off;
1193
1194 if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
1195 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
1196 else
1197 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
1198
1199 /* stage 0 to stage 2 */
1200 off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
1201
1202 bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
1203 MDP4_MIXER_STAGE_BASE);
1204 if (bg_pipe == NULL) {
1205 pr_err("%s: Error: no bg_pipe\n", __func__);
1206 return;
1207 }
1208
1209 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1210
1211 blend_op = 0;
1212
1213 if (pipe->is_fg) {
1214 blend_op |= (MDP4_BLEND_FG_ALPHA_FG_CONST |
1215 MDP4_BLEND_BG_ALPHA_BG_CONST);
1216 outpdw(overlay_base + off + 0x108, pipe->alpha);
1217 outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
1218 if (pipe->alpha == 0xff) {
1219 rgb_base = MDP_BASE + MDP4_RGB_BASE;
1220 rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
1221 rgb_src_format = inpdw(rgb_base + 0x50);
1222 rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
1223 outpdw(rgb_base + 0x50, rgb_src_format);
1224 outpdw(rgb_base + 0x1008, constant_color);
1225 }
1226 } else {
1227 if (bg_pipe->alpha_enable && pipe->alpha_enable) {
1228 /* both pipe have alpha */
1229 blend_op |= (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
1230 MDP4_BLEND_FG_INV_ALPHA |
1231 MDP4_BLEND_BG_ALPHA_BG_PIXEL);
1232 } else if (bg_pipe->alpha_enable && pipe->alpha_enable == 0) {
1233 /* no alpha on both pipe */
1234 blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
1235 MDP4_BLEND_FG_ALPHA_BG_PIXEL |
1236 MDP4_BLEND_FG_INV_ALPHA);
1237 }
1238 }
1239
1240
1241 if (pipe->transp != MDP_TRANSP_NOP) {
1242 if (pipe->is_fg) {
1243 transp_color_key(pipe->src_format, pipe->transp,
1244 &c0, &c1, &c2);
1245 /* Fg blocked */
1246 blend_op |= MDP4_BLEND_FG_TRANSP_EN;
1247 /* lower limit */
1248 outpdw(overlay_base + off + 0x110,
1249 (c1 << 16 | c0));/* low */
1250 outpdw(overlay_base + off + 0x114, c2);/* low */
1251 /* upper limit */
1252 outpdw(overlay_base + off + 0x118,
1253 (c1 << 16 | c0));
1254 outpdw(overlay_base + off + 0x11c, c2);
1255 } else {
1256 transp_color_key(bg_pipe->src_format,
1257 pipe->transp, &c0, &c1, &c2);
1258 /* bg blocked */
1259 blend_op |= MDP4_BLEND_BG_TRANSP_EN;
1260 /* lower limit */
1261 outpdw(overlay_base + 0x180,
1262 (c1 << 16 | c0));/* low */
1263 outpdw(overlay_base + 0x184, c2);/* low */
1264 /* upper limit */
1265 outpdw(overlay_base + 0x188,
1266 (c1 << 16 | c0));/* high */
1267 outpdw(overlay_base + 0x18c, c2);/* high */
1268 }
1269 }
1270
1271 outpdw(overlay_base + off + 0x104, blend_op);
1272
1273 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1274}
1275
1276void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
1277{
1278 struct mdp4_overlay_pipe *bg_pipe;
1279 uint32 bits = 0;
1280
1281 if (pipe->mixer_num == MDP4_MIXER1)
1282 bits |= 0x02;
1283 else
1284 bits |= 0x01;
1285
1286 if (all) {
1287 if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1288 if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
1289 bits |= 0x20;
1290 else
1291 bits |= 0x10;
1292 } else {
1293 if (pipe->is_fg && pipe->alpha == 0xFF) {
1294 bg_pipe = mdp4_overlay_stage_pipe(
1295 pipe->mixer_num,
1296 MDP4_MIXER_STAGE_BASE);
1297 if (bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1298 if (bg_pipe->pipe_num ==
1299 OVERLAY_PIPE_RGB2)
1300 bits |= 0x20;
1301 else
1302 bits |= 0x10;
1303 }
1304 }
1305 if (pipe->pipe_num == OVERLAY_PIPE_VG2)
1306 bits |= 0x08;
1307 else
1308 bits |= 0x04;
1309 }
1310 }
1311
1312 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1313 outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
1314 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1315}
1316
1317struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
1318{
1319 return ctrl->stage[mixer][stage];
1320}
1321
1322struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
1323{
1324 struct mdp4_overlay_pipe *pipe;
1325
1326 if (ndx <= 0 || ndx > MDP4_MAX_PIPE)
1327 return NULL;
1328
1329 pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
1330
1331 if (pipe->pipe_used == 0)
1332 return NULL;
1333
1334 return pipe;
1335}
1336
1337struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(
1338 int ptype, int mixer, int req_share)
1339{
1340 int i, j, ndx, found;
1341 struct mdp4_overlay_pipe *pipe, *opipe;
1342 struct mdp4_pipe_desc *pd;
1343
1344 found = 0;
1345 pipe = &ctrl->plist[0];
1346
1347 for (i = 0; i < MDP4_MAX_PIPE; i++) {
1348 if (pipe->pipe_type == ptype && pipe->pipe_used == 0) {
1349 pd = &ctrl->ov_pipe[pipe->pipe_num];
1350 if (pd->share) { /* pipe can be shared */
1351 if (pd->ref_cnt == 0) {
1352 /* not yet been used */
1353 found++;
1354 break;
1355 }
1356 /* pipe occupied already */
1357 if (req_share && pd->ref_cnt < MDP4_MAX_SHARE) {
1358 for (j = 0; j < MDP4_MAX_SHARE; j++) {
1359 ndx = pd->ndx_list[j];
1360 if (ndx != 0)
1361 break;
1362 }
1363 /* ndx satrt from 1 */
1364 opipe = &ctrl->plist[ndx - 1];
1365 /*
1366 * occupied pipe willing to share and
1367 * same mixer
1368 */
1369 if (opipe->pipe_share &&
1370 opipe->mixer_num == mixer) {
1371 found++;
1372 break;
1373 }
1374 }
1375 } else { /* not a shared pipe */
1376 if (req_share == 0 && pd->ref_cnt == 0) {
1377 found++;
1378 break;
1379 }
1380 }
1381 }
1382 pipe++;
1383 }
1384
1385 if (found) {
1386 init_completion(&pipe->comp);
1387 init_completion(&pipe->dmas_comp);
1388 pr_info("%s: pipe=%x ndx=%d num=%d share=%d cnt=%d\n",
1389 __func__, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
1390 pd->share, pd->ref_cnt);
1391 return pipe;
1392 }
1393
1394 pr_debug("%s: ptype=%d mixer=%d req_share=%d FAILED\n",
1395 __func__, ptype, mixer, req_share);
1396
1397 return NULL;
1398}
1399
1400
1401void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
1402{
1403 int i;
1404 uint32 ptype, num, ndx;
1405 struct mdp4_pipe_desc *pd;
1406
1407 pr_debug("%s: pipe=%x ndx=%d\n", __func__,
1408 (int)pipe, pipe->pipe_ndx);
1409 pd = &ctrl->ov_pipe[pipe->pipe_num];
1410 if (pd->ref_cnt) {
1411 pd->ref_cnt--;
1412 for (i = 0; i < MDP4_MAX_SHARE; i++) {
1413 if (pd->ndx_list[i] == pipe->pipe_ndx) {
1414 pd->ndx_list[i] = 0;
1415 break;
1416 }
1417 }
1418 }
1419
1420 pd->player = NULL;
1421
1422 ptype = pipe->pipe_type;
1423 num = pipe->pipe_num;
1424 ndx = pipe->pipe_ndx;
1425
1426 memset(pipe, 0, sizeof(*pipe));
1427
1428 pipe->pipe_type = ptype;
1429 pipe->pipe_num = num;
1430 pipe->pipe_ndx = ndx;
1431}
1432
1433int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
1434{
1435 struct mdp4_overlay_pipe *pipe;
1436
1437 pipe = ctrl->stage[mixer][z_order];
1438
1439 if (pipe == NULL)
1440 return 0;
1441
1442 if (pipe->pipe_ndx == id) /* same req, recycle */
1443 return 0;
1444
1445 if (id == MSMFB_NEW_REQUEST) { /* new request */
1446 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) /* share pipe */
1447 return 0;
1448 }
1449
1450 return -EPERM;
1451}
1452
1453static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
1454 struct msm_fb_data_type *mfd, uint32 perf_level, uint32 pclk_rate)
1455{
1456 __u32 panel_clk_khz, mdp_clk_khz;
1457 __u32 num_hsync_pix_clks, mdp_clks_per_hsync, src_wh;
1458 __u32 hsync_period_ps, mdp_period_ps, total_hsync_period_ps;
1459 unsigned long fill_rate_y_dir, fill_rate_x_dir;
1460 unsigned long fillratex100, mdp_pixels_produced;
1461 unsigned long mdp_clk_hz;
1462
1463 pr_debug("%s: LCDC Mode Downscale validation with MDP Core"
1464 " Clk rate\n", __func__);
1465 pr_debug("src_w %u, src_h %u, dst_w %u, dst_h %u\n",
1466 req->src_rect.w, req->src_rect.h, req->dst_rect.w,
1467 req->dst_rect.h);
1468
1469
1470 panel_clk_khz = pclk_rate/1000;
1471 mdp_clk_hz = mdp_perf_level2clk_rate(perf_level);
1472
1473 if (!mdp_clk_hz) {
1474 pr_debug("mdp_perf_level2clk_rate returned 0,"
1475 "Downscale Validation incomplete\n");
1476 return 0;
1477 }
1478
1479 mdp_clk_khz = mdp_clk_hz/1000;
1480
1481 num_hsync_pix_clks = mfd->panel_info.lcdc.h_back_porch +
1482 mfd->panel_info.lcdc.h_front_porch +
1483 mfd->panel_info.lcdc.h_pulse_width +
1484 mfd->panel_info.xres;
1485
1486 hsync_period_ps = 1000000000/panel_clk_khz;
1487 mdp_period_ps = 1000000000/mdp_clk_khz;
1488
1489 total_hsync_period_ps = num_hsync_pix_clks * hsync_period_ps;
1490 mdp_clks_per_hsync = total_hsync_period_ps/mdp_period_ps;
1491
1492 pr_debug("hsync_period_ps %u, mdp_period_ps %u,"
1493 "total_hsync_period_ps %u\n", hsync_period_ps,
1494 mdp_period_ps, total_hsync_period_ps);
1495
1496 src_wh = req->src_rect.w * req->src_rect.h;
1497 if (src_wh % req->dst_rect.h)
1498 fill_rate_y_dir = (src_wh / req->dst_rect.h) + 1;
1499 else
1500 fill_rate_y_dir = (src_wh / req->dst_rect.h);
1501
1502 fill_rate_x_dir = (mfd->panel_info.xres - req->dst_rect.w)
1503 + req->src_rect.w;
1504
1505 if (fill_rate_y_dir >= fill_rate_x_dir)
1506 fillratex100 = 100 * fill_rate_y_dir / mfd->panel_info.xres;
1507 else
1508 fillratex100 = 100 * fill_rate_x_dir / mfd->panel_info.xres;
1509
1510 pr_debug("mdp_clks_per_hsync %u, fill_rate_y_dir %lu,"
1511 "fill_rate_x_dir %lu\n", mdp_clks_per_hsync,
1512 fill_rate_y_dir, fill_rate_x_dir);
1513
1514 mdp_pixels_produced = 100 * mdp_clks_per_hsync/fillratex100;
1515 pr_debug("fillratex100 %lu, mdp_pixels_produced %lu\n",
1516 fillratex100, mdp_pixels_produced);
1517 if (mdp_pixels_produced <= mfd->panel_info.xres) {
1518 pr_err("%s(): LCDC underflow detected during downscale\n",
1519 __func__);
1520 return -ERANGE;
1521 }
1522
1523 return 0;
1524}
1525
1526static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
1527 struct mdp4_overlay_pipe **ppipe,
1528 struct msm_fb_data_type *mfd)
1529{
1530 struct mdp4_overlay_pipe *pipe;
1531 struct mdp4_pipe_desc *pd;
1532 int ret, ptype, req_share;
1533 int j;
1534
1535 if (mfd == NULL) {
1536 pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
1537 return -ENODEV;
1538 }
1539
1540 if (mixer >= MDP4_MAX_MIXER) {
1541 pr_err("%s: mixer out of range!\n", __func__);
1542 mdp4_stat.err_mixer++;
1543 return -ERANGE;
1544 }
1545
1546 if (req->z_order < 0 || req->z_order > 2) {
1547 pr_err("%s: z_order=%d out of range!\n", __func__,
1548 req->z_order);
1549 mdp4_stat.err_zorder++;
1550 return -ERANGE;
1551 }
1552
1553 if (req->src_rect.h == 0 || req->src_rect.w == 0) {
1554 pr_err("%s: src img of zero size!\n", __func__);
1555 mdp4_stat.err_size++;
1556 return -EINVAL;
1557 }
1558
1559
1560 if (req->dst_rect.h > (req->src_rect.h * 8)) { /* too much */
1561 mdp4_stat.err_scale++;
1562 pr_err("%s: scale up, too much (h)!\n", __func__);
1563 return -ERANGE;
1564 }
1565
1566 if (req->src_rect.h > (req->dst_rect.h * 8)) { /* too little */
1567 mdp4_stat.err_scale++;
1568 pr_err("%s: scale down, too little (h)!\n", __func__);
1569 return -ERANGE;
1570 }
1571
1572 if (req->dst_rect.w > (req->src_rect.w * 8)) { /* too much */
1573 mdp4_stat.err_scale++;
1574 pr_err("%s: scale up, too much (w)!\n", __func__);
1575 return -ERANGE;
1576 }
1577
1578 if (req->src_rect.w > (req->dst_rect.w * 8)) { /* too little */
1579 mdp4_stat.err_scale++;
1580 pr_err("%s: scale down, too little (w)!\n", __func__);
1581 return -ERANGE;
1582 }
1583
1584 if (mdp_hw_revision == MDP4_REVISION_V1) {
1585 /* non integer down saceling ratio smaller than 1/4
1586 * is not supportted
1587 */
1588 if (req->src_rect.h > (req->dst_rect.h * 4)) {
1589 if (req->src_rect.h % req->dst_rect.h) {
1590 mdp4_stat.err_scale++;
1591 pr_err("%s: need integer (h)!\n", __func__);
1592 return -ERANGE;
1593 }
1594 }
1595
1596 if (req->src_rect.w > (req->dst_rect.w * 4)) {
1597 if (req->src_rect.w % req->dst_rect.w) {
1598 mdp4_stat.err_scale++;
1599 pr_err("%s: need integer (w)!\n", __func__);
1600 return -ERANGE;
1601 }
1602 }
1603 }
1604
1605 if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
1606 ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
1607 mdp4_stat.err_size++;
1608 pr_err("%s invalid src rectangle\n", __func__);
1609 return -ERANGE;
1610 }
1611
1612 if (ctrl->panel_3d != MDP4_3D_SIDE_BY_SIDE) {
1613 int xres;
1614 int yres;
1615
1616 xres = mfd->panel_info.xres;
1617 yres = mfd->panel_info.yres;
1618
1619 if (((req->dst_rect.x + req->dst_rect.w) > xres) ||
1620 ((req->dst_rect.y + req->dst_rect.h) > yres)) {
1621 mdp4_stat.err_size++;
1622 pr_err("%s invalid dst rectangle\n", __func__);
1623 return -ERANGE;
1624 }
1625 }
1626
1627 ptype = mdp4_overlay_format2type(req->src.format);
1628 if (ptype < 0) {
1629 pr_err("%s: mdp4_overlay_format2type!\n", __func__);
1630 return ptype;
1631 }
1632
1633 req_share = (req->flags & MDP_OV_PIPE_SHARE);
1634
1635 if (req->id == MSMFB_NEW_REQUEST) /* new request */
1636 pipe = mdp4_overlay_pipe_alloc(ptype, mixer, req_share);
1637 else
1638 pipe = mdp4_overlay_ndx2pipe(req->id);
1639
1640 if (pipe == NULL) {
1641 pr_err("%s: pipe == NULL!\n", __func__);
1642 return -ENOMEM;
1643 }
1644
1645 /* no down scale at rgb pipe */
1646 if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1647 if ((req->src_rect.h > req->dst_rect.h) ||
1648 (req->src_rect.w > req->dst_rect.w)) {
1649 pr_err("%s: h>h || w>w!\n", __func__);
1650 return -ERANGE;
1651 }
1652 }
1653
1654 pipe->src_format = req->src.format;
1655 ret = mdp4_overlay_format2pipe(pipe);
1656 if (ret < 0) {
1657 pr_err("%s: mdp4_overlay_format2pipe!\n", __func__);
1658 return ret;
1659 }
1660
1661 /*
1662 * base layer == 1, reserved for frame buffer
1663 * zorder 0 == stage 0 == 2
1664 * zorder 1 == stage 1 == 3
1665 * zorder 2 == stage 2 == 4
1666 */
1667 if (req->id == MSMFB_NEW_REQUEST) { /* new request */
1668 pd = &ctrl->ov_pipe[pipe->pipe_num];
1669 for (j = 0; j < MDP4_MAX_SHARE; j++) {
1670 if (pd->ndx_list[j] == 0) {
1671 pd->ndx_list[j] = pipe->pipe_ndx;
1672 break;
1673 }
1674 }
1675 pipe->pipe_share = req_share;
1676 pd->ref_cnt++;
1677 pipe->pipe_used++;
1678 pipe->mixer_num = mixer;
1679 pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
1680 pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
1681 req->z_order, pipe->pipe_ndx, pipe->pipe_num);
1682
1683 }
1684
1685 pipe->src_width = req->src.width & 0x07ff; /* source img width */
1686 pipe->src_height = req->src.height & 0x07ff; /* source img height */
1687 pipe->src_h = req->src_rect.h & 0x07ff;
1688 pipe->src_w = req->src_rect.w & 0x07ff;
1689 pipe->src_y = req->src_rect.y & 0x07ff;
1690 pipe->src_x = req->src_rect.x & 0x07ff;
1691 pipe->dst_h = req->dst_rect.h & 0x07ff;
1692 pipe->dst_w = req->dst_rect.w & 0x07ff;
1693 pipe->dst_y = req->dst_rect.y & 0x07ff;
1694 pipe->dst_x = req->dst_rect.x & 0x07ff;
1695
1696 pipe->op_mode = 0;
1697
1698 if (req->flags & MDP_FLIP_LR)
1699 pipe->op_mode |= MDP4_OP_FLIP_LR;
1700
1701 if (req->flags & MDP_FLIP_UD)
1702 pipe->op_mode |= MDP4_OP_FLIP_UD;
1703
1704 if (req->flags & MDP_DITHER)
1705 pipe->op_mode |= MDP4_OP_DITHER_EN;
1706
1707 if (req->flags & MDP_DEINTERLACE)
1708 pipe->op_mode |= MDP4_OP_DEINT_EN;
1709
1710 if (req->flags & MDP_DEINTERLACE_ODD)
1711 pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
1712
1713 pipe->is_fg = req->is_fg;/* control alpha and color key */
1714
1715 pipe->alpha = req->alpha & 0x0ff;
1716
1717 pipe->transp = req->transp_mask;
1718
1719 *ppipe = pipe;
1720
1721 return 0;
1722}
1723
1724static int get_img(struct msmfb_data *img, struct fb_info *info,
1725 unsigned long *start, unsigned long *len, struct file **pp_file)
1726{
1727 int put_needed, ret = 0, fb_num;
1728 struct file *file;
1729#ifdef CONFIG_ANDROID_PMEM
1730 unsigned long vstart;
1731#endif
1732
1733 if (img->flags & MDP_BLIT_SRC_GEM) {
1734 *pp_file = NULL;
1735 return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
1736 start, len);
1737 }
1738
1739#ifdef CONFIG_ANDROID_PMEM
1740 if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1741 return 0;
1742#endif
1743 file = fget_light(img->memory_id, &put_needed);
1744 if (file == NULL)
1745 return -1;
1746
1747 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1748 fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
1749 if (get_fb_phys_info(start, len, fb_num))
1750 ret = -1;
1751 else
1752 *pp_file = file;
1753 } else
1754 ret = -1;
1755 if (ret)
1756 fput_light(file, put_needed);
1757 return ret;
1758}
1759
kuogee hsieh4aea2742011-07-06 11:05:05 -07001760#ifdef CONFIG_FB_MSM_MIPI_DSI
1761int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762{
1763 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1764 int ret = -EPERM;
1765
1766 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1767 return -EINTR;
1768
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001769 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
kuogee hsieh4aea2742011-07-06 11:05:05 -07001770 mdp4_dsi_cmd_3d_sbys(mfd, req);
1771 ret = 0;
1772 } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
1773 mdp4_dsi_video_3d_sbys(mfd, req);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001774 ret = 0;
1775 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001776 mutex_unlock(&mfd->dma->ov_mutex);
1777
1778 return ret;
1779}
kuogee hsieh4aea2742011-07-06 11:05:05 -07001780#else
1781int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req)
1782{
1783 /* do nothing */
1784 return -EPERM;
1785}
1786#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001787
1788#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
1789int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req)
1790{
1791 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1792
1793 if (mfd == NULL)
1794 return -ENODEV;
1795
1796 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1797 return -EINTR;
1798
1799 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
1800 mdp4_dsi_overlay_blt(mfd, req);
1801 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
1802 mdp4_dsi_video_overlay_blt(mfd, req);
1803 else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
1804 mdp4_lcdc_overlay_blt(mfd, req);
1805
1806 mutex_unlock(&mfd->dma->ov_mutex);
1807
1808 return 0;
1809}
1810
1811int mdp4_overlay_blt_offset(struct fb_info *info, struct msmfb_overlay_blt *req)
1812{
1813 int ret = 0;
1814
1815 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1816
1817 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1818 return -EINTR;
1819
1820 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
1821 ret = mdp4_dsi_overlay_blt_offset(mfd, req);
1822 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
1823 ret = mdp4_dsi_video_overlay_blt_offset(mfd, req);
1824 else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
1825 ret = mdp4_lcdc_overlay_blt_offset(mfd, req);
1826
1827 mutex_unlock(&mfd->dma->ov_mutex);
1828
1829 return ret;
1830}
1831#endif
1832
1833int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
1834{
1835 struct mdp4_overlay_pipe *pipe;
1836
1837 pipe = mdp4_overlay_ndx2pipe(req->id);
1838 if (pipe == NULL)
1839 return -ENODEV;
1840
1841 *req = pipe->req_data;
1842
1843 return 0;
1844}
1845
1846#define OVERLAY_VGA_SIZE 0x04B000
1847#define OVERLAY_720P_TILE_SIZE 0x0E6000
1848#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
1849#define OVERLAY_PERF_LEVEL1 1
1850#define OVERLAY_PERF_LEVEL2 2
1851#define OVERLAY_PERF_LEVEL3 3
1852#define OVERLAY_PERF_LEVEL4 4
1853
1854#ifdef CONFIG_MSM_BUS_SCALING
1855#define OVERLAY_BUS_SCALE_TABLE_BASE 6
1856#endif
1857
1858static int mdp4_overlay_is_rgb_type(int format)
1859{
1860 switch (format) {
1861 case MDP_RGB_565:
1862 case MDP_RGB_888:
1863 case MDP_BGR_565:
1864 case MDP_XRGB_8888:
1865 case MDP_ARGB_8888:
1866 case MDP_RGBA_8888:
1867 case MDP_BGRA_8888:
1868 case MDP_RGBX_8888:
1869 return 1;
1870 default:
1871 return 0;
1872 }
1873}
1874
1875static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req)
1876{
1877 int is_fg;
1878
1879 if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
1880 is_fg = 1;
1881
1882 if (req->flags & MDP_DEINTERLACE)
1883 return OVERLAY_PERF_LEVEL1;
1884
1885 if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
1886 ((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
1887 return OVERLAY_PERF_LEVEL4;
1888 else if (mdp4_overlay_is_rgb_type(req->src.format))
1889 return OVERLAY_PERF_LEVEL1;
1890
1891 if (ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt &&
1892 ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt)
1893 return OVERLAY_PERF_LEVEL1;
1894
1895 if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
1896 return OVERLAY_PERF_LEVEL3;
1897 else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE)
1898 return OVERLAY_PERF_LEVEL2;
1899 else
1900 return OVERLAY_PERF_LEVEL1;
1901}
1902
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001903void mdp4_set_perf_level(void)
1904{
1905 static int old_perf_level;
1906
1907 if (old_perf_level != new_perf_level) {
1908 mdp_set_core_clk(new_perf_level);
1909 old_perf_level = new_perf_level;
1910 }
1911}
1912
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001913int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
1914{
1915 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001916 int ret, mixer, perf_level;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001917 struct mdp4_overlay_pipe *pipe;
1918
1919 if (mfd == NULL) {
1920 pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
1921 return -ENODEV;
1922 }
1923
1924 if (!mfd->panel_power_on) /* suspended */
1925 return -EPERM;
1926
1927 if (req->src.format == MDP_FB_FORMAT)
1928 req->src.format = mfd->fb_imgType;
1929
1930 if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) {
1931 pr_err("%s: mutex_lock_interruptible, -EINTR\n", __func__);
1932 return -EINTR;
1933 }
1934
1935 perf_level = mdp4_overlay_get_perf_level(req);
1936
1937 if ((mfd->panel_info.type == LCDC_PANEL) &&
1938 (req->src_rect.h >
1939 req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
1940 if (mdp4_overlay_validate_downscale(req, mfd,
1941 perf_level, mfd->panel_info.clk_rate)) {
1942 mutex_unlock(&mfd->dma->ov_mutex);
1943 return -ERANGE;
1944 }
1945 }
1946 if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) &&
1947 (req->src_rect.h >
1948 req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
1949 if (mdp4_overlay_validate_downscale(req, mfd,
1950 perf_level, (&mfd->panel_info.mipi)->dsi_pclk_rate)) {
1951 mutex_unlock(&mfd->dma->ov_mutex);
1952 return -ERANGE;
1953 }
1954 }
1955 mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
1956
1957 ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
1958 if (ret < 0) {
1959 mutex_unlock(&mfd->dma->ov_mutex);
1960 pr_err("%s: mdp4_overlay_req2pipe, ret=%d\n", __func__, ret);
1961 return ret;
1962 }
1963
1964#ifdef CONFIG_FB_MSM_MIPI_DSI
1965 /*
1966 * writeback (blt) mode to provide work around for
1967 * dsi cmd mode interface hardware bug.
1968 */
1969 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
1970 if (mixer == MDP4_MIXER0 && req->dst_rect.x != 0) {
1971 mdp4_dsi_blt_dmap_busy_wait(mfd);
1972 mdp4_dsi_overlay_blt_start(mfd);
1973 }
1974 }
1975#endif
1976
1977 /* return id back to user */
1978 req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
1979 pipe->req_data = *req; /* keep original req */
1980
1981 pipe->flags = req->flags;
1982
1983 if (pipe->flags & MDP_SHARPENING) {
1984 bool test = ((pipe->req_data.dpp.sharp_strength > 0) &&
1985 ((req->src_rect.w > req->dst_rect.w) &&
1986 (req->src_rect.h > req->dst_rect.h)));
1987 if (test) {
1988 pr_warn("%s: No sharpening while downscaling.\n",
1989 __func__);
1990 pipe->flags &= ~MDP_SHARPENING;
1991 }
1992 }
1993
1994 mdp4_stat.overlay_set[pipe->mixer_num]++;
1995
1996 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
1997 if (mdp_hw_revision == MDP4_REVISION_V2_1 &&
1998 pipe->mixer_num == MDP4_MIXER0)
1999 mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, true);
2000 }
2001
2002 mdp4_del_res_rel = 0;
2003 mutex_unlock(&mfd->dma->ov_mutex);
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07002004
2005 new_perf_level = perf_level;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002006
2007#ifdef CONFIG_MSM_BUS_SCALING
2008 if (pipe->mixer_num == MDP4_MIXER0) {
2009 mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
2010 - perf_level);
2011 }
2012#endif
2013
2014 return 0;
2015}
2016
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002017int mdp4_overlay_unset(struct fb_info *info, int ndx)
2018{
2019 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2020 struct mdp4_overlay_pipe *pipe;
2021 uint32 flags;
2022
2023 if (mfd == NULL)
2024 return -ENODEV;
2025
2026 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
2027 return -EINTR;
2028
2029 pipe = mdp4_overlay_ndx2pipe(ndx);
2030
2031 if (pipe == NULL) {
2032 mutex_unlock(&mfd->dma->ov_mutex);
2033 return -ENODEV;
2034 }
2035
2036 if (pipe->mixer_num == MDP4_MIXER1)
2037 ctrl->mixer1_played = 0;
2038 else {
2039 /* mixer 0 */
2040 ctrl->mixer0_played = 0;
2041#ifdef CONFIG_FB_MSM_MIPI_DSI
2042 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2043 if (mfd->panel_power_on) {
2044 mdp4_dsi_blt_dmap_busy_wait(mfd);
2045 }
2046 }
2047#else
2048 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2049 if (mfd->panel_power_on)
2050 mdp4_mddi_dma_busy_wait(mfd);
2051 }
2052#endif
2053 }
2054
2055 mdp4_mixer_stage_down(pipe);
2056
2057 if (pipe->mixer_num == MDP4_MIXER0) {
2058#ifdef CONFIG_FB_MSM_MIPI_DSI
2059 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2060 if (mfd->panel_power_on)
2061 if (mdp4_dsi_overlay_blt_stop(mfd) == 0)
2062 mdp4_dsi_cmd_overlay_restore();
2063 } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
2064 flags = pipe->flags;
2065 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
kuogee hsiehebca0c72011-07-14 13:30:33 -07002066 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002067 mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
2068 pipe->flags = flags;
2069 }
2070#else
2071 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2072 if (mdp_hw_revision == MDP4_REVISION_V2_1)
2073 mdp4_overlay_status_write(
2074 MDP4_OVERLAY_TYPE_UNSET, true);
2075 if (mfd->panel_power_on)
2076 mdp4_mddi_overlay_restore();
2077 }
2078#endif
2079 else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
2080 flags = pipe->flags;
2081 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
kuogee hsiehebca0c72011-07-14 13:30:33 -07002082 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002083 mdp4_overlay_lcdc_vsync_push(mfd, pipe);
2084 pipe->flags = flags;
2085 }
2086 }
2087#ifdef CONFIG_FB_MSM_DTV
2088 else { /* mixer1, DTV, ATV */
2089 flags = pipe->flags;
2090 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
2091 mdp4_overlay_dtv_vsync_push(mfd, pipe);
2092 pipe->flags = flags;
2093 }
2094#endif
2095
2096 mdp4_stat.overlay_unset[pipe->mixer_num]++;
2097
2098 mdp4_overlay_pipe_free(pipe);
2099
2100 if (!(ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt +
2101 ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt))
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07002102 new_perf_level = OVERLAY_PERF_LEVEL4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002103
2104 mutex_unlock(&mfd->dma->ov_mutex);
2105
2106#ifdef CONFIG_MSM_BUS_SCALING
2107 if (pipe->mixer_num == MDP4_MIXER0)
2108 if (mfd->panel_power_on)
2109 mdp_bus_scale_update_request(2);
2110#endif
2111 return 0;
2112}
2113
2114struct tile_desc {
2115 uint32 width; /* tile's width */
2116 uint32 height; /* tile's height */
2117 uint32 row_tile_w; /* tiles per row's width */
2118 uint32 row_tile_h; /* tiles per row's height */
2119};
2120
2121void tile_samsung(struct tile_desc *tp)
2122{
2123 /*
2124 * each row of samsung tile consists of two tiles in height
2125 * and two tiles in width which means width should align to
2126 * 64 x 2 bytes and height should align to 32 x 2 bytes.
2127 * video decoder generate two tiles in width and one tile
2128 * in height which ends up height align to 32 X 1 bytes.
2129 */
2130 tp->width = 64; /* 64 bytes */
2131 tp->row_tile_w = 2; /* 2 tiles per row's width */
2132 tp->height = 32; /* 32 bytes */
2133 tp->row_tile_h = 1; /* 1 tiles per row's height */
2134}
2135
2136uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
2137{
2138 uint32 tile_w, tile_h;
2139 uint32 row_num_w, row_num_h;
2140
2141
2142 tile_w = tp->width * tp->row_tile_w;
2143 tile_h = tp->height * tp->row_tile_h;
2144
2145 row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
2146 row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
2147 return ((row_num_w * row_num_h * tile_w * tile_h) + 8191) & ~8191;
2148}
2149
2150int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
2151 struct file **pp_src_file, struct file **pp_src_plane1_file,
2152 struct file **pp_src_plane2_file)
2153{
2154 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2155 struct msmfb_data *img;
2156 struct mdp4_overlay_pipe *pipe;
2157 struct mdp4_pipe_desc *pd;
2158 ulong start, addr;
2159 ulong len = 0;
2160 struct file *p_src_file = 0;
2161 struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
2162 uint32_t overlay_version = 0;
2163
2164 if (mfd == NULL)
2165 return -ENODEV;
2166
2167 if (!mfd->panel_power_on) /* suspended */
2168 return -EPERM;
2169
2170 pipe = mdp4_overlay_ndx2pipe(req->id);
2171 if (pipe == NULL) {
2172 pr_err("%s: req_id=%d Error\n", __func__, req->id);
2173 return -ENODEV;
2174 }
2175
2176 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
2177 return -EINTR;
2178
2179 pd = &ctrl->ov_pipe[pipe->pipe_num];
2180 if (pd->player && pipe != pd->player) {
2181 if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
2182 mutex_unlock(&mfd->dma->ov_mutex);
2183 return 0; /* ignore it, kicked out already */
2184 }
2185 }
2186
2187 pd->player = pipe; /* keep */
2188
2189 img = &req->data;
2190 get_img(img, info, &start, &len, &p_src_file);
2191 if (len == 0) {
2192 mutex_unlock(&mfd->dma->ov_mutex);
2193 pr_err("%s: pmem Error\n", __func__);
2194 return -1;
2195 }
2196 *pp_src_file = p_src_file;
2197
2198 addr = start + img->offset;
2199 pipe->srcp0_addr = addr;
2200 pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
2201
2202 if ((req->version_key & VERSION_KEY_MASK) == 0xF9E8D700)
2203 overlay_version = (req->version_key & ~VERSION_KEY_MASK);
2204
2205 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
2206 if (overlay_version > 0) {
2207 img = &req->plane1_data;
2208 get_img(img, info, &start, &len, &p_src_plane1_file);
2209 if (len == 0) {
2210 mutex_unlock(&mfd->dma->ov_mutex);
2211 pr_err("%s: Error to get plane1\n", __func__);
2212 return -EINVAL;
2213 }
2214 pipe->srcp1_addr = start + img->offset;
2215 *pp_src_plane1_file = p_src_plane1_file;
2216 } else if (pipe->frame_format ==
2217 MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
2218 struct tile_desc tile;
2219
2220 tile_samsung(&tile);
2221 pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
2222 } else {
2223 pipe->srcp1_addr = addr + (pipe->src_width *
2224 pipe->src_height);
2225 }
2226 pipe->srcp0_ystride = pipe->src_width;
2227 if ((pipe->src_format == MDP_Y_CRCB_H1V1) ||
2228 (pipe->src_format == MDP_Y_CBCR_H1V1)) {
2229 if (pipe->src_width > YUV_444_MAX_WIDTH)
2230 pipe->srcp1_ystride = pipe->src_width << 2;
2231 else
2232 pipe->srcp1_ystride = pipe->src_width << 1;
2233 } else
2234 pipe->srcp1_ystride = pipe->src_width;
2235
2236 } else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
2237 if (overlay_version > 0) {
2238 img = &req->plane1_data;
2239 get_img(img, info, &start, &len, &p_src_plane1_file);
2240 if (len == 0) {
2241 mutex_unlock(&mfd->dma->ov_mutex);
2242 pr_err("%s: Error to get plane1\n", __func__);
2243 return -EINVAL;
2244 }
2245 pipe->srcp1_addr = start + img->offset;
2246 *pp_src_plane1_file = p_src_plane1_file;
2247
2248 img = &req->plane2_data;
2249 get_img(img, info, &start, &len, &p_src_plane2_file);
2250 if (len == 0) {
2251 mutex_unlock(&mfd->dma->ov_mutex);
2252 pr_err("%s: Error to get plane2\n", __func__);
2253 return -EINVAL;
2254 }
2255 pipe->srcp2_addr = start + img->offset;
2256 *pp_src_plane2_file = p_src_plane2_file;
2257 } else {
2258 addr += (pipe->src_width * pipe->src_height);
2259 pipe->srcp1_addr = addr;
2260 addr += ((pipe->src_width / 2) *
2261 (pipe->src_height / 2));
2262 pipe->srcp2_addr = addr;
2263 }
2264 pipe->srcp0_ystride = pipe->src_width;
2265 pipe->srcp1_ystride = pipe->src_width / 2;
2266 pipe->srcp2_ystride = pipe->src_width / 2;
2267 }
2268
2269 if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
2270 mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
2271 else {
2272 if (pipe->flags & MDP_SHARPENING) {
2273 pr_warn(
2274 "%s: Sharpening/Smoothing not supported on RGB pipe\n",
2275 __func__);
2276 pipe->flags &= ~MDP_SHARPENING;
2277 }
2278 mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
2279 }
2280
2281 mdp4_mixer_blend_setup(pipe);
2282 mdp4_mixer_stage_up(pipe);
2283
2284 if (pipe->mixer_num == MDP4_MIXER1) {
2285 ctrl->mixer1_played++;
2286 /* enternal interface */
2287 if (ctrl->panel_mode & MDP4_PANEL_DTV)
2288#ifdef CONFIG_FB_MSM_DTV
2289 mdp4_overlay_dtv_ov_done_push(mfd, pipe);
2290#else
2291 mdp4_overlay_reg_flush(pipe, 1);
2292#endif
2293 else if (ctrl->panel_mode & MDP4_PANEL_ATV)
2294 mdp4_overlay_reg_flush(pipe, 1);
2295 } else {
2296 /* primary interface */
2297 ctrl->mixer0_played++;
kuogee hsieh3de11f32011-07-08 14:09:11 -07002298 if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
2299 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002300 mdp4_overlay_lcdc_vsync_push(mfd, pipe);
kuogee hsieh3de11f32011-07-08 14:09:11 -07002301 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002302#ifdef CONFIG_FB_MSM_MIPI_DSI
kuogee hsieh3de11f32011-07-08 14:09:11 -07002303 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
2304 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002305 mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
kuogee hsieh3de11f32011-07-08 14:09:11 -07002306 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002307#endif
2308 else {
2309 /* mddi & mipi dsi cmd mode */
2310 if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
2311 mdp4_stat.overlay_play[pipe->mixer_num]++;
2312 mutex_unlock(&mfd->dma->ov_mutex);
2313 return 0;
2314 }
2315#ifdef CONFIG_FB_MSM_MIPI_DSI
2316 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2317 mdp4_dsi_cmd_dma_busy_wait(mfd);
2318 mdp4_dsi_cmd_kickoff_video(mfd, pipe);
2319 }
2320#else
2321 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2322 mdp4_mddi_dma_busy_wait(mfd);
2323 mdp4_mddi_kickoff_video(mfd, pipe);
2324 }
2325#endif
2326 }
2327 }
2328
2329 mdp4_stat.overlay_play[pipe->mixer_num]++;
2330
2331 mutex_unlock(&mfd->dma->ov_mutex);
2332
2333 return 0;
2334}