blob: 1b80d4c503ecaaf5c23a6320439378ffae46aa55 [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 {
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -070044 struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
45 struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046 uint32 panel_3d;
47 uint32 panel_mode;
48 uint32 mixer0_played;
49 uint32 mixer1_played;
50} mdp4_overlay_db = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051 .plist = {
52 {
53 .pipe_type = OVERLAY_TYPE_RGB,
54 .pipe_num = OVERLAY_PIPE_RGB1,
55 .pipe_ndx = 1,
56 },
57 {
58 .pipe_type = OVERLAY_TYPE_RGB,
59 .pipe_num = OVERLAY_PIPE_RGB2,
60 .pipe_ndx = 2,
61 },
62 {
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -070063 .pipe_type = OVERLAY_TYPE_VIDEO,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070064 .pipe_num = OVERLAY_PIPE_VG1,
65 .pipe_ndx = 3,
66 },
67 {
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -070068 .pipe_type = OVERLAY_TYPE_VIDEO,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070069 .pipe_num = OVERLAY_PIPE_VG2,
70 .pipe_ndx = 4,
71 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072 },
73};
74
75static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
kuogee hsieh9452ecb2011-08-01 18:26:23 -070076static int new_perf_level;
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -070077
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078/* static array with index 0 for unset status and 1 for set status */
79static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
80
81void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val)
82{
83 overlay_status[type] = val;
84}
85
86bool mdp4_overlay_status_read(enum mdp4_overlay_status type)
87{
88 return overlay_status[type];
89}
90
91int mdp4_overlay_mixer_play(int mixer_num)
92{
93 if (mixer_num == MDP4_MIXER1)
94 return ctrl->mixer1_played;
95 else
96 return ctrl->mixer0_played;
97}
98
99void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d)
100{
101 ctrl->panel_3d = panel_3d;
102}
103
104void mdp4_overlay_panel_mode(int mixer_num, uint32 mode)
105{
106 ctrl->panel_mode |= mode;
107}
108
109uint32 mdp4_overlay_panel_list(void)
110{
111 return ctrl->panel_mode;
112}
113
114void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv)
115{
116 uint32 dmae_cfg_reg;
117
118 if (atv)
119 dmae_cfg_reg = DMA_DEFLKR_EN;
120 else
121 dmae_cfg_reg = 0;
122
123 if (mfd->fb_imgType == MDP_BGR_565)
124 dmae_cfg_reg |= DMA_PACK_PATTERN_BGR;
125 else
126 dmae_cfg_reg |= DMA_PACK_PATTERN_RGB;
127
128
129 if (mfd->panel_info.bpp == 18) {
130 dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
131 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
132 } else if (mfd->panel_info.bpp == 16) {
133 dmae_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
134 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
135 } else {
136 dmae_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
137 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
138 }
139
140 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
141
142 /* dma2 config register */
143 MDP_OUTP(MDP_BASE + 0xb0000, dmae_cfg_reg);
144 if (atv) {
145 MDP_OUTP(MDP_BASE + 0xb0070, 0xeb0010);
146 MDP_OUTP(MDP_BASE + 0xb0074, 0xf00010);
147 MDP_OUTP(MDP_BASE + 0xb0078, 0xf00010);
148 MDP_OUTP(MDP_BASE + 0xb3000, 0x80);
149 MDP_OUTP(MDP_BASE + 0xb3010, 0x1800040);
150 MDP_OUTP(MDP_BASE + 0xb3014, 0x1000080);
151 MDP_OUTP(MDP_BASE + 0xb4004, 0x67686970);
152 } else {
153 MDP_OUTP(MDP_BASE + 0xb0070, 0xff0000);
154 MDP_OUTP(MDP_BASE + 0xb0074, 0xff0000);
155 MDP_OUTP(MDP_BASE + 0xb0078, 0xff0000);
156 }
157
158 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
159}
160
Manoj Raob91fa712011-06-29 09:07:55 -0700161#ifdef CONFIG_FB_MSM_HDMI_3D
162void unfill_black_screen(void) { return; }
163#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164void unfill_black_screen(void)
165{
166 uint32 temp_src_format;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700167 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
168 /*
169 * VG2 Constant Color
170 */
171 temp_src_format = inpdw(MDP_BASE + 0x30050);
172 MDP_OUTP(MDP_BASE + 0x30050, temp_src_format&(~BIT(22)));
173 /*
174 * MDP_OVERLAY_REG_FLUSH
175 */
176 MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
177 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
Manoj Raob91fa712011-06-29 09:07:55 -0700178 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700179}
Manoj Raob91fa712011-06-29 09:07:55 -0700180#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181
Manoj Raob91fa712011-06-29 09:07:55 -0700182#ifdef CONFIG_FB_MSM_HDMI_3D
183void fill_black_screen(void) { return; }
184#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700185void fill_black_screen(void)
186{
187 /*Black color*/
188 uint32 color = 0x00000000;
189 uint32 temp_src_format;
190 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
191 /*
192 * VG2 Constant Color
193 */
194 MDP_OUTP(MDP_BASE + 0x31008, color);
195 /*
196 * MDP_VG2_SRC_FORMAT
197 */
198 temp_src_format = inpdw(MDP_BASE + 0x30050);
199 MDP_OUTP(MDP_BASE + 0x30050, temp_src_format | BIT(22));
200 /*
201 * MDP_OVERLAY_REG_FLUSH
202 */
203 MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
204 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
Manoj Raob91fa712011-06-29 09:07:55 -0700205 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206}
Manoj Raob91fa712011-06-29 09:07:55 -0700207#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700208
209void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
210{
211
212 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
213
214 /* dma_p source */
215 MDP_OUTP(MDP_BASE + 0xb0004,
216 (pipe->src_height << 16 | pipe->src_width));
217 MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
218 MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
219
220 /* dma_p dest */
221 MDP_OUTP(MDP_BASE + 0xb0010, (pipe->dst_y << 16 | pipe->dst_x));
222
223 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
224}
225
226void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
227{
228 uint32 dma2_cfg_reg;
229
230 dma2_cfg_reg = DMA_DITHER_EN;
231#ifdef BLT_RGB565
232 /* RGB888 is 0 */
233 dma2_cfg_reg |= DMA_BUF_FORMAT_RGB565; /* blt only */
234#endif
235
236 if (mfd->fb_imgType == MDP_BGR_565)
237 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
238 else
239 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
240
241
242 if (mfd->panel_info.bpp == 18) {
243 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
244 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
245 } else if (mfd->panel_info.bpp == 16) {
246 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
247 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
248 } else {
249 dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
250 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
251 }
252
253 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
254
255#ifndef CONFIG_FB_MSM_LCDC_CHIMEI_WXGA_PANEL
256 if (lcdc)
257 dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
258#endif
259
260 /* dma2 config register */
261 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
262
263 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
264}
265
266/*
267 * mdp4_overlay_dmap_xy: called form baselayer only
268 */
269void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
270{
271 uint32 off, bpp;
272
273 if (mdp_is_in_isr == FALSE)
274 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
275
276 /* dma_p source */
277 MDP_OUTP(MDP_BASE + 0x90004,
278 (pipe->src_height << 16 | pipe->src_width));
279 if (pipe->blt_addr) {
280#ifdef BLT_RGB565
281 bpp = 2; /* overlay ouput is RGB565 */
282#else
283 bpp = 3; /* overlay ouput is RGB888 */
284#endif
285 off = 0;
286 if (pipe->dmap_cnt & 0x01)
287 off = pipe->src_height * pipe->src_width * bpp;
288 MDP_OUTP(MDP_BASE + 0x90008, pipe->blt_addr + off);
289 /* RGB888, output of overlay blending */
290 MDP_OUTP(MDP_BASE + 0x9000c, pipe->src_width * bpp);
291 } else {
292 MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
293 MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
294 }
295
296 /* dma_p dest */
297 MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
298
299 if (mdp_is_in_isr == FALSE)
300 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
301}
302
303#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
304#define MDP4_VG_PHASE_STEP_SHIFT 29
305
306static int mdp4_leading_0(uint32 num)
307{
308 uint32 bit = 0x80000000;
309 int i;
310
311 for (i = 0; i < 32; i++) {
312 if (bit & num)
313 return i;
314 bit >>= 1;
315 }
316
317 return i;
318}
319
320static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
321{
322 uint32 val;
323 int n;
324
325 n = mdp4_leading_0(src);
326 if (n > f_num)
327 n = f_num;
328 val = src << n; /* maximum to reduce lose of resolution */
329 val /= dst;
330 if (n < f_num) {
331 n = f_num - n;
332 val <<= n;
333 }
334
335 return val;
336}
337
338static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
339{
340 int ptype;
341
342 pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
343 pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
344 ptype = mdp4_overlay_format2type(pipe->src_format);
345
346 if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
347 if (pipe->dst_h > pipe->src_h * 8) /* too much */
348 return;
349 pipe->op_mode |= MDP4_OP_SCALEY_EN;
350
351 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
352 if (pipe->dst_h <= (pipe->src_h / 4))
353 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
354 else
355 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
356 }
357
358 pipe->phasey_step = mdp4_scale_phase_step(29,
359 pipe->src_h, pipe->dst_h);
360 }
361
362 if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
363 if (pipe->dst_w > pipe->src_w * 8) /* too much */
364 return;
365 pipe->op_mode |= MDP4_OP_SCALEX_EN;
366
367 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {
368 if (pipe->dst_w <= (pipe->src_w / 4))
369 pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
370 else
371 pipe->op_mode |= MDP4_OP_SCALEX_FIR;
372 }
373
374 pipe->phasex_step = mdp4_scale_phase_step(29,
375 pipe->src_w, pipe->dst_w);
376 }
377}
378
379void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
380{
381 char *rgb_base;
382 uint32 src_size, src_xy, dst_size, dst_xy;
383 uint32 format, pattern;
384
385 rgb_base = MDP_BASE + MDP4_RGB_BASE;
386 rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
387
388 src_size = ((pipe->src_h << 16) | pipe->src_w);
389 src_xy = ((pipe->src_y << 16) | pipe->src_x);
390 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
391 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
392
393 format = mdp4_overlay_format(pipe);
394 pattern = mdp4_overlay_unpack_pattern(pipe);
395
396#ifdef MDP4_IGC_LUT_ENABLE
397 pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
398#endif
399
400 mdp4_scale_setup(pipe);
401
402 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
403
404 outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
405 outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
406 outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
407 outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
408
409 outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
410 outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
411
412 outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
413 outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
414 outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
415 outpdw(rgb_base + 0x005c, pipe->phasex_step);
416 outpdw(rgb_base + 0x0060, pipe->phasey_step);
417
418 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
419
420 mdp4_stat.pipe[pipe->pipe_num]++;
421}
422
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700423
424static void mdp4_overlay_vg_get_src_offset(struct mdp4_overlay_pipe *pipe,
425 char *vg_base, uint32 *luma_off, uint32 *chroma_off)
426{
427 uint32 src_xy;
428 *luma_off = 0;
429 *chroma_off = 0;
430
Nagamalleswararao Ganji1c8fc4a2011-10-10 20:51:31 -0700431 if (pipe->src_x && (pipe->frame_format ==
432 MDP4_FRAME_FORMAT_LINEAR)) {
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700433 src_xy = (pipe->src_y << 16) | pipe->src_x;
434 src_xy &= 0xffff0000;
435 outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
436
437 switch (pipe->src_format) {
438 case MDP_Y_CR_CB_H2V2:
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +0530439 case MDP_Y_CR_CB_GH2V2:
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700440 case MDP_Y_CB_CR_H2V2:
441 *luma_off = pipe->src_x;
442 *chroma_off = pipe->src_x/2;
443 break;
444
445 case MDP_Y_CBCR_H2V2_TILE:
446 case MDP_Y_CRCB_H2V2_TILE:
447 case MDP_Y_CBCR_H2V2:
448 case MDP_Y_CRCB_H2V2:
449 case MDP_Y_CRCB_H1V1:
450 case MDP_Y_CBCR_H1V1:
451 case MDP_Y_CRCB_H2V1:
452 case MDP_Y_CBCR_H2V1:
453 *luma_off = pipe->src_x;
454 *chroma_off = pipe->src_x;
455 break;
456
457 case MDP_YCRYCB_H2V1:
458 if (pipe->src_x & 0x1)
459 pipe->src_x += 1;
460 *luma_off += pipe->src_x * 2;
461 break;
462
463 case MDP_ARGB_8888:
464 case MDP_RGBA_8888:
465 case MDP_BGRA_8888:
466 case MDP_RGBX_8888:
467 case MDP_RGB_565:
468 case MDP_BGR_565:
469 case MDP_XRGB_8888:
470 case MDP_RGB_888:
471 *luma_off = pipe->src_x * pipe->bpp;
472 break;
473
474 default:
475 pr_err("Source format %u not supported for x offset adjustment\n",
476 pipe->src_format);
477 break;
478 }
479 }
480}
481
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700482void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
483{
484 char *vg_base;
485 uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700486 uint32 format, pattern, luma_offset, chroma_offset;
kuogee hsiehe1ed1ae2011-09-02 08:53:36 -0700487 int pnum, ptype;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700488
489 pnum = pipe->pipe_num - OVERLAY_PIPE_VG1; /* start from 0 */
490 vg_base = MDP_BASE + MDP4_VIDEO_BASE;
491 vg_base += (MDP4_VIDEO_OFF * pnum);
492
493 frame_size = ((pipe->src_height << 16) | pipe->src_width);
494 src_size = ((pipe->src_h << 16) | pipe->src_w);
495 src_xy = ((pipe->src_y << 16) | pipe->src_x);
496 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
497 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
498
kuogee hsiehe1ed1ae2011-09-02 08:53:36 -0700499 ptype = mdp4_overlay_format2type(pipe->src_format);
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +0530500 if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
501 frame_size = ((pipe->src_height << 16) |
502 ALIGN(pipe->src_width, 16));
503 src_size = ((pipe->src_h << 16) | ALIGN(pipe->src_w, 16));
504 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700505 format = mdp4_overlay_format(pipe);
506 pattern = mdp4_overlay_unpack_pattern(pipe);
507
508 /* not RGB use VG pipe, pure VG pipe */
kuogee hsiehe1ed1ae2011-09-02 08:53:36 -0700509 if (ptype != OVERLAY_TYPE_RGB)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700510 pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR);
kuogee hsiehe1ed1ae2011-09-02 08:53:36 -0700511
512#ifdef MDP4_IGC_LUT_ENABLE
513 pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514#endif
515
516 mdp4_scale_setup(pipe);
517
518 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
519
520 outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
521 outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
522 outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
523 outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
Nagamalleswararao Ganjic6ecb832011-09-14 10:00:18 -0700524
Nagamalleswararao Ganji1c8fc4a2011-10-10 20:51:31 -0700525 if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR)
Nagamalleswararao Ganjic6ecb832011-09-14 10:00:18 -0700526 outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700528 /*
529 * Adjust src X offset to avoid MDP from overfetching pixels
530 * present before the offset. This is required for video
531 * frames coming with unused green pixels along the left margin
532 */
kuogee hsiehe1ed1ae2011-09-02 08:53:36 -0700533 /* not RGB use VG pipe, pure VG pipe */
534 if (ptype != OVERLAY_TYPE_RGB) {
535 mdp4_overlay_vg_get_src_offset(pipe, vg_base, &luma_offset,
536 &chroma_offset);
537 } else {
538 luma_offset = 0;
539 chroma_offset = 0;
540 }
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542 /* luma component plane */
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700543 outpdw(vg_base + 0x0010, pipe->srcp0_addr + luma_offset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700544
545 /* chroma component plane or planar color 1 */
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700546 outpdw(vg_base + 0x0014, pipe->srcp1_addr + chroma_offset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547
548 /* planar color 2 */
Ravishangar Kalyanam01d68282011-07-18 18:45:06 -0700549 outpdw(vg_base + 0x0018, pipe->srcp2_addr + chroma_offset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550
551 outpdw(vg_base + 0x0040,
552 pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
553
554 outpdw(vg_base + 0x0044,
555 pipe->srcp3_ystride << 16 | pipe->srcp2_ystride);
556
557 outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */
558 outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */
559 outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
560 outpdw(vg_base + 0x005c, pipe->phasex_step);
561 outpdw(vg_base + 0x0060, pipe->phasey_step);
562
563 if (pipe->op_mode & MDP4_OP_DITHER_EN) {
564 outpdw(vg_base + 0x0068,
565 pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
566 }
567
568 if (pipe->flags & MDP_SHARPENING) {
569 outpdw(vg_base + 0x8200,
570 mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
571 0));
572 outpdw(vg_base + 0x8204,
573 mdp4_ss_table_value(pipe->req_data.dpp.sharp_strength,
574 1));
575 }
576
577 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
578
579 mdp4_stat.pipe[pipe->pipe_num]++;
580}
581
582int mdp4_overlay_format2type(uint32 format)
583{
584 switch (format) {
585 case MDP_RGB_565:
586 case MDP_RGB_888:
587 case MDP_BGR_565:
588 case MDP_XRGB_8888:
589 case MDP_ARGB_8888:
590 case MDP_RGBA_8888:
591 case MDP_BGRA_8888:
592 case MDP_RGBX_8888:
593 return OVERLAY_TYPE_RGB;
594 case MDP_YCRYCB_H2V1:
595 case MDP_Y_CRCB_H2V1:
596 case MDP_Y_CBCR_H2V1:
597 case MDP_Y_CRCB_H2V2:
598 case MDP_Y_CBCR_H2V2:
599 case MDP_Y_CBCR_H2V2_TILE:
600 case MDP_Y_CRCB_H2V2_TILE:
601 case MDP_Y_CR_CB_H2V2:
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +0530602 case MDP_Y_CR_CB_GH2V2:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 case MDP_Y_CB_CR_H2V2:
604 case MDP_Y_CRCB_H1V1:
605 case MDP_Y_CBCR_H1V1:
606 return OVERLAY_TYPE_VIDEO;
607 default:
608 mdp4_stat.err_format++;
609 return -ERANGE;
610 }
611
612}
613
614#define C3_ALPHA 3 /* alpha */
615#define C2_R_Cr 2 /* R/Cr */
616#define C1_B_Cb 1 /* B/Cb */
617#define C0_G_Y 0 /* G/luma */
618#define YUV_444_MAX_WIDTH 1280 /* Max width for YUV 444*/
619
620int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
621{
622 switch (pipe->src_format) {
623 case MDP_RGB_565:
624 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
625 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
626 pipe->a_bit = 0;
627 pipe->r_bit = 1; /* R, 5 bits */
628 pipe->b_bit = 1; /* B, 5 bits */
629 pipe->g_bit = 2; /* G, 6 bits */
630 pipe->alpha_enable = 0;
631 pipe->unpack_tight = 1;
632 pipe->unpack_align_msb = 0;
633 pipe->unpack_count = 2;
634 pipe->element2 = C2_R_Cr; /* R */
635 pipe->element1 = C0_G_Y; /* G */
636 pipe->element0 = C1_B_Cb; /* B */
637 pipe->bpp = 2; /* 2 bpp */
638 break;
639 case MDP_RGB_888:
640 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
641 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
642 pipe->a_bit = 0;
643 pipe->r_bit = 3; /* R, 8 bits */
644 pipe->b_bit = 3; /* B, 8 bits */
645 pipe->g_bit = 3; /* G, 8 bits */
646 pipe->alpha_enable = 0;
647 pipe->unpack_tight = 1;
648 pipe->unpack_align_msb = 0;
649 pipe->unpack_count = 2;
650 pipe->element2 = C2_R_Cr; /* R */
651 pipe->element1 = C0_G_Y; /* G */
652 pipe->element0 = C1_B_Cb; /* B */
653 pipe->bpp = 3; /* 3 bpp */
654 break;
655 case MDP_BGR_565:
656 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
657 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
658 pipe->a_bit = 0;
659 pipe->r_bit = 1; /* R, 5 bits */
660 pipe->b_bit = 1; /* B, 5 bits */
661 pipe->g_bit = 2; /* G, 6 bits */
662 pipe->alpha_enable = 0;
663 pipe->unpack_tight = 1;
664 pipe->unpack_align_msb = 0;
665 pipe->unpack_count = 2;
666 pipe->element2 = C1_B_Cb; /* B */
667 pipe->element1 = C0_G_Y; /* G */
668 pipe->element0 = C2_R_Cr; /* R */
669 pipe->bpp = 2; /* 2 bpp */
670 break;
671 case MDP_XRGB_8888:
672 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
673 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
674 pipe->a_bit = 3; /* alpha, 4 bits */
675 pipe->r_bit = 3; /* R, 8 bits */
676 pipe->b_bit = 3; /* B, 8 bits */
677 pipe->g_bit = 3; /* G, 8 bits */
678 pipe->alpha_enable = 0;
679 pipe->unpack_tight = 1;
680 pipe->unpack_align_msb = 0;
681 pipe->unpack_count = 3;
682 pipe->element3 = C3_ALPHA; /* alpha */
683 pipe->element2 = C2_R_Cr; /* R */
684 pipe->element1 = C0_G_Y; /* G */
685 pipe->element0 = C1_B_Cb; /* B */
686 pipe->bpp = 4; /* 4 bpp */
687 break;
688 case MDP_ARGB_8888:
689 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
690 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
691 pipe->a_bit = 3; /* alpha, 4 bits */
692 pipe->r_bit = 3; /* R, 8 bits */
693 pipe->b_bit = 3; /* B, 8 bits */
694 pipe->g_bit = 3; /* G, 8 bits */
695 pipe->alpha_enable = 1;
696 pipe->unpack_tight = 1;
697 pipe->unpack_align_msb = 0;
698 pipe->unpack_count = 3;
699 pipe->element3 = C3_ALPHA; /* alpha */
700 pipe->element2 = C2_R_Cr; /* R */
701 pipe->element1 = C0_G_Y; /* G */
702 pipe->element0 = C1_B_Cb; /* B */
703 pipe->bpp = 4; /* 4 bpp */
704 break;
705 case MDP_RGBA_8888:
706 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
707 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
708 pipe->a_bit = 3; /* alpha, 4 bits */
709 pipe->r_bit = 3; /* R, 8 bits */
710 pipe->b_bit = 3; /* B, 8 bits */
711 pipe->g_bit = 3; /* G, 8 bits */
712 pipe->alpha_enable = 1;
713 pipe->unpack_tight = 1;
714 pipe->unpack_align_msb = 0;
715 pipe->unpack_count = 3;
716 pipe->element3 = C3_ALPHA; /* alpha */
717 pipe->element2 = C1_B_Cb; /* B */
718 pipe->element1 = C0_G_Y; /* G */
719 pipe->element0 = C2_R_Cr; /* R */
720 pipe->bpp = 4; /* 4 bpp */
721 break;
722 case MDP_RGBX_8888:
723 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
724 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
725 pipe->a_bit = 3;
726 pipe->r_bit = 3; /* R, 8 bits */
727 pipe->b_bit = 3; /* B, 8 bits */
728 pipe->g_bit = 3; /* G, 8 bits */
729 pipe->alpha_enable = 0;
730 pipe->unpack_tight = 1;
731 pipe->unpack_align_msb = 0;
732 pipe->unpack_count = 3;
733 pipe->element3 = C3_ALPHA; /* alpha */
734 pipe->element2 = C1_B_Cb; /* B */
735 pipe->element1 = C0_G_Y; /* G */
736 pipe->element0 = C2_R_Cr; /* R */
737 pipe->bpp = 4; /* 4 bpp */
738 break;
739 case MDP_BGRA_8888:
740 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
741 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
742 pipe->a_bit = 3; /* alpha, 4 bits */
743 pipe->r_bit = 3; /* R, 8 bits */
744 pipe->b_bit = 3; /* B, 8 bits */
745 pipe->g_bit = 3; /* G, 8 bits */
746 pipe->alpha_enable = 1;
747 pipe->unpack_tight = 1;
748 pipe->unpack_align_msb = 0;
749 pipe->unpack_count = 3;
750 pipe->element3 = C3_ALPHA; /* alpha */
751 pipe->element2 = C2_R_Cr; /* R */
752 pipe->element1 = C0_G_Y; /* G */
753 pipe->element0 = C1_B_Cb; /* B */
754 pipe->bpp = 4; /* 4 bpp */
755 break;
756 case MDP_YCRYCB_H2V1:
757 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
758 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
759 pipe->a_bit = 0; /* alpha, 4 bits */
760 pipe->r_bit = 3; /* R, 8 bits */
761 pipe->b_bit = 3; /* B, 8 bits */
762 pipe->g_bit = 3; /* G, 8 bits */
763 pipe->alpha_enable = 0;
764 pipe->unpack_tight = 1;
765 pipe->unpack_align_msb = 0;
766 pipe->unpack_count = 3;
767 pipe->element3 = C0_G_Y; /* G */
768 pipe->element2 = C2_R_Cr; /* R */
769 pipe->element1 = C0_G_Y; /* G */
770 pipe->element0 = C1_B_Cb; /* B */
771 pipe->bpp = 2; /* 2 bpp */
772 pipe->chroma_sample = MDP4_CHROMA_H2V1;
773 break;
774 case MDP_Y_CRCB_H2V1:
775 case MDP_Y_CBCR_H2V1:
776 case MDP_Y_CRCB_H2V2:
777 case MDP_Y_CBCR_H2V2:
778 case MDP_Y_CRCB_H1V1:
779 case MDP_Y_CBCR_H1V1:
780 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
781 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
782 pipe->a_bit = 0;
783 pipe->r_bit = 3; /* R, 8 bits */
784 pipe->b_bit = 3; /* B, 8 bits */
785 pipe->g_bit = 3; /* G, 8 bits */
786 pipe->alpha_enable = 0;
787 pipe->unpack_tight = 1;
788 pipe->unpack_align_msb = 0;
789 pipe->unpack_count = 1; /* 2 */
790 pipe->element3 = C0_G_Y; /* not used */
791 pipe->element2 = C0_G_Y; /* not used */
792 if (pipe->src_format == MDP_Y_CRCB_H2V1) {
793 pipe->element1 = C2_R_Cr; /* R */
794 pipe->element0 = C1_B_Cb; /* B */
795 pipe->chroma_sample = MDP4_CHROMA_H2V1;
796 } else if (pipe->src_format == MDP_Y_CRCB_H1V1) {
797 pipe->element1 = C2_R_Cr; /* R */
798 pipe->element0 = C1_B_Cb; /* B */
799 if (pipe->src_width > YUV_444_MAX_WIDTH)
800 pipe->chroma_sample = MDP4_CHROMA_H1V2;
801 else
802 pipe->chroma_sample = MDP4_CHROMA_RGB;
803 } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
804 pipe->element1 = C1_B_Cb; /* B */
805 pipe->element0 = C2_R_Cr; /* R */
806 pipe->chroma_sample = MDP4_CHROMA_H2V1;
807 } else if (pipe->src_format == MDP_Y_CBCR_H1V1) {
808 pipe->element1 = C1_B_Cb; /* B */
809 pipe->element0 = C2_R_Cr; /* R */
810 if (pipe->src_width > YUV_444_MAX_WIDTH)
811 pipe->chroma_sample = MDP4_CHROMA_H1V2;
812 else
813 pipe->chroma_sample = MDP4_CHROMA_RGB;
814 } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
815 pipe->element1 = C2_R_Cr; /* R */
816 pipe->element0 = C1_B_Cb; /* B */
817 pipe->chroma_sample = MDP4_CHROMA_420;
818 } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
819 pipe->element1 = C1_B_Cb; /* B */
820 pipe->element0 = C2_R_Cr; /* R */
821 pipe->chroma_sample = MDP4_CHROMA_420;
822 }
823 pipe->bpp = 2; /* 2 bpp */
824 break;
825 case MDP_Y_CBCR_H2V2_TILE:
826 case MDP_Y_CRCB_H2V2_TILE:
827 pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
828 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
829 pipe->a_bit = 0;
830 pipe->r_bit = 3; /* R, 8 bits */
831 pipe->b_bit = 3; /* B, 8 bits */
832 pipe->g_bit = 3; /* G, 8 bits */
833 pipe->alpha_enable = 0;
834 pipe->unpack_tight = 1;
835 pipe->unpack_align_msb = 0;
836 pipe->unpack_count = 1; /* 2 */
837 pipe->element3 = C0_G_Y; /* not used */
838 pipe->element2 = C0_G_Y; /* not used */
839 if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
840 pipe->element1 = C2_R_Cr; /* R */
841 pipe->element0 = C1_B_Cb; /* B */
842 pipe->chroma_sample = MDP4_CHROMA_420;
843 } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
844 pipe->element1 = C1_B_Cb; /* B */
845 pipe->element0 = C2_R_Cr; /* R */
846 pipe->chroma_sample = MDP4_CHROMA_420;
847 }
848 pipe->bpp = 2; /* 2 bpp */
849 break;
850 case MDP_Y_CR_CB_H2V2:
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +0530851 case MDP_Y_CR_CB_GH2V2:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 case MDP_Y_CB_CR_H2V2:
853 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
854 pipe->fetch_plane = OVERLAY_PLANE_PLANAR;
855 pipe->a_bit = 0;
856 pipe->r_bit = 3; /* R, 8 bits */
857 pipe->b_bit = 3; /* B, 8 bits */
858 pipe->g_bit = 3; /* G, 8 bits */
859 pipe->alpha_enable = 0;
Adrian Salido-Moreno33dc7b92011-08-18 16:16:12 -0700860 pipe->chroma_sample = MDP4_CHROMA_420;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861 pipe->bpp = 2; /* 2 bpp */
862 break;
863 default:
864 /* not likely */
865 mdp4_stat.err_format++;
866 return -ERANGE;
867 }
868
869 return 0;
870}
871
872/*
873 * color_key_convert: output with 12 bits color key
874 */
875static uint32 color_key_convert(int start, int num, uint32 color)
876{
877 uint32 data;
878
879 data = (color >> start) & ((1 << num) - 1);
880
881 /* convert to 8 bits */
882 if (num == 5)
883 data = ((data << 3) | (data >> 2));
884 else if (num == 6)
885 data = ((data << 2) | (data >> 4));
886
887 /* convert 8 bits to 12 bits */
888 data = (data << 4) | (data >> 4);
889
890 return data;
891}
892
893void transp_color_key(int format, uint32 transp,
894 uint32 *c0, uint32 *c1, uint32 *c2)
895{
896 int b_start, g_start, r_start;
897 int b_num, g_num, r_num;
898
899 switch (format) {
900 case MDP_RGB_565:
901 b_start = 0;
902 g_start = 5;
903 r_start = 11;
904 r_num = 5;
905 g_num = 6;
906 b_num = 5;
907 break;
908 case MDP_RGB_888:
909 case MDP_XRGB_8888:
910 case MDP_ARGB_8888:
911 case MDP_BGRA_8888:
912 b_start = 0;
913 g_start = 8;
914 r_start = 16;
915 r_num = 8;
916 g_num = 8;
917 b_num = 8;
918 break;
919 case MDP_RGBA_8888:
920 case MDP_RGBX_8888:
921 b_start = 16;
922 g_start = 8;
923 r_start = 0;
924 r_num = 8;
925 g_num = 8;
926 b_num = 8;
927 break;
928 case MDP_BGR_565:
929 b_start = 11;
930 g_start = 5;
931 r_start = 0;
932 r_num = 5;
933 g_num = 6;
934 b_num = 5;
935 break;
936 case MDP_Y_CB_CR_H2V2:
937 case MDP_Y_CBCR_H2V2:
938 case MDP_Y_CBCR_H2V1:
939 b_start = 8;
940 g_start = 16;
941 r_start = 0;
942 r_num = 8;
943 g_num = 8;
944 b_num = 8;
945 break;
946 case MDP_Y_CR_CB_H2V2:
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +0530947 case MDP_Y_CR_CB_GH2V2:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700948 case MDP_Y_CRCB_H2V2:
949 case MDP_Y_CRCB_H2V1:
950 case MDP_Y_CRCB_H1V1:
951 case MDP_Y_CBCR_H1V1:
952 b_start = 0;
953 g_start = 16;
954 r_start = 8;
955 r_num = 8;
956 g_num = 8;
957 b_num = 8;
958 break;
959 default:
960 b_start = 0;
961 g_start = 8;
962 r_start = 16;
963 r_num = 8;
964 g_num = 8;
965 b_num = 8;
966 break;
967 }
968
969 *c0 = color_key_convert(g_start, g_num, transp);
970 *c1 = color_key_convert(b_start, b_num, transp);
971 *c2 = color_key_convert(r_start, r_num, transp);
972}
973
974uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
975{
976 uint32 format;
977
978 format = 0;
979
980 if (pipe->solid_fill)
981 format |= MDP4_FORMAT_SOLID_FILL;
982
983 if (pipe->unpack_align_msb)
984 format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
985
986 if (pipe->unpack_tight)
987 format |= MDP4_FORMAT_UNPACK_TIGHT;
988
989 if (pipe->alpha_enable)
990 format |= MDP4_FORMAT_ALPHA_ENABLE;
991
992 if (pipe->flags & MDP_SOURCE_ROTATED_90)
993 format |= MDP4_FORMAT_90_ROTATED;
994 format |= (pipe->unpack_count << 13);
995 format |= ((pipe->bpp - 1) << 9);
996 format |= (pipe->a_bit << 6);
997 format |= (pipe->r_bit << 4);
998 format |= (pipe->b_bit << 2);
999 format |= pipe->g_bit;
1000
1001 format |= (pipe->frame_format << 29);
1002
1003 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR ||
1004 pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
1005 /* video/graphic */
1006 format |= (pipe->fetch_plane << 19);
1007 format |= (pipe->chroma_site << 28);
1008 format |= (pipe->chroma_sample << 26);
1009 }
1010
1011 return format;
1012}
1013
1014uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
1015{
1016 return (pipe->element3 << 24) | (pipe->element2 << 16) |
1017 (pipe->element1 << 8) | pipe->element0;
1018}
1019
1020/*
1021 * mdp4_overlayproc_cfg: only be called from base layer
1022 */
1023void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
1024{
1025 uint32 data, intf;
1026 char *overlay_base;
1027
1028 intf = 0;
1029 if (pipe->mixer_num == MDP4_MIXER1) {
1030 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
1031 intf = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
1032 intf >>= 4;
1033 intf &= 0x03;
1034 } else
1035 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
1036
1037 if (mdp_is_in_isr == FALSE)
1038 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1039
1040 /*
1041 * BLT only siupport at primary display
1042 */
Vinay Kalia27020d12011-10-14 17:50:29 -07001043 if (pipe->blt_addr) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001044 int off, bpp;
1045#ifdef BLT_RGB565
1046 bpp = 2; /* overlay ouput is RGB565 */
1047#else
1048 bpp = 3; /* overlay ouput is RGB888 */
1049#endif
1050 data = pipe->src_height;
1051 data <<= 16;
1052 data |= pipe->src_width;
1053 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
Vinay Kalia27020d12011-10-14 17:50:29 -07001054 if (pipe->mixer_num == MDP4_MIXER0) {
1055 off = 0;
1056 if (pipe->ov_cnt & 0x01)
1057 off = pipe->src_height * pipe->src_width * bpp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058
Vinay Kalia27020d12011-10-14 17:50:29 -07001059 outpdw(overlay_base + 0x000c, pipe->blt_addr + off);
1060 /* overlay ouput is RGB888 */
1061 outpdw(overlay_base + 0x0010, pipe->src_width * bpp);
1062 outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
1063 /* MDDI - BLT + on demand */
1064 outpdw(overlay_base + 0x0004, 0x08);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001065#ifdef BLT_RGB565
Vinay Kalia27020d12011-10-14 17:50:29 -07001066 outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001067#else
Vinay Kalia27020d12011-10-14 17:50:29 -07001068 outpdw(overlay_base + 0x0014, 0x0); /* RGB888 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069#endif
Vinay Kalia27020d12011-10-14 17:50:29 -07001070 } else {
1071 if (ctrl->panel_mode & MDP4_PANEL_WRITEBACK) {
1072 off = 0;
1073 bpp = 2;
1074 if (pipe->ov_cnt & 0x01)
1075 off = pipe->src_height *
1076 pipe->src_width * bpp;
1077
1078 outpdw(overlay_base + 0x000c,
1079 pipe->blt_addr + off);
1080 /* overlay ouput is RGB888 */
1081 outpdw(overlay_base + 0x0010,
1082 pipe->src_width * bpp);
1083 outpdw(overlay_base + 0x001c,
1084 pipe->blt_addr + off);
1085 /* MDDI - BLT + on demand */
1086 outpdw(overlay_base + 0x0004, 0x08);
1087 outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
1088 }
1089 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090 } else {
1091 data = pipe->src_height;
1092 data <<= 16;
1093 data |= pipe->src_width;
1094 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
1095 outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
1096 outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
1097 outpdw(overlay_base + 0x0004, 0x01); /* directout */
1098 }
1099
1100 if (pipe->mixer_num == MDP4_MIXER1) {
1101 if (intf == TV_INTF) {
1102 outpdw(overlay_base + 0x0014, 0x02); /* yuv422 */
1103 /* overlay1 CSC config */
1104 outpdw(overlay_base + 0x0200, 0x05); /* rgb->yuv */
1105 }
1106 }
1107
1108#ifdef MDP4_IGC_LUT_ENABLE
1109 outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
1110#endif
1111
1112 if (mdp_is_in_isr == FALSE)
1113 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1114}
1115
1116int mdp4_overlay_pipe_staged(int mixer)
1117{
1118 uint32 data, mask, i;
1119 int p1, p2;
1120
1121 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1122 data = inpdw(MDP_BASE + 0x10100);
1123 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1124 p1 = 0;
1125 p2 = 0;
1126 for (i = 0; i < 8; i++) {
1127 mask = data & 0x0f;
1128 if (mask) {
1129 if (mask <= 4)
1130 p1++;
1131 else
1132 p2++;
1133 }
1134 data >>= 4;
1135 }
1136
1137 if (mixer)
1138 return p2;
1139 else
1140 return p1;
1141}
1142
kuogee hsieh405dc302011-07-21 15:06:59 -07001143int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info)
1144{
1145
1146 int ndx, cnt;
1147 struct mdp4_overlay_pipe *pipe;
1148
1149 if (mixer_num > MDP4_MIXER_MAX)
1150 return -ENODEV;
1151
1152 cnt = 0;
1153 ndx = 1; /* ndx 0 if not used */
1154
1155 for ( ; ndx < MDP4_MIXER_STAGE_MAX; ndx++) {
1156 pipe = ctrl->stage[mixer_num][ndx];
1157 if (pipe == NULL)
1158 continue;
1159 info->z_order = pipe->mixer_stage - MDP4_MIXER_STAGE0;
1160 info->ptype = pipe->pipe_type;
1161 info->pnum = pipe->pipe_num;
1162 info->pndx = pipe->pipe_ndx;
1163 info->mixer_num = pipe->mixer_num;
1164 info++;
1165 cnt++;
1166 }
1167 return cnt;
1168}
1169
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001170void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
1171{
1172 uint32 data, mask, snum, stage, mixer, pnum;
Adrian Salido-Morenoc4302232011-09-26 12:54:03 -07001173 struct mdp4_overlay_pipe *spipe;
1174
1175 spipe = mdp4_overlay_stage_pipe(pipe->mixer_num, pipe->mixer_stage);
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001176 if ((spipe != NULL) && (spipe->pipe_num != pipe->pipe_num)) {
Adrian Salido-Morenoc4302232011-09-26 12:54:03 -07001177 pr_err("%s: unable to stage pipe=%d at mixer_stage=%d\n",
1178 __func__, pipe->pipe_ndx, pipe->mixer_stage);
1179 return;
1180 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001181
1182 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1183
1184 stage = pipe->mixer_stage;
1185 mixer = pipe->mixer_num;
1186 pnum = pipe->pipe_num;
1187
1188 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
1189 data = inpdw(MDP_BASE + 0x10100);
1190
1191 if (mixer == MDP4_MIXER1)
1192 stage += 8;
1193
1194 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
1195 pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
1196 snum = 0;
1197 snum += (4 * pnum);
1198 } else {
1199 snum = 8;
1200 snum += (4 * pnum); /* RGB1 and RGB2 */
1201 }
1202
1203 mask = 0x0f;
1204 mask <<= snum;
1205 stage <<= snum;
1206 data &= ~mask; /* clear old bits */
1207
1208 data |= stage;
1209
1210 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
1211
1212 data = inpdw(MDP_BASE + 0x10100);
1213
1214 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1215
1216 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
1217}
1218
1219void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
1220{
1221 uint32 data, mask, snum, stage, mixer, pnum;
1222
1223 stage = pipe->mixer_stage;
1224 mixer = pipe->mixer_num;
1225 pnum = pipe->pipe_num;
1226
1227 if (pipe != ctrl->stage[mixer][stage]) /* not runing */
1228 return;
1229
1230 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1231
1232 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
1233 data = inpdw(MDP_BASE + 0x10100);
1234
1235 if (mixer == MDP4_MIXER1)
1236 stage += 8;
1237
1238 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) {/* VG1 and VG2 */
1239 pnum -= OVERLAY_PIPE_VG1; /* start from 0 */
1240 snum = 0;
1241 snum += (4 * pnum);
1242 } else {
1243 snum = 8;
1244 snum += (4 * pnum); /* RGB1 and RGB2 */
1245 }
1246
1247 mask = 0x0f;
1248 mask <<= snum;
1249 data &= ~mask; /* clear old bits */
1250
1251 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
1252
1253 data = inpdw(MDP_BASE + 0x10100);
1254
1255 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1256
1257 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
1258}
1259
1260void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
1261{
1262 struct mdp4_overlay_pipe *bg_pipe;
1263 unsigned char *overlay_base, *rgb_base;
1264 uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
1265 int off;
1266
1267 if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
1268 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
1269 else
1270 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
1271
1272 /* stage 0 to stage 2 */
1273 off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
1274
1275 bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
1276 MDP4_MIXER_STAGE_BASE);
1277 if (bg_pipe == NULL) {
1278 pr_err("%s: Error: no bg_pipe\n", __func__);
1279 return;
1280 }
1281
1282 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1283
1284 blend_op = 0;
1285
1286 if (pipe->is_fg) {
1287 blend_op |= (MDP4_BLEND_FG_ALPHA_FG_CONST |
1288 MDP4_BLEND_BG_ALPHA_BG_CONST);
1289 outpdw(overlay_base + off + 0x108, pipe->alpha);
1290 outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
1291 if (pipe->alpha == 0xff) {
1292 rgb_base = MDP_BASE + MDP4_RGB_BASE;
1293 rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
1294 rgb_src_format = inpdw(rgb_base + 0x50);
1295 rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
1296 outpdw(rgb_base + 0x50, rgb_src_format);
1297 outpdw(rgb_base + 0x1008, constant_color);
1298 }
1299 } else {
1300 if (bg_pipe->alpha_enable && pipe->alpha_enable) {
1301 /* both pipe have alpha */
1302 blend_op |= (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
1303 MDP4_BLEND_FG_INV_ALPHA |
1304 MDP4_BLEND_BG_ALPHA_BG_PIXEL);
1305 } else if (bg_pipe->alpha_enable && pipe->alpha_enable == 0) {
1306 /* no alpha on both pipe */
1307 blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
1308 MDP4_BLEND_FG_ALPHA_BG_PIXEL |
1309 MDP4_BLEND_FG_INV_ALPHA);
1310 }
1311 }
1312
1313
1314 if (pipe->transp != MDP_TRANSP_NOP) {
1315 if (pipe->is_fg) {
1316 transp_color_key(pipe->src_format, pipe->transp,
1317 &c0, &c1, &c2);
1318 /* Fg blocked */
1319 blend_op |= MDP4_BLEND_FG_TRANSP_EN;
1320 /* lower limit */
1321 outpdw(overlay_base + off + 0x110,
1322 (c1 << 16 | c0));/* low */
1323 outpdw(overlay_base + off + 0x114, c2);/* low */
1324 /* upper limit */
1325 outpdw(overlay_base + off + 0x118,
1326 (c1 << 16 | c0));
1327 outpdw(overlay_base + off + 0x11c, c2);
1328 } else {
1329 transp_color_key(bg_pipe->src_format,
1330 pipe->transp, &c0, &c1, &c2);
1331 /* bg blocked */
1332 blend_op |= MDP4_BLEND_BG_TRANSP_EN;
1333 /* lower limit */
1334 outpdw(overlay_base + 0x180,
1335 (c1 << 16 | c0));/* low */
1336 outpdw(overlay_base + 0x184, c2);/* low */
1337 /* upper limit */
1338 outpdw(overlay_base + 0x188,
1339 (c1 << 16 | c0));/* high */
1340 outpdw(overlay_base + 0x18c, c2);/* high */
1341 }
1342 }
1343
1344 outpdw(overlay_base + off + 0x104, blend_op);
1345
1346 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1347}
1348
1349void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
1350{
1351 struct mdp4_overlay_pipe *bg_pipe;
1352 uint32 bits = 0;
1353
1354 if (pipe->mixer_num == MDP4_MIXER1)
1355 bits |= 0x02;
1356 else
1357 bits |= 0x01;
1358
1359 if (all) {
1360 if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1361 if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
1362 bits |= 0x20;
1363 else
1364 bits |= 0x10;
1365 } else {
1366 if (pipe->is_fg && pipe->alpha == 0xFF) {
1367 bg_pipe = mdp4_overlay_stage_pipe(
1368 pipe->mixer_num,
1369 MDP4_MIXER_STAGE_BASE);
1370 if (bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1371 if (bg_pipe->pipe_num ==
1372 OVERLAY_PIPE_RGB2)
1373 bits |= 0x20;
1374 else
1375 bits |= 0x10;
1376 }
1377 }
1378 if (pipe->pipe_num == OVERLAY_PIPE_VG2)
1379 bits |= 0x08;
1380 else
1381 bits |= 0x04;
1382 }
1383 }
1384
1385 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1386 outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
1387 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1388}
1389
1390struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
1391{
1392 return ctrl->stage[mixer][stage];
1393}
1394
1395struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
1396{
1397 struct mdp4_overlay_pipe *pipe;
1398
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001399 if (ndx <= 0 || ndx > OVERLAY_PIPE_MAX)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001400 return NULL;
1401
1402 pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
1403
1404 if (pipe->pipe_used == 0)
1405 return NULL;
1406
1407 return pipe;
1408}
1409
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001410struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001411{
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001412 int i;
1413 struct mdp4_overlay_pipe *pipe;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001415 for (i = 0; i < OVERLAY_PIPE_MAX; i++) {
1416 pipe = &ctrl->plist[i];
1417 if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
1418 (ptype == OVERLAY_TYPE_RGB &&
1419 pipe->pipe_type == OVERLAY_TYPE_VIDEO))) {
1420 init_completion(&pipe->comp);
1421 init_completion(&pipe->dmas_comp);
1422 pr_info("%s: pipe=%x ndx=%d num=%d\n", __func__,
1423 (int)pipe, pipe->pipe_ndx, pipe->pipe_num);
1424 return pipe;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001425 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426 }
1427
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001428 pr_err("%s: ptype=%d FAILED\n", __func__, ptype);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429
1430 return NULL;
1431}
1432
1433
1434void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
1435{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436 uint32 ptype, num, ndx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001437
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001438 pr_info("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001439
1440 ptype = pipe->pipe_type;
1441 num = pipe->pipe_num;
1442 ndx = pipe->pipe_ndx;
1443
1444 memset(pipe, 0, sizeof(*pipe));
1445
1446 pipe->pipe_type = ptype;
1447 pipe->pipe_num = num;
1448 pipe->pipe_ndx = ndx;
1449}
1450
1451int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
1452{
1453 struct mdp4_overlay_pipe *pipe;
1454
1455 pipe = ctrl->stage[mixer][z_order];
1456
1457 if (pipe == NULL)
1458 return 0;
1459
1460 if (pipe->pipe_ndx == id) /* same req, recycle */
1461 return 0;
1462
1463 if (id == MSMFB_NEW_REQUEST) { /* new request */
1464 if (pipe->pipe_num >= OVERLAY_PIPE_VG1) /* share pipe */
1465 return 0;
1466 }
1467
1468 return -EPERM;
1469}
1470
1471static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
1472 struct msm_fb_data_type *mfd, uint32 perf_level, uint32 pclk_rate)
1473{
1474 __u32 panel_clk_khz, mdp_clk_khz;
1475 __u32 num_hsync_pix_clks, mdp_clks_per_hsync, src_wh;
1476 __u32 hsync_period_ps, mdp_period_ps, total_hsync_period_ps;
1477 unsigned long fill_rate_y_dir, fill_rate_x_dir;
1478 unsigned long fillratex100, mdp_pixels_produced;
1479 unsigned long mdp_clk_hz;
1480
1481 pr_debug("%s: LCDC Mode Downscale validation with MDP Core"
1482 " Clk rate\n", __func__);
1483 pr_debug("src_w %u, src_h %u, dst_w %u, dst_h %u\n",
1484 req->src_rect.w, req->src_rect.h, req->dst_rect.w,
1485 req->dst_rect.h);
1486
1487
1488 panel_clk_khz = pclk_rate/1000;
1489 mdp_clk_hz = mdp_perf_level2clk_rate(perf_level);
1490
Ravishangar Kalyanamc42862a2011-09-14 11:42:34 -07001491 if (!mdp_clk_hz || !req->dst_rect.w || !req->dst_rect.h) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001492 pr_debug("mdp_perf_level2clk_rate returned 0,"
Ravishangar Kalyanamc42862a2011-09-14 11:42:34 -07001493 "or dst_rect height/width is 0,"
1494 "Downscale Validation incomplete\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495 return 0;
1496 }
1497
1498 mdp_clk_khz = mdp_clk_hz/1000;
1499
1500 num_hsync_pix_clks = mfd->panel_info.lcdc.h_back_porch +
1501 mfd->panel_info.lcdc.h_front_porch +
1502 mfd->panel_info.lcdc.h_pulse_width +
1503 mfd->panel_info.xres;
1504
1505 hsync_period_ps = 1000000000/panel_clk_khz;
1506 mdp_period_ps = 1000000000/mdp_clk_khz;
1507
1508 total_hsync_period_ps = num_hsync_pix_clks * hsync_period_ps;
1509 mdp_clks_per_hsync = total_hsync_period_ps/mdp_period_ps;
1510
1511 pr_debug("hsync_period_ps %u, mdp_period_ps %u,"
1512 "total_hsync_period_ps %u\n", hsync_period_ps,
1513 mdp_period_ps, total_hsync_period_ps);
1514
1515 src_wh = req->src_rect.w * req->src_rect.h;
1516 if (src_wh % req->dst_rect.h)
1517 fill_rate_y_dir = (src_wh / req->dst_rect.h) + 1;
1518 else
1519 fill_rate_y_dir = (src_wh / req->dst_rect.h);
1520
1521 fill_rate_x_dir = (mfd->panel_info.xres - req->dst_rect.w)
1522 + req->src_rect.w;
1523
1524 if (fill_rate_y_dir >= fill_rate_x_dir)
1525 fillratex100 = 100 * fill_rate_y_dir / mfd->panel_info.xres;
1526 else
1527 fillratex100 = 100 * fill_rate_x_dir / mfd->panel_info.xres;
1528
1529 pr_debug("mdp_clks_per_hsync %u, fill_rate_y_dir %lu,"
1530 "fill_rate_x_dir %lu\n", mdp_clks_per_hsync,
1531 fill_rate_y_dir, fill_rate_x_dir);
1532
1533 mdp_pixels_produced = 100 * mdp_clks_per_hsync/fillratex100;
1534 pr_debug("fillratex100 %lu, mdp_pixels_produced %lu\n",
1535 fillratex100, mdp_pixels_produced);
1536 if (mdp_pixels_produced <= mfd->panel_info.xres) {
1537 pr_err("%s(): LCDC underflow detected during downscale\n",
1538 __func__);
1539 return -ERANGE;
1540 }
1541
1542 return 0;
1543}
1544
1545static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
1546 struct mdp4_overlay_pipe **ppipe,
1547 struct msm_fb_data_type *mfd)
1548{
1549 struct mdp4_overlay_pipe *pipe;
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001550 int ret, ptype;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001551
1552 if (mfd == NULL) {
1553 pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
1554 return -ENODEV;
1555 }
1556
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001557 if (mixer >= MDP4_MIXER_MAX) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001558 pr_err("%s: mixer out of range!\n", __func__);
1559 mdp4_stat.err_mixer++;
1560 return -ERANGE;
1561 }
1562
1563 if (req->z_order < 0 || req->z_order > 2) {
1564 pr_err("%s: z_order=%d out of range!\n", __func__,
1565 req->z_order);
1566 mdp4_stat.err_zorder++;
1567 return -ERANGE;
1568 }
1569
1570 if (req->src_rect.h == 0 || req->src_rect.w == 0) {
1571 pr_err("%s: src img of zero size!\n", __func__);
1572 mdp4_stat.err_size++;
1573 return -EINVAL;
1574 }
1575
1576
1577 if (req->dst_rect.h > (req->src_rect.h * 8)) { /* too much */
1578 mdp4_stat.err_scale++;
1579 pr_err("%s: scale up, too much (h)!\n", __func__);
1580 return -ERANGE;
1581 }
1582
1583 if (req->src_rect.h > (req->dst_rect.h * 8)) { /* too little */
1584 mdp4_stat.err_scale++;
1585 pr_err("%s: scale down, too little (h)!\n", __func__);
1586 return -ERANGE;
1587 }
1588
1589 if (req->dst_rect.w > (req->src_rect.w * 8)) { /* too much */
1590 mdp4_stat.err_scale++;
1591 pr_err("%s: scale up, too much (w)!\n", __func__);
1592 return -ERANGE;
1593 }
1594
1595 if (req->src_rect.w > (req->dst_rect.w * 8)) { /* too little */
1596 mdp4_stat.err_scale++;
1597 pr_err("%s: scale down, too little (w)!\n", __func__);
1598 return -ERANGE;
1599 }
1600
1601 if (mdp_hw_revision == MDP4_REVISION_V1) {
1602 /* non integer down saceling ratio smaller than 1/4
1603 * is not supportted
1604 */
1605 if (req->src_rect.h > (req->dst_rect.h * 4)) {
1606 if (req->src_rect.h % req->dst_rect.h) {
1607 mdp4_stat.err_scale++;
1608 pr_err("%s: need integer (h)!\n", __func__);
1609 return -ERANGE;
1610 }
1611 }
1612
1613 if (req->src_rect.w > (req->dst_rect.w * 4)) {
1614 if (req->src_rect.w % req->dst_rect.w) {
1615 mdp4_stat.err_scale++;
1616 pr_err("%s: need integer (w)!\n", __func__);
1617 return -ERANGE;
1618 }
1619 }
1620 }
1621
1622 if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
1623 ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
1624 mdp4_stat.err_size++;
1625 pr_err("%s invalid src rectangle\n", __func__);
1626 return -ERANGE;
1627 }
1628
1629 if (ctrl->panel_3d != MDP4_3D_SIDE_BY_SIDE) {
1630 int xres;
1631 int yres;
1632
1633 xres = mfd->panel_info.xres;
1634 yres = mfd->panel_info.yres;
1635
1636 if (((req->dst_rect.x + req->dst_rect.w) > xres) ||
1637 ((req->dst_rect.y + req->dst_rect.h) > yres)) {
1638 mdp4_stat.err_size++;
1639 pr_err("%s invalid dst rectangle\n", __func__);
1640 return -ERANGE;
1641 }
1642 }
1643
1644 ptype = mdp4_overlay_format2type(req->src.format);
1645 if (ptype < 0) {
1646 pr_err("%s: mdp4_overlay_format2type!\n", __func__);
1647 return ptype;
1648 }
1649
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001650 if (req->flags & MDP_OV_PIPE_SHARE)
1651 ptype = OVERLAY_TYPE_VIDEO; /* VG pipe supports both RGB+YUV */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001652
1653 if (req->id == MSMFB_NEW_REQUEST) /* new request */
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001654 pipe = mdp4_overlay_pipe_alloc(ptype, mixer);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001655 else
1656 pipe = mdp4_overlay_ndx2pipe(req->id);
1657
1658 if (pipe == NULL) {
1659 pr_err("%s: pipe == NULL!\n", __func__);
1660 return -ENOMEM;
1661 }
1662
1663 /* no down scale at rgb pipe */
1664 if (pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
1665 if ((req->src_rect.h > req->dst_rect.h) ||
1666 (req->src_rect.w > req->dst_rect.w)) {
1667 pr_err("%s: h>h || w>w!\n", __func__);
1668 return -ERANGE;
1669 }
1670 }
1671
1672 pipe->src_format = req->src.format;
1673 ret = mdp4_overlay_format2pipe(pipe);
1674 if (ret < 0) {
1675 pr_err("%s: mdp4_overlay_format2pipe!\n", __func__);
1676 return ret;
1677 }
1678
1679 /*
1680 * base layer == 1, reserved for frame buffer
1681 * zorder 0 == stage 0 == 2
1682 * zorder 1 == stage 1 == 3
1683 * zorder 2 == stage 2 == 4
1684 */
1685 if (req->id == MSMFB_NEW_REQUEST) { /* new request */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001686 pipe->pipe_used++;
1687 pipe->mixer_num = mixer;
1688 pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
1689 pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
1690 req->z_order, pipe->pipe_ndx, pipe->pipe_num);
1691
1692 }
1693
1694 pipe->src_width = req->src.width & 0x07ff; /* source img width */
1695 pipe->src_height = req->src.height & 0x07ff; /* source img height */
1696 pipe->src_h = req->src_rect.h & 0x07ff;
1697 pipe->src_w = req->src_rect.w & 0x07ff;
1698 pipe->src_y = req->src_rect.y & 0x07ff;
1699 pipe->src_x = req->src_rect.x & 0x07ff;
1700 pipe->dst_h = req->dst_rect.h & 0x07ff;
1701 pipe->dst_w = req->dst_rect.w & 0x07ff;
1702 pipe->dst_y = req->dst_rect.y & 0x07ff;
1703 pipe->dst_x = req->dst_rect.x & 0x07ff;
1704
1705 pipe->op_mode = 0;
1706
1707 if (req->flags & MDP_FLIP_LR)
1708 pipe->op_mode |= MDP4_OP_FLIP_LR;
1709
1710 if (req->flags & MDP_FLIP_UD)
1711 pipe->op_mode |= MDP4_OP_FLIP_UD;
1712
1713 if (req->flags & MDP_DITHER)
1714 pipe->op_mode |= MDP4_OP_DITHER_EN;
1715
1716 if (req->flags & MDP_DEINTERLACE)
1717 pipe->op_mode |= MDP4_OP_DEINT_EN;
1718
1719 if (req->flags & MDP_DEINTERLACE_ODD)
1720 pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
1721
1722 pipe->is_fg = req->is_fg;/* control alpha and color key */
1723
1724 pipe->alpha = req->alpha & 0x0ff;
1725
1726 pipe->transp = req->transp_mask;
1727
1728 *ppipe = pipe;
1729
1730 return 0;
1731}
1732
1733static int get_img(struct msmfb_data *img, struct fb_info *info,
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001734 unsigned long *start, unsigned long *len, struct file **srcp_file,
1735 struct ion_handle **srcp_ihdl)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736{
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001737#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
1738 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1739#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001740 struct file *file;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001741 int put_needed, ret = 0, fb_num;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001742#ifdef CONFIG_ANDROID_PMEM
1743 unsigned long vstart;
1744#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 if (img->flags & MDP_BLIT_SRC_GEM) {
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001746 *srcp_file = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001747 return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
1748 start, len);
1749 }
1750
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001751 if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
1752 file = fget_light(img->memory_id, &put_needed);
1753 if (file == NULL)
1754 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001756 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1757 fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
1758 if (get_fb_phys_info(start, len, fb_num))
1759 ret = -1;
1760 else
1761 *srcp_file = file;
1762 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001763 ret = -1;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07001764 if (ret)
1765 fput_light(file, put_needed);
1766 return ret;
1767 }
1768
1769#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
1770 *srcp_ihdl = ion_import_fd(mfd->client, img->memory_id);
1771 if (IS_ERR_OR_NULL(*srcp_ihdl))
1772 return PTR_ERR(*srcp_ihdl);
1773 if (!ion_phys(mfd->client, *srcp_ihdl, start, (size_t *) len))
1774 return 0;
1775 else
1776 return -EINVAL;
1777#endif
1778#ifdef CONFIG_ANDROID_PMEM
1779 if (!get_pmem_file(img->memory_id, start, &vstart,
1780 len, srcp_file))
1781 return 0;
1782 else
1783 return -EINVAL;
1784#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785}
1786
kuogee hsieh4aea2742011-07-06 11:05:05 -07001787#ifdef CONFIG_FB_MSM_MIPI_DSI
1788int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001789{
1790 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1791 int ret = -EPERM;
1792
1793 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1794 return -EINTR;
1795
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001796 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
kuogee hsieh4aea2742011-07-06 11:05:05 -07001797 mdp4_dsi_cmd_3d_sbys(mfd, req);
1798 ret = 0;
1799 } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
1800 mdp4_dsi_video_3d_sbys(mfd, req);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001801 ret = 0;
1802 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001803 mutex_unlock(&mfd->dma->ov_mutex);
1804
1805 return ret;
1806}
kuogee hsieh4aea2742011-07-06 11:05:05 -07001807#else
1808int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req)
1809{
1810 /* do nothing */
1811 return -EPERM;
1812}
1813#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001814
1815#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
1816int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req)
1817{
1818 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1819
1820 if (mfd == NULL)
1821 return -ENODEV;
1822
1823 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1824 return -EINTR;
1825
1826 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
1827 mdp4_dsi_overlay_blt(mfd, req);
1828 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
1829 mdp4_dsi_video_overlay_blt(mfd, req);
1830 else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
1831 mdp4_lcdc_overlay_blt(mfd, req);
1832
1833 mutex_unlock(&mfd->dma->ov_mutex);
1834
1835 return 0;
1836}
1837
1838int mdp4_overlay_blt_offset(struct fb_info *info, struct msmfb_overlay_blt *req)
1839{
1840 int ret = 0;
1841
1842 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1843
1844 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1845 return -EINTR;
1846
1847 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
1848 ret = mdp4_dsi_overlay_blt_offset(mfd, req);
1849 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
1850 ret = mdp4_dsi_video_overlay_blt_offset(mfd, req);
1851 else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
1852 ret = mdp4_lcdc_overlay_blt_offset(mfd, req);
1853
1854 mutex_unlock(&mfd->dma->ov_mutex);
1855
1856 return ret;
1857}
1858#endif
1859
1860int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
1861{
1862 struct mdp4_overlay_pipe *pipe;
1863
1864 pipe = mdp4_overlay_ndx2pipe(req->id);
1865 if (pipe == NULL)
1866 return -ENODEV;
1867
1868 *req = pipe->req_data;
1869
1870 return 0;
1871}
1872
1873#define OVERLAY_VGA_SIZE 0x04B000
1874#define OVERLAY_720P_TILE_SIZE 0x0E6000
1875#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001876
1877#ifdef CONFIG_MSM_BUS_SCALING
1878#define OVERLAY_BUS_SCALE_TABLE_BASE 6
1879#endif
1880
1881static int mdp4_overlay_is_rgb_type(int format)
1882{
1883 switch (format) {
1884 case MDP_RGB_565:
1885 case MDP_RGB_888:
1886 case MDP_BGR_565:
1887 case MDP_XRGB_8888:
1888 case MDP_ARGB_8888:
1889 case MDP_RGBA_8888:
1890 case MDP_BGRA_8888:
1891 case MDP_RGBX_8888:
1892 return 1;
1893 default:
1894 return 0;
1895 }
1896}
1897
1898static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req)
1899{
1900 int is_fg;
1901
1902 if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
1903 is_fg = 1;
1904
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -07001905 if (mdp4_extn_disp)
1906 return OVERLAY_PERF_LEVEL1;
1907
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001908 if (req->flags & MDP_DEINTERLACE)
1909 return OVERLAY_PERF_LEVEL1;
1910
1911 if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
1912 ((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
1913 return OVERLAY_PERF_LEVEL4;
1914 else if (mdp4_overlay_is_rgb_type(req->src.format))
1915 return OVERLAY_PERF_LEVEL1;
1916
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07001917 if (ctrl->plist[OVERLAY_PIPE_VG1].pipe_used &&
1918 ctrl->plist[OVERLAY_PIPE_VG2].pipe_used)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001919 return OVERLAY_PERF_LEVEL1;
1920
1921 if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
1922 return OVERLAY_PERF_LEVEL3;
1923 else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE)
1924 return OVERLAY_PERF_LEVEL2;
1925 else
1926 return OVERLAY_PERF_LEVEL1;
1927}
1928
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -07001929void mdp4_update_perf_level(u32 perf_level)
1930{
1931 new_perf_level = perf_level;
1932}
1933
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001934void mdp4_set_perf_level(void)
1935{
1936 static int old_perf_level;
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -07001937 int cur_perf_level;
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001938
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -07001939 if (mdp4_extn_disp)
1940 cur_perf_level = OVERLAY_PERF_LEVEL1;
1941 else
1942 cur_perf_level = new_perf_level;
1943
1944 if (old_perf_level != cur_perf_level) {
1945 mdp_set_core_clk(cur_perf_level);
1946 old_perf_level = cur_perf_level;
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001947 }
1948}
1949
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001950int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
1951{
1952 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
kuogee hsiehc4b8b2f2011-07-12 13:32:14 -07001953 int ret, mixer, perf_level;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001954 struct mdp4_overlay_pipe *pipe;
1955
1956 if (mfd == NULL) {
1957 pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
1958 return -ENODEV;
1959 }
1960
1961 if (!mfd->panel_power_on) /* suspended */
1962 return -EPERM;
1963
1964 if (req->src.format == MDP_FB_FORMAT)
1965 req->src.format = mfd->fb_imgType;
1966
1967 if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) {
1968 pr_err("%s: mutex_lock_interruptible, -EINTR\n", __func__);
1969 return -EINTR;
1970 }
1971
1972 perf_level = mdp4_overlay_get_perf_level(req);
1973
1974 if ((mfd->panel_info.type == LCDC_PANEL) &&
1975 (req->src_rect.h >
1976 req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
1977 if (mdp4_overlay_validate_downscale(req, mfd,
kuogee hsieh21ef2fe2011-08-18 17:12:42 -07001978 perf_level, mfd->panel_info.clk_rate))
1979 mdp4_lcdc_overlay_blt_start(mfd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001980 }
kuogee hsieh4d3c7792011-07-25 11:02:24 -07001981
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001982 if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) &&
1983 (req->src_rect.h >
1984 req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
1985 if (mdp4_overlay_validate_downscale(req, mfd,
kuogee hsieh4d3c7792011-07-25 11:02:24 -07001986 perf_level, (&mfd->panel_info.mipi)->dsi_pclk_rate))
kuogee hsieh21ef2fe2011-08-18 17:12:42 -07001987 mdp4_dsi_video_blt_start(mfd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001988 }
kuogee hsieh4d3c7792011-07-25 11:02:24 -07001989
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001990 mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
1991
1992 ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
1993 if (ret < 0) {
1994 mutex_unlock(&mfd->dma->ov_mutex);
1995 pr_err("%s: mdp4_overlay_req2pipe, ret=%d\n", __func__, ret);
1996 return ret;
1997 }
1998
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001999 /*
2000 * writeback (blt) mode to provide work around for
2001 * dsi cmd mode interface hardware bug.
2002 */
2003 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2004 if (mixer == MDP4_MIXER0 && req->dst_rect.x != 0) {
2005 mdp4_dsi_blt_dmap_busy_wait(mfd);
2006 mdp4_dsi_overlay_blt_start(mfd);
2007 }
2008 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002009
2010 /* return id back to user */
2011 req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
2012 pipe->req_data = *req; /* keep original req */
2013
2014 pipe->flags = req->flags;
2015
2016 if (pipe->flags & MDP_SHARPENING) {
2017 bool test = ((pipe->req_data.dpp.sharp_strength > 0) &&
2018 ((req->src_rect.w > req->dst_rect.w) &&
2019 (req->src_rect.h > req->dst_rect.h)));
2020 if (test) {
2021 pr_warn("%s: No sharpening while downscaling.\n",
2022 __func__);
2023 pipe->flags &= ~MDP_SHARPENING;
2024 }
2025 }
2026
Liyuan Lid9736632011-11-11 13:47:59 -08002027 /* precompute HSIC matrices */
2028 if (req->flags & MDP_DPP_HSIC)
2029 mdp4_hsic_set(pipe, &(req->dpp));
2030
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002031 mdp4_stat.overlay_set[pipe->mixer_num]++;
2032
2033 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2034 if (mdp_hw_revision == MDP4_REVISION_V2_1 &&
2035 pipe->mixer_num == MDP4_MIXER0)
2036 mdp4_overlay_status_write(MDP4_OVERLAY_TYPE_SET, true);
2037 }
2038
Adrian Salido-Moreno5e912032011-08-29 11:15:47 -07002039 if (new_perf_level != perf_level) {
Nagamalleswararao Ganji074ee022011-09-02 12:06:37 -07002040 mdp4_update_perf_level(perf_level);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002041
Adrian Salido-Moreno5e912032011-08-29 11:15:47 -07002042 /* change clck base on perf level */
Adrian Salido-Moreno5e912032011-08-29 11:15:47 -07002043 if (pipe->mixer_num == MDP4_MIXER0) {
2044 if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
kuogee hsiehaff429a2011-09-22 17:50:05 -07002045 mdp4_overlay_dsi_video_set_perf(mfd);
Adrian Salido-Moreno5e912032011-08-29 11:15:47 -07002046 } else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2047 mdp4_dsi_cmd_dma_busy_wait(mfd);
2048 mdp4_dsi_blt_dmap_busy_wait(mfd);
2049 mdp4_set_perf_level();
2050 } else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
kuogee hsiehaff429a2011-09-22 17:50:05 -07002051 mdp4_overlay_lcdc_set_perf(mfd);
Adrian Salido-Moreno5e912032011-08-29 11:15:47 -07002052 } else if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2053 mdp4_mddi_dma_busy_wait(mfd);
2054 mdp4_set_perf_level();
2055 }
2056 } else {
2057 if (ctrl->panel_mode & MDP4_PANEL_DTV)
2058 mdp4_overlay_dtv_vsync_push(mfd, pipe);
kuogee hsieh9452ecb2011-08-01 18:26:23 -07002059 }
kuogee hsieh9452ecb2011-08-01 18:26:23 -07002060 }
kuogee hsieh9452ecb2011-08-01 18:26:23 -07002061
2062 mutex_unlock(&mfd->dma->ov_mutex);
2063
2064
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002065#ifdef CONFIG_MSM_BUS_SCALING
2066 if (pipe->mixer_num == MDP4_MIXER0) {
2067 mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
2068 - perf_level);
2069 }
2070#endif
2071
2072 return 0;
2073}
2074
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002075int mdp4_overlay_unset(struct fb_info *info, int ndx)
2076{
2077 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2078 struct mdp4_overlay_pipe *pipe;
2079 uint32 flags;
Liyuan Lid9736632011-11-11 13:47:59 -08002080 struct dpp_ctrl dpp;
2081 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002082
2083 if (mfd == NULL)
2084 return -ENODEV;
2085
2086 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
2087 return -EINTR;
2088
2089 pipe = mdp4_overlay_ndx2pipe(ndx);
2090
2091 if (pipe == NULL) {
2092 mutex_unlock(&mfd->dma->ov_mutex);
2093 return -ENODEV;
2094 }
2095
2096 if (pipe->mixer_num == MDP4_MIXER1)
2097 ctrl->mixer1_played = 0;
2098 else {
2099 /* mixer 0 */
2100 ctrl->mixer0_played = 0;
2101#ifdef CONFIG_FB_MSM_MIPI_DSI
2102 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2103 if (mfd->panel_power_on) {
2104 mdp4_dsi_blt_dmap_busy_wait(mfd);
2105 }
2106 }
2107#else
2108 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2109 if (mfd->panel_power_on)
2110 mdp4_mddi_dma_busy_wait(mfd);
2111 }
2112#endif
2113 }
2114
2115 mdp4_mixer_stage_down(pipe);
2116
2117 if (pipe->mixer_num == MDP4_MIXER0) {
2118#ifdef CONFIG_FB_MSM_MIPI_DSI
2119 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2120 if (mfd->panel_power_on)
2121 if (mdp4_dsi_overlay_blt_stop(mfd) == 0)
2122 mdp4_dsi_cmd_overlay_restore();
2123 } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
kuogee hsiehebca0c72011-07-14 13:30:33 -07002124 mdp4_overlay_reg_flush(pipe, 1);
kuogee hsieh5c6cfbf2011-09-06 19:01:31 -07002125 if (mfd->panel_power_on) {
2126 flags = pipe->flags;
2127 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
2128 mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
2129 pipe->flags = flags;
2130 }
kuogee hsieh4d3c7792011-07-25 11:02:24 -07002131 mdp4_dsi_video_blt_stop(mfd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002132 }
2133#else
2134 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2135 if (mdp_hw_revision == MDP4_REVISION_V2_1)
2136 mdp4_overlay_status_write(
2137 MDP4_OVERLAY_TYPE_UNSET, true);
2138 if (mfd->panel_power_on)
2139 mdp4_mddi_overlay_restore();
2140 }
2141#endif
2142 else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
kuogee hsiehebca0c72011-07-14 13:30:33 -07002143 mdp4_overlay_reg_flush(pipe, 1);
kuogee hsieh5c6cfbf2011-09-06 19:01:31 -07002144 if (mfd->panel_power_on) {
2145 flags = pipe->flags;
2146 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
2147 mdp4_overlay_lcdc_vsync_push(mfd, pipe);
2148 pipe->flags = flags;
2149 }
kuogee hsieh21ef2fe2011-08-18 17:12:42 -07002150 mdp4_lcdc_overlay_blt_stop(mfd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002151 }
2152 }
2153#ifdef CONFIG_FB_MSM_DTV
2154 else { /* mixer1, DTV, ATV */
kuogee hsieh9452ecb2011-08-01 18:26:23 -07002155 if (ctrl->panel_mode & MDP4_PANEL_DTV) {
kuogee hsieh5c6cfbf2011-09-06 19:01:31 -07002156 if (mfd->panel_power_on) {
2157 flags = pipe->flags;
2158 pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
2159 mdp4_overlay_dtv_vsync_push(mfd, pipe);
2160 pipe->flags = flags;
2161 }
kuogee hsieh9452ecb2011-08-01 18:26:23 -07002162 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002163 }
2164#endif
2165
Liyuan Lid9736632011-11-11 13:47:59 -08002166 /* Reset any HSIC settings to default */
2167 if (pipe->flags & MDP_DPP_HSIC) {
2168 for (i = 0; i < NUM_HSIC_PARAM; i++)
2169 dpp.hsic_params[i] = 0;
2170
2171 mdp4_hsic_set(pipe, &dpp);
2172 mdp4_hsic_update(pipe);
2173 }
2174
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002175 mdp4_stat.overlay_unset[pipe->mixer_num]++;
2176
2177 mdp4_overlay_pipe_free(pipe);
2178
Adrian Salido-Morenocb8fbbc2011-10-26 13:00:18 -07002179 if (!(ctrl->plist[OVERLAY_PIPE_VG1].pipe_used +
2180 ctrl->plist[OVERLAY_PIPE_VG2].pipe_used))
2181 mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002182
2183 mutex_unlock(&mfd->dma->ov_mutex);
2184
2185#ifdef CONFIG_MSM_BUS_SCALING
2186 if (pipe->mixer_num == MDP4_MIXER0)
2187 if (mfd->panel_power_on)
2188 mdp_bus_scale_update_request(2);
2189#endif
2190 return 0;
2191}
2192
2193struct tile_desc {
2194 uint32 width; /* tile's width */
2195 uint32 height; /* tile's height */
2196 uint32 row_tile_w; /* tiles per row's width */
2197 uint32 row_tile_h; /* tiles per row's height */
2198};
2199
2200void tile_samsung(struct tile_desc *tp)
2201{
2202 /*
2203 * each row of samsung tile consists of two tiles in height
2204 * and two tiles in width which means width should align to
2205 * 64 x 2 bytes and height should align to 32 x 2 bytes.
2206 * video decoder generate two tiles in width and one tile
2207 * in height which ends up height align to 32 X 1 bytes.
2208 */
2209 tp->width = 64; /* 64 bytes */
2210 tp->row_tile_w = 2; /* 2 tiles per row's width */
2211 tp->height = 32; /* 32 bytes */
2212 tp->row_tile_h = 1; /* 1 tiles per row's height */
2213}
2214
2215uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
2216{
2217 uint32 tile_w, tile_h;
2218 uint32 row_num_w, row_num_h;
2219
2220
2221 tile_w = tp->width * tp->row_tile_w;
2222 tile_h = tp->height * tp->row_tile_h;
2223
2224 row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
2225 row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
2226 return ((row_num_w * row_num_h * tile_w * tile_h) + 8191) & ~8191;
2227}
2228
Nagamalleswararao Ganji0737d652011-10-14 02:02:33 -07002229int mdp4_overlay_play_wait(struct fb_info *info, struct msmfb_overlay_data *req)
2230{
2231 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2232 struct mdp4_overlay_pipe *pipe;
2233
2234 if (mfd == NULL)
2235 return -ENODEV;
2236
2237 if (!mfd->panel_power_on) /* suspended */
2238 return -EPERM;
2239
2240 pipe = mdp4_overlay_ndx2pipe(req->id);
2241
2242 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
2243 return -EINTR;
2244
2245 mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
2246
2247 mutex_unlock(&mfd->dma->ov_mutex);
2248
2249 return 0;
2250}
2251
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002252int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002253{
2254 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2255 struct msmfb_data *img;
2256 struct mdp4_overlay_pipe *pipe;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002257 ulong start, addr;
2258 ulong len = 0;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002259 struct file *srcp0_file = NULL;
2260 struct file *srcp1_file = NULL, *srcp2_file = NULL;
2261 struct ion_handle *srcp0_ihdl = NULL;
2262 struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002263 uint32_t overlay_version = 0;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002264 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002265
2266 if (mfd == NULL)
2267 return -ENODEV;
2268
2269 if (!mfd->panel_power_on) /* suspended */
2270 return -EPERM;
2271
2272 pipe = mdp4_overlay_ndx2pipe(req->id);
2273 if (pipe == NULL) {
2274 pr_err("%s: req_id=%d Error\n", __func__, req->id);
2275 return -ENODEV;
2276 }
2277
2278 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
2279 return -EINTR;
2280
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002281 img = &req->data;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002282 get_img(img, info, &start, &len, &srcp0_file, &srcp0_ihdl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002283 if (len == 0) {
2284 mutex_unlock(&mfd->dma->ov_mutex);
2285 pr_err("%s: pmem Error\n", __func__);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002286 ret = -1;
2287 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002288 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002289
2290 addr = start + img->offset;
2291 pipe->srcp0_addr = addr;
2292 pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
2293
2294 if ((req->version_key & VERSION_KEY_MASK) == 0xF9E8D700)
2295 overlay_version = (req->version_key & ~VERSION_KEY_MASK);
2296
2297 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
2298 if (overlay_version > 0) {
2299 img = &req->plane1_data;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002300 get_img(img, info, &start, &len, &srcp1_file,
2301 &srcp1_ihdl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002302 if (len == 0) {
2303 mutex_unlock(&mfd->dma->ov_mutex);
2304 pr_err("%s: Error to get plane1\n", __func__);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002305 ret = -EINVAL;
2306 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002307 }
2308 pipe->srcp1_addr = start + img->offset;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002309 } else if (pipe->frame_format ==
2310 MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
2311 struct tile_desc tile;
2312
2313 tile_samsung(&tile);
2314 pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
2315 } else {
2316 pipe->srcp1_addr = addr + (pipe->src_width *
2317 pipe->src_height);
2318 }
2319 pipe->srcp0_ystride = pipe->src_width;
2320 if ((pipe->src_format == MDP_Y_CRCB_H1V1) ||
2321 (pipe->src_format == MDP_Y_CBCR_H1V1)) {
2322 if (pipe->src_width > YUV_444_MAX_WIDTH)
2323 pipe->srcp1_ystride = pipe->src_width << 2;
2324 else
2325 pipe->srcp1_ystride = pipe->src_width << 1;
2326 } else
2327 pipe->srcp1_ystride = pipe->src_width;
2328
2329 } else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
2330 if (overlay_version > 0) {
2331 img = &req->plane1_data;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002332 get_img(img, info, &start, &len, &srcp1_file,
2333 &srcp1_ihdl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002334 if (len == 0) {
2335 mutex_unlock(&mfd->dma->ov_mutex);
2336 pr_err("%s: Error to get plane1\n", __func__);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002337 ret = -EINVAL;
2338 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002339 }
2340 pipe->srcp1_addr = start + img->offset;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002341
2342 img = &req->plane2_data;
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002343 get_img(img, info, &start, &len, &srcp2_file,
2344 &srcp2_ihdl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002345 if (len == 0) {
2346 mutex_unlock(&mfd->dma->ov_mutex);
2347 pr_err("%s: Error to get plane2\n", __func__);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002348 ret = -EINVAL;
2349 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002350 }
2351 pipe->srcp2_addr = start + img->offset;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002352 } else {
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +05302353 if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
2354 addr += (ALIGN(pipe->src_width, 16) *
2355 pipe->src_height);
2356 pipe->srcp1_addr = addr;
2357 addr += ((ALIGN((pipe->src_width / 2), 16)) *
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002358 (pipe->src_height / 2));
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +05302359 pipe->srcp2_addr = addr;
2360 } else {
2361 addr += (pipe->src_width * pipe->src_height);
2362 pipe->srcp1_addr = addr;
2363 addr += ((pipe->src_width / 2) *
2364 (pipe->src_height / 2));
2365 pipe->srcp2_addr = addr;
2366 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002367 }
Adrian Salido-Moreno33dc7b92011-08-18 16:16:12 -07002368 /* mdp planar format expects Cb in srcp1 and Cr in p2 */
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +05302369 if ((pipe->src_format == MDP_Y_CR_CB_H2V2) ||
2370 (pipe->src_format == MDP_Y_CR_CB_GH2V2))
Adrian Salido-Moreno33dc7b92011-08-18 16:16:12 -07002371 swap(pipe->srcp1_addr, pipe->srcp2_addr);
Pradeep Jilagam959fd6f2011-10-05 21:19:46 +05302372
2373 if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
2374 pipe->srcp0_ystride = ALIGN(pipe->src_width, 16);
2375 pipe->srcp1_ystride = ALIGN(pipe->src_width / 2, 16);
2376 pipe->srcp2_ystride = ALIGN(pipe->src_width / 2, 16);
2377 } else {
2378 pipe->srcp0_ystride = pipe->src_width;
2379 pipe->srcp1_ystride = pipe->src_width / 2;
2380 pipe->srcp2_ystride = pipe->src_width / 2;
2381 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002382 }
2383
2384 if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
2385 mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
2386 else {
2387 if (pipe->flags & MDP_SHARPENING) {
2388 pr_warn(
2389 "%s: Sharpening/Smoothing not supported on RGB pipe\n",
2390 __func__);
2391 pipe->flags &= ~MDP_SHARPENING;
2392 }
2393 mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
2394 }
2395
2396 mdp4_mixer_blend_setup(pipe);
2397 mdp4_mixer_stage_up(pipe);
2398
2399 if (pipe->mixer_num == MDP4_MIXER1) {
2400 ctrl->mixer1_played++;
2401 /* enternal interface */
2402 if (ctrl->panel_mode & MDP4_PANEL_DTV)
2403#ifdef CONFIG_FB_MSM_DTV
2404 mdp4_overlay_dtv_ov_done_push(mfd, pipe);
2405#else
2406 mdp4_overlay_reg_flush(pipe, 1);
2407#endif
2408 else if (ctrl->panel_mode & MDP4_PANEL_ATV)
2409 mdp4_overlay_reg_flush(pipe, 1);
Vinay Kalia27020d12011-10-14 17:50:29 -07002410#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
2411 else if (ctrl->panel_mode & MDP4_PANEL_WRITEBACK) {
2412 mdp4_writeback_dma_busy_wait(mfd);
2413 mdp4_writeback_kickoff_video(mfd, pipe);
2414 }
2415#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002416 } else {
2417 /* primary interface */
2418 ctrl->mixer0_played++;
kuogee hsieh3de11f32011-07-08 14:09:11 -07002419 if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
2420 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002421 mdp4_overlay_lcdc_vsync_push(mfd, pipe);
kuogee hsieh3de11f32011-07-08 14:09:11 -07002422 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002423#ifdef CONFIG_FB_MSM_MIPI_DSI
kuogee hsieh3de11f32011-07-08 14:09:11 -07002424 else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
2425 mdp4_overlay_reg_flush(pipe, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002426 mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
kuogee hsieh3de11f32011-07-08 14:09:11 -07002427 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002428#endif
2429 else {
2430 /* mddi & mipi dsi cmd mode */
2431 if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
2432 mdp4_stat.overlay_play[pipe->mixer_num]++;
2433 mutex_unlock(&mfd->dma->ov_mutex);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002434 goto end;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002435 }
2436#ifdef CONFIG_FB_MSM_MIPI_DSI
2437 if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
2438 mdp4_dsi_cmd_dma_busy_wait(mfd);
2439 mdp4_dsi_cmd_kickoff_video(mfd, pipe);
2440 }
2441#else
2442 if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
2443 mdp4_mddi_dma_busy_wait(mfd);
2444 mdp4_mddi_kickoff_video(mfd, pipe);
2445 }
2446#endif
2447 }
2448 }
2449
Liyuan Lid9736632011-11-11 13:47:59 -08002450 /* write out DPP HSIC registers */
2451 if (pipe->flags & MDP_DPP_HSIC)
2452 mdp4_hsic_update(pipe);
2453
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002454 mdp4_stat.overlay_play[pipe->mixer_num]++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002455 mutex_unlock(&mfd->dma->ov_mutex);
Nagamalleswararao Ganjie69bed82011-10-17 16:21:42 -07002456end:
2457#ifdef CONFIG_ANDROID_PMEM
2458 if (srcp0_file)
2459 put_pmem_file(srcp0_file);
2460 if (srcp1_file)
2461 put_pmem_file(srcp1_file);
2462 if (srcp2_file)
2463 put_pmem_file(srcp2_file);
2464#endif
2465#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
2466 if (!IS_ERR_OR_NULL(srcp0_ihdl))
2467 ion_free(mfd->client, srcp0_ihdl);
2468 if (!IS_ERR_OR_NULL(srcp1_ihdl))
2469 ion_free(mfd->client, srcp1_ihdl);
2470 if (!IS_ERR_OR_NULL(srcp2_ihdl))
2471 ion_free(mfd->client, srcp2_ihdl);
2472#endif
2473 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002474}