]>
Commit | Line | Data |
---|---|---|
9d200153 SM |
1 | /* drivers/video/msm/src/drv/mdp/mdp_ppp.c |
2 | * | |
3 | * Copyright (C) 2007 Google Incorporated | |
4 | * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | |
5 | * | |
6 | * This software is licensed under the terms of the GNU General Public | |
7 | * License version 2, as published by the Free Software Foundation, and | |
8 | * may be copied, distributed, and modified under those terms. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | */ | |
15 | ||
16 | #include <linux/module.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/sched.h> | |
19 | #include <linux/time.h> | |
20 | #include <linux/init.h> | |
21 | #include <linux/interrupt.h> | |
22 | #include <linux/fb.h> | |
23 | #include <msm_mdp.h> | |
24 | #include <linux/file.h> | |
25 | #include <linux/major.h> | |
26 | ||
27 | #include "linux/proc_fs.h" | |
28 | ||
29 | #include <mach/hardware.h> | |
30 | #include <linux/io.h> | |
31 | ||
32 | #include <asm/system.h> | |
33 | #include <asm/mach-types.h> | |
34 | #include <linux/semaphore.h> | |
35 | ||
36 | #include "mdp.h" | |
37 | #include "msm_fb.h" | |
38 | ||
39 | #define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \ | |
40 | (((x) < MDP_IMGTYPE2_START) || \ | |
41 | ((x) >= MDP_IMGTYPE_LIMIT2))) | |
42 | ||
43 | static uint32_t bytes_per_pixel[] = { | |
44 | [MDP_RGB_565] = 2, | |
45 | [MDP_RGB_888] = 3, | |
46 | [MDP_XRGB_8888] = 4, | |
47 | [MDP_ARGB_8888] = 4, | |
48 | [MDP_RGBA_8888] = 4, | |
49 | [MDP_BGRA_8888] = 4, | |
50 | [MDP_Y_CBCR_H2V1] = 1, | |
51 | [MDP_Y_CBCR_H2V2] = 1, | |
52 | [MDP_Y_CRCB_H2V1] = 1, | |
53 | [MDP_Y_CRCB_H2V2] = 1, | |
54 | [MDP_YCRYCB_H2V1] = 2, | |
55 | [MDP_BGR_565] = 2 | |
56 | }; | |
57 | ||
58 | extern uint32 mdp_plv[]; | |
59 | extern struct semaphore mdp_ppp_mutex; | |
60 | ||
61 | uint32_t mdp_get_bytes_per_pixel(uint32_t format) | |
62 | { | |
63 | uint32_t bpp = 0; | |
64 | if (format < ARRAY_SIZE(bytes_per_pixel)) | |
65 | bpp = bytes_per_pixel[format]; | |
66 | ||
67 | BUG_ON(!bpp); | |
68 | return bpp; | |
69 | } | |
70 | ||
71 | static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel, | |
72 | uint16 *matrix_and_bias_vector, | |
73 | uint32 *clamp_vector, | |
74 | uint32 *look_up_table) | |
75 | { | |
76 | uint8 input_C2, input_C0, input_C1; | |
77 | uint32 output; | |
78 | int32 comp_C2, comp_C1, comp_C0, temp; | |
79 | int32 temp1, temp2, temp3; | |
80 | int32 matrix[9]; | |
81 | int32 bias_vector[3]; | |
82 | int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; | |
83 | int32 i; | |
84 | uint32 _is_lookup_table_enabled; | |
85 | ||
86 | input_C2 = (input_pixel >> 16) & 0xFF; | |
87 | input_C1 = (input_pixel >> 8) & 0xFF; | |
88 | input_C0 = (input_pixel >> 0) & 0xFF; | |
89 | ||
90 | comp_C0 = input_C0; | |
91 | comp_C1 = input_C1; | |
92 | comp_C2 = input_C2; | |
93 | ||
94 | for (i = 0; i < 9; i++) | |
95 | matrix[i] = | |
96 | ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; | |
97 | ||
98 | bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); | |
99 | bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); | |
100 | bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); | |
101 | ||
102 | Y_low_limit = (int32) clamp_vector[0]; | |
103 | Y_high_limit = (int32) clamp_vector[1]; | |
104 | C_low_limit = (int32) clamp_vector[2]; | |
105 | C_high_limit = (int32) clamp_vector[3]; | |
106 | ||
107 | if (look_up_table == 0) /* check for NULL point */ | |
108 | _is_lookup_table_enabled = 0; | |
109 | else | |
110 | _is_lookup_table_enabled = 1; | |
111 | ||
112 | if (_is_lookup_table_enabled == 1) { | |
113 | comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; | |
114 | comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; | |
115 | comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; | |
116 | } | |
117 | /* | |
118 | * Color Conversion | |
119 | * reorder input colors | |
120 | */ | |
121 | temp = comp_C2; | |
122 | comp_C2 = comp_C1; | |
123 | comp_C1 = comp_C0; | |
124 | comp_C0 = temp; | |
125 | ||
126 | /* matrix multiplication */ | |
127 | temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; | |
128 | temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; | |
129 | temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; | |
130 | ||
131 | comp_C0 = temp1 + 0x100; | |
132 | comp_C1 = temp2 + 0x100; | |
133 | comp_C2 = temp3 + 0x100; | |
134 | ||
135 | /* take interger part */ | |
136 | comp_C0 >>= 9; | |
137 | comp_C1 >>= 9; | |
138 | comp_C2 >>= 9; | |
139 | ||
140 | /* post bias (+) */ | |
141 | comp_C0 += bias_vector[0]; | |
142 | comp_C1 += bias_vector[1]; | |
143 | comp_C2 += bias_vector[2]; | |
144 | ||
145 | /* limit pixel to 8-bit */ | |
146 | if (comp_C0 < 0) | |
147 | comp_C0 = 0; | |
148 | ||
149 | if (comp_C0 > 255) | |
150 | comp_C0 = 255; | |
151 | ||
152 | if (comp_C1 < 0) | |
153 | comp_C1 = 0; | |
154 | ||
155 | if (comp_C1 > 255) | |
156 | comp_C1 = 255; | |
157 | ||
158 | if (comp_C2 < 0) | |
159 | comp_C2 = 0; | |
160 | ||
161 | if (comp_C2 > 255) | |
162 | comp_C2 = 255; | |
163 | ||
164 | /* clamp */ | |
165 | if (comp_C0 < Y_low_limit) | |
166 | comp_C0 = Y_low_limit; | |
167 | ||
168 | if (comp_C0 > Y_high_limit) | |
169 | comp_C0 = Y_high_limit; | |
170 | ||
171 | if (comp_C1 < C_low_limit) | |
172 | comp_C1 = C_low_limit; | |
173 | ||
174 | if (comp_C1 > C_high_limit) | |
175 | comp_C1 = C_high_limit; | |
176 | ||
177 | if (comp_C2 < C_low_limit) | |
178 | comp_C2 = C_low_limit; | |
179 | ||
180 | if (comp_C2 > C_high_limit) | |
181 | comp_C2 = C_high_limit; | |
182 | ||
183 | output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; | |
184 | return output; | |
185 | } | |
186 | ||
187 | uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel, | |
188 | uint16 *matrix_and_bias_vector, | |
189 | uint32 *clamp_vector, uint32 *look_up_table) | |
190 | { | |
191 | uint8 input_C2, input_C0, input_C1; | |
192 | uint32 output; | |
193 | int32 comp_C2, comp_C1, comp_C0, temp; | |
194 | int32 temp1, temp2, temp3; | |
195 | int32 matrix[9]; | |
196 | int32 bias_vector[3]; | |
197 | int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; | |
198 | int32 i; | |
199 | uint32 _is_lookup_table_enabled; | |
200 | ||
201 | input_C2 = (input_pixel >> 16) & 0xFF; | |
202 | input_C1 = (input_pixel >> 8) & 0xFF; | |
203 | input_C0 = (input_pixel >> 0) & 0xFF; | |
204 | ||
205 | comp_C0 = input_C0; | |
206 | comp_C1 = input_C1; | |
207 | comp_C2 = input_C2; | |
208 | ||
209 | for (i = 0; i < 9; i++) | |
210 | matrix[i] = | |
211 | ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; | |
212 | ||
213 | bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); | |
214 | bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); | |
215 | bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); | |
216 | ||
217 | Y_low_limit = (int32) clamp_vector[0]; | |
218 | Y_high_limit = (int32) clamp_vector[1]; | |
219 | C_low_limit = (int32) clamp_vector[2]; | |
220 | C_high_limit = (int32) clamp_vector[3]; | |
221 | ||
222 | if (look_up_table == 0) /* check for NULL point */ | |
223 | _is_lookup_table_enabled = 0; | |
224 | else | |
225 | _is_lookup_table_enabled = 1; | |
226 | ||
227 | /* clamp */ | |
228 | if (comp_C0 < Y_low_limit) | |
229 | comp_C0 = Y_low_limit; | |
230 | ||
231 | if (comp_C0 > Y_high_limit) | |
232 | comp_C0 = Y_high_limit; | |
233 | ||
234 | if (comp_C1 < C_low_limit) | |
235 | comp_C1 = C_low_limit; | |
236 | ||
237 | if (comp_C1 > C_high_limit) | |
238 | comp_C1 = C_high_limit; | |
239 | ||
240 | if (comp_C2 < C_low_limit) | |
241 | comp_C2 = C_low_limit; | |
242 | ||
243 | if (comp_C2 > C_high_limit) | |
244 | comp_C2 = C_high_limit; | |
245 | ||
246 | /* | |
247 | * Color Conversion | |
248 | * pre bias (-) | |
249 | */ | |
250 | comp_C0 -= bias_vector[0]; | |
251 | comp_C1 -= bias_vector[1]; | |
252 | comp_C2 -= bias_vector[2]; | |
253 | ||
254 | /* matrix multiplication */ | |
255 | temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; | |
256 | temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; | |
257 | temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; | |
258 | ||
259 | comp_C0 = temp1 + 0x100; | |
260 | comp_C1 = temp2 + 0x100; | |
261 | comp_C2 = temp3 + 0x100; | |
262 | ||
263 | /* take interger part */ | |
264 | comp_C0 >>= 9; | |
265 | comp_C1 >>= 9; | |
266 | comp_C2 >>= 9; | |
267 | ||
268 | /* reorder output colors */ | |
269 | temp = comp_C0; | |
270 | comp_C0 = comp_C1; | |
271 | comp_C1 = comp_C2; | |
272 | comp_C2 = temp; | |
273 | ||
274 | /* limit pixel to 8-bit */ | |
275 | if (comp_C0 < 0) | |
276 | comp_C0 = 0; | |
277 | ||
278 | if (comp_C0 > 255) | |
279 | comp_C0 = 255; | |
280 | ||
281 | if (comp_C1 < 0) | |
282 | comp_C1 = 0; | |
283 | ||
284 | if (comp_C1 > 255) | |
285 | comp_C1 = 255; | |
286 | ||
287 | if (comp_C2 < 0) | |
288 | comp_C2 = 0; | |
289 | ||
290 | if (comp_C2 > 255) | |
291 | comp_C2 = 255; | |
292 | ||
293 | /* Look-up table */ | |
294 | if (_is_lookup_table_enabled == 1) { | |
295 | comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; | |
296 | comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; | |
297 | comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; | |
298 | } | |
299 | ||
300 | output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; | |
301 | return output; | |
302 | } | |
303 | ||
304 | static uint32 mdp_calc_tpval(MDPIMG *mdpImg) | |
305 | { | |
306 | uint32 tpVal; | |
307 | uint8 plane_tp; | |
308 | ||
309 | tpVal = 0; | |
310 | if ((mdpImg->imgType == MDP_RGB_565) | |
311 | || (mdpImg->imgType == MDP_BGR_565)) { | |
312 | /* | |
313 | * transparent color conversion into 24 bpp | |
314 | * | |
315 | * C2R_8BIT | |
316 | * left shift the entire bit and or it with the upper most bits | |
317 | */ | |
318 | plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11); | |
319 | tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16; | |
320 | ||
321 | /* C1B_8BIT */ | |
322 | plane_tp = (uint8) (mdpImg->tpVal & 0x1F); | |
323 | tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8; | |
324 | ||
325 | /* C0G_8BIT */ | |
326 | plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5); | |
327 | tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4)); | |
328 | } else { | |
329 | /* 24bit RGB to RBG conversion */ | |
330 | ||
331 | tpVal = (mdpImg->tpVal & 0xFF00) >> 8; | |
332 | tpVal |= (mdpImg->tpVal & 0xFF) << 8; | |
333 | tpVal |= (mdpImg->tpVal & 0xFF0000); | |
334 | } | |
335 | ||
336 | return tpVal; | |
337 | } | |
338 | ||
339 | static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf) | |
340 | { | |
341 | uint8 *dest1; | |
342 | ||
343 | dest1 = NULL; | |
344 | switch (iBuf->ibuf_type) { | |
345 | case MDP_Y_CBCR_H2V2: | |
346 | case MDP_Y_CRCB_H2V2: | |
347 | case MDP_Y_CBCR_H2V1: | |
348 | case MDP_Y_CRCB_H2V1: | |
349 | dest1 = (uint8 *) iBuf->buf; | |
350 | dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp; | |
351 | break; | |
352 | ||
353 | default: | |
354 | break; | |
355 | } | |
356 | ||
357 | return dest1; | |
358 | } | |
359 | ||
360 | static void mdp_ppp_setbg(MDPIBUF *iBuf) | |
361 | { | |
362 | uint8 *bg0_addr; | |
363 | uint8 *bg1_addr; | |
364 | uint32 bg0_ystride, bg1_ystride; | |
365 | uint32 ppp_src_cfg_reg, unpack_pattern; | |
366 | int v_slice, h_slice; | |
367 | ||
368 | v_slice = h_slice = 1; | |
369 | bg0_addr = (uint8 *) iBuf->buf; | |
370 | bg1_addr = mdp_get_chroma_addr(iBuf); | |
371 | ||
372 | bg0_ystride = iBuf->ibuf_width * iBuf->bpp; | |
373 | bg1_ystride = iBuf->ibuf_width * iBuf->bpp; | |
374 | ||
375 | switch (iBuf->ibuf_type) { | |
376 | case MDP_BGR_565: | |
377 | case MDP_RGB_565: | |
378 | /* 888 = 3bytes | |
379 | * RGB = 3Components | |
380 | * RGB interleaved | |
381 | */ | |
382 | ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | | |
383 | PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | |
384 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
385 | PPP_SRC_UNPACK_ALIGN_LSB | | |
386 | PPP_SRC_FETCH_PLANES_INTERLVD; | |
387 | ||
388 | if (iBuf->ibuf_type == MDP_RGB_565) | |
389 | unpack_pattern = | |
390 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
391 | else | |
392 | unpack_pattern = | |
393 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | |
394 | break; | |
395 | ||
396 | case MDP_RGB_888: | |
397 | /* | |
398 | * 888 = 3bytes | |
399 | * RGB = 3Components | |
400 | * RGB interleaved | |
401 | */ | |
402 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | |
403 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | | |
404 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
405 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD; | |
406 | ||
407 | unpack_pattern = | |
408 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
409 | break; | |
410 | ||
411 | case MDP_BGRA_8888: | |
412 | case MDP_RGBA_8888: | |
413 | case MDP_ARGB_8888: | |
414 | case MDP_XRGB_8888: | |
415 | /* | |
416 | * 8888 = 4bytes | |
417 | * ARGB = 4Components | |
418 | * ARGB interleaved | |
419 | */ | |
420 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | |
421 | PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN | | |
422 | PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS | | |
423 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB | | |
424 | PPP_SRC_FETCH_PLANES_INTERLVD; | |
425 | ||
426 | if (iBuf->ibuf_type == MDP_BGRA_8888) | |
427 | unpack_pattern = | |
428 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
429 | 8); | |
430 | else if (iBuf->ibuf_type == MDP_RGBA_8888) | |
431 | unpack_pattern = | |
432 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | |
433 | 8); | |
434 | else | |
435 | unpack_pattern = | |
436 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
437 | 8); | |
438 | break; | |
439 | ||
440 | case MDP_Y_CBCR_H2V2: | |
441 | case MDP_Y_CRCB_H2V2: | |
442 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | |
443 | PPP_SRC_C0G_8BITS | | |
444 | PPP_SRC_C1B_8BITS | | |
445 | PPP_SRC_C3A_8BITS | | |
446 | PPP_SRC_BPP_INTERLVD_2BYTES | | |
447 | PPP_SRC_INTERLVD_2COMPONENTS | | |
448 | PPP_SRC_UNPACK_TIGHT | | |
449 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | |
450 | ||
451 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | |
452 | unpack_pattern = | |
453 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
454 | else | |
455 | unpack_pattern = | |
456 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
457 | v_slice = h_slice = 2; | |
458 | break; | |
459 | ||
460 | case MDP_YCRYCB_H2V1: | |
461 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | |
462 | PPP_SRC_C0G_8BITS | | |
463 | PPP_SRC_C1B_8BITS | | |
464 | PPP_SRC_C3A_8BITS | | |
465 | PPP_SRC_BPP_INTERLVD_2BYTES | | |
466 | PPP_SRC_INTERLVD_4COMPONENTS | | |
467 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; | |
468 | ||
469 | unpack_pattern = | |
470 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | |
471 | h_slice = 2; | |
472 | break; | |
473 | ||
474 | case MDP_Y_CBCR_H2V1: | |
475 | case MDP_Y_CRCB_H2V1: | |
476 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | |
477 | PPP_SRC_C0G_8BITS | | |
478 | PPP_SRC_C1B_8BITS | | |
479 | PPP_SRC_C3A_8BITS | | |
480 | PPP_SRC_BPP_INTERLVD_2BYTES | | |
481 | PPP_SRC_INTERLVD_2COMPONENTS | | |
482 | PPP_SRC_UNPACK_TIGHT | | |
483 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | |
484 | ||
485 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | |
486 | unpack_pattern = | |
487 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
488 | else | |
489 | unpack_pattern = | |
490 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
491 | h_slice = 2; | |
492 | break; | |
493 | ||
494 | default: | |
495 | return; | |
496 | } | |
497 | ||
498 | /* starting input address adjustment */ | |
499 | mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice, | |
500 | iBuf->roi.lcd_x, iBuf->roi.lcd_y, | |
501 | iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, | |
502 | iBuf, 1); | |
503 | ||
504 | /* | |
505 | * 0x01c0: background plane 0 addr | |
506 | * 0x01c4: background plane 1 addr | |
507 | * 0x01c8: background plane 2 addr | |
508 | * 0x01cc: bg y stride for plane 0 and 1 | |
509 | * 0x01d0: bg y stride for plane 2 | |
510 | * 0x01d4: bg src PPP config | |
511 | * 0x01d8: unpack pattern | |
512 | */ | |
513 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr); | |
514 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr); | |
515 | ||
516 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc, | |
517 | (bg1_ystride << 16) | bg0_ystride); | |
518 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg); | |
519 | ||
520 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern); | |
521 | } | |
522 | ||
523 | #define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \ | |
524 | (img == MDP_Y_CBCR_H2V2) | \ | |
525 | (img == MDP_Y_CRCB_H2V1) | \ | |
526 | (img == MDP_Y_CBCR_H2V1)) | |
527 | ||
528 | #define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp) | |
529 | ||
530 | #define Y_TO_CRCB_RATIO(format) \ | |
531 | ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\ | |
532 | (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1) | |
533 | ||
534 | static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp, | |
535 | uint32_t *len0, uint32_t *len1) | |
536 | { | |
537 | *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp); | |
538 | if (IS_PSEUDOPLNR(img->format)) | |
539 | *len1 = *len0/Y_TO_CRCB_RATIO(img->format); | |
540 | else | |
541 | *len1 = 0; | |
542 | } | |
543 | ||
544 | static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp, | |
545 | struct file *p_src_file, struct file *p_dst_file) | |
546 | { | |
547 | #ifdef CONFIG_ANDROID_PMEM | |
548 | uint32_t src0_len, src1_len, dst0_len, dst1_len; | |
549 | ||
550 | /* flush src images to memory before dma to mdp */ | |
551 | get_len(&req->src, &req->src_rect, src_bpp, | |
552 | &src0_len, &src1_len); | |
553 | ||
554 | flush_pmem_file(p_src_file, | |
555 | req->src.offset, src0_len); | |
556 | ||
557 | if (IS_PSEUDOPLNR(req->src.format)) | |
558 | flush_pmem_file(p_src_file, | |
559 | req->src.offset + src0_len, src1_len); | |
560 | ||
561 | get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len); | |
562 | flush_pmem_file(p_dst_file, req->dst.offset, dst0_len); | |
563 | ||
564 | if (IS_PSEUDOPLNR(req->dst.format)) | |
565 | flush_pmem_file(p_dst_file, | |
566 | req->dst.offset + dst0_len, dst1_len); | |
567 | #endif | |
568 | } | |
569 | ||
570 | static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf, | |
571 | struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file) | |
572 | { | |
573 | uint8 *src0, *src1; | |
574 | uint8 *dest0, *dest1; | |
575 | uint16 inpBpp; | |
576 | uint32 dest0_ystride; | |
577 | uint32 src_width; | |
578 | uint32 src_height; | |
579 | uint32 src0_ystride; | |
580 | uint32 dst_roi_width; | |
581 | uint32 dst_roi_height; | |
582 | uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg; | |
583 | uint32 alpha, tpVal; | |
584 | uint32 packPattern; | |
585 | uint32 dst_packPattern; | |
586 | boolean inputRGB, outputRGB, pseudoplanr_output; | |
587 | int sv_slice, sh_slice; | |
588 | int dv_slice, dh_slice; | |
589 | boolean perPixelAlpha = FALSE; | |
590 | boolean ppp_lookUp_enable = FALSE; | |
591 | ||
592 | sv_slice = sh_slice = dv_slice = dh_slice = 1; | |
593 | alpha = tpVal = 0; | |
594 | src_width = iBuf->mdpImg.width; | |
595 | src_height = iBuf->roi.y + iBuf->roi.height; | |
596 | src1 = NULL; | |
597 | dest1 = NULL; | |
598 | ||
599 | inputRGB = outputRGB = TRUE; | |
600 | pseudoplanr_output = FALSE; | |
601 | ppp_operation_reg = 0; | |
602 | ppp_dst_cfg_reg = 0; | |
603 | ppp_src_cfg_reg = 0; | |
604 | ||
605 | /* Wait for the pipe to clear */ | |
606 | do { } while (mdp_ppp_pipe_wait() <= 0); | |
607 | ||
608 | /* | |
609 | * destination config | |
610 | */ | |
611 | switch (iBuf->ibuf_type) { | |
612 | case MDP_RGB_888: | |
613 | dst_packPattern = | |
614 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
615 | ppp_dst_cfg_reg = | |
616 | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT | | |
617 | PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | | |
618 | PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | | |
619 | PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD; | |
620 | break; | |
621 | ||
622 | case MDP_XRGB_8888: | |
623 | case MDP_ARGB_8888: | |
624 | case MDP_RGBA_8888: | |
625 | if (iBuf->ibuf_type == MDP_BGRA_8888) | |
626 | dst_packPattern = | |
627 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
628 | 8); | |
629 | else if (iBuf->ibuf_type == MDP_RGBA_8888) | |
630 | dst_packPattern = | |
631 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | |
632 | 8); | |
633 | else | |
634 | dst_packPattern = | |
635 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
636 | 8); | |
637 | ||
638 | ppp_dst_cfg_reg = PPP_DST_C0G_8BIT | | |
639 | PPP_DST_C1B_8BIT | | |
640 | PPP_DST_C2R_8BIT | | |
641 | PPP_DST_C3A_8BIT | | |
642 | PPP_DST_C3ALPHA_EN | | |
643 | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | | |
644 | PPP_DST_PACK_TIGHT | | |
645 | PPP_DST_PACK_ALIGN_LSB | | |
646 | PPP_DST_OUT_SEL_AXI | | |
647 | PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD; | |
648 | break; | |
649 | ||
650 | case MDP_Y_CBCR_H2V2: | |
651 | case MDP_Y_CRCB_H2V2: | |
652 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2) | |
653 | dst_packPattern = | |
654 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
655 | else | |
656 | dst_packPattern = | |
657 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
658 | ||
659 | ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | | |
660 | PPP_DST_C0G_8BIT | | |
661 | PPP_DST_C1B_8BIT | | |
662 | PPP_DST_C3A_8BIT | | |
663 | PPP_DST_PACKET_CNT_INTERLVD_2ELEM | | |
664 | PPP_DST_PACK_TIGHT | | |
665 | PPP_DST_PACK_ALIGN_LSB | | |
666 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; | |
667 | ||
668 | ppp_operation_reg |= PPP_OP_DST_CHROMA_420; | |
669 | outputRGB = FALSE; | |
670 | pseudoplanr_output = TRUE; | |
671 | /* | |
672 | * vertically (y direction) and horizontally (x direction) | |
673 | * sample reduction by 2 | |
674 | */ | |
675 | ||
676 | /* | |
677 | * H2V2(YUV420) Cosite | |
678 | * | |
679 | * Y Y Y Y | |
680 | * CbCr CbCr | |
681 | * Y Y Y Y | |
682 | * Y Y Y Y | |
683 | * CbCr CbCr | |
684 | * Y Y Y Y | |
685 | */ | |
686 | dv_slice = dh_slice = 2; | |
687 | ||
688 | /* (x,y) and (width,height) must be even numbern */ | |
689 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | |
690 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | |
691 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | |
692 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | |
693 | ||
694 | iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2; | |
695 | iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2; | |
696 | iBuf->roi.y = (iBuf->roi.y / 2) * 2; | |
697 | iBuf->roi.height = (iBuf->roi.height / 2) * 2; | |
698 | break; | |
699 | ||
700 | case MDP_YCRYCB_H2V1: | |
701 | dst_packPattern = | |
702 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | |
703 | ppp_dst_cfg_reg = | |
704 | PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | | |
705 | PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | | |
706 | PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | | |
707 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | | |
708 | PPP_DST_PLANE_INTERLVD; | |
709 | ||
710 | ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; | |
711 | outputRGB = FALSE; | |
712 | /* | |
713 | * horizontally (x direction) sample reduction by 2 | |
714 | * | |
715 | * H2V1(YUV422) Cosite | |
716 | * | |
717 | * YCbCr Y YCbCr Y | |
718 | * YCbCr Y YCbCr Y | |
719 | * YCbCr Y YCbCr Y | |
720 | * YCbCr Y YCbCr Y | |
721 | */ | |
722 | dh_slice = 2; | |
723 | ||
724 | /* | |
725 | * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the | |
726 | * preloaded gamma setting of 2.2 when the content is | |
727 | * non-linear ppp_lookUp_enable = TRUE; | |
728 | */ | |
729 | ||
730 | /* x and width must be even number */ | |
731 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | |
732 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | |
733 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | |
734 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | |
735 | break; | |
736 | ||
737 | case MDP_Y_CBCR_H2V1: | |
738 | case MDP_Y_CRCB_H2V1: | |
739 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | |
740 | dst_packPattern = | |
741 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
742 | else | |
743 | dst_packPattern = | |
744 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
745 | ||
746 | ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | | |
747 | PPP_DST_C0G_8BIT | | |
748 | PPP_DST_C1B_8BIT | | |
749 | PPP_DST_C3A_8BIT | | |
750 | PPP_DST_PACKET_CNT_INTERLVD_2ELEM | | |
751 | PPP_DST_PACK_TIGHT | | |
752 | PPP_DST_PACK_ALIGN_LSB | | |
753 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; | |
754 | ||
755 | ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; | |
756 | outputRGB = FALSE; | |
757 | pseudoplanr_output = TRUE; | |
758 | /* horizontally (x direction) sample reduction by 2 */ | |
759 | dh_slice = 2; | |
760 | ||
761 | /* x and width must be even number */ | |
762 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | |
763 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | |
764 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | |
765 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | |
766 | break; | |
767 | ||
768 | case MDP_BGR_565: | |
769 | case MDP_RGB_565: | |
770 | default: | |
771 | if (iBuf->ibuf_type == MDP_RGB_565) | |
772 | dst_packPattern = | |
773 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
774 | else | |
775 | dst_packPattern = | |
776 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | |
777 | ||
778 | ppp_dst_cfg_reg = PPP_DST_C0G_6BIT | | |
779 | PPP_DST_C1B_5BIT | | |
780 | PPP_DST_C2R_5BIT | | |
781 | PPP_DST_PACKET_CNT_INTERLVD_3ELEM | | |
782 | PPP_DST_PACK_TIGHT | | |
783 | PPP_DST_PACK_ALIGN_LSB | | |
784 | PPP_DST_OUT_SEL_AXI | | |
785 | PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD; | |
786 | break; | |
787 | } | |
788 | ||
789 | /* source config */ | |
790 | switch (iBuf->mdpImg.imgType) { | |
791 | case MDP_RGB_888: | |
792 | inpBpp = 3; | |
793 | /* | |
794 | * 565 = 2bytes | |
795 | * RGB = 3Components | |
796 | * RGB interleaved | |
797 | */ | |
798 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | |
799 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | | |
800 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
801 | PPP_SRC_UNPACK_ALIGN_LSB | | |
802 | PPP_SRC_FETCH_PLANES_INTERLVD; | |
803 | ||
804 | packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
805 | ||
806 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | |
807 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | |
808 | break; | |
809 | ||
810 | case MDP_BGRA_8888: | |
811 | case MDP_RGBA_8888: | |
812 | case MDP_ARGB_8888: | |
813 | perPixelAlpha = TRUE; | |
814 | case MDP_XRGB_8888: | |
815 | inpBpp = 4; | |
816 | /* | |
817 | * 8888 = 4bytes | |
818 | * ARGB = 4Components | |
819 | * ARGB interleaved | |
820 | */ | |
821 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | |
822 | PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | | |
823 | PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | | |
824 | PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
825 | PPP_SRC_UNPACK_ALIGN_LSB | | |
826 | PPP_SRC_FETCH_PLANES_INTERLVD; | |
827 | ||
828 | if (iBuf->mdpImg.imgType == MDP_BGRA_8888) | |
829 | packPattern = | |
830 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
831 | 8); | |
832 | else if (iBuf->mdpImg.imgType == MDP_RGBA_8888) | |
833 | packPattern = | |
834 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | |
835 | 8); | |
836 | else | |
837 | packPattern = | |
838 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | |
839 | 8); | |
840 | ||
841 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | |
842 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | |
843 | break; | |
844 | ||
845 | case MDP_Y_CBCR_H2V2: | |
846 | case MDP_Y_CRCB_H2V2: | |
847 | inpBpp = 1; | |
848 | src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; | |
849 | ||
850 | /* | |
851 | * CbCr = 2bytes | |
852 | * CbCr = 2Components | |
853 | * Y+CbCr | |
854 | */ | |
855 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | |
856 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | |
857 | PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
858 | PPP_SRC_UNPACK_ALIGN_LSB | | |
859 | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | |
860 | ||
861 | if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2) | |
862 | packPattern = | |
863 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
864 | else | |
865 | packPattern = | |
866 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
867 | ||
868 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR | | |
869 | PPP_OP_SRC_CHROMA_420 | | |
870 | PPP_OP_SRC_CHROMA_COSITE | | |
871 | PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE; | |
872 | ||
873 | inputRGB = FALSE; | |
874 | sh_slice = sv_slice = 2; | |
875 | break; | |
876 | ||
877 | case MDP_YCRYCB_H2V1: | |
878 | inpBpp = 2; | |
879 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | |
880 | PPP_SRC_C0G_8BITS | | |
881 | PPP_SRC_C1B_8BITS | | |
882 | PPP_SRC_C3A_8BITS | | |
883 | PPP_SRC_BPP_INTERLVD_2BYTES | | |
884 | PPP_SRC_INTERLVD_4COMPONENTS | | |
885 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; | |
886 | ||
887 | packPattern = | |
888 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | |
889 | ||
890 | ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | | |
891 | PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; | |
892 | ||
893 | /* | |
894 | * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the | |
895 | * preloaded inverse gamma setting of 2.2 since they're | |
896 | * symetric when the content is non-linear | |
897 | * ppp_lookUp_enable = TRUE; | |
898 | */ | |
899 | ||
900 | /* x and width must be even number */ | |
901 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | |
902 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | |
903 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | |
904 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | |
905 | ||
906 | inputRGB = FALSE; | |
907 | sh_slice = 2; | |
908 | break; | |
909 | ||
910 | case MDP_Y_CBCR_H2V1: | |
911 | case MDP_Y_CRCB_H2V1: | |
912 | inpBpp = 1; | |
913 | src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; | |
914 | ||
915 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | |
916 | PPP_SRC_C0G_8BITS | | |
917 | PPP_SRC_C1B_8BITS | | |
918 | PPP_SRC_C3A_8BITS | | |
919 | PPP_SRC_BPP_INTERLVD_2BYTES | | |
920 | PPP_SRC_INTERLVD_2COMPONENTS | | |
921 | PPP_SRC_UNPACK_TIGHT | | |
922 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | |
923 | ||
924 | if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1) | |
925 | packPattern = | |
926 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | |
927 | else | |
928 | packPattern = | |
929 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | |
930 | ||
931 | ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | | |
932 | PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; | |
933 | inputRGB = FALSE; | |
934 | sh_slice = 2; | |
935 | break; | |
936 | ||
937 | case MDP_BGR_565: | |
938 | case MDP_RGB_565: | |
939 | default: | |
940 | inpBpp = 2; | |
941 | /* | |
942 | * 565 = 2bytes | |
943 | * RGB = 3Components | |
944 | * RGB interleaved | |
945 | */ | |
946 | ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | | |
947 | PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | |
948 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | |
949 | PPP_SRC_UNPACK_ALIGN_LSB | | |
950 | PPP_SRC_FETCH_PLANES_INTERLVD; | |
951 | ||
952 | if (iBuf->mdpImg.imgType == MDP_RGB_565) | |
953 | packPattern = | |
954 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | |
955 | else | |
956 | packPattern = | |
957 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | |
958 | ||
959 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | |
960 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | |
961 | break; | |
962 | ||
963 | } | |
964 | ||
965 | if (pseudoplanr_output) | |
966 | ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN; | |
967 | ||
968 | /* YCbCr to RGB color conversion flag */ | |
969 | if ((!inputRGB) && (outputRGB)) { | |
970 | ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB | | |
971 | PPP_OP_CONVERT_ON; | |
972 | ||
973 | /* | |
974 | * primary/secondary is sort of misleading term...but | |
975 | * in mdp2.2/3.0 we only use primary matrix (forward/rev) | |
976 | * in mdp3.1 we use set1(prim) and set2(secd) | |
977 | */ | |
978 | #ifdef CONFIG_FB_MSM_MDP31 | |
979 | ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY | | |
980 | PPP_OP_DST_RGB; | |
981 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0); | |
982 | #endif | |
983 | ||
984 | if (ppp_lookUp_enable) { | |
985 | ppp_operation_reg |= PPP_OP_LUT_C0_ON | | |
986 | PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; | |
987 | } | |
988 | } | |
989 | /* RGB to YCbCr color conversion flag */ | |
990 | if ((inputRGB) && (!outputRGB)) { | |
991 | ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR | | |
992 | PPP_OP_CONVERT_ON; | |
993 | ||
994 | #ifdef CONFIG_FB_MSM_MDP31 | |
995 | ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY | | |
996 | PPP_OP_DST_YCBCR; | |
997 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e); | |
998 | #endif | |
999 | ||
1000 | if (ppp_lookUp_enable) { | |
1001 | ppp_operation_reg |= PPP_OP_LUT_C0_ON | | |
1002 | PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; | |
1003 | } | |
1004 | } | |
1005 | /* YCbCr to YCbCr color conversion flag */ | |
1006 | if ((!inputRGB) && (!outputRGB)) { | |
1007 | if ((ppp_lookUp_enable) && | |
1008 | (iBuf->mdpImg.imgType != iBuf->ibuf_type)) { | |
1009 | ppp_operation_reg |= PPP_OP_LUT_C0_ON; | |
1010 | } | |
1011 | } | |
1012 | ||
1013 | ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0; | |
1014 | ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0; | |
1015 | ||
1016 | if (req->flags & MDP_DEINTERLACE) | |
1017 | ppp_operation_reg |= PPP_OP_DEINT_EN; | |
1018 | ||
1019 | /* Dither at DMA side only since iBuf format is RGB888 */ | |
1020 | if (iBuf->mdpImg.mdpOp & MDPOP_DITHER) | |
1021 | ppp_operation_reg |= PPP_OP_DITHER_EN; | |
1022 | ||
1023 | if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) { | |
1024 | ppp_operation_reg |= PPP_OP_ROT_ON; | |
1025 | ||
1026 | if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { | |
1027 | ppp_operation_reg |= PPP_OP_ROT_90; | |
1028 | } | |
1029 | if (iBuf->mdpImg.mdpOp & MDPOP_LR) { | |
1030 | ppp_operation_reg |= PPP_OP_FLIP_LR; | |
1031 | } | |
1032 | if (iBuf->mdpImg.mdpOp & MDPOP_UD) { | |
1033 | ppp_operation_reg |= PPP_OP_FLIP_UD; | |
1034 | } | |
1035 | } | |
1036 | ||
1037 | src0_ystride = src_width * inpBpp; | |
1038 | dest0_ystride = iBuf->ibuf_width * iBuf->bpp; | |
1039 | ||
1040 | /* no need to care about rotation since it's the real-XY. */ | |
1041 | dst_roi_width = iBuf->roi.dst_width; | |
1042 | dst_roi_height = iBuf->roi.dst_height; | |
1043 | ||
1044 | src0 = (uint8 *) iBuf->mdpImg.bmy_addr; | |
1045 | dest0 = (uint8 *) iBuf->buf; | |
1046 | ||
1047 | /* Jumping from Y-Plane to Chroma Plane */ | |
1048 | dest1 = mdp_get_chroma_addr(iBuf); | |
1049 | ||
1050 | /* first pixel addr calculation */ | |
1051 | mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x, | |
1052 | iBuf->roi.y, src_width, src_height, inpBpp, iBuf, | |
1053 | 0); | |
1054 | mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice, | |
1055 | iBuf->roi.lcd_x, iBuf->roi.lcd_y, | |
1056 | iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, | |
1057 | iBuf, 2); | |
1058 | ||
1059 | /* set scale operation */ | |
1060 | mdp_set_scale(iBuf, dst_roi_width, dst_roi_height, | |
1061 | inputRGB, outputRGB, &ppp_operation_reg); | |
1062 | ||
1063 | /* | |
1064 | * setting background source for blending | |
1065 | */ | |
1066 | mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha, | |
1067 | &ppp_operation_reg); | |
1068 | ||
1069 | if (ppp_operation_reg & PPP_OP_BLEND_ON) { | |
1070 | mdp_ppp_setbg(iBuf); | |
1071 | ||
1072 | if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { | |
1073 | ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1; | |
1074 | ||
1075 | if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { | |
1076 | tpVal = mdp_conv_matx_rgb2yuv(tpVal, | |
1077 | (uint16 *) & | |
1078 | mdp_ccs_rgb2yuv, | |
1079 | &mdp_plv[0], NULL); | |
1080 | } | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | /* | |
1085 | * 0x0004: enable dbg bus | |
1086 | * 0x0100: "don't care" Edge Condit until scaling is on | |
1087 | * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit | |
1088 | * 0x0108: src pixel size | |
1089 | * 0x010c: component plane 0 starting address | |
1090 | * 0x011c: component plane 0 ystride | |
1091 | * 0x0124: PPP source config register | |
1092 | * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR) | |
1093 | */ | |
1094 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 | | |
1095 | iBuf->roi.width)); | |
1096 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */ | |
1097 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */ | |
1098 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c, | |
1099 | (src0_ystride << 16 | src0_ystride)); | |
1100 | ||
1101 | /* setup for rgb 565 */ | |
1102 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg); | |
1103 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern); | |
1104 | /* | |
1105 | * 0x0138: PPP destination operation register | |
1106 | * 0x014c: constant_alpha|transparent_color | |
1107 | * 0x0150: PPP destination config register | |
1108 | * 0x0154: PPP packing pattern | |
1109 | */ | |
1110 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg); | |
1111 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal); | |
1112 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg); | |
1113 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern); | |
1114 | ||
1115 | /* | |
1116 | * 0x0164: ROI height and width | |
1117 | * 0x0168: Component Plane 0 starting addr | |
1118 | * 0x016c: Component Plane 1 starting addr | |
1119 | * 0x0178: Component Plane 1/0 y stride | |
1120 | */ | |
1121 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164, | |
1122 | (dst_roi_height << 16 | dst_roi_width)); | |
1123 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0); | |
1124 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1); | |
1125 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178, | |
1126 | (dest0_ystride << 16 | dest0_ystride)); | |
1127 | ||
1128 | flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file); | |
1129 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | |
1130 | mdp_ppp_process_curr_djob(); | |
1131 | #else | |
1132 | mdp_pipe_kickoff(MDP_PPP_TERM, mfd); | |
1133 | #endif | |
1134 | } | |
1135 | ||
1136 | static int mdp_ppp_verify_req(struct mdp_blit_req *req) | |
1137 | { | |
1138 | u32 src_width, src_height, dst_width, dst_height; | |
1139 | ||
1140 | if (req == NULL) | |
1141 | return -1; | |
1142 | ||
1143 | if (MDP_IS_IMGTYPE_BAD(req->src.format) || | |
1144 | MDP_IS_IMGTYPE_BAD(req->dst.format)) | |
1145 | return -1; | |
1146 | ||
1147 | if ((req->src.width == 0) || (req->src.height == 0) || | |
1148 | (req->src_rect.w == 0) || (req->src_rect.h == 0) || | |
1149 | (req->dst.width == 0) || (req->dst.height == 0) || | |
1150 | (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) | |
1151 | ||
1152 | return -1; | |
1153 | ||
1154 | if (((req->src_rect.x + req->src_rect.w) > req->src.width) || | |
1155 | ((req->src_rect.y + req->src_rect.h) > req->src.height)) | |
1156 | return -1; | |
1157 | ||
1158 | if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) || | |
1159 | ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) | |
1160 | return -1; | |
1161 | ||
1162 | /* | |
1163 | * scaling range check | |
1164 | */ | |
1165 | src_width = req->src_rect.w; | |
1166 | src_height = req->src_rect.h; | |
1167 | ||
1168 | if (req->flags & MDP_ROT_90) { | |
1169 | dst_width = req->dst_rect.h; | |
1170 | dst_height = req->dst_rect.w; | |
1171 | } else { | |
1172 | dst_width = req->dst_rect.w; | |
1173 | dst_height = req->dst_rect.h; | |
1174 | } | |
1175 | ||
1176 | switch (req->dst.format) { | |
1177 | case MDP_Y_CRCB_H2V2: | |
1178 | case MDP_Y_CBCR_H2V2: | |
1179 | src_width = (src_width / 2) * 2; | |
1180 | src_height = (src_height / 2) * 2; | |
1181 | dst_width = (src_width / 2) * 2; | |
1182 | dst_height = (src_height / 2) * 2; | |
1183 | break; | |
1184 | ||
1185 | case MDP_Y_CRCB_H2V1: | |
1186 | case MDP_Y_CBCR_H2V1: | |
1187 | case MDP_YCRYCB_H2V1: | |
1188 | src_width = (src_width / 2) * 2; | |
1189 | dst_width = (src_width / 2) * 2; | |
1190 | break; | |
1191 | ||
1192 | default: | |
1193 | break; | |
1194 | } | |
1195 | ||
1196 | if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width > | |
1197 | MDP_MAX_X_SCALE_FACTOR) | |
1198 | || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width < | |
1199 | MDP_MIN_X_SCALE_FACTOR)) | |
1200 | return -1; | |
1201 | ||
1202 | if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height > | |
1203 | MDP_MAX_Y_SCALE_FACTOR) | |
1204 | || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height < | |
1205 | MDP_MIN_Y_SCALE_FACTOR)) | |
1206 | return -1; | |
1207 | ||
1208 | return 0; | |
1209 | } | |
1210 | ||
1211 | /** | |
1212 | * get_gem_img() - retrieve drm obj's start address and size | |
1213 | * @img: contains drm file descriptor and gem handle | |
1214 | * @start: repository of starting address of drm obj allocated memory | |
1215 | * @len: repository of size of drm obj alloacted memory | |
1216 | * | |
1217 | **/ | |
1218 | int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len) | |
1219 | { | |
1220 | panic("waaaaaaaah"); | |
1221 | //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len); | |
1222 | } | |
1223 | ||
1224 | int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start, | |
1225 | unsigned long *len, struct file **pp_file) | |
1226 | { | |
1227 | int put_needed, ret = 0; | |
1228 | struct file *file; | |
1229 | unsigned long vstart; | |
1230 | #ifdef CONFIG_ANDROID_PMEM | |
1231 | if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) | |
1232 | return 0; | |
1233 | #endif | |
1234 | file = fget_light(img->memory_id, &put_needed); | |
1235 | if (file == NULL) | |
1236 | return -1; | |
1237 | ||
1238 | if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { | |
1239 | *start = info->fix.smem_start; | |
1240 | *len = info->fix.smem_len; | |
1241 | *pp_file = file; | |
1242 | } else { | |
1243 | ret = -1; | |
1244 | fput_light(file, put_needed); | |
1245 | } | |
1246 | return ret; | |
1247 | } | |
1248 | ||
1249 | int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, | |
1250 | struct file **pp_src_file, struct file **pp_dst_file) | |
1251 | { | |
1252 | unsigned long src_start, dst_start; | |
1253 | unsigned long src_len = 0; | |
1254 | unsigned long dst_len = 0; | |
1255 | MDPIBUF iBuf; | |
1256 | u32 dst_width, dst_height; | |
1257 | struct file *p_src_file = 0 , *p_dst_file = 0; | |
1258 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | |
1259 | ||
1260 | if (req->dst.format == MDP_FB_FORMAT) | |
1261 | req->dst.format = mfd->fb_imgType; | |
1262 | if (req->src.format == MDP_FB_FORMAT) | |
1263 | req->src.format = mfd->fb_imgType; | |
1264 | ||
1265 | if (req->flags & MDP_BLIT_SRC_GEM) { | |
1266 | if (get_gem_img(&req->src, &src_start, &src_len) < 0) | |
1267 | return -1; | |
1268 | } else { | |
1269 | get_img(&req->src, info, &src_start, &src_len, &p_src_file); | |
1270 | } | |
1271 | if (src_len == 0) { | |
1272 | printk(KERN_ERR "mdp_ppp: could not retrieve image from " | |
1273 | "memory\n"); | |
1274 | return -1; | |
1275 | } | |
1276 | ||
1277 | if (req->flags & MDP_BLIT_DST_GEM) { | |
1278 | if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0) | |
1279 | return -1; | |
1280 | } else { | |
1281 | get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file); | |
1282 | } | |
1283 | if (dst_len == 0) { | |
1284 | printk(KERN_ERR "mdp_ppp: could not retrieve image from " | |
1285 | "memory\n"); | |
1286 | return -1; | |
1287 | } | |
1288 | *pp_src_file = p_src_file; | |
1289 | *pp_dst_file = p_dst_file; | |
1290 | if (mdp_ppp_verify_req(req)) { | |
1291 | printk(KERN_ERR "mdp_ppp: invalid image!\n"); | |
1292 | return -1; | |
1293 | } | |
1294 | ||
1295 | iBuf.ibuf_width = req->dst.width; | |
1296 | iBuf.ibuf_height = req->dst.height; | |
1297 | iBuf.bpp = bytes_per_pixel[req->dst.format]; | |
1298 | ||
1299 | iBuf.ibuf_type = req->dst.format; | |
1300 | iBuf.buf = (uint8 *) dst_start; | |
1301 | iBuf.buf += req->dst.offset; | |
1302 | ||
1303 | iBuf.roi.lcd_x = req->dst_rect.x; | |
1304 | iBuf.roi.lcd_y = req->dst_rect.y; | |
1305 | iBuf.roi.dst_width = req->dst_rect.w; | |
1306 | iBuf.roi.dst_height = req->dst_rect.h; | |
1307 | ||
1308 | iBuf.roi.x = req->src_rect.x; | |
1309 | iBuf.roi.width = req->src_rect.w; | |
1310 | iBuf.roi.y = req->src_rect.y; | |
1311 | iBuf.roi.height = req->src_rect.h; | |
1312 | ||
1313 | iBuf.mdpImg.width = req->src.width; | |
1314 | iBuf.mdpImg.imgType = req->src.format; | |
1315 | ||
1316 | iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset); | |
1317 | iBuf.mdpImg.cbcr_addr = | |
1318 | (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr + | |
1319 | req->src.width * req->src.height); | |
1320 | ||
1321 | iBuf.mdpImg.mdpOp = MDPOP_NOP; | |
1322 | ||
1323 | /* blending check */ | |
1324 | if (req->transp_mask != MDP_TRANSP_NOP) { | |
1325 | iBuf.mdpImg.mdpOp |= MDPOP_TRANSP; | |
1326 | iBuf.mdpImg.tpVal = req->transp_mask; | |
1327 | iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg); | |
1328 | } | |
1329 | ||
1330 | req->alpha &= 0xff; | |
1331 | if (req->alpha < MDP_ALPHA_NOP) { | |
1332 | iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB; | |
1333 | iBuf.mdpImg.alpha = req->alpha; | |
1334 | } | |
1335 | ||
1336 | /* rotation check */ | |
1337 | if (req->flags & MDP_FLIP_LR) | |
1338 | iBuf.mdpImg.mdpOp |= MDPOP_LR; | |
1339 | if (req->flags & MDP_FLIP_UD) | |
1340 | iBuf.mdpImg.mdpOp |= MDPOP_UD; | |
1341 | if (req->flags & MDP_ROT_90) | |
1342 | iBuf.mdpImg.mdpOp |= MDPOP_ROT90; | |
1343 | if (req->flags & MDP_DITHER) | |
1344 | iBuf.mdpImg.mdpOp |= MDPOP_DITHER; | |
1345 | ||
1346 | if (req->flags & MDP_BLEND_FG_PREMULT) { | |
1347 | #ifdef CONFIG_FB_MSM_MDP31 | |
1348 | iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA; | |
1349 | #else | |
1350 | return -EINVAL; | |
1351 | #endif | |
1352 | } | |
1353 | ||
1354 | if (req->flags & MDP_DEINTERLACE) { | |
1355 | #ifdef CONFIG_FB_MSM_MDP31 | |
1356 | if ((req->src.format != MDP_Y_CBCR_H2V2) && | |
1357 | (req->src.format != MDP_Y_CRCB_H2V2)) | |
1358 | #endif | |
1359 | return -EINVAL; | |
1360 | } | |
1361 | ||
1362 | /* scale check */ | |
1363 | if (req->flags & MDP_ROT_90) { | |
1364 | dst_width = req->dst_rect.h; | |
1365 | dst_height = req->dst_rect.w; | |
1366 | } else { | |
1367 | dst_width = req->dst_rect.w; | |
1368 | dst_height = req->dst_rect.h; | |
1369 | } | |
1370 | ||
1371 | if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height)) | |
1372 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE; | |
1373 | ||
1374 | if (req->flags & MDP_BLUR) { | |
1375 | #ifdef CONFIG_FB_MSM_MDP31 | |
1376 | if (req->flags & MDP_SHARPENING) | |
1377 | printk(KERN_WARNING | |
1378 | "mdp: MDP_SHARPENING is set with MDP_BLUR!\n"); | |
1379 | req->flags |= MDP_SHARPENING; | |
1380 | req->sharpening_strength = -127; | |
1381 | #else | |
1382 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR; | |
1383 | ||
1384 | #endif | |
1385 | } | |
1386 | ||
1387 | if (req->flags & MDP_SHARPENING) { | |
1388 | #ifdef CONFIG_FB_MSM_MDP31 | |
1389 | if ((req->sharpening_strength > 127) || | |
1390 | (req->sharpening_strength < -127)) { | |
1391 | printk(KERN_ERR | |
1392 | "%s: sharpening strength out of range\n", | |
1393 | __func__); | |
1394 | return -EINVAL; | |
1395 | } | |
1396 | ||
1397 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING; | |
1398 | iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff; | |
1399 | #else | |
1400 | return -EINVAL; | |
1401 | #endif | |
1402 | } | |
1403 | ||
1404 | down(&mdp_ppp_mutex); | |
1405 | /* MDP cmd block enable */ | |
1406 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | |
1407 | ||
1408 | #ifdef CONFIG_FB_MSM_MDP31 | |
1409 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | |
1410 | #else | |
1411 | /* bg tile fetching HW workaround */ | |
1412 | if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) || | |
1413 | (req->src.format == MDP_ARGB_8888) || | |
1414 | (req->src.format == MDP_BGRA_8888) || | |
1415 | (req->src.format == MDP_RGBA_8888)) && | |
1416 | (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) { | |
1417 | int dst_h, src_w, i; | |
1418 | ||
1419 | src_w = req->src_rect.w; | |
1420 | dst_h = iBuf.roi.dst_height; | |
1421 | ||
1422 | for (i = 0; i < (req->dst_rect.h / 16); i++) { | |
1423 | /* this tile size */ | |
1424 | iBuf.roi.dst_height = 16; | |
1425 | iBuf.roi.width = | |
1426 | (16 * req->src_rect.w) / req->dst_rect.h; | |
1427 | ||
1428 | /* if it's out of scale range... */ | |
1429 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1430 | iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) | |
1431 | iBuf.roi.width = | |
1432 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1433 | MDP_MAX_X_SCALE_FACTOR; | |
1434 | else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1435 | iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) | |
1436 | iBuf.roi.width = | |
1437 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1438 | MDP_MIN_X_SCALE_FACTOR; | |
1439 | ||
1440 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | |
1441 | ||
1442 | /* next tile location */ | |
1443 | iBuf.roi.lcd_y += 16; | |
1444 | iBuf.roi.x += iBuf.roi.width; | |
1445 | ||
1446 | /* this is for a remainder update */ | |
1447 | dst_h -= 16; | |
1448 | src_w -= iBuf.roi.width; | |
1449 | } | |
1450 | ||
1451 | if ((dst_h < 0) || (src_w < 0)) | |
1452 | printk | |
1453 | ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n", | |
1454 | __LINE__); | |
1455 | ||
1456 | /* remainder update */ | |
1457 | if ((dst_h > 0) && (src_w > 0)) { | |
1458 | u32 tmp_v; | |
1459 | ||
1460 | iBuf.roi.dst_height = dst_h; | |
1461 | iBuf.roi.width = src_w; | |
1462 | ||
1463 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1464 | iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) { | |
1465 | tmp_v = | |
1466 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1467 | MDP_MAX_X_SCALE_FACTOR + | |
1468 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % | |
1469 | MDP_MAX_X_SCALE_FACTOR ? 1 : 0; | |
1470 | ||
1471 | /* move x location as roi width gets bigger */ | |
1472 | iBuf.roi.x -= tmp_v - iBuf.roi.width; | |
1473 | iBuf.roi.width = tmp_v; | |
1474 | } else | |
1475 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1476 | iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) { | |
1477 | tmp_v = | |
1478 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | |
1479 | MDP_MIN_X_SCALE_FACTOR + | |
1480 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % | |
1481 | MDP_MIN_X_SCALE_FACTOR ? 1 : 0; | |
1482 | ||
1483 | /* | |
1484 | * we don't move x location for continuity of | |
1485 | * source image | |
1486 | */ | |
1487 | iBuf.roi.width = tmp_v; | |
1488 | } | |
1489 | ||
1490 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | |
1491 | } | |
1492 | } else { | |
1493 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | |
1494 | } | |
1495 | #endif | |
1496 | ||
1497 | /* MDP cmd block disable */ | |
1498 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | |
1499 | up(&mdp_ppp_mutex); | |
1500 | ||
1501 | return 0; | |
1502 | } |