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 
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];
49 } mdp4_overlay_db;
50 
51 static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
52 
53 
mdp4_overlay_dmap_cfg(struct msm_fb_data_type * mfd,int lcdc)54 void 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 
mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe * pipe)85 void 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 
mdp4_leading_0(uint32 num)101 static 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 
mdp4_scale_phase_step(int f_num,uint32 src,uint32 dst)115 static 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 
mdp4_scale_setup(struct mdp4_overlay_pipe * pipe)133 static 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 
mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe * pipe)172 void 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 
mdp4_overlay_vg_setup(struct mdp4_overlay_pipe * pipe)211 void 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 
mdp4_overlay_format2type(uint32 format)264 int 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 
mdp4_overlay_format2pipe(struct mdp4_overlay_pipe * pipe)293 int 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  */
color_key_convert(int start,int num,uint32 color)484 static 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 
transp_color_key(int format,uint32 transp,uint32 * c0,uint32 * c1,uint32 * c2)502 void 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 
mdp4_overlay_format(struct mdp4_overlay_pipe * pipe)568 uint32 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 
mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe * pipe)605 uint32 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 
mdp4_overlayproc_cfg(struct mdp4_overlay_pipe * pipe)611 void 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 
mdp4_overlay_active(int mixer)632 int 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 
mdp4_mixer_stage_up(struct mdp4_overlay_pipe * pipe)657 void 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 
mdp4_mixer_stage_down(struct mdp4_overlay_pipe * pipe)692 void 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 
mdp4_mixer_blend_setup(struct mdp4_overlay_pipe * pipe)727 void 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 
mdp4_overlay_reg_flush(struct mdp4_overlay_pipe * pipe,int all)823 void 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 
mdp4_overlay_ndx2pipe(int ndx)852 struct 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 
mdp4_overlay_pipe_alloc(void)867 struct 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 
mdp4_overlay_pipe_free(struct mdp4_overlay_pipe * pipe)888 void 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 
get_pipe_num(int ptype,int stage)895 static 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 
mdp4_overlay_req_check(uint32 id,uint32 z_order,uint32 mixer)910 int 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 
mdp4_overlay_req2pipe(struct mdp_overlay * req,int mixer,struct mdp4_overlay_pipe ** ppipe)925 static 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 
get_img(struct msmfb_data * img,struct fb_info * info,unsigned long * start,unsigned long * len,struct file ** pp_file)1017 int 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 }
mdp4_overlay_get(struct fb_info * info,struct mdp_overlay * req)1044 int 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 
mdp4_overlay_set(struct fb_info * info,struct mdp_overlay * req)1057 int 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 
mdp4_overlay_unset(struct fb_info * info,int ndx)1097 int 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 
1139 struct 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 
tile_samsung(struct tile_desc * tp)1146 void 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 
tile_mem_size(struct mdp4_overlay_pipe * pipe,struct tile_desc * tp)1161 uint32 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 
mdp4_overlay_play(struct fb_info * info,struct msmfb_overlay_data * req,struct file ** pp_src_file)1176 int 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 }
1260