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 running */
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=%p ndx=%d\n",
878
pipe, pipe->pipe_ndx);
888
void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
890
printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%p ndx=%d\n",
891
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);