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