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