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