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(&regs, 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, &regs, 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(&regs, 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, &regs, sizeof(regs));
181     }
182 
183     memset(&regs, 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, &regs, 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, &regs, sizeof(regs));
196 
197             memset(&regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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(&regs, 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, &regs, 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, &regs, 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(&regs, 0, sizeof(regs));
434         regs.overlay_read_mask = OV_REGRWBITS_OVADD;
435         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, 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, &regs, 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(&regs, 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, &regs, 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(&regs, 0, sizeof(regs));
1394         regs.display_read_mask = REGRWBITS_DSPBCNTR;
1395         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, 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, &regs, 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(&regs, 0, sizeof(regs));
1424         regs.display_read_mask = REGRWBITS_DSPBCNTR;
1425         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, 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, &regs, 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