1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
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.
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.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/time.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/spinlock.h>
25 #include <linux/hrtimer.h>
26 #include <linux/clk.h>
27 #include <mach/hardware.h>
29 #include <linux/debugfs.h>
32 #include <linux/file.h>
33 #include "android_pmem.h"
34 #include <linux/major.h>
35 #include <asm/system.h>
36 #include <asm/mach-types.h>
37 #include <linux/semaphore.h>
38 #include <linux/uaccess.h>
39 #include <linux/mutex.h>
46 struct mdp4_overlay_ctrl
{
47 struct mdp4_overlay_pipe plist
[MDP4_MAX_OVERLAY_PIPE
];
48 struct mdp4_overlay_pipe
*stage
[MDP4_MAX_MIXER
][MDP4_MAX_STAGE
];
51 static struct mdp4_overlay_ctrl
*ctrl
= &mdp4_overlay_db
;
54 void mdp4_overlay_dmap_cfg(struct msm_fb_data_type
*mfd
, int lcdc
)
58 dma2_cfg_reg
= DMA_DITHER_EN
;
60 if (mfd
->fb_imgType
== MDP_BGR_565
)
61 dma2_cfg_reg
|= DMA_PACK_PATTERN_BGR
;
63 dma2_cfg_reg
|= DMA_PACK_PATTERN_RGB
;
66 if (mfd
->panel_info
.bpp
== 18) {
67 dma2_cfg_reg
|= DMA_DSTC0G_6BITS
| /* 666 18BPP */
68 DMA_DSTC1B_6BITS
| DMA_DSTC2R_6BITS
;
69 } else if (mfd
->panel_info
.bpp
== 16) {
70 dma2_cfg_reg
|= DMA_DSTC0G_6BITS
| /* 565 16BPP */
71 DMA_DSTC1B_5BITS
| DMA_DSTC2R_5BITS
;
73 dma2_cfg_reg
|= DMA_DSTC0G_8BITS
| /* 888 16BPP */
74 DMA_DSTC1B_8BITS
| DMA_DSTC2R_8BITS
;
78 dma2_cfg_reg
|= DMA_PACK_ALIGN_MSB
;
80 /* dma2 config register */
81 MDP_OUTP(MDP_BASE
+ 0x90000, dma2_cfg_reg
);
85 void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe
*pipe
)
89 MDP_OUTP(MDP_BASE
+ 0x90004,
90 (pipe
->src_height
<< 16 | pipe
->src_width
));
91 MDP_OUTP(MDP_BASE
+ 0x90008, pipe
->srcp0_addr
);
92 MDP_OUTP(MDP_BASE
+ 0x9000c, pipe
->srcp0_ystride
);
95 MDP_OUTP(MDP_BASE
+ 0x90010, (pipe
->dst_y
<< 16 | pipe
->dst_x
));
98 #define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
99 #define MDP4_VG_PHASE_STEP_SHIFT 29
101 static int mdp4_leading_0(uint32 num
)
103 uint32 bit
= 0x80000000;
106 for (i
= 0; i
< 32; i
++) {
115 static uint32
mdp4_scale_phase_step(int f_num
, uint32 src
, uint32 dst
)
120 n
= mdp4_leading_0(src
);
123 val
= src
<< n
; /* maximum to reduce lose of resolution */
133 static void mdp4_scale_setup(struct mdp4_overlay_pipe
*pipe
)
136 pipe
->phasex_step
= MDP4_VG_PHASE_STEP_DEFAULT
;
137 pipe
->phasey_step
= MDP4_VG_PHASE_STEP_DEFAULT
;
139 if (pipe
->dst_h
&& pipe
->src_h
!= pipe
->dst_h
) {
140 if (pipe
->dst_h
>= pipe
->src_h
* 8) /* too much */
142 pipe
->op_mode
|= MDP4_OP_SCALEY_EN
;
144 if (pipe
->pipe_type
== OVERLAY_TYPE_VG
) {
145 if (pipe
->dst_h
<= (pipe
->src_h
/ 4))
146 pipe
->op_mode
|= MDP4_OP_SCALEY_MN_PHASE
;
148 pipe
->op_mode
|= MDP4_OP_SCALEY_FIR
;
151 pipe
->phasey_step
= mdp4_scale_phase_step(29,
152 pipe
->src_h
, pipe
->dst_h
);
155 if (pipe
->dst_w
&& pipe
->src_w
!= pipe
->dst_w
) {
156 if (pipe
->dst_w
>= pipe
->src_w
* 8) /* too much */
158 pipe
->op_mode
|= MDP4_OP_SCALEX_EN
;
160 if (pipe
->pipe_type
== OVERLAY_TYPE_VG
) {
161 if (pipe
->dst_w
<= (pipe
->src_w
/ 4))
162 pipe
->op_mode
|= MDP4_OP_SCALEY_MN_PHASE
;
164 pipe
->op_mode
|= MDP4_OP_SCALEY_FIR
;
167 pipe
->phasex_step
= mdp4_scale_phase_step(29,
168 pipe
->src_w
, pipe
->dst_w
);
172 void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe
*pipe
)
175 uint32 src_size
, src_xy
, dst_size
, dst_xy
;
176 uint32 format
, pattern
;
178 rgb_base
= MDP_BASE
+ MDP4_RGB_BASE
;
179 rgb_base
+= (MDP4_RGB_OFF
* pipe
->pipe_num
);
181 src_size
= ((pipe
->src_h
<< 16) | pipe
->src_w
);
182 src_xy
= ((pipe
->src_y
<< 16) | pipe
->src_x
);
183 dst_size
= ((pipe
->dst_h
<< 16) | pipe
->dst_w
);
184 dst_xy
= ((pipe
->dst_y
<< 16) | pipe
->dst_x
);
186 format
= mdp4_overlay_format(pipe
);
187 pattern
= mdp4_overlay_unpack_pattern(pipe
);
189 pipe
->op_mode
|= MDP4_OP_IGC_LUT_EN
;
191 mdp4_scale_setup(pipe
);
193 outpdw(rgb_base
+ 0x0000, src_size
); /* MDP_RGB_SRC_SIZE */
194 outpdw(rgb_base
+ 0x0004, src_xy
); /* MDP_RGB_SRC_XY */
195 outpdw(rgb_base
+ 0x0008, dst_size
); /* MDP_RGB_DST_SIZE */
196 outpdw(rgb_base
+ 0x000c, dst_xy
); /* MDP_RGB_DST_XY */
198 outpdw(rgb_base
+ 0x0010, pipe
->srcp0_addr
);
199 outpdw(rgb_base
+ 0x0040, pipe
->srcp0_ystride
);
201 outpdw(rgb_base
+ 0x0050, format
);/* MDP_RGB_SRC_FORMAT */
202 outpdw(rgb_base
+ 0x0054, pattern
);/* MDP_RGB_SRC_UNPACK_PATTERN */
203 outpdw(rgb_base
+ 0x0058, pipe
->op_mode
);/* MDP_RGB_OP_MODE */
204 outpdw(rgb_base
+ 0x005c, pipe
->phasex_step
);
205 outpdw(rgb_base
+ 0x0060, pipe
->phasey_step
);
207 /* 16 bytes-burst x 3 req <= 48 bytes */
208 outpdw(rgb_base
+ 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */
211 void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe
*pipe
)
214 uint32 frame_size
, src_size
, src_xy
, dst_size
, dst_xy
;
215 uint32 format
, pattern
;
217 vg_base
= MDP_BASE
+ MDP4_VIDEO_BASE
;
218 vg_base
+= (MDP4_VIDEO_OFF
* pipe
->pipe_num
);
220 frame_size
= ((pipe
->src_height
<< 16) | pipe
->src_width
);
221 src_size
= ((pipe
->src_h
<< 16) | pipe
->src_w
);
222 src_xy
= ((pipe
->src_y
<< 16) | pipe
->src_x
);
223 dst_size
= ((pipe
->dst_h
<< 16) | pipe
->dst_w
);
224 dst_xy
= ((pipe
->dst_y
<< 16) | pipe
->dst_x
);
226 format
= mdp4_overlay_format(pipe
);
227 pattern
= mdp4_overlay_unpack_pattern(pipe
);
229 pipe
->op_mode
|= (MDP4_OP_CSC_EN
| MDP4_OP_SRC_DATA_YCBCR
|
232 mdp4_scale_setup(pipe
);
234 outpdw(vg_base
+ 0x0000, src_size
); /* MDP_RGB_SRC_SIZE */
235 outpdw(vg_base
+ 0x0004, src_xy
); /* MDP_RGB_SRC_XY */
236 outpdw(vg_base
+ 0x0008, dst_size
); /* MDP_RGB_DST_SIZE */
237 outpdw(vg_base
+ 0x000c, dst_xy
); /* MDP_RGB_DST_XY */
238 outpdw(vg_base
+ 0x0048, frame_size
); /* TILE frame size */
240 /* luma component plane */
241 outpdw(vg_base
+ 0x0010, pipe
->srcp0_addr
);
243 /* chroma component plane */
244 outpdw(vg_base
+ 0x0014, pipe
->srcp1_addr
);
246 outpdw(vg_base
+ 0x0040,
247 pipe
->srcp1_ystride
<< 16 | pipe
->srcp0_ystride
);
249 outpdw(vg_base
+ 0x0050, format
); /* MDP_RGB_SRC_FORMAT */
250 outpdw(vg_base
+ 0x0054, pattern
); /* MDP_RGB_SRC_UNPACK_PATTERN */
251 outpdw(vg_base
+ 0x0058, pipe
->op_mode
);/* MDP_RGB_OP_MODE */
252 outpdw(vg_base
+ 0x005c, pipe
->phasex_step
);
253 outpdw(vg_base
+ 0x0060, pipe
->phasey_step
);
255 if (pipe
->op_mode
& MDP4_OP_DITHER_EN
) {
256 outpdw(vg_base
+ 0x0068,
257 pipe
->r_bit
<< 4 | pipe
->b_bit
<< 2 | pipe
->g_bit
);
260 /* 16 bytes-burst x 3 req <= 48 bytes */
261 outpdw(vg_base
+ 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */
264 int mdp4_overlay_format2type(uint32 format
)
273 return OVERLAY_TYPE_RGB
;
274 case MDP_YCRYCB_H2V1
:
275 case MDP_Y_CRCB_H2V1
:
276 case MDP_Y_CBCR_H2V1
:
277 case MDP_Y_CRCB_H2V2
:
278 case MDP_Y_CBCR_H2V2
:
279 case MDP_Y_CBCR_H2V2_TILE
:
280 case MDP_Y_CRCB_H2V2_TILE
:
281 return OVERLAY_TYPE_VG
;
288 #define C3_ALPHA 3 /* alpha */
289 #define C2_R_Cr 2 /* R/Cr */
290 #define C1_B_Cb 1 /* B/Cb */
291 #define C0_G_Y 0 /* G/luma */
293 int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe
*pipe
)
295 switch (pipe
->src_format
) {
297 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
298 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
300 pipe
->r_bit
= 1; /* R, 5 bits */
301 pipe
->b_bit
= 1; /* B, 5 bits */
302 pipe
->g_bit
= 2; /* G, 6 bits */
303 pipe
->alpha_enable
= 0;
304 pipe
->unpack_tight
= 1;
305 pipe
->unpack_align_msb
= 0;
306 pipe
->unpack_count
= 2;
307 pipe
->element2
= C2_R_Cr
; /* R */
308 pipe
->element1
= C0_G_Y
; /* G */
309 pipe
->element0
= C1_B_Cb
; /* B */
310 pipe
->bpp
= 2; /* 2 bpp */
313 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
314 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
316 pipe
->r_bit
= 3; /* R, 8 bits */
317 pipe
->b_bit
= 3; /* B, 8 bits */
318 pipe
->g_bit
= 3; /* G, 8 bits */
319 pipe
->alpha_enable
= 0;
320 pipe
->unpack_tight
= 1;
321 pipe
->unpack_align_msb
= 0;
322 pipe
->unpack_count
= 2;
323 pipe
->element2
= C2_R_Cr
; /* R */
324 pipe
->element1
= C0_G_Y
; /* G */
325 pipe
->element0
= C1_B_Cb
; /* B */
326 pipe
->bpp
= 3; /* 3 bpp */
329 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
330 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
332 pipe
->r_bit
= 1; /* R, 5 bits */
333 pipe
->b_bit
= 1; /* B, 5 bits */
334 pipe
->g_bit
= 2; /* G, 6 bits */
335 pipe
->alpha_enable
= 0;
336 pipe
->unpack_tight
= 1;
337 pipe
->unpack_align_msb
= 0;
338 pipe
->unpack_count
= 2;
339 pipe
->element2
= C1_B_Cb
; /* B */
340 pipe
->element1
= C0_G_Y
; /* G */
341 pipe
->element0
= C2_R_Cr
; /* R */
342 pipe
->bpp
= 2; /* 2 bpp */
345 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
346 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
347 pipe
->a_bit
= 3; /* alpha, 4 bits */
348 pipe
->r_bit
= 3; /* R, 8 bits */
349 pipe
->b_bit
= 3; /* B, 8 bits */
350 pipe
->g_bit
= 3; /* G, 8 bits */
351 pipe
->alpha_enable
= 1;
352 pipe
->unpack_tight
= 1;
353 pipe
->unpack_align_msb
= 0;
354 pipe
->unpack_count
= 3;
355 pipe
->element3
= C3_ALPHA
; /* alpha */
356 pipe
->element2
= C2_R_Cr
; /* R */
357 pipe
->element1
= C0_G_Y
; /* G */
358 pipe
->element0
= C1_B_Cb
; /* B */
359 pipe
->bpp
= 4; /* 4 bpp */
362 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
363 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
364 pipe
->a_bit
= 3; /* alpha, 4 bits */
365 pipe
->r_bit
= 3; /* R, 8 bits */
366 pipe
->b_bit
= 3; /* B, 8 bits */
367 pipe
->g_bit
= 3; /* G, 8 bits */
368 pipe
->alpha_enable
= 1;
369 pipe
->unpack_tight
= 1;
370 pipe
->unpack_align_msb
= 0;
371 pipe
->unpack_count
= 3;
372 pipe
->element3
= C2_R_Cr
; /* R */
373 pipe
->element2
= C0_G_Y
; /* G */
374 pipe
->element1
= C1_B_Cb
; /* B */
375 pipe
->element0
= C3_ALPHA
; /* alpha */
376 pipe
->bpp
= 4; /* 4 bpp */
379 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
380 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
381 pipe
->a_bit
= 3; /* alpha, 4 bits */
382 pipe
->r_bit
= 3; /* R, 8 bits */
383 pipe
->b_bit
= 3; /* B, 8 bits */
384 pipe
->g_bit
= 3; /* G, 8 bits */
385 pipe
->alpha_enable
= 1;
386 pipe
->unpack_tight
= 1;
387 pipe
->unpack_align_msb
= 0;
388 pipe
->unpack_count
= 3;
389 pipe
->element3
= C1_B_Cb
; /* B */
390 pipe
->element2
= C0_G_Y
; /* G */
391 pipe
->element1
= C2_R_Cr
; /* R */
392 pipe
->element0
= C3_ALPHA
; /* alpha */
393 pipe
->bpp
= 4; /* 4 bpp */
395 case MDP_YCRYCB_H2V1
:
396 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
397 pipe
->fetch_plane
= OVERLAY_PLANE_INTERLEAVED
;
398 pipe
->a_bit
= 0; /* alpha, 4 bits */
399 pipe
->r_bit
= 3; /* R, 8 bits */
400 pipe
->b_bit
= 3; /* B, 8 bits */
401 pipe
->g_bit
= 3; /* G, 8 bits */
402 pipe
->alpha_enable
= 0;
403 pipe
->unpack_tight
= 1;
404 pipe
->unpack_align_msb
= 0;
405 pipe
->unpack_count
= 3;
406 pipe
->element3
= C0_G_Y
; /* G */
407 pipe
->element2
= C2_R_Cr
; /* R */
408 pipe
->element1
= C0_G_Y
; /* G */
409 pipe
->element0
= C1_B_Cb
; /* B */
410 pipe
->bpp
= 2; /* 2 bpp */
411 pipe
->chroma_sample
= MDP4_CHROMA_H2V1
;
413 case MDP_Y_CRCB_H2V1
:
414 case MDP_Y_CBCR_H2V1
:
415 case MDP_Y_CRCB_H2V2
:
416 case MDP_Y_CBCR_H2V2
:
417 pipe
->frame_format
= MDP4_FRAME_FORMAT_LINEAR
;
418 pipe
->fetch_plane
= OVERLAY_PLANE_PSEUDO_PLANAR
;
420 pipe
->r_bit
= 3; /* R, 8 bits */
421 pipe
->b_bit
= 3; /* B, 8 bits */
422 pipe
->g_bit
= 3; /* G, 8 bits */
423 pipe
->alpha_enable
= 0;
424 pipe
->unpack_tight
= 1;
425 pipe
->unpack_align_msb
= 0;
426 pipe
->unpack_count
= 1; /* 2 */
427 pipe
->element3
= C0_G_Y
; /* not used */
428 pipe
->element2
= C0_G_Y
; /* not used */
429 if (pipe
->src_format
== MDP_Y_CRCB_H2V1
) {
430 pipe
->element1
= C2_R_Cr
; /* R */
431 pipe
->element0
= C1_B_Cb
; /* B */
432 pipe
->chroma_sample
= MDP4_CHROMA_H2V1
;
433 } else if (pipe
->src_format
== MDP_Y_CBCR_H2V1
) {
434 pipe
->element1
= C1_B_Cb
; /* B */
435 pipe
->element0
= C2_R_Cr
; /* R */
436 pipe
->chroma_sample
= MDP4_CHROMA_H2V1
;
437 } else if (pipe
->src_format
== MDP_Y_CRCB_H2V2
) {
438 pipe
->element1
= C2_R_Cr
; /* R */
439 pipe
->element0
= C1_B_Cb
; /* B */
440 pipe
->chroma_sample
= MDP4_CHROMA_420
;
441 } else if (pipe
->src_format
== MDP_Y_CBCR_H2V2
) {
442 pipe
->element1
= C1_B_Cb
; /* B */
443 pipe
->element0
= C2_R_Cr
; /* R */
444 pipe
->chroma_sample
= MDP4_CHROMA_420
;
446 pipe
->bpp
= 2; /* 2 bpp */
448 case MDP_Y_CBCR_H2V2_TILE
:
449 case MDP_Y_CRCB_H2V2_TILE
:
450 pipe
->frame_format
= MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
;
451 pipe
->fetch_plane
= OVERLAY_PLANE_PSEUDO_PLANAR
;
453 pipe
->r_bit
= 3; /* R, 8 bits */
454 pipe
->b_bit
= 3; /* B, 8 bits */
455 pipe
->g_bit
= 3; /* G, 8 bits */
456 pipe
->alpha_enable
= 0;
457 pipe
->unpack_tight
= 1;
458 pipe
->unpack_align_msb
= 0;
459 pipe
->unpack_count
= 1; /* 2 */
460 pipe
->element3
= C0_G_Y
; /* not used */
461 pipe
->element2
= C0_G_Y
; /* not used */
462 if (pipe
->src_format
== MDP_Y_CRCB_H2V2_TILE
) {
463 pipe
->element1
= C2_R_Cr
; /* R */
464 pipe
->element0
= C1_B_Cb
; /* B */
465 pipe
->chroma_sample
= MDP4_CHROMA_420
;
466 } else if (pipe
->src_format
== MDP_Y_CBCR_H2V2_TILE
) {
467 pipe
->element1
= C1_B_Cb
; /* B */
468 pipe
->element0
= C2_R_Cr
; /* R */
469 pipe
->chroma_sample
= MDP4_CHROMA_420
;
471 pipe
->bpp
= 2; /* 2 bpp */
482 * color_key_convert: output with 12 bits color key
484 static uint32
color_key_convert(int start
, int num
, uint32 color
)
489 data
= (color
>> start
) & ((1 << num
) - 1);
492 data
= (data
<< 7) + (data
<< 2) + (data
>> 3);
494 data
= (data
<< 6) + data
;
496 data
= (data
<< 4) + (data
>> 4);
502 void transp_color_key(int format
, uint32 transp
,
503 uint32
*c0
, uint32
*c1
, uint32
*c2
)
505 int b_start
, g_start
, r_start
;
506 int b_num
, g_num
, r_num
;
535 case MDP_Y_CBCR_H2V2
:
536 case MDP_Y_CBCR_H2V1
:
544 case MDP_Y_CRCB_H2V2
:
545 case MDP_Y_CRCB_H2V1
:
563 *c0
= color_key_convert(g_start
, g_num
, transp
);
564 *c1
= color_key_convert(b_start
, b_num
, transp
);
565 *c2
= color_key_convert(r_start
, r_num
, transp
);
568 uint32
mdp4_overlay_format(struct mdp4_overlay_pipe
*pipe
)
574 if (pipe
->solid_fill
)
575 format
|= MDP4_FORMAT_SOLID_FILL
;
577 if (pipe
->unpack_align_msb
)
578 format
|= MDP4_FORMAT_UNPACK_ALIGN_MSB
;
580 if (pipe
->unpack_tight
)
581 format
|= MDP4_FORMAT_UNPACK_TIGHT
;
583 if (pipe
->alpha_enable
)
584 format
|= MDP4_FORMAT_ALPHA_ENABLE
;
586 format
|= (pipe
->unpack_count
<< 13);
587 format
|= ((pipe
->bpp
- 1) << 9);
588 format
|= (pipe
->a_bit
<< 6);
589 format
|= (pipe
->r_bit
<< 4);
590 format
|= (pipe
->b_bit
<< 2);
591 format
|= pipe
->g_bit
;
593 format
|= (pipe
->frame_format
<< 29);
595 if (pipe
->fetch_plane
== OVERLAY_PLANE_PSEUDO_PLANAR
) {
597 format
|= (pipe
->fetch_plane
<< 19);
598 format
|= (pipe
->chroma_site
<< 28);
599 format
|= (pipe
->chroma_sample
<< 26);
605 uint32
mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe
*pipe
)
607 return (pipe
->element3
<< 24) | (pipe
->element2
<< 16) |
608 (pipe
->element1
<< 8) | pipe
->element0
;
611 void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe
*pipe
)
616 if (pipe
->mixer_num
== MDP4_MIXER1
)
617 overlay_base
= MDP_BASE
+ MDP4_OVERLAYPROC1_BASE
;/* 0x18000 */
619 overlay_base
= MDP_BASE
+ MDP4_OVERLAYPROC0_BASE
;/* 0x10000 */
621 /* MDP_OVERLAYPROC_CFG */
622 outpdw(overlay_base
+ 0x0004, 0x01); /* directout */
623 data
= pipe
->src_height
;
625 data
|= pipe
->src_width
;
626 outpdw(overlay_base
+ 0x0008, data
); /* ROI, height + width */
627 outpdw(overlay_base
+ 0x000c, pipe
->srcp0_addr
);
628 outpdw(overlay_base
+ 0x0010, pipe
->srcp0_ystride
);
629 outpdw(overlay_base
+ 0x0014, 0x4); /* GC_LUT_EN, 888 */
632 int mdp4_overlay_active(int mixer
)
634 uint32 data
, mask
, i
;
637 data
= inpdw(MDP_BASE
+ 0x10100);
640 for (i
= 0; i
< 8; i
++) {
657 void mdp4_mixer_stage_up(struct mdp4_overlay_pipe
*pipe
)
659 uint32 data
, mask
, snum
, stage
, mixer
;
661 stage
= pipe
->mixer_stage
;
662 mixer
= pipe
->mixer_num
;
664 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
665 data
= inpdw(MDP_BASE
+ 0x10100);
667 if (mixer
== MDP4_MIXER1
)
670 if (pipe
->pipe_type
== OVERLAY_TYPE_VG
) {/* VG1 and VG2 */
672 snum
+= (4 * pipe
->pipe_num
);
675 snum
+= (4 * pipe
->pipe_num
); /* RGB1 and RGB2 */
681 data
&= ~mask
; /* clear old bits */
685 outpdw(MDP_BASE
+ 0x10100, data
); /* MDP_LAYERMIXER_IN_CFG */
687 data
= inpdw(MDP_BASE
+ 0x10100);
689 ctrl
->stage
[pipe
->mixer_num
][pipe
->mixer_stage
] = pipe
; /* keep it */
692 void mdp4_mixer_stage_down(struct mdp4_overlay_pipe
*pipe
)
694 uint32 data
, mask
, snum
, stage
, mixer
;
696 stage
= pipe
->mixer_stage
;
697 mixer
= pipe
->mixer_num
;
699 if (pipe
!= ctrl
->stage
[mixer
][stage
]) /* not runing */
702 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
703 data
= inpdw(MDP_BASE
+ 0x10100);
705 if (mixer
== MDP4_MIXER1
)
708 if (pipe
->pipe_type
== OVERLAY_TYPE_VG
) {/* VG1 and VG2 */
710 snum
+= (4 * pipe
->pipe_num
);
713 snum
+= (4 * pipe
->pipe_num
); /* RGB1 and RGB2 */
718 data
&= ~mask
; /* clear old bits */
720 outpdw(MDP_BASE
+ 0x10100, data
); /* MDP_LAYERMIXER_IN_CFG */
722 data
= inpdw(MDP_BASE
+ 0x10100);
724 ctrl
->stage
[pipe
->mixer_num
][pipe
->mixer_stage
] = NULL
; /* clear it */
727 void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe
*pipe
)
729 unsigned char *overlay_base
;
730 uint32 c0
, c1
, c2
, blend_op
;
733 if (pipe
->mixer_num
) /* mixer number, /dev/fb0, /dev/fb1 */
734 overlay_base
= MDP_BASE
+ MDP4_OVERLAYPROC1_BASE
;/* 0x18000 */
736 overlay_base
= MDP_BASE
+ MDP4_OVERLAYPROC0_BASE
;/* 0x10000 */
738 /* stage 0 to stage 2 */
739 off
= 0x20 * (pipe
->mixer_stage
- MDP4_MIXER_STAGE0
);
742 if (pipe
->alpha_enable
) /* ARGB */
743 blend_op
= MDP4_BLEND_FG_ALPHA_FG_PIXEL
|
744 MDP4_BLEND_BG_ALPHA_FG_PIXEL
;
746 blend_op
= (MDP4_BLEND_BG_ALPHA_BG_CONST
|
747 MDP4_BLEND_FG_ALPHA_FG_CONST
);
750 if (pipe
->alpha_enable
== 0) { /* not ARGB */
752 outpdw(overlay_base
+ off
+ 0x108, pipe
->alpha
);
753 outpdw(overlay_base
+ off
+ 0x10c, 0xff - pipe
->alpha
);
755 outpdw(overlay_base
+ off
+ 0x108, 0xff - pipe
->alpha
);
756 outpdw(overlay_base
+ off
+ 0x10c, pipe
->alpha
);
760 if (pipe
->transp
!= MDP_TRANSP_NOP
) {
761 transp_color_key(pipe
->src_format
, pipe
->transp
, &c0
, &c1
, &c2
);
763 blend_op
|= MDP4_BLEND_FG_TRANSP_EN
; /* Fg blocked */
771 outpdw(overlay_base
+ off
+ 0x110,
772 (c1
<< 16 | c0
));/* low */
773 outpdw(overlay_base
+ off
+ 0x114, c2
);/* low */
775 if ((c0
+ 0x20) < 0x0fff)
779 if ((c1
+ 0x20) < 0x0fff)
783 if ((c2
+ 0x20) < 0x0fff)
787 outpdw(overlay_base
+ off
+ 0x118,
788 (c1
<< 16 | c0
));/* high */
789 outpdw(overlay_base
+ off
+ 0x11c, c2
);/* high */
791 blend_op
|= MDP4_BLEND_BG_TRANSP_EN
; /* bg blocked */
799 outpdw(overlay_base
+ 0x180,
800 (c1
<< 16 | c0
));/* low */
801 outpdw(overlay_base
+ 0x184, c2
);/* low */
803 if ((c0
+ 0x20) < 0x0fff)
807 if ((c1
+ 0x20) < 0x0fff)
811 if ((c2
+ 0x20) < 0x0fff)
815 outpdw(overlay_base
+ 0x188,
816 (c1
<< 16 | c0
));/* high */
817 outpdw(overlay_base
+ 0x18c, c2
);/* high */
820 outpdw(overlay_base
+ off
+ 0x104, blend_op
);
823 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe
*pipe
, int all
)
827 if (pipe
->mixer_num
== MDP4_MIXER1
)
833 if (pipe
->pipe_type
== OVERLAY_TYPE_RGB
) {
834 if (pipe
->pipe_num
== OVERLAY_PIPE_RGB2
)
839 if (pipe
->pipe_num
== OVERLAY_PIPE_VG2
)
846 outpdw(MDP_BASE
+ 0x18000, bits
); /* MDP_OVERLAY_REG_FLUSH */
848 while (inpdw(MDP_BASE
+ 0x18000) & bits
) /* self clear when complete */
852 struct mdp4_overlay_pipe
*mdp4_overlay_ndx2pipe(int ndx
)
854 struct mdp4_overlay_pipe
*pipe
;
856 if (ndx
== 0 || ndx
>= MDP4_MAX_OVERLAY_PIPE
)
859 pipe
= &ctrl
->plist
[ndx
- 1]; /* ndx start from 1 */
861 if (pipe
->pipe_ndx
== 0)
867 struct mdp4_overlay_pipe
*mdp4_overlay_pipe_alloc(void)
870 struct mdp4_overlay_pipe
*pipe
;
872 pipe
= &ctrl
->plist
[0];
873 for (i
= 0; i
< MDP4_MAX_OVERLAY_PIPE
; i
++) {
874 if (pipe
->pipe_ndx
== 0) {
875 pipe
->pipe_ndx
= i
+ 1; /* start from 1 */
876 init_completion(&pipe
->comp
);
877 printk(KERN_INFO
"mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
878 (int)pipe
, pipe
->pipe_ndx
);
888 void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe
*pipe
)
890 printk(KERN_INFO
"mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
891 (int)pipe
, pipe
->pipe_ndx
);
892 memset(pipe
, 0, sizeof(*pipe
));
895 static int get_pipe_num(int ptype
, int stage
)
897 if (ptype
== OVERLAY_TYPE_RGB
) {
898 if (stage
== MDP4_MIXER_STAGE_BASE
)
899 return OVERLAY_PIPE_RGB1
;
901 return OVERLAY_PIPE_RGB2
;
903 if (stage
== MDP4_MIXER_STAGE0
)
904 return OVERLAY_PIPE_VG1
;
906 return OVERLAY_PIPE_VG2
;
910 int mdp4_overlay_req_check(uint32 id
, uint32 z_order
, uint32 mixer
)
912 struct mdp4_overlay_pipe
*pipe
;
914 pipe
= ctrl
->stage
[mixer
][z_order
];
919 if (pipe
->pipe_ndx
== id
) /* same req, recycle */
925 static int mdp4_overlay_req2pipe(struct mdp_overlay
*req
, int mixer
,
926 struct mdp4_overlay_pipe
**ppipe
)
928 struct mdp4_overlay_pipe
*pipe
;
931 if (mixer
>= MDP4_MAX_MIXER
) {
932 printk(KERN_ERR
"mpd_overlay_req2pipe: mixer out of range!\n");
936 if (req
->z_order
< 0 || req
->z_order
> 2) {
937 printk(KERN_ERR
"mpd_overlay_req2pipe: z_order=%d out of range!\n",
942 if (req
->src_rect
.h
== 0 || req
->src_rect
.w
== 0) {
943 printk(KERN_ERR
"mpd_overlay_req2pipe: src img of zero size!\n");
947 ret
= mdp4_overlay_req_check(req
->id
, req
->z_order
, mixer
);
951 ptype
= mdp4_overlay_format2type(req
->src
.format
);
955 if (req
->id
== MSMFB_NEW_REQUEST
) /* new request */
956 pipe
= mdp4_overlay_pipe_alloc();
958 pipe
= mdp4_overlay_ndx2pipe(req
->id
);
963 pipe
->src_format
= req
->src
.format
;
964 ret
= mdp4_overlay_format2pipe(pipe
);
970 * base layer == 1, reserved for frame buffer
971 * zorder 0 == stage 0 == 2
972 * zorder 1 == stage 1 == 3
973 * zorder 2 == stage 2 == 4
975 if (req
->id
== MSMFB_NEW_REQUEST
) { /* new request */
976 pipe
->mixer_stage
= req
->z_order
+ MDP4_MIXER_STAGE0
;
977 pipe
->pipe_type
= ptype
;
978 pipe
->pipe_num
= get_pipe_num(ptype
, pipe
->mixer_stage
);
979 printk(KERN_INFO
"mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
980 req
->z_order
, pipe
->pipe_num
);
983 pipe
->src_width
= req
->src
.width
& 0x07ff; /* source img width */
984 pipe
->src_height
= req
->src
.height
& 0x07ff; /* source img height */
985 pipe
->src_h
= req
->src_rect
.h
& 0x07ff;
986 pipe
->src_w
= req
->src_rect
.w
& 0x07ff;
987 pipe
->src_y
= req
->src_rect
.y
& 0x07ff;
988 pipe
->src_x
= req
->src_rect
.x
& 0x07ff;
989 pipe
->dst_h
= req
->dst_rect
.h
& 0x07ff;
990 pipe
->dst_w
= req
->dst_rect
.w
& 0x07ff;
991 pipe
->dst_y
= req
->dst_rect
.y
& 0x07ff;
992 pipe
->dst_x
= req
->dst_rect
.x
& 0x07ff;
994 if (req
->flags
& MDP_FLIP_LR
)
995 pipe
->op_mode
|= MDP4_OP_FLIP_LR
;
997 if (req
->flags
& MDP_FLIP_UD
)
998 pipe
->op_mode
|= MDP4_OP_FLIP_UD
;
1000 if (req
->flags
& MDP_DITHER
)
1001 pipe
->op_mode
|= MDP4_OP_DITHER_EN
;
1003 if (req
->flags
& MDP_DEINTERLACE
)
1004 pipe
->op_mode
|= MDP4_OP_DEINT_ODD_REF
;
1006 pipe
->is_fg
= req
->is_fg
;/* control alpha and color key */
1008 pipe
->alpha
= req
->alpha
& 0x0ff;
1010 pipe
->transp
= req
->transp_mask
;
1017 int get_img(struct msmfb_data
*img
, struct fb_info
*info
,
1018 unsigned long *start
, unsigned long *len
, struct file
**pp_file
)
1020 int put_needed
, ret
= 0;
1022 #ifdef CONFIG_ANDROID_PMEM
1023 unsigned long vstart
;
1026 #ifdef CONFIG_ANDROID_PMEM
1027 if (!get_pmem_file(img
->memory_id
, start
, &vstart
, len
, pp_file
))
1030 file
= fget_light(img
->memory_id
, &put_needed
);
1034 if (MAJOR(file
->f_dentry
->d_inode
->i_rdev
) == FB_MAJOR
) {
1035 *start
= info
->fix
.smem_start
;
1036 *len
= info
->fix
.smem_len
;
1040 fput_light(file
, put_needed
);
1044 int mdp4_overlay_get(struct fb_info
*info
, struct mdp_overlay
*req
)
1046 struct mdp4_overlay_pipe
*pipe
;
1048 pipe
= mdp4_overlay_ndx2pipe(req
->id
);
1052 *req
= pipe
->req_data
;
1057 int mdp4_overlay_set(struct fb_info
*info
, struct mdp_overlay
*req
)
1059 struct msm_fb_data_type
*mfd
= (struct msm_fb_data_type
*)info
->par
;
1061 struct mdp4_overlay_pipe
*pipe
;
1067 if (req
->src
.format
== MDP_FB_FORMAT
)
1068 req
->src
.format
= mfd
->fb_imgType
;
1070 if (mutex_lock_interruptible(&mfd
->dma
->ov_mutex
))
1073 mixer
= info
->node
; /* minor number of char device */
1075 ret
= mdp4_overlay_req2pipe(req
, mixer
, &pipe
);
1077 mutex_unlock(&mfd
->dma
->ov_mutex
);
1081 lcdc
= inpdw(MDP_BASE
+ 0xc0000);
1083 if (lcdc
== 0) { /* mddi */
1084 /* MDP cmd block enable */
1085 mdp_pipe_ctrl(MDP_CMD_BLOCK
, MDP_BLOCK_POWER_ON
, FALSE
);
1088 /* return id back to user */
1089 req
->id
= pipe
->pipe_ndx
; /* pipe_ndx start from 1 */
1090 pipe
->req_data
= *req
; /* keep original req */
1092 mutex_unlock(&mfd
->dma
->ov_mutex
);
1097 int mdp4_overlay_unset(struct fb_info
*info
, int ndx
)
1099 struct msm_fb_data_type
*mfd
= (struct msm_fb_data_type
*)info
->par
;
1100 struct mdp4_overlay_pipe
*pipe
;
1106 if (mutex_lock_interruptible(&mfd
->dma
->ov_mutex
))
1109 pipe
= mdp4_overlay_ndx2pipe(ndx
);
1112 mutex_unlock(&mfd
->dma
->ov_mutex
);
1116 lcdc
= inpdw(MDP_BASE
+ 0xc0000);
1118 mdp4_mixer_stage_down(pipe
);
1120 if (lcdc
== 0) { /* mddi */
1121 /* MDP cmd block disable */
1122 mdp_pipe_ctrl(MDP_CMD_BLOCK
, MDP_BLOCK_POWER_OFF
, FALSE
);
1125 if (lcdc
) /* LCDC mode */
1126 mdp4_overlay_reg_flush(pipe
, 0);
1128 mdp4_overlay_pipe_free(pipe
);
1130 if (lcdc
== 0) { /* mddi */
1131 mdp4_mddi_overlay_restore();
1134 mutex_unlock(&mfd
->dma
->ov_mutex
);
1140 uint32 width
; /* tile's width */
1141 uint32 height
; /* tile's height */
1142 uint32 row_tile_w
; /* tiles per row's width */
1143 uint32 row_tile_h
; /* tiles per row's height */
1146 void tile_samsung(struct tile_desc
*tp
)
1149 * each row of samsung tile consists of two tiles in height
1150 * and two tiles in width which means width should align to
1151 * 64 x 2 bytes and height should align to 32 x 2 bytes.
1152 * video decoder generate two tiles in width and one tile
1153 * in height which ends up height align to 32 X 1 bytes.
1155 tp
->width
= 64; /* 64 bytes */
1156 tp
->row_tile_w
= 2; /* 2 tiles per row's width */
1157 tp
->height
= 32; /* 32 bytes */
1158 tp
->row_tile_h
= 1; /* 1 tiles per row's height */
1161 uint32
tile_mem_size(struct mdp4_overlay_pipe
*pipe
, struct tile_desc
*tp
)
1163 uint32 tile_w
, tile_h
;
1164 uint32 row_num_w
, row_num_h
;
1167 tile_w
= tp
->width
* tp
->row_tile_w
;
1168 tile_h
= tp
->height
* tp
->row_tile_h
;
1170 row_num_w
= (pipe
->src_width
+ tile_w
- 1) / tile_w
;
1171 row_num_h
= (pipe
->src_height
+ tile_h
- 1) / tile_h
;
1173 return row_num_w
* row_num_h
* tile_w
* tile_h
;
1176 int mdp4_overlay_play(struct fb_info
*info
, struct msmfb_overlay_data
*req
,
1177 struct file
**pp_src_file
)
1179 struct msm_fb_data_type
*mfd
= (struct msm_fb_data_type
*)info
->par
;
1180 struct msmfb_data
*img
;
1181 struct mdp4_overlay_pipe
*pipe
;
1184 struct file
*p_src_file
= 0;
1190 pipe
= mdp4_overlay_ndx2pipe(req
->id
);
1194 if (mutex_lock_interruptible(&mfd
->dma
->ov_mutex
))
1198 get_img(img
, info
, &start
, &len
, &p_src_file
);
1200 mutex_unlock(&mfd
->dma
->ov_mutex
);
1201 printk(KERN_ERR
"mdp_overlay_play: could not retrieve"
1202 " image from memory\n");
1205 *pp_src_file
= p_src_file
;
1207 addr
= start
+ img
->offset
;
1208 pipe
->srcp0_addr
= addr
;
1209 pipe
->srcp0_ystride
= pipe
->src_width
* pipe
->bpp
;
1211 if (pipe
->fetch_plane
== OVERLAY_PLANE_PSEUDO_PLANAR
) {
1212 if (pipe
->frame_format
== MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
) {
1213 struct tile_desc tile
;
1215 tile_samsung(&tile
);
1216 pipe
->srcp1_addr
= addr
+ tile_mem_size(pipe
, &tile
);
1218 pipe
->srcp1_addr
= addr
+
1219 pipe
->src_width
* pipe
->src_height
;
1221 pipe
->srcp0_ystride
= pipe
->src_width
;
1222 pipe
->srcp1_ystride
= pipe
->src_width
;
1225 lcdc
= inpdw(MDP_BASE
+ 0xc0000);
1226 lcdc
&= 0x01; /* LCDC mode */
1228 if (pipe
->pipe_type
== OVERLAY_TYPE_VG
)
1229 mdp4_overlay_vg_setup(pipe
); /* video/graphic pipe */
1231 mdp4_overlay_rgb_setup(pipe
); /* rgb pipe */
1233 mdp4_mixer_blend_setup(pipe
);
1234 mdp4_mixer_stage_up(pipe
);
1236 if (lcdc
) { /* LCDC mode */
1237 mdp4_overlay_reg_flush(pipe
, 1);
1240 if (lcdc
) { /* LCDC mode */
1241 if (pipe
->mixer_stage
!= MDP4_MIXER_STAGE_BASE
) { /* done */
1242 mutex_unlock(&mfd
->dma
->ov_mutex
);
1247 if (lcdc
== 0) { /* MDDI mode */
1248 #ifdef MDP4_NONBLOCKING
1249 if (mfd
->panel_power_on
)
1251 if (!mfd
->dma
->busy
&& mfd
->panel_power_on
)
1253 mdp4_mddi_overlay_kickoff(mfd
, pipe
);
1256 mutex_unlock(&mfd
->dma
->ov_mutex
);