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