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