PageRenderTime 207ms CodeModel.GetById 31ms app.highlight 163ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/staging/msm/mdp4_overlay.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 1259 lines | 998 code | 209 blank | 52 comment | 196 complexity | 6262d4f49cc3773d965efcbeab87eba8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   1/* Copyright (c) 2008-2009, 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 * 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
  15 * 02110-1301, USA.
  16 */
  17
  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>
  28#include <linux/io.h>
  29#include <linux/debugfs.h>
  30#include <linux/fb.h>
  31#include <msm_mdp.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>
  40
  41#include "mdp.h"
  42#include "msm_fb.h"
  43#include "mdp4.h"
  44
  45
  46struct 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];
  49} mdp4_overlay_db;
  50
  51static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
  52
  53
  54void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
  55{
  56	uint32	dma2_cfg_reg;
  57
  58	dma2_cfg_reg = DMA_DITHER_EN;
  59
  60	if (mfd->fb_imgType == MDP_BGR_565)
  61		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
  62	else
  63		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
  64
  65
  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;
  72	} else {
  73		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 16BPP */
  74		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
  75	}
  76
  77	if (lcdc)
  78		dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
  79
  80	/* dma2 config register */
  81	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
  82
  83}
  84
  85void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
  86{
  87
  88	/* dma_p source */
  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);
  93
  94	/* dma_p dest */
  95	MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
  96}
  97
  98#define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000
  99#define MDP4_VG_PHASE_STEP_SHIFT	29
 100
 101static int mdp4_leading_0(uint32 num)
 102{
 103	uint32 bit = 0x80000000;
 104	int i;
 105
 106	for (i = 0; i < 32; i++) {
 107		if (bit & num)
 108			return i;
 109		bit >>= 1;
 110	}
 111
 112	return i;
 113}
 114
 115static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
 116{
 117	uint32 val;
 118	int	n;
 119
 120	n = mdp4_leading_0(src);
 121	if (n > f_num)
 122		n = f_num;
 123	val = src << n;	/* maximum to reduce lose of resolution */
 124	val /= dst;
 125	if (n < f_num) {
 126		n = f_num - n;
 127		val <<= n;
 128	}
 129
 130	return val;
 131}
 132
 133static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
 134{
 135
 136	pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
 137	pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
 138
 139	if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
 140		if (pipe->dst_h >= pipe->src_h * 8)	/* too much */
 141			return;
 142		pipe->op_mode |= MDP4_OP_SCALEY_EN;
 143
 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;
 147			else
 148				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
 149		}
 150
 151		pipe->phasey_step = mdp4_scale_phase_step(29,
 152					pipe->src_h, pipe->dst_h);
 153	}
 154
 155	if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
 156		if (pipe->dst_w >= pipe->src_w * 8)	/* too much */
 157			return;
 158		pipe->op_mode |= MDP4_OP_SCALEX_EN;
 159
 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;
 163			else
 164				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
 165		}
 166
 167		pipe->phasex_step = mdp4_scale_phase_step(29,
 168					pipe->src_w, pipe->dst_w);
 169	}
 170}
 171
 172void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
 173{
 174	char *rgb_base;
 175	uint32 src_size, src_xy, dst_size, dst_xy;
 176	uint32 format, pattern;
 177
 178	rgb_base = MDP_BASE + MDP4_RGB_BASE;
 179	rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
 180
 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);
 185
 186	format = mdp4_overlay_format(pipe);
 187	pattern = mdp4_overlay_unpack_pattern(pipe);
 188
 189	pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
 190
 191	mdp4_scale_setup(pipe);
 192
 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 */
 197
 198	outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
 199	outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
 200
 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);
 206
 207	/* 16 bytes-burst x 3 req <= 48 bytes */
 208	outpdw(rgb_base + 0x1004, 0xc2);	/* MDP_RGB_FETCH_CFG */
 209}
 210
 211void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
 212{
 213	char *vg_base;
 214	uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
 215	uint32 format, pattern;
 216
 217	vg_base = MDP_BASE + MDP4_VIDEO_BASE;
 218	vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
 219
 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);
 225
 226	format = mdp4_overlay_format(pipe);
 227	pattern = mdp4_overlay_unpack_pattern(pipe);
 228
 229	pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
 230				MDP4_OP_IGC_LUT_EN);
 231
 232	mdp4_scale_setup(pipe);
 233
 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 */
 239
 240	/* luma component plane */
 241	outpdw(vg_base + 0x0010, pipe->srcp0_addr);
 242
 243	/* chroma component plane */
 244	outpdw(vg_base + 0x0014, pipe->srcp1_addr);
 245
 246	outpdw(vg_base + 0x0040,
 247			pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
 248
 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);
 254
 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);
 258	}
 259
 260	/* 16 bytes-burst x 3 req <= 48 bytes */
 261	outpdw(vg_base + 0x1004, 0xc2);	/* MDP_VG_FETCH_CFG */
 262}
 263
 264int mdp4_overlay_format2type(uint32 format)
 265{
 266	switch (format) {
 267	case MDP_RGB_565:
 268	case MDP_RGB_888:
 269	case MDP_BGR_565:
 270	case MDP_ARGB_8888:
 271	case MDP_RGBA_8888:
 272	case MDP_BGRA_8888:
 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;
 282	default:
 283		return -ERANGE;
 284	}
 285
 286}
 287
 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 */
 292
 293int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
 294{
 295	switch (pipe->src_format) {
 296	case MDP_RGB_565:
 297		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
 298		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
 299		pipe->a_bit = 0;
 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 */
 311		break;
 312	case MDP_RGB_888:
 313		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
 314		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
 315		pipe->a_bit = 0;
 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 */
 327		break;
 328	case MDP_BGR_565:
 329		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
 330		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
 331		pipe->a_bit = 0;
 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 */
 343		break;
 344	case MDP_ARGB_8888:
 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 */
 360		break;
 361	case MDP_RGBA_8888:
 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 */
 377		break;
 378	case MDP_BGRA_8888:
 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 */
 394		break;
 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;
 412		break;
 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;
 419		pipe->a_bit = 0;
 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;
 445		}
 446		pipe->bpp = 2;	/* 2 bpp */
 447		break;
 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;
 452		pipe->a_bit = 0;
 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;
 470		}
 471		pipe->bpp = 2;	/* 2 bpp */
 472		break;
 473	default:
 474		/* not likely */
 475		return -ERANGE;
 476	}
 477
 478	return 0;
 479}
 480
 481/*
 482 * color_key_convert: output with 12 bits color key
 483 */
 484static uint32 color_key_convert(int start, int num, uint32 color)
 485{
 486
 487	uint32 data;
 488
 489	data = (color >> start) & ((1 << num) - 1);
 490
 491	if (num == 5)
 492		data = (data << 7) + (data << 2) + (data >> 3);
 493	else if (num == 6)
 494		data = (data << 6) + data;
 495	else	/* 8 bits */
 496		data = (data << 4) + (data >> 4);
 497
 498	return data;
 499
 500}
 501
 502void transp_color_key(int format, uint32 transp,
 503			uint32 *c0, uint32 *c1, uint32 *c2)
 504{
 505	int b_start, g_start, r_start;
 506	int b_num, g_num, r_num;
 507
 508	switch (format) {
 509	case MDP_RGB_565:
 510		b_start = 0;
 511		g_start = 5;
 512		r_start = 11;
 513		r_num = 5;
 514		g_num = 6;
 515		b_num = 5;
 516		break;
 517	case MDP_RGB_888:
 518	case MDP_XRGB_8888:
 519	case MDP_ARGB_8888:
 520		b_start = 0;
 521		g_start = 8;
 522		r_start = 16;
 523		r_num = 8;
 524		g_num = 8;
 525		b_num = 8;
 526		break;
 527	case MDP_BGR_565:
 528		b_start = 11;
 529		g_start = 5;
 530		r_start = 0;
 531		r_num = 5;
 532		g_num = 6;
 533		b_num = 5;
 534		break;
 535	case MDP_Y_CBCR_H2V2:
 536	case MDP_Y_CBCR_H2V1:
 537		b_start = 8;
 538		g_start = 16;
 539		r_start = 0;
 540		r_num = 8;
 541		g_num = 8;
 542		b_num = 8;
 543		break;
 544	case MDP_Y_CRCB_H2V2:
 545	case MDP_Y_CRCB_H2V1:
 546		b_start = 0;
 547		g_start = 16;
 548		r_start = 8;
 549		r_num = 8;
 550		g_num = 8;
 551		b_num = 8;
 552		break;
 553	default:
 554		b_start = 0;
 555		g_start = 8;
 556		r_start = 16;
 557		r_num = 8;
 558		g_num = 8;
 559		b_num = 8;
 560		break;
 561	}
 562
 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);
 566}
 567
 568uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
 569{
 570	uint32	format;
 571
 572	format = 0;
 573
 574	if (pipe->solid_fill)
 575		format |= MDP4_FORMAT_SOLID_FILL;
 576
 577	if (pipe->unpack_align_msb)
 578		format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
 579
 580	if (pipe->unpack_tight)
 581		format |= MDP4_FORMAT_UNPACK_TIGHT;
 582
 583	if (pipe->alpha_enable)
 584		format |= MDP4_FORMAT_ALPHA_ENABLE;
 585
 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;
 592
 593	format |= (pipe->frame_format << 29);
 594
 595	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
 596		/* video/graphic */
 597		format |= (pipe->fetch_plane << 19);
 598		format |= (pipe->chroma_site << 28);
 599		format |= (pipe->chroma_sample << 26);
 600	}
 601
 602	return format;
 603}
 604
 605uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
 606{
 607	return (pipe->element3 << 24) | (pipe->element2 << 16) |
 608			(pipe->element1 << 8) | pipe->element0;
 609}
 610
 611void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
 612{
 613	uint32 data;
 614	char *overlay_base;
 615
 616	if (pipe->mixer_num == MDP4_MIXER1)
 617		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
 618	else
 619		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
 620
 621	/* MDP_OVERLAYPROC_CFG */
 622	outpdw(overlay_base + 0x0004, 0x01); /* directout */
 623	data = pipe->src_height;
 624	data <<= 16;
 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 */
 630}
 631
 632int mdp4_overlay_active(int mixer)
 633{
 634	uint32 data, mask, i;
 635	int p1, p2;
 636
 637	data = inpdw(MDP_BASE + 0x10100);
 638	p1 = 0;
 639	p2 = 0;
 640	for (i = 0; i < 8; i++) {
 641		mask = data & 0x0f;
 642		if (mask) {
 643			if (mask <= 4)
 644				p1++;
 645			else
 646				p2++;
 647		}
 648		data >>= 4;
 649	}
 650
 651	if (mixer)
 652		return p2;
 653	else
 654		return p1;
 655}
 656
 657void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
 658{
 659	uint32 data, mask, snum, stage, mixer;
 660
 661	stage = pipe->mixer_stage;
 662	mixer = pipe->mixer_num;
 663
 664	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
 665	data = inpdw(MDP_BASE + 0x10100);
 666
 667	if (mixer == MDP4_MIXER1)
 668		stage += 8;
 669
 670	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
 671		snum = 0;
 672		snum += (4 * pipe->pipe_num);
 673	} else {
 674		snum = 8;
 675		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
 676	}
 677
 678	mask = 0x0f;
 679	mask <<= snum;
 680	stage <<= snum;
 681	data &= ~mask;	/* clear old bits */
 682
 683	data |= stage;
 684
 685	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
 686
 687	data = inpdw(MDP_BASE + 0x10100);
 688
 689	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe;	/* keep it */
 690}
 691
 692void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
 693{
 694	uint32 data, mask, snum, stage, mixer;
 695
 696	stage = pipe->mixer_stage;
 697	mixer = pipe->mixer_num;
 698
 699	if (pipe != ctrl->stage[mixer][stage])	/* not running */
 700		return;
 701
 702	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
 703	data = inpdw(MDP_BASE + 0x10100);
 704
 705	if (mixer == MDP4_MIXER1)
 706		stage += 8;
 707
 708	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
 709		snum = 0;
 710		snum += (4 * pipe->pipe_num);
 711	} else {
 712		snum = 8;
 713		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
 714	}
 715
 716	mask = 0x0f;
 717	mask <<= snum;
 718	data &= ~mask;	/* clear old bits */
 719
 720	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
 721
 722	data = inpdw(MDP_BASE + 0x10100);
 723
 724	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;	/* clear it */
 725}
 726
 727void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
 728{
 729	unsigned char *overlay_base;
 730	uint32 c0, c1, c2, blend_op;
 731	int off;
 732
 733	if (pipe->mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
 734		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
 735	else
 736		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
 737
 738	/* stage 0 to stage 2 */
 739	off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
 740
 741	blend_op = 0;
 742	if (pipe->alpha_enable) 	/* ARGB */
 743		blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
 744				MDP4_BLEND_BG_ALPHA_FG_PIXEL;
 745	else
 746		blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
 747				MDP4_BLEND_FG_ALPHA_FG_CONST);
 748
 749
 750	if (pipe->alpha_enable == 0) { 	/* not ARGB */
 751		if (pipe->is_fg) {
 752			outpdw(overlay_base + off + 0x108, pipe->alpha);
 753			outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
 754		} else {
 755			outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
 756			outpdw(overlay_base + off + 0x10c, pipe->alpha);
 757		}
 758	}
 759
 760	if (pipe->transp != MDP_TRANSP_NOP) {
 761		transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
 762		if (pipe->is_fg) {
 763			blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
 764			/* lower limit */
 765			if (c0 > 0x10)
 766				c0 -= 0x10;
 767			if (c1 > 0x10)
 768				c1 -= 0x10;
 769			if (c2 > 0x10)
 770				c2 -= 0x10;
 771			outpdw(overlay_base + off + 0x110,
 772						(c1 << 16 | c0));/* low */
 773			outpdw(overlay_base + off + 0x114, c2);/* low */
 774			/* upper limit */
 775			if ((c0 + 0x20) < 0x0fff)
 776				c0 += 0x20;
 777			else
 778				c0 = 0x0fff;
 779			if ((c1 + 0x20) < 0x0fff)
 780				c1 += 0x20;
 781			else
 782				c1 = 0x0fff;
 783			if ((c2 + 0x20) < 0x0fff)
 784				c2 += 0x20;
 785			else
 786				c2 = 0x0fff;
 787			outpdw(overlay_base + off + 0x118,
 788					(c1 << 16 | c0));/* high */
 789			outpdw(overlay_base + off + 0x11c, c2);/* high */
 790		} else {
 791			blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
 792			/* lower limit */
 793			if (c0 > 0x10)
 794				c0 -= 0x10;
 795			if (c1 > 0x10)
 796				c1 -= 0x10;
 797			if (c2 > 0x10)
 798				c2 -= 0x10;
 799			outpdw(overlay_base + 0x180,
 800						(c1 << 16 | c0));/* low */
 801			outpdw(overlay_base + 0x184, c2);/* low */
 802			/* upper limit */
 803			if ((c0 + 0x20) < 0x0fff)
 804				c0 += 0x20;
 805			else
 806				c0 = 0x0fff;
 807			if ((c1 + 0x20) < 0x0fff)
 808				c1 += 0x20;
 809			else
 810				c1 = 0x0fff;
 811			if ((c2 + 0x20) < 0x0fff)
 812				c2 += 0x20;
 813			else
 814				c2 = 0x0fff;
 815			outpdw(overlay_base + 0x188,
 816						(c1 << 16 | c0));/* high */
 817			outpdw(overlay_base + 0x18c, c2);/* high */
 818		}
 819	}
 820	outpdw(overlay_base + off + 0x104, blend_op);
 821}
 822
 823void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
 824{
 825	uint32 bits = 0;
 826
 827	if (pipe->mixer_num == MDP4_MIXER1)
 828		bits |= 0x02;
 829	else
 830		bits |= 0x01;
 831
 832	if (all) {
 833		if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
 834			if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
 835				bits |= 0x20;
 836			else
 837				bits |= 0x10;
 838		} else {
 839			if (pipe->pipe_num == OVERLAY_PIPE_VG2)
 840				bits |= 0x08;
 841			else
 842				bits |= 0x04;
 843		}
 844	}
 845
 846	outpdw(MDP_BASE + 0x18000, bits);	/* MDP_OVERLAY_REG_FLUSH */
 847
 848	while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
 849		;
 850}
 851
 852struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
 853{
 854	struct mdp4_overlay_pipe *pipe;
 855
 856	if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
 857		return NULL;
 858
 859	pipe = &ctrl->plist[ndx - 1];	/* ndx start from 1 */
 860
 861	if (pipe->pipe_ndx == 0)
 862		return NULL;
 863
 864	return pipe;
 865}
 866
 867struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
 868{
 869	int i;
 870	struct mdp4_overlay_pipe *pipe;
 871
 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);
 879			return pipe;
 880		}
 881		pipe++;
 882	}
 883
 884	return NULL;
 885}
 886
 887
 888void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
 889{
 890	printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%p ndx=%d\n",
 891					pipe, pipe->pipe_ndx);
 892	memset(pipe, 0, sizeof(*pipe));
 893}
 894
 895static int get_pipe_num(int ptype, int stage)
 896{
 897	if (ptype == OVERLAY_TYPE_RGB) {
 898		if (stage == MDP4_MIXER_STAGE_BASE)
 899			return OVERLAY_PIPE_RGB1;
 900		else
 901			return OVERLAY_PIPE_RGB2;
 902	} else {
 903		if (stage == MDP4_MIXER_STAGE0)
 904			return OVERLAY_PIPE_VG1;
 905		else
 906			return OVERLAY_PIPE_VG2;
 907	}
 908}
 909
 910int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
 911{
 912	struct mdp4_overlay_pipe *pipe;
 913
 914	pipe = ctrl->stage[mixer][z_order];
 915
 916	if (pipe == NULL)
 917		return 0;
 918
 919	if (pipe->pipe_ndx == id)	/* same req, recycle */
 920		return 0;
 921
 922	return -EPERM;
 923}
 924
 925static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
 926			struct mdp4_overlay_pipe **ppipe)
 927{
 928	struct mdp4_overlay_pipe *pipe;
 929	int ret, ptype;
 930
 931	if (mixer >= MDP4_MAX_MIXER) {
 932		printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
 933		return -ERANGE;
 934	}
 935
 936	if (req->z_order < 0 || req->z_order > 2) {
 937		printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
 938				req->z_order);
 939		return -ERANGE;
 940	}
 941
 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");
 944		return -EINVAL;
 945	}
 946
 947	ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
 948	if (ret < 0)
 949		return ret;
 950
 951	ptype = mdp4_overlay_format2type(req->src.format);
 952	if (ptype < 0)
 953		return ptype;
 954
 955	if (req->id == MSMFB_NEW_REQUEST)  /* new request */
 956		pipe = mdp4_overlay_pipe_alloc();
 957	else
 958		pipe = mdp4_overlay_ndx2pipe(req->id);
 959
 960	if (pipe == NULL)
 961		return -ENOMEM;
 962
 963	pipe->src_format = req->src.format;
 964	ret = mdp4_overlay_format2pipe(pipe);
 965
 966	if (ret < 0)
 967		return ret;
 968
 969	/*
 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
 974	 */
 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);
 981	}
 982
 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;
 993
 994	if (req->flags & MDP_FLIP_LR)
 995		pipe->op_mode |= MDP4_OP_FLIP_LR;
 996
 997	if (req->flags & MDP_FLIP_UD)
 998		pipe->op_mode |= MDP4_OP_FLIP_UD;
 999
1000	if (req->flags & MDP_DITHER)
1001		pipe->op_mode |= MDP4_OP_DITHER_EN;
1002
1003	if (req->flags & MDP_DEINTERLACE)
1004		pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
1005
1006	pipe->is_fg = req->is_fg;/* control alpha and color key */
1007
1008	pipe->alpha = req->alpha & 0x0ff;
1009
1010	pipe->transp = req->transp_mask;
1011
1012	*ppipe = pipe;
1013
1014	return 0;
1015}
1016
1017int get_img(struct msmfb_data *img, struct fb_info *info,
1018	unsigned long *start, unsigned long *len, struct file **pp_file)
1019{
1020	int put_needed, ret = 0;
1021	struct file *file;
1022#ifdef CONFIG_ANDROID_PMEM
1023	unsigned long vstart;
1024#endif
1025
1026#ifdef CONFIG_ANDROID_PMEM
1027	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1028		return 0;
1029#endif
1030	file = fget_light(img->memory_id, &put_needed);
1031	if (file == NULL)
1032		return -1;
1033
1034	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1035		*start = info->fix.smem_start;
1036		*len = info->fix.smem_len;
1037		*pp_file = file;
1038	} else {
1039		ret = -1;
1040		fput_light(file, put_needed);
1041	}
1042	return ret;
1043}
1044int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
1045{
1046	struct mdp4_overlay_pipe *pipe;
1047
1048	pipe = mdp4_overlay_ndx2pipe(req->id);
1049	if (pipe == NULL)
1050		return -ENODEV;
1051
1052	*req = pipe->req_data;
1053
1054	return 0;
1055}
1056
1057int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
1058{
1059	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1060	int ret, mixer;
1061	struct mdp4_overlay_pipe *pipe;
1062	int lcdc;
1063
1064	if (mfd == NULL)
1065		return -ENODEV;
1066
1067	if (req->src.format == MDP_FB_FORMAT)
1068		req->src.format = mfd->fb_imgType;
1069
1070	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1071		return -EINTR;
1072
1073	mixer = info->node; /* minor number of char device */
1074
1075	ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
1076	if (ret < 0) {
1077		mutex_unlock(&mfd->dma->ov_mutex);
1078		return ret;
1079	}
1080
1081	lcdc = inpdw(MDP_BASE + 0xc0000);
1082
1083	if (lcdc == 0) { /* mddi */
1084		/* MDP cmd block enable */
1085		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1086	}
1087
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 */
1091
1092	mutex_unlock(&mfd->dma->ov_mutex);
1093
1094	return 0;
1095}
1096
1097int mdp4_overlay_unset(struct fb_info *info, int ndx)
1098{
1099	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1100	struct mdp4_overlay_pipe *pipe;
1101	int lcdc;
1102
1103	if (mfd == NULL)
1104		return -ENODEV;
1105
1106	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1107		return -EINTR;
1108
1109	pipe = mdp4_overlay_ndx2pipe(ndx);
1110
1111	if (pipe == NULL) {
1112		mutex_unlock(&mfd->dma->ov_mutex);
1113		return -ENODEV;
1114	}
1115
1116	lcdc = inpdw(MDP_BASE + 0xc0000);
1117
1118	mdp4_mixer_stage_down(pipe);
1119
1120	if (lcdc == 0) { /* mddi */
1121		/* MDP cmd block disable */
1122		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1123	}
1124
1125	if (lcdc) /* LCDC mode */
1126		mdp4_overlay_reg_flush(pipe, 0);
1127
1128	mdp4_overlay_pipe_free(pipe);
1129
1130	if (lcdc == 0) { /* mddi */
1131		mdp4_mddi_overlay_restore();
1132	}
1133
1134	mutex_unlock(&mfd->dma->ov_mutex);
1135
1136	return 0;
1137}
1138
1139struct tile_desc {
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 */
1144};
1145
1146void tile_samsung(struct tile_desc *tp)
1147{
1148	/*
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.
1154	 */
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 */
1159}
1160
1161uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
1162{
1163	uint32 tile_w, tile_h;
1164	uint32 row_num_w, row_num_h;
1165
1166
1167	tile_w = tp->width * tp->row_tile_w;
1168	tile_h = tp->height * tp->row_tile_h;
1169
1170	row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
1171	row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
1172
1173	return row_num_w * row_num_h * tile_w * tile_h;
1174}
1175
1176int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
1177		struct file **pp_src_file)
1178{
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;
1182	ulong start, addr;
1183	ulong len = 0;
1184	struct file *p_src_file = 0;
1185	int lcdc;
1186
1187	if (mfd == NULL)
1188		return -ENODEV;
1189
1190	pipe = mdp4_overlay_ndx2pipe(req->id);
1191	if (pipe == NULL)
1192		return -ENODEV;
1193
1194	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1195		return -EINTR;
1196
1197	img = &req->data;
1198	get_img(img, info, &start, &len, &p_src_file);
1199	if (len == 0) {
1200		mutex_unlock(&mfd->dma->ov_mutex);
1201		printk(KERN_ERR "mdp_overlay_play: could not retrieve"
1202				       " image from memory\n");
1203		return -1;
1204	}
1205	*pp_src_file = p_src_file;
1206
1207	addr = start + img->offset;
1208	pipe->srcp0_addr = addr;
1209	pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
1210
1211	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
1212		if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
1213			struct tile_desc tile;
1214
1215			tile_samsung(&tile);
1216			pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
1217		} else
1218			pipe->srcp1_addr = addr +
1219					pipe->src_width * pipe->src_height;
1220
1221		pipe->srcp0_ystride = pipe->src_width;
1222		pipe->srcp1_ystride = pipe->src_width;
1223	}
1224
1225	lcdc = inpdw(MDP_BASE + 0xc0000);
1226	lcdc &= 0x01; /* LCDC mode */
1227
1228	if (pipe->pipe_type == OVERLAY_TYPE_VG)
1229		mdp4_overlay_vg_setup(pipe);	/* video/graphic pipe */
1230	else
1231		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
1232
1233	mdp4_mixer_blend_setup(pipe);
1234	mdp4_mixer_stage_up(pipe);
1235
1236	if (lcdc) { /* LCDC mode */
1237		mdp4_overlay_reg_flush(pipe, 1);
1238	}
1239
1240	if (lcdc) { /* LCDC mode */
1241		if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
1242			mutex_unlock(&mfd->dma->ov_mutex);
1243			return 0;
1244		}
1245	}
1246
1247	if (lcdc == 0) { /* MDDI mode */
1248#ifdef MDP4_NONBLOCKING
1249		if (mfd->panel_power_on)
1250#else
1251		if (!mfd->dma->busy && mfd->panel_power_on)
1252#endif
1253			mdp4_mddi_overlay_kickoff(mfd, pipe);
1254	}
1255
1256	mutex_unlock(&mfd->dma->ov_mutex);
1257
1258	return 0;
1259}