1 /*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Shengquan Yuan <shengquan.yuan@intel.com>
26 * Binglin Chen <binglin.chen@intel.com>
27 * Jason Hu <jason.hu@intel.com>
28 * Zeng Li <zeng.li@intel.com>
29 */
30
31 /*
32 * Most of rendering codes are ported from xf86-video-i810/src/i810_overlay.c
33 */
34
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <math.h>
40 #include <va/va_backend.h>
41 #include <wsbm/wsbm_manager.h>
42 #include "psb_drv_video.h"
43 #include "psb_output.h"
44 #include "psb_overlay.h"
45 #include "psb_drv_debug.h"
46
47 #ifdef ANDROID
48 #define psb_xrandr_single_mode() 0
49 #else
50 int psb_xrandr_single_mode();
51 #endif
52
53 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
54 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
55 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
56 //#define GET_SURFACE_INFO_rotate(psb_surface) ((int) (psb_surface)->extra_info[5])
57
58 #ifndef VA_FOURCC_I420
59 #define VA_FOURCC_I420 0x30323449
60 #endif
61
62 /**********************************************************************************************
63 * I830ResetVideo
64 *
65 * Description: Use this function to reset the overlay register back buffer to its default
66 * values. Note that this function does not actually apply these values. To do so, please
67 * write to OVADD.
68 **********************************************************************************************/
69 static void
I830ResetVideo(VADriverContextP ctx,PsbPortPrivPtr pPriv)70 I830ResetVideo(VADriverContextP ctx, PsbPortPrivPtr pPriv)
71 {
72 INIT_DRIVER_DATA;
73 I830OverlayRegPtr overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
74 I830OverlayRegPtr overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
75
76 memset(overlayA, 0, sizeof(*overlayA));
77 memset(overlayC, 0, sizeof(*overlayC));
78
79 overlayA->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
80 overlayA->OCLRC1 = pPriv->saturation.Value;
81
82 overlayC->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
83 overlayC->OCLRC1 = pPriv->saturation.Value;
84
85 #if USE_DCLRK
86 /* case bit depth 16 */
87 overlayA->DCLRKV = pPriv->colorKey;
88 overlayA->DCLRKM |= DEST_KEY_ENABLE;
89 overlayA->DCLRKM &= ~CONST_ALPHA_ENABLE;
90
91 overlayC->DCLRKV = pPriv->colorKey;
92 overlayC->DCLRKM |= DEST_KEY_ENABLE;
93 overlayC->DCLRKM &= ~CONST_ALPHA_ENABLE;
94 #else
95 overlayA->DCLRKM &= ~DEST_KEY_ENABLE;
96 overlayC->DCLRKM &= ~DEST_KEY_ENABLE;
97 #endif
98 overlayA->DWINSZ = 0x00000000;
99 overlayA->OCONFIG = CC_OUT_8BIT;
100
101 overlayC->DWINSZ = 0x00000000;
102 overlayC->OCONFIG = CC_OUT_8BIT;
103 }
104
I830BoundGammaElt(uint32_t elt,uint32_t eltPrev)105 static uint32_t I830BoundGammaElt(uint32_t elt, uint32_t eltPrev)
106 {
107 elt &= 0xff;
108 eltPrev &= 0xff;
109 if (elt < eltPrev)
110 elt = eltPrev;
111 else if ((elt - eltPrev) > 0x7e)
112 elt = eltPrev + 0x7e;
113 return elt;
114 }
115
I830BoundGamma(uint32_t gamma,uint32_t gammaPrev)116 static uint32_t I830BoundGamma(uint32_t gamma, uint32_t gammaPrev)
117 {
118 return (I830BoundGammaElt(gamma >> 24, gammaPrev >> 24) << 24 |
119 I830BoundGammaElt(gamma >> 16, gammaPrev >> 16) << 16 |
120 I830BoundGammaElt(gamma >> 8, gammaPrev >> 8) << 8 |
121 I830BoundGammaElt(gamma , gammaPrev));
122 }
123
124 static void
I830UpdateGamma(VADriverContextP ctx,PsbPortPrivPtr pPriv)125 I830UpdateGamma(VADriverContextP ctx, PsbPortPrivPtr pPriv)
126 {
127 #ifndef BAYTRAIL
128 INIT_DRIVER_DATA;
129 uint32_t gamma0 = pPriv->gamma0;
130 uint32_t gamma1 = pPriv->gamma1;
131 uint32_t gamma2 = pPriv->gamma2;
132 uint32_t gamma3 = pPriv->gamma3;
133 uint32_t gamma4 = pPriv->gamma4;
134 uint32_t gamma5 = pPriv->gamma5;
135 struct drm_psb_register_rw_arg regs;
136
137 gamma1 = I830BoundGamma(gamma1, gamma0);
138 gamma2 = I830BoundGamma(gamma2, gamma1);
139 gamma3 = I830BoundGamma(gamma3, gamma2);
140 gamma4 = I830BoundGamma(gamma4, gamma3);
141 gamma5 = I830BoundGamma(gamma5, gamma4);
142
143 memset(®s, 0, sizeof(regs));
144 if (pPriv->is_mfld)
145 regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL | OVC_REGRWBITS_OGAM_ALL;
146 else
147 regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL;
148 regs.overlay.OGAMC0 = gamma0;
149 regs.overlay.OGAMC1 = gamma1;
150 regs.overlay.OGAMC2 = gamma2;
151 regs.overlay.OGAMC3 = gamma3;
152 regs.overlay.OGAMC4 = gamma4;
153 regs.overlay.OGAMC5 = gamma5;
154 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
155 #endif
156 }
157
I830StopVideo(VADriverContextP ctx)158 static void I830StopVideo(VADriverContextP ctx)
159 {
160 #ifndef BAYTRAIL
161 INIT_DRIVER_DATA;
162 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
163 I830OverlayRegPtr overlayA, overlayC;
164 struct drm_psb_register_rw_arg regs;
165
166 if (!pPriv->overlayA_enabled && !pPriv->overlayC_enabled) {
167 drv_debug_msg(VIDEO_DEBUG_GENERAL, "I830StopVideo : no overlay has been enabled, do nothing.\n");
168 return;
169 }
170
171 overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
172 overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
173 #if 0
174 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
175 #endif
176 memset(®s, 0, sizeof(regs));
177 if (pPriv->subpicture_enabled) {
178 regs.subpicture_disable_mask = pPriv->subpicture_enable_mask;
179 pPriv->subpicture_enabled = 0;
180 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
181 }
182
183 memset(®s, 0, sizeof(regs));
184
185 if (pPriv->is_mfld && psb_xrandr_single_mode() == 0) {
186 if (pPriv->overlayC_enabled) {
187 regs.overlay_read_mask = OVC_REGRWBITS_OVADD;
188 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
189
190 overlayC->DWINSZ = 0x00000000;
191 overlayC->OCMD &= ~OVERLAY_ENABLE;
192 regs.overlay_read_mask = 0;
193 regs.overlay_write_mask = OVC_REGRWBITS_OVADD;
194 regs.overlay.b_wait_vblank = 1;
195 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
196
197 memset(®s, 0, sizeof(regs));
198 pPriv->overlayC_enabled = 0;
199 }
200 if (pPriv->overlayA_enabled) {
201 regs.overlay_read_mask = OV_REGRWBITS_OVADD;
202 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
203
204 overlayA->DWINSZ = 0x00000000;
205 overlayA->OCMD &= ~OVERLAY_ENABLE;
206 regs.overlay_read_mask = 0;
207 regs.overlay_write_mask = OV_REGRWBITS_OVADD;
208 regs.overlay.b_wait_vblank = 1;
209 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
210 pPriv->overlayA_enabled = 0;
211 }
212 } else {
213 regs.overlay_read_mask = OV_REGRWBITS_OVADD;
214 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
215
216 overlayA->DWINSZ = 0x00000000;
217 overlayA->OCMD &= ~OVERLAY_ENABLE;
218 regs.overlay_read_mask = 0;
219 regs.overlay_write_mask = OV_REGRWBITS_OVADD;
220 regs.overlay.b_wait_vblank = 1;
221 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
222 pPriv->overlayA_enabled = 0;
223 }
224 #endif
225 }
226
227 #if 0
228 static void I830SwitchPipe(VADriverContextP ctx , int overlayId, int pipeId)
229 {
230 INIT_DRIVER_DATA;
231 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
232 I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]);
233 struct drm_psb_register_rw_arg regs;
234 uint32_t overlay_mask;
235
236 if ((overlayId == OVERLAY_A) && pPriv->overlayA_enabled)
237 overlay_mask = OV_REGRWBITS_OVADD;
238 else if ((overlayId == OVERLAY_C) && pPriv->overlayC_enabled)
239 overlay_mask = OVC_REGRWBITS_OVADD;
240 else
241 return; /*No overlay enabled, do nothing.*/
242
243 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overlay %d switch to pipe %d\n", overlayId, pipeId);
244 memset(®s, 0, sizeof(regs));
245 memset(overlay, 0, sizeof(*overlay));
246 overlay->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff);
247 overlay->OCLRC1 = pPriv->saturation.Value;
248
249 /* case bit depth 16 */
250 overlay->DCLRKV = pPriv->colorKey;
251 overlay->DCLRKM |= DEST_KEY_ENABLE;
252 overlay->DCLRKM &= ~CONST_ALPHA_ENABLE;
253 overlay->DWINSZ = 0x00000000;
254 overlay->OCONFIG = CC_OUT_8BIT;
255
256 regs.overlay_read_mask = overlay_mask;
257 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
258
259 switch (pipeId) {
260 case PIPEA:
261 overlay->OCONFIG |= OVERLAY_C_PIPE_A;
262 break;
263 case PIPEB:
264 overlay->OCONFIG |= OVERLAY_C_PIPE_B;
265 break;
266 case PIPEC:
267 overlay->OCONFIG |= OVERLAY_C_PIPE_C;
268 break;
269 }
270 regs.overlay_read_mask = 0;
271 regs.overlay_write_mask = overlay_mask;
272 regs.overlay.b_wait_vblank = 1;
273 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
274 }
275 #endif
276
277 static int
i830_swidth(unsigned int offset,unsigned int width,unsigned int mask,int shift)278 i830_swidth(unsigned int offset, unsigned int width, unsigned int mask, int shift)
279 {
280 int swidth = ((offset + width + mask) >> shift) - (offset >> shift);
281 swidth <<= 1;
282 swidth -= 1;
283 return swidth << 2;
284 }
285
286 static Bool
SetCoeffRegs(double * coeff,int mantSize,coeffPtr pCoeff,int pos)287 SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos)
288 {
289 int maxVal, icoeff, res;
290 int sign;
291 double c;
292
293 sign = 0;
294 maxVal = 1 << mantSize;
295 c = *coeff;
296 if (c < 0.0) {
297 sign = 1;
298 c = -c;
299 }
300
301 res = 12 - mantSize;
302 if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
303 pCoeff[pos].exponent = 3;
304 pCoeff[pos].mantissa = icoeff << res;
305 *coeff = (double)icoeff / (double)(4 * maxVal);
306 } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
307 pCoeff[pos].exponent = 2;
308 pCoeff[pos].mantissa = icoeff << res;
309 *coeff = (double)icoeff / (double)(2 * maxVal);
310 } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
311 pCoeff[pos].exponent = 1;
312 pCoeff[pos].mantissa = icoeff << res;
313 *coeff = (double)icoeff / (double)(maxVal);
314 } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
315 pCoeff[pos].exponent = 0;
316 pCoeff[pos].mantissa = icoeff << res;
317 *coeff = (double)icoeff / (double)(maxVal / 2);
318 } else {
319 /* Coeff out of range */
320 return FALSE;
321 }
322
323 pCoeff[pos].sign = sign;
324 if (sign)
325 *coeff = -(*coeff);
326 return TRUE;
327 }
328
329 static void
UpdateCoeff(int taps,double fCutoff,Bool isHoriz,Bool isY,coeffPtr pCoeff)330 UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff)
331 {
332 int i, j, j1, num, pos, mantSize;
333 double pi = 3.1415926535, val, sinc, window, sum;
334 double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
335 double diff;
336 int tapAdjust[MAX_TAPS], tap2Fix;
337 Bool isVertAndUV;
338
339 if (isHoriz)
340 mantSize = 7;
341 else
342 mantSize = 6;
343
344 isVertAndUV = !isHoriz && !isY;
345 num = taps * 16;
346 for (i = 0; i < num * 2; i++) {
347 val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
348 if (val == 0.0)
349 sinc = 1.0;
350 else
351 sinc = sin(val) / val;
352
353 /* Hamming window */
354 window = (0.5 - 0.5 * cos(i * pi / num));
355 rawCoeff[i] = sinc * window;
356 }
357
358 for (i = 0; i < N_PHASES; i++) {
359 /* Normalise the coefficients. */
360 sum = 0.0;
361 for (j = 0; j < taps; j++) {
362 pos = i + j * 32;
363 sum += rawCoeff[pos];
364 }
365 for (j = 0; j < taps; j++) {
366 pos = i + j * 32;
367 coeffs[i][j] = rawCoeff[pos] / sum;
368 }
369
370 /* Set the register values. */
371 for (j = 0; j < taps; j++) {
372 pos = j + i * taps;
373 if ((j == (taps - 1) / 2) && !isVertAndUV)
374 SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
375 else
376 SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
377 }
378
379 tapAdjust[0] = (taps - 1) / 2;
380 for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
381 tapAdjust[j1] = tapAdjust[0] - j;
382 tapAdjust[++j1] = tapAdjust[0] + j;
383 }
384
385 /* Adjust the coefficients. */
386 sum = 0.0;
387 for (j = 0; j < taps; j++)
388 sum += coeffs[i][j];
389 if (sum != 1.0) {
390 for (j1 = 0; j1 < taps; j1++) {
391 tap2Fix = tapAdjust[j1];
392 diff = 1.0 - sum;
393 coeffs[i][tap2Fix] += diff;
394 pos = tap2Fix + i * taps;
395 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
396 SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
397 else
398 SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
399
400 sum = 0.0;
401 for (j = 0; j < taps; j++)
402 sum += coeffs[i][j];
403 if (sum == 1.0)
404 break;
405 }
406 }
407 }
408 }
409
410 static void
i830_display_video(VADriverContextP ctx,PsbPortPrivPtr pPriv,VASurfaceID __maybe_unused surface,int id,short width,short height,int dstPitch,int srcPitch,int __maybe_unused x1,int __maybe_unused y1,int __maybe_unused x2,int __maybe_unused y2,BoxPtr dstBox,short src_w,short src_h,short drw_w,short drw_h,unsigned int flags,int overlayId,int pipeId)411 i830_display_video(
412 VADriverContextP ctx, PsbPortPrivPtr pPriv, VASurfaceID __maybe_unused surface,
413 int id, short width, short height,
414 int dstPitch, int srcPitch, int __maybe_unused x1, int __maybe_unused y1, int __maybe_unused x2, int __maybe_unused y2, BoxPtr dstBox,
415 short src_w, short src_h, short drw_w, short drw_h,
416 unsigned int flags, int overlayId, int pipeId)
417 {
418 #ifndef BAYTRAIL
419 INIT_DRIVER_DATA;
420 unsigned int swidth, swidthy, swidthuv;
421 unsigned int mask, shift, offsety, offsetu;
422 int tmp;
423 uint32_t OCMD;
424 Bool scaleChanged = FALSE;
425 unsigned int offset = wsbmBOOffsetHint(pPriv->wsbo[overlayId]) & 0x0FFFFFFF;
426 I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]);
427 struct drm_psb_register_rw_arg regs;
428 int i32EnableIEP = 0;
429 int i32EnableIEPBLE = 0;
430
431 /*before enabling overlay, make sure overlay is disabled first.*/
432 if ((overlayId == OVERLAY_A) && !pPriv->overlayA_enabled) {
433 memset(®s, 0, sizeof(regs));
434 regs.overlay_read_mask = OV_REGRWBITS_OVADD;
435 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
436
437 overlay->OCMD &= ~OVERLAY_ENABLE;
438 regs.overlay_read_mask = 0;
439 regs.overlay_write_mask = OV_REGRWBITS_OVADD;
440 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
441 }
442
443 /* FIXME: don't know who and why add this
444 * comment it for full screen scale issue
445 * any concern contact qiang.miao@intel.com
446 */
447 #if 0
448 if (drw_w >= 800) {
449 x2 = x2 / 4;
450 y2 = y2 / 4;
451 dstBox->x2 = dstBox->x2 / 4;
452 dstBox->y2 = dstBox->y2 / 4;
453 drw_w = drw_w / 4;
454 drw_h = drw_h / 4;
455 }
456 #endif
457
458 #if USE_DCLRK
459 overlay->DCLRKM &= ~CONST_ALPHA_ENABLE;
460 if (pPriv->subpicture_enabled)
461 overlay->DCLRKM &= ~DEST_KEY_ENABLE;
462 else
463 overlay->DCLRKM |= DEST_KEY_ENABLE;
464 overlay->DCLRKV = pPriv->colorKey;
465 overlay->DCLRKM |= 0xffffff;
466 #else
467 /* disable overlay destination color key didn't work,
468 * it seems z-order of overlay has been bellow display pipe.
469 */
470 overlay->DCLRKM &= ~DEST_KEY_ENABLE;
471 #endif
472
473 #if USE_ROTATION_FUNC
474 if (((pipeId == PIPEA) && (driver_data->mipi0_rotation != VA_ROTATION_NONE)) ||
475 ((pipeId == PIPEB) && (driver_data->hdmi_rotation != VA_ROTATION_NONE))) {
476 switch (pPriv->rotation) {
477 case VA_ROTATION_NONE:
478 break;
479 case VA_ROTATION_270:
480 tmp = dstBox->x1;
481 dstBox->x1 = dstBox->y1;
482 dstBox->y1 = pPriv->height_save - tmp;
483 tmp = dstBox->x2;
484 dstBox->x2 = dstBox->y2;
485 dstBox->y2 = pPriv->height_save - tmp;
486 tmp = dstBox->y1;
487 dstBox->y1 = dstBox->y2;
488 dstBox->y2 = tmp;
489 tmp = drw_w;
490 drw_w = drw_h;
491 drw_h = tmp;
492 break;
493 case VA_ROTATION_180:
494 tmp = dstBox->x1;
495 dstBox->x1 = pPriv->width_save - dstBox->x2;
496 dstBox->x2 = pPriv->width_save - tmp;
497 tmp = dstBox->y1;
498 dstBox->y1 = pPriv->height_save - dstBox->y2;
499 dstBox->y2 = pPriv->height_save - tmp;
500 break;
501 case VA_ROTATION_90:
502 tmp = dstBox->x1;
503 dstBox->x1 = pPriv->width_save - dstBox->y1;
504 dstBox->y1 = tmp;
505 tmp = dstBox->x2;
506 dstBox->x2 = pPriv->width_save - dstBox->y2;
507 dstBox->y2 = tmp;
508 tmp = dstBox->x1;
509 dstBox->x1 = dstBox->x2;
510 dstBox->x2 = tmp;
511 tmp = drw_w;
512 drw_w = drw_h;
513 drw_h = tmp;
514 break;
515 }
516 }
517 #endif
518
519 if (pPriv->oneLineMode) {
520 /* change the coordinates with panel fitting active */
521 dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
522 dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
523
524 /* Now, alter the height, so we scale to the correct size */
525 drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
526 }
527
528 shift = 6;
529 mask = 0x3f;
530
531 if (pPriv->curBuf == 0) {
532 offsety = pPriv->YBuf0offset;
533 offsetu = pPriv->UBuf0offset;
534 } else {
535 offsety = pPriv->YBuf1offset;
536 offsetu = pPriv->UBuf1offset;
537 }
538
539 switch (id) {
540 case VA_FOURCC_NV12:
541 overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16);
542 swidthy = i830_swidth(offsety, width, mask, shift);
543 swidthuv = i830_swidth(offsetu, width / 2, mask, shift);
544 overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
545 overlay->SHEIGHT = height | ((height / 2) << 16);
546 break;
547 case VA_FOURCC_YV12:
548 case VA_FOURCC_I420:
549 overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16);
550 swidthy = i830_swidth(offsety, width, mask, shift);
551 swidthuv = i830_swidth(offsetu, width / 2, mask, shift);
552 overlay->SWIDTHSW = (swidthy) | (swidthuv << 16);
553 overlay->SHEIGHT = height | ((height / 2) << 16);
554 break;
555 case VA_FOURCC_UYVY:
556 case VA_FOURCC_YUY2:
557 default:
558 overlay->SWIDTH = width;
559 swidth = ((offsety + (width << 1) + mask) >> shift) -
560 (offsety >> shift);
561
562 swidth <<= 1;
563 swidth -= 1;
564 swidth <<= 2;
565
566 overlay->SWIDTHSW = swidth;
567 overlay->SHEIGHT = height;
568 break;
569 }
570
571 overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
572
573 overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) |
574 (dstBox->x2 - dstBox->x1));
575
576 /* buffer locations */
577 overlay->OBUF_0Y = pPriv->YBuf0offset;
578 overlay->OBUF_0U = pPriv->UBuf0offset;
579 overlay->OBUF_0V = pPriv->VBuf0offset;
580 overlay->OBUF_1Y = pPriv->YBuf1offset;
581 overlay->OBUF_1U = pPriv->UBuf1offset;
582 overlay->OBUF_1V = pPriv->VBuf1offset;
583
584 /*
585 * Calculate horizontal and vertical scaling factors and polyphase
586 * coefficients.
587 */
588
589 if (1) {
590 int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
591 int xscaleIntUV, xscaleFractUV;
592 int yscaleIntUV, yscaleFractUV;
593 /* UV is half the size of Y -- YUV420 */
594 int uvratio = 2;
595 uint32_t newval;
596 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
597 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
598 int i, j, pos;
599 int deinterlace_factor;
600
601 /*
602 * Y down-scale factor as a multiple of 4096.
603 */
604 if ((id == VA_FOURCC_NV12) && (0 != (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD))))
605 deinterlace_factor = 2;
606 else
607 deinterlace_factor = 1;
608
609 /* deinterlace requires twice of VSCALE setting*/
610 if (src_w == drw_w && src_h == drw_h) {
611 xscaleFract = 1 << 12;
612 yscaleFract = (1 << 12) / deinterlace_factor;
613 } else {
614 xscaleFract = ((src_w - 1) << 12) / drw_w;
615 yscaleFract = ((src_h - 1) << 12) / (deinterlace_factor * drw_h);
616 }
617
618 /* Calculate the UV scaling factor. */
619 xscaleFractUV = xscaleFract / uvratio;
620 yscaleFractUV = yscaleFract / uvratio;
621
622 /*
623 * To keep the relative Y and UV ratios exact, round the Y scales
624 * to a multiple of the Y/UV ratio.
625 */
626 xscaleFract = xscaleFractUV * uvratio;
627 yscaleFract = yscaleFractUV * uvratio;
628
629 /* Integer (un-multiplied) values. */
630 xscaleInt = xscaleFract >> 12;
631 yscaleInt = yscaleFract >> 12;
632
633 xscaleIntUV = xscaleFractUV >> 12;
634 yscaleIntUV = yscaleFractUV >> 12;
635
636 /* shouldn't get here */
637 if (xscaleInt > 7) {
638 return;
639 }
640
641 /* shouldn't get here */
642 if (xscaleIntUV > 7) {
643 return;
644 }
645
646 if (pPriv->is_mfld)
647 newval = (xscaleInt << 15) |
648 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
649 else
650 newval = (xscaleInt << 16) |
651 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
652
653 if (newval != overlay->YRGBSCALE) {
654 scaleChanged = TRUE;
655 overlay->YRGBSCALE = newval;
656 }
657
658 if (pPriv->is_mfld)
659 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
660 ((yscaleFractUV & 0xFFF) << 20);
661 else
662 newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) |
663 ((yscaleFractUV & 0xFFF) << 20);
664
665 if (newval != overlay->UVSCALE) {
666 scaleChanged = TRUE;
667 overlay->UVSCALE = newval;
668 }
669
670 newval = yscaleInt << 16 | yscaleIntUV;
671 if (newval != overlay->UVSCALEV) {
672 scaleChanged = TRUE;
673 overlay->UVSCALEV = newval;
674 }
675
676 /* Recalculate coefficients if the scaling changed. */
677
678 /*
679 * Only Horizontal coefficients so far.
680 */
681 if (scaleChanged) {
682 double fCutoffY;
683 double fCutoffUV;
684
685 fCutoffY = xscaleFract / 4096.0;
686 fCutoffUV = xscaleFractUV / 4096.0;
687
688 /* Limit to between 1.0 and 3.0. */
689 if (fCutoffY < MIN_CUTOFF_FREQ)
690 fCutoffY = MIN_CUTOFF_FREQ;
691 if (fCutoffY > MAX_CUTOFF_FREQ)
692 fCutoffY = MAX_CUTOFF_FREQ;
693 if (fCutoffUV < MIN_CUTOFF_FREQ)
694 fCutoffUV = MIN_CUTOFF_FREQ;
695 if (fCutoffUV > MAX_CUTOFF_FREQ)
696 fCutoffUV = MAX_CUTOFF_FREQ;
697
698 UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY);
699 UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV);
700
701 for (i = 0; i < N_PHASES; i++) {
702 for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
703 pos = i * N_HORIZ_Y_TAPS + j;
704 overlay->Y_HCOEFS[pos] = (xcoeffY[pos].sign << 15 |
705 xcoeffY[pos].exponent << 12 |
706 xcoeffY[pos].mantissa);
707 }
708 }
709 for (i = 0; i < N_PHASES; i++) {
710 for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
711 pos = i * N_HORIZ_UV_TAPS + j;
712 overlay->UV_HCOEFS[pos] = (xcoeffUV[pos].sign << 15 |
713 xcoeffUV[pos].exponent << 12 |
714 xcoeffUV[pos].mantissa);
715 }
716 }
717 }
718 }
719
720 OCMD = OVERLAY_ENABLE;
721
722 switch (id) {
723 case VA_FOURCC_NV12:
724 overlay->OSTRIDE = dstPitch | (dstPitch << 16);
725 OCMD &= ~SOURCE_FORMAT;
726 OCMD &= ~OV_BYTE_ORDER;
727 OCMD |= NV12;//in the spec, there are two NV12, which to use?
728 break;
729 case VA_FOURCC_YV12:
730 case VA_FOURCC_I420:
731 /* set UV vertical phase to -0.25 */
732 /* overlay->UV_VPH = 0x30003000; */
733 overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16);
734 OCMD &= ~SOURCE_FORMAT;
735 OCMD &= ~OV_BYTE_ORDER;
736 OCMD |= YUV_420;
737 break;
738 case VA_FOURCC_UYVY:
739 case VA_FOURCC_YUY2:
740 overlay->OSTRIDE = dstPitch;
741 OCMD &= ~SOURCE_FORMAT;
742 OCMD |= YUV_422;
743 OCMD &= ~OV_BYTE_ORDER;
744 if (id == VA_FOURCC_UYVY)
745 OCMD |= Y_SWAP;
746 break;
747 }
748
749 if (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD)) {
750 OCMD |= BUF_TYPE_FIELD;
751 OCMD &= ~FIELD_SELECT;
752
753 if (flags & VA_BOTTOM_FIELD) {
754 OCMD |= FIELD1;
755 overlay->OBUF_0Y = pPriv->YBuf0offset - srcPitch;
756 overlay->OBUF_0U = pPriv->UBuf0offset - srcPitch;
757 overlay->OBUF_0V = pPriv->VBuf0offset - srcPitch;
758 overlay->OBUF_1Y = pPriv->YBuf1offset - srcPitch;
759 overlay->OBUF_1U = pPriv->UBuf1offset - srcPitch;
760 overlay->OBUF_1V = pPriv->VBuf1offset - srcPitch;
761 } else
762 OCMD |= FIELD0;
763 } else {
764 OCMD &= ~(FIELD_SELECT);
765 OCMD &= ~BUF_TYPE_FIELD;
766 }
767
768 OCMD &= ~(BUFFER_SELECT);
769
770 if (pPriv->curBuf == 0)
771 OCMD |= BUFFER0;
772 else
773 OCMD |= BUFFER1;
774
775 overlay->OCMD = OCMD;
776
777 memset(®s, 0, sizeof(regs));
778 switch (overlayId) {
779 case OVERLAY_A:
780 pPriv->overlayA_enabled = 1;
781 regs.overlay_write_mask = OV_REGRWBITS_OVADD;
782 break;
783 case OVERLAY_C:
784 pPriv->overlayC_enabled = 1;
785 regs.overlay_write_mask = OVC_REGRWBITS_OVADD;
786 break;
787 }
788
789 if (pPriv->is_mfld) {
790 i32EnableIEP = 0;
791
792 i32EnableIEPBLE = 0;
793
794 if (i32EnableIEP == 0) {
795 overlay->OCONFIG = CC_OUT_8BIT;
796 overlay->OCONFIG &= OVERLAY_C_PIPE_A | (~OVERLAY_C_PIPE_MASK);
797 overlay->OCONFIG |= IEP_LITE_BYPASS;
798 regs.overlay.OVADD = offset | 1;
799 regs.overlay.IEP_ENABLED = 0;
800 regs.overlay.buffer_handle = wsbmKBufHandle(wsbmKBuf(pPriv->wsbo[overlayId]));
801 }
802 } else {
803 overlay->OCONFIG = CC_OUT_8BIT;
804 overlay->OCONFIG |= IEP_LITE_BYPASS;
805 regs.overlay.OVADD = offset | 1;
806 }
807
808 if (pPriv->is_mfld) {
809 switch (pipeId) {
810 case PIPEA:
811 overlay->OCONFIG |= OVERLAY_C_PIPE_A;
812 overlay->OCONFIG |= ZORDER_TOP;
813 break;
814 case PIPEB:
815 overlay->OCONFIG |= OVERLAY_C_PIPE_B;
816 overlay->OCONFIG |= ZORDER_TOP;
817 regs.overlay.OVADD |= 0x80;
818 break;
819 case PIPEC:
820 overlay->OCONFIG |= OVERLAY_C_PIPE_C;
821 overlay->OCONFIG |= ZORDER_TOP;
822 regs.overlay.OVADD |= 0x40;
823 break;
824 }
825 overlay->OCONFIG |= ZORDER_TOP;
826 } else
827 overlay->OCONFIG |= pipeId << 18; /* mrst */
828
829 if (IS_CTP(driver_data) || IS_MRFL(driver_data) )
830 regs.overlay.b_wms = 1;
831
832 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
833
834 if (pPriv->is_mfld) {
835 if (regs.overlay.IEP_ENABLED) {
836 #if 0
837 printf("regs.overlay BLE minmax 0x%x, BSSCC control 0x%x\n",
838 regs.overlay.IEP_BLE_MINMAX, regs.overlay.IEP_BSSCC_CONTROL);
839 #endif
840 *(unsigned int *)((unsigned int)&(overlay->IEP_SPACE[0]) + 0x804) = regs.overlay.IEP_BLE_MINMAX;
841 }
842 }
843 #endif
844 }
845
846
I830PutImageFlipRotateSurface(VADriverContextP ctx,object_surface_p obj_surface,int * src_w_new,int * src_h_new,int * width_new,int * height_new,psb_surface_p * psb_surface_new,int pipeId)847 static void I830PutImageFlipRotateSurface(
848 VADriverContextP ctx,
849 object_surface_p obj_surface,
850 int *src_w_new, int *src_h_new,
851 int *width_new, int *height_new,
852 psb_surface_p *psb_surface_new,
853 int pipeId)
854 {
855 int src_w = *src_w_new, src_h = *src_h_new;
856 int width = *width_new, height = *height_new;
857 int tmp = 0;
858
859 psb_surface_p psb_surface = NULL;
860 INIT_DRIVER_DATA;
861 PsbPortPrivPtr pPriv;
862
863 /* local/extend display doesn't have render rotation */
864 if (((pipeId == PIPEA) && (driver_data->local_rotation == VA_ROTATION_NONE)) ||
865 ((pipeId == PIPEB) && (driver_data->extend_rotation == VA_ROTATION_NONE)))
866 return;
867
868 pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
869
870 if (pipeId == PIPEA) {
871 if (driver_data->local_rotation != VA_ROTATION_NONE) {
872 psb_surface = obj_surface->out_loop_surface;
873 width = obj_surface->width_r;
874 height = obj_surface->height_r;
875 if (driver_data->local_rotation != VA_ROTATION_180) {
876 tmp = src_w;
877 src_w = src_h;
878 src_h = tmp;
879 }
880 }
881 if ((driver_data->local_rotation == VA_ROTATION_NONE) ||
882 (driver_data->local_rotation == VA_ROTATION_180)) {
883 pPriv->width_save = pPriv->display_width;
884 pPriv->height_save = pPriv->display_height;
885 } else {
886 pPriv->width_save = pPriv->display_height;
887 pPriv->height_save = pPriv->display_width;
888 }
889 if (driver_data->is_android == 0)
890 pPriv->rotation = driver_data->local_rotation;
891 else
892 pPriv->rotation = 0;
893 } else if (pipeId == PIPEB) {
894 if (driver_data->extend_rotation != VA_ROTATION_NONE) {
895 psb_surface = obj_surface->out_loop_surface;
896 width = obj_surface->width_r;
897 height = obj_surface->height_r;
898 if (driver_data->extend_rotation != VA_ROTATION_180) {
899 tmp = src_w;
900 src_w = src_h;
901 src_h = tmp;
902 }
903 }
904 if ((driver_data->extend_rotation == VA_ROTATION_NONE) ||
905 (driver_data->extend_rotation == VA_ROTATION_180)) {
906 pPriv->width_save = pPriv->extend_display_width;
907 pPriv->height_save = pPriv->extend_display_height;
908 } else {
909 pPriv->width_save = pPriv->extend_display_height;
910 pPriv->height_save = pPriv->extend_display_width;
911 }
912 if (driver_data->is_android == 0)
913 pPriv->rotation = driver_data->extend_rotation;
914 else
915 pPriv->rotation = 0;
916 }
917
918 *src_w_new = src_w;
919 *src_h_new = src_h;
920 *width_new = width;
921 *height_new = height;
922 *psb_surface_new = psb_surface;
923 }
924
925
I830PutImageFlipRotateDebug(VADriverContextP ctx,VASurfaceID surface,short __maybe_unused src_x,short __maybe_unused src_y,short __maybe_unused src_w,short __maybe_unused src_h,short __maybe_unused drw_x,short __maybe_unused drw_y,short __maybe_unused drw_w,short __maybe_unused drw_h,int __maybe_unused fourcc,int __maybe_unused flags,int __maybe_unused overlayId,int pipeId)926 static int I830PutImageFlipRotateDebug(
927 VADriverContextP ctx,
928 VASurfaceID surface,
929 short __maybe_unused src_x, short __maybe_unused src_y,
930 short __maybe_unused src_w, short __maybe_unused src_h,
931 short __maybe_unused drw_x, short __maybe_unused drw_y,
932 short __maybe_unused drw_w, short __maybe_unused drw_h,
933 int __maybe_unused fourcc, int __maybe_unused flags,
934 int __maybe_unused overlayId,
935 int pipeId)
936 {
937 INIT_DRIVER_DATA;
938 object_surface_p obj_surface;
939 psb_surface_p psb_surface = NULL;
940 VAStatus vaStatus = VA_STATUS_SUCCESS;
941
942 obj_surface = SURFACE(surface);
943 CHECK_SURFACE(obj_surface);
944
945 if (pipeId != 0)
946 return -1;
947
948 psb_surface = obj_surface->out_loop_surface;
949 psb_buffer_p buf = &psb_surface->buf;
950 unsigned char *data, *chroma, *buffer, *header;
951 static FILE *pf = NULL;
952 int ret, i;
953 if (!psb_surface)
954 goto dump_out;
955 if (pf == NULL)
956 if ((pf = fopen("/home/dump.yuv", "w+")) == NULL) {
957 printf("Open yuv file fails\n");
958 return -1;
959 }
960 ret = psb_buffer_map(buf, &data);
961
962 if (ret) {
963 printf("Map buffer fail\n");
964 return -1;
965 }
966 for (i = 0; i < obj_surface->height_r; i++) {
967 fwrite(data, 1, obj_surface->width_r, pf);
968 data += psb_surface->stride;
969 }
970
971 buffer = malloc(obj_surface->height_r * obj_surface->width_r);
972 if (!buffer) {
973 printf("Alloc chroma buffer fail\n");
974 return -1;
975 }
976 header = buffer;
977 chroma = data;
978 for (i = 0; i < obj_surface->height_r / 2; i++) {
979 int j;
980 for (j = 0; j < obj_surface->width_r / 2; j++) {
981 *buffer++ = data[j*2];
982 }
983 data += psb_surface->stride;
984 }
985
986 data = chroma;
987 for (i = 0; i < obj_surface->height_r / 2; i++) {
988 int j;
989 for (j = 0; j < obj_surface->width_r / 2; j++) {
990 *buffer++ = data[j*2 + 1];
991 }
992 data += psb_surface->stride;
993 }
994
995 fwrite(header, obj_surface->height_r / 2, obj_surface->width_r, pf);
996 free(header);
997 psb_buffer_unmap(buf);
998 return 0;
999
1000 dump_out:
1001 return -1;
1002 }
1003
1004
1005 /*
1006 * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
1007 * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
1008 * id is a fourcc code for the format of the video.
1009 * buf is the pointer to the source data in system memory.
1010 * width and height are the w/h of the source data.
1011 * If "sync" is TRUE, then we must be finished with *buf at the point of return
1012 * (which we always are).
1013 * clipBoxes is the clipping region in screen space.
1014 * data is a pointer to our port private.
1015 * pDraw is a Drawable, which might not be the screen in the case of
1016 * compositing. It's a new argument to the function in the 1.1 server.
1017 */
I830PutImage(VADriverContextP ctx,VASurfaceID surface,int src_x,int src_y,int src_w,int src_h,int drw_x,int drw_y,int drw_w,int drw_h,int fourcc,int flags,int overlayId,int pipeId)1018 static int I830PutImage(
1019 VADriverContextP ctx,
1020 VASurfaceID surface,
1021 int src_x, int src_y,
1022 int src_w, int src_h,
1023 int drw_x, int drw_y,
1024 int drw_w, int drw_h,
1025 int fourcc, int flags,
1026 int overlayId,
1027 int pipeId)
1028 {
1029 INIT_DRIVER_DATA;
1030 int x1, x2, y1, y2;
1031 int width, height;
1032 int top, left, npixels;
1033 int pitch = 0, pitch2 = 0;
1034 unsigned int pre_add;
1035 unsigned int gtt_ofs;
1036 struct _WsbmBufferObject *drm_buf;
1037 BoxRec dstBox;
1038 PsbPortPrivPtr pPriv;
1039 object_surface_p obj_surface = SURFACE(surface);
1040 psb_surface_p psb_surface = NULL;
1041
1042 /* silent kw */
1043 if (NULL == obj_surface)
1044 return 1;
1045
1046 pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
1047
1048 switch (fourcc) {
1049 case VA_FOURCC_NV12:
1050 width = obj_surface->width;
1051 height = obj_surface->height;
1052 break;
1053 default:
1054 width = obj_surface->width;
1055 height = obj_surface->height;
1056 break;
1057 }
1058
1059 /* rotate support here: more check?
1060 * and for oold also?
1061 */
1062 psb_surface = obj_surface->psb_surface;
1063 I830PutImageFlipRotateSurface(ctx, obj_surface,
1064 &src_w, &src_h, &width, &height,
1065 &psb_surface, pipeId);
1066
1067 if (NULL == psb_surface) {
1068 /*Rotate surface may not be ready, so we have to discard this frame.*/
1069 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Discard this frame if rotate surface hasn't be ready.\n");
1070
1071 return 1;
1072 }
1073 width = (width <= 1920) ? width : 1920;
1074
1075 /* If dst width and height are less than 1/8th the src size, the
1076 * src/dst scale factor becomes larger than 8 and doesn't fit in
1077 * the scale register.
1078 */
1079 if (src_w >= (drw_w * 8))
1080 drw_w = src_w / 7;
1081
1082 if (src_h >= (drw_h * 8))
1083 drw_h = src_h / 7;
1084
1085 /* Clip */
1086 x1 = src_x;
1087 x2 = src_x + src_w;
1088 y1 = src_y;
1089 y2 = src_y + src_h;
1090
1091 dstBox.x1 = drw_x;
1092 dstBox.x2 = drw_x + drw_w;
1093 dstBox.y1 = drw_y;
1094 dstBox.y2 = drw_y + drw_h;
1095
1096 #if USE_CLIP_FUNC
1097 if (!i830_get_crtc(pScrn, &crtc, &dstBox))
1098 return Success;
1099
1100 /*
1101 *Update drw_* and 'clipBoxes' according to current downscale/upscale state
1102 * Make sure the area determined by drw_* is in 'clipBoxes'
1103 */
1104 if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1105 h_ratio = (float)pScrn->pScreen->height / pPriv->width_save;
1106 v_ratio = (float)pScrn->pScreen->width / pPriv->height_save;
1107 } else {
1108 h_ratio = (float)pScrn->pScreen->width / pPriv->width_save;
1109 v_ratio = (float)pScrn->pScreen->height / pPriv->height_save;
1110 }
1111
1112 /* Horizontal downscale/upscale */
1113 if ((int)h_ratio)
1114 clipBoxes->extents.x1 /= h_ratio;
1115 else if (!(int)h_ratio)
1116 clipBoxes->extents.x2 /= h_ratio;
1117
1118 /* Vertical downscale/upscale */
1119 if ((int)v_ratio)
1120 clipBoxes->extents.y1 /= v_ratio;
1121 else if (!(int)v_ratio)
1122 clipBoxes->extents.y2 /= v_ratio;
1123
1124 drw_x /= h_ratio;
1125 drw_y /= v_ratio;
1126 drw_w /= h_ratio;
1127 drw_h /= v_ratio;
1128
1129 dstBox.x1 = drw_x;
1130 dstBox.x2 = drw_x + drw_w;
1131 dstBox.y1 = drw_y;
1132 dstBox.y2 = drw_y + drw_h;
1133
1134 /* Count in client supplied clipboxes */
1135 clipRegion = clipBoxes;
1136 psb_perform_clip(pScrn, vaPtr->clipbox, vaPtr->num_clipbox, clipBoxes, clipRegion, pDraw);
1137
1138 if (!i830_clip_video_helper(pScrn,
1139 &crtc,
1140 &dstBox, &x1, &x2, &y1, &y2, clipRegion,
1141 width, height)) {
1142 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Fail to clip video to any crtc!\n", __FUNCTION__);
1143 return 0;
1144 }
1145 #endif
1146
1147 switch (fourcc) {
1148 case VA_FOURCC_NV12:
1149 pitch = (width + 0x3) & ~0x3;
1150 pitch2 = psb_surface->stride;
1151 break;
1152 case VA_FOURCC_YV12:
1153 case VA_FOURCC_I420:
1154 pitch = (width + 0x3) & ~0x3;
1155 break;
1156 #if USE_DISPLAY_C_SPRITE
1157 case FOURCC_RGBA:
1158 pitch = width << 2;
1159 break;
1160 #endif
1161 case VA_FOURCC_UYVY:
1162 case VA_FOURCC_YUY2:
1163 default:
1164 pitch = width << 1;
1165 break;
1166 }
1167
1168 top = (y1) & ~1;
1169 left = (x1) & ~1;
1170 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
1171
1172 if (fourcc == VA_FOURCC_NV12) {
1173 pre_add = psb_surface->buf.buffer_ofs;
1174 drm_buf = psb_surface->buf.drm_buf;
1175 gtt_ofs = wsbmBOOffsetHint(drm_buf) & 0x0FFFFFFF;
1176
1177 /*skip pad bytes.*/
1178 if (driver_data->local_rotation == VA_ROTATION_90) {
1179 left += ((src_w + 0xf) & ~0xf) - src_w;
1180 } else if (driver_data->local_rotation == VA_ROTATION_270) {
1181 top += ((src_h + 0xf) & ~0xf) - src_h;
1182 } else if (driver_data->local_rotation == VA_ROTATION_180) {
1183 left += ((src_w + 0xf) & ~0xf) - src_w;
1184 top += ((src_h + 0xf) & ~0xf) - src_h;
1185 }
1186 pPriv->YBuf0offset = pre_add + gtt_ofs + top * pitch2 + left;
1187 pPriv->YBuf1offset = pPriv->YBuf0offset;
1188 pPriv->UBuf0offset = pre_add + gtt_ofs + (pitch2 * height) + top * (pitch2 / 2) + left;
1189 pPriv->VBuf0offset = pPriv->UBuf0offset;
1190 pPriv->UBuf1offset = pPriv->UBuf0offset;
1191 pPriv->VBuf1offset = pPriv->UBuf0offset;
1192 } else {
1193 //TBD
1194 //pPriv->YBuf0offset = pPriv->videoBuf0_gtt_offset << PAGE_SHIFT;
1195 //pPriv->YBuf1offset = pPriv->videoBuf1_gtt_offset << PAGE_SHIFT;
1196 if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
1197 pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2 * width);
1198 pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * width / 2);
1199 pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * width);
1200 pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * width / 2);
1201 } else {
1202 pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2 * height);
1203 pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * height / 2);
1204 pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * height);
1205 pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * height / 2);
1206 }
1207 }
1208
1209 #if USE_DISPLAY_C_SPRITE
1210 if (fourcc == FOURCC_RGBA \
1211 || (fourcc == FOURCC_XVVA \
1212 && (pPriv->rotation != RR_Rotate_0) \
1213 && (vaPtr->dst_srf.fourcc == VA_FOURCC_RGBA)))
1214 i830_display_video_sprite(pScrn, crtc, width, height, dstPitch,
1215 &dstBox, sprite_offset);
1216 else
1217 #endif
1218 i830_display_video(ctx, pPriv, surface, fourcc, src_w, src_h, pitch2, pitch,
1219 x1, y1, x2, y2, &dstBox, src_w, src_h,
1220 drw_w, drw_h, flags, overlayId, pipeId);
1221
1222 // FIXME : do I use two buffers here really?
1223 // pPriv->curBuf = (pPriv->curBuf + 1) & 1;
1224
1225 return Success;
1226 }
1227
1228
1229
psbPortPrivCreate(PsbPortPrivPtr pPriv)1230 static void psbPortPrivCreate(PsbPortPrivPtr pPriv)
1231 {
1232 #if 0
1233 REGION_NULL(pScreen, &pPriv->clip);
1234 #endif
1235
1236 /* coeffs defaut value */
1237 pPriv->brightness.Value = OV_BRIGHTNESS_DEFAULT_VALUE;
1238 pPriv->brightness.Fraction = 0;
1239
1240 pPriv->contrast.Value = OV_CONTRAST_DEFAULT_VALUE;
1241 pPriv->contrast.Fraction = 0;
1242
1243 pPriv->hue.Value = OV_HUE_DEFAULT_VALUE;
1244 pPriv->hue.Fraction = 0;
1245
1246 pPriv->saturation.Value = OV_SATURATION_DEFAULT_VALUE;
1247 pPriv->saturation.Fraction = 0;
1248 pPriv->subpicture_enabled = 0;
1249 pPriv->subpicture_enable_mask = 0;
1250 pPriv->overlayA_enabled = 0;
1251 pPriv->overlayC_enabled = 0;
1252 pPriv->overlayA_pipeId = PIPEA;
1253 pPriv->overlayC_pipeId = PIPEB;
1254
1255 /* FIXME: is this right? set up to current screen size */
1256 #if 1
1257 pPriv->width_save = 1024;
1258 pPriv->height_save = 600;
1259 #endif
1260 }
1261
1262 static void
psbPortPrivDestroy(VADriverContextP ctx,PsbPortPrivPtr pPriv)1263 psbPortPrivDestroy(VADriverContextP ctx, PsbPortPrivPtr pPriv)
1264 {
1265 I830StopVideo(ctx);
1266
1267 wsbmBOUnmap(pPriv->wsbo[0]);
1268 wsbmBOUnreference(&pPriv->wsbo[0]);
1269 wsbmBOUnmap(pPriv->wsbo[1]);
1270 wsbmBOUnreference(&pPriv->wsbo[1]);
1271 if (pPriv->is_mfld) {
1272 if (pPriv->p_iep_lite_context)
1273 free(pPriv->p_iep_lite_context);
1274 }
1275 pPriv->p_iep_lite_context = NULL;
1276 }
1277
1278 static int
psbSetupImageVideoOverlay(VADriverContextP ctx,PsbPortPrivPtr pPriv)1279 psbSetupImageVideoOverlay(VADriverContextP ctx, PsbPortPrivPtr pPriv)
1280 {
1281 INIT_DRIVER_DATA;
1282 I830OverlayRegPtr overlayA = NULL;
1283 I830OverlayRegPtr overlayC = NULL;
1284 int ret;
1285 psbPortPrivCreate(pPriv);
1286
1287
1288 /* use green as color key by default for android media player */
1289 pPriv->colorKey = driver_data->color_key/*0x0440*/;
1290
1291 /*Bypass color correction. Because these color
1292 correction can be done in pipe color correction in future.*/
1293 pPriv->brightness.Value = 0; /*-19*/
1294 pPriv->contrast.Value = 0x40; /*75*/
1295 pPriv->saturation.Value = 0x80; /*146*/
1296
1297 pPriv->gamma5 = 0xc0c0c0;
1298 pPriv->gamma4 = 0x808080;
1299 pPriv->gamma3 = 0x404040;
1300 pPriv->gamma2 = 0x202020;
1301 pPriv->gamma1 = 0x101010;
1302 pPriv->gamma0 = 0x080808;
1303
1304 pPriv->rotation = VA_ROTATION_NONE;
1305 pPriv->subpic_clear_flag = 1;
1306 #if 0
1307 /* gotta uninit this someplace */
1308 REGION_NULL(pScreen, &pPriv->clip);
1309 #endif
1310
1311 /* With LFP's we need to detect whether we're in One Line Mode, which
1312 * essentially means a resolution greater than 1024x768, and fix up
1313 * the scaler accordingly.
1314 */
1315 pPriv->scaleRatio = 0x10000;
1316 pPriv->oneLineMode = FALSE;
1317
1318 ret = wsbmGenBuffers(driver_data->main_pool, 2,
1319 &pPriv->wsbo[0], 64 * 1024, /* 64k alignment */
1320 WSBM_PL_FLAG_TT);
1321 if (ret)
1322 goto out_err;
1323
1324 ret = wsbmBOData(pPriv->wsbo[0],
1325 5 * 4096,
1326 NULL, NULL,
1327 WSBM_PL_FLAG_TT);
1328 if (ret)
1329 goto out_err_bo0;
1330
1331 pPriv->regmap[0] = wsbmBOMap(pPriv->wsbo[0], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
1332 if (!pPriv->regmap[0]) {
1333 goto out_err_bo0;
1334 }
1335
1336 ret = wsbmBOData(pPriv->wsbo[1],
1337 5 * 4096,
1338 NULL, NULL,
1339 WSBM_PL_FLAG_TT);
1340 if (ret)
1341 goto out_err_bo1;
1342
1343 pPriv->regmap[1] = wsbmBOMap(pPriv->wsbo[1], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
1344 if (!pPriv->regmap[1]) {
1345 goto out_err_bo1;
1346 }
1347
1348 overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]);
1349 overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]);
1350
1351 if (pPriv->is_mfld) {
1352 driver_data->ble_black_mode.value = 1;
1353 driver_data->ble_white_mode.value = 3;
1354 driver_data->blueStretch_gain.value = 200;
1355 driver_data->skinColorCorrection_gain.value = 100;
1356 driver_data->hue.value = (5.25f * (1 << 25));
1357 driver_data->saturation.value = (1.07f * (1 << 25));
1358 driver_data->brightness.value = (-10.1f * (1 << 10));
1359 driver_data->contrast.value = (0.99f * (1 << 25));
1360 }
1361
1362 return 0;
1363
1364 out_err_bo1:
1365 wsbmBOUnreference(&pPriv->wsbo[1]);
1366 out_err_bo0:
1367 wsbmBOUnreference(&pPriv->wsbo[0]);
1368
1369 out_err:
1370 return -1;
1371 }
1372
psb_coverlay_init(VADriverContextP ctx)1373 int psb_coverlay_init(VADriverContextP ctx)
1374 {
1375 #ifndef BAYTRAIL
1376 INIT_DRIVER_DATA;
1377 PsbPortPrivPtr pPriv = &driver_data->coverlay_priv;
1378 struct drm_psb_register_rw_arg regs;
1379 int ret;
1380
1381 memset(pPriv, 0, sizeof(PsbPortPrivRec));
1382 pPriv->is_mfld = (IS_MFLD(driver_data) || IS_MRFL(driver_data));
1383
1384 ret = psbSetupImageVideoOverlay(ctx, pPriv);
1385 if (ret != 0) {
1386 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb_coverlay_init : Create overlay cmd buffer failed.\n");
1387 return -1;
1388 }
1389
1390 if (pPriv->is_mfld && driver_data->is_android) {
1391 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane on the bottom.\n");
1392
1393 memset(®s, 0, sizeof(regs));
1394 regs.display_read_mask = REGRWBITS_DSPBCNTR;
1395 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
1396 regs.display.dspcntr_b |= DISPPLANE_BOTTOM;
1397 regs.display_write_mask = REGRWBITS_DSPBCNTR;
1398 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
1399 }
1400
1401 I830ResetVideo(ctx, pPriv);
1402 I830UpdateGamma(ctx, pPriv);
1403 #endif
1404 return 0;
1405 }
1406
psb_coverlay_stop(VADriverContextP ctx)1407 int psb_coverlay_stop(VADriverContextP ctx)
1408 {
1409 I830StopVideo(ctx);
1410 return 0;
1411 }
1412
psb_coverlay_deinit(VADriverContextP ctx)1413 int psb_coverlay_deinit(VADriverContextP ctx)
1414 {
1415 #ifndef BAYTRAIL
1416 INIT_DRIVER_DATA;
1417 PsbPortPrivPtr pPriv = &driver_data->coverlay_priv;
1418 struct drm_psb_register_rw_arg regs;
1419
1420 if (pPriv->is_mfld && driver_data->is_android) {
1421 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane normal.\n");
1422
1423 memset(®s, 0, sizeof(regs));
1424 regs.display_read_mask = REGRWBITS_DSPBCNTR;
1425 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
1426 regs.display.dspcntr_b &= ~DISPPLANE_BOTTOM;
1427 regs.display_write_mask = REGRWBITS_DSPBCNTR;
1428 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs));
1429 }
1430
1431 psbPortPrivDestroy(ctx, pPriv);
1432 #endif
1433 return 0;
1434 }
1435
psb_putsurface_overlay(VADriverContextP ctx,VASurfaceID surface,short srcx,short srcy,unsigned short srcw,unsigned short srch,short destx,short desty,unsigned short destw,unsigned short desth,unsigned int flags,int overlayId,int pipeId)1436 VAStatus psb_putsurface_overlay(
1437 VADriverContextP ctx,
1438 VASurfaceID surface,
1439 short srcx,
1440 short srcy,
1441 unsigned short srcw,
1442 unsigned short srch,
1443 short destx,
1444 short desty,
1445 unsigned short destw,
1446 unsigned short desth,
1447 unsigned int flags, /* de-interlacing flags */
1448 int overlayId,
1449 int pipeId
1450 )
1451 {
1452 INIT_DRIVER_DATA;
1453 object_surface_p obj_surface = SURFACE(surface);
1454 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
1455 #if 0
1456 if ((overlayId == OVERLAY_A) && (pPriv->overlayA_pipeId != pipeId)) {
1457 pPriv->overlayA_pipeId = pipeId;
1458 I830SwitchPipe(ctx, OVERLAY_A, pipeId);
1459 drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayA switch pipe to %d, stop overlayA first.\n", pipeId);
1460 } else if ((overlayId == OVERLAY_C) && (pPriv->overlayC_pipeId != pipeId)) {
1461 pPriv->overlayC_pipeId = pipeId;
1462 I830SwitchPipe(ctx, OVERLAY_C, pipeId);
1463 drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayC switch pipe to %d, stop overlayC first.\n", pipeId);
1464 }
1465 #endif
1466 I830PutImage(ctx, surface, srcx, srcy, srcw, srch,
1467 destx, desty, destw, desth,
1468 VA_FOURCC_NV12, flags, overlayId, pipeId);
1469
1470 /* current surface is being displayed */
1471 if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE)
1472 driver_data->last_displaying_surface = driver_data->cur_displaying_surface;
1473
1474 if (obj_surface == NULL) {
1475 drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surface ID: 0x%08x\n", surface);
1476 return VA_STATUS_ERROR_INVALID_SURFACE;
1477 }
1478
1479 obj_surface->display_timestamp = GetTickCount();
1480 driver_data->cur_displaying_surface = surface;
1481
1482 return VA_STATUS_SUCCESS;
1483 }
1484