nv50: use bios provided load detect value
[nouveau] / src / nv10_xv_ovl.c
1 /*
2  * Copyright 2007 Arthur Huillet
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "xf86xv.h"
28 #include <X11/extensions/Xv.h>
29 #include "exa.h"
30 #include "damage.h"
31 #include "dixstruct.h"
32 #include "fourcc.h"
33
34 #include "nv_include.h"
35 #include "nv_dma.h"
36
37 extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
38 extern Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
39 extern Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
40
41 /**
42  * NV10PutOverlayImage
43  * program hardware to overlay image into front buffer
44  * 
45  * @param pScrn screen
46  * @param offset card offset to the pixel data
47  * @param id format of image
48  * @param dstPitch pitch of the pixel data in VRAM
49  * @param dstBox destination box
50  * @param x1 first source point - x
51  * @param y1 first source point - y
52  * @param x2 second source point - x
53  * @param y2 second source point - y
54  * @param width width of the source image = x2 - x1
55  * @param height height
56  * @param src_w width of the image data in VRAM
57  * @param src_h height
58  * @param drw_w width of the image to draw to screen
59  * @param drw_h height
60  * @param clipBoxes ???
61  */
62 void
63 NV10PutOverlayImage(ScrnInfoPtr pScrn,
64                     struct nouveau_bo *src, int offset, int uvoffset, int id,
65                     int dstPitch, BoxPtr dstBox, int x1, int y1, int x2, int y2,
66                     short width, short height, short src_w, short src_h,
67                     short drw_w, short drw_h, RegionPtr clipBoxes)
68 {
69         NVPtr         pNv    = NVPTR(pScrn);
70         NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
71         int           buffer = pPriv->currentBuffer;
72
73         if (!pNv->randr12_enable) {
74                 if (pScrn->currentMode->Flags & V_DBLSCAN) {
75                         dstBox->y1 <<= 1;
76                         dstBox->y2 <<= 1;
77                         drw_h <<= 1;
78                 }
79         } else {
80                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
81                 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC];
82                 if (crtc->mode.Flags & V_DBLSCAN) {
83                         dstBox->y1 <<= 1;
84                         dstBox->y2 <<= 1;
85                         drw_h <<= 1;
86                 }
87         }
88
89         /* paint the color key */
90         if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
91                 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
92                 /* we always paint V4L's color key */
93                 if (!pPriv->grabbedByV4L)
94                         REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
95                 {
96                 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
97                 }
98         }
99
100         //xf86DrvMsg(0, X_INFO, "SIZE_IN h %d w %d, POINT_IN x %d y %d, DS_DX %d DT_DY %d, POINT_OUT x %d y %d SIZE_OUT h %d w %d\n", height, width, x1 >>
101         //16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h,  (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1));
102
103         nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer)     , 0);
104         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer),
105                           src->offset + offset);
106         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer)  , (height << 16) | width);
107         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
108                           ((y1 << 4) & 0xffff0000) | (x1 >> 12));
109         nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer)    , (src_w << 20) / drw_w);
110         nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer)    , (src_h << 20) / drw_h);
111         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
112                           (dstBox->y1 << 16) | dstBox->x1);
113         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
114                           ((dstBox->y2 - dstBox->y1) << 16) |
115                            (dstBox->x2 - dstBox->x1));
116
117         dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;   /* use color key */
118         if(id != FOURCC_UYVY)
119                 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
120         if(pPriv->iturbt_709)
121                 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
122
123         if( id == FOURCC_YV12 || id == FOURCC_I420 )
124                 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
125
126         /* Those are important only for planar formats (NV12) */
127         if (uvoffset) {
128                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
129                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer),
130                                   src->offset + uvoffset);
131         }
132
133         nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
134         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
135         nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 :  0x1);
136
137         pPriv->videoStatus = CLIENT_VIDEO_ON;
138 }
139
140 /**
141  * NV10SetOverlayPortAttribute
142  * sets the attribute "attribute" of port "data" to value "value"
143  * calls NVResetVideo(pScrn) to apply changes to hardware
144  * 
145  * @param pScrenInfo
146  * @param attribute attribute to set
147  * @param value value to which attribute is to be set
148  * @param data port from which the attribute is to be set
149  * 
150  * @return Success, if setting is successful
151  * BadValue/BadMatch, if value/attribute are invalid
152  * @see NVResetVideo(ScrnInfoPtr pScrn)
153  */
154 int
155 NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
156                           INT32 value, pointer data)
157 {
158         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
159         NVPtr         pNv   = NVPTR(pScrn);
160
161         if (attribute == xvBrightness) {
162                 if ((value < -512) || (value > 512))
163                         return BadValue;
164                 pPriv->brightness = value;
165         } else
166         if (attribute == xvDoubleBuffer) {
167                 if ((value < 0) || (value > 1))
168                         return BadValue;
169                 pPriv->doubleBuffer = value;
170         } else
171         if (attribute == xvContrast) {
172                 if ((value < 0) || (value > 8191))
173                         return BadValue;
174                 pPriv->contrast = value;
175         } else
176         if (attribute == xvHue) {
177                 value %= 360;
178                 if (value < 0)
179                         value += 360;
180                 pPriv->hue = value;
181         } else
182         if (attribute == xvSaturation) {
183                 if ((value < 0) || (value > 8191))
184                         return BadValue;
185                 pPriv->saturation = value;
186         } else
187         if (attribute == xvColorKey) {
188                 pPriv->colorKey = value;
189                 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
190         } else
191         if (attribute == xvAutopaintColorKey) {
192                 if ((value < 0) || (value > 1))
193                         return BadValue;
194                 pPriv->autopaintColorKey = value;
195         } else
196         if (attribute == xvITURBT709) {
197                 if ((value < 0) || (value > 1))
198                         return BadValue;
199                 pPriv->iturbt_709 = value;
200         } else
201         if (attribute == xvSetDefaults) {
202                 NVSetPortDefaults(pScrn, pPriv);
203         } else
204         if ( attribute == xvOnCRTCNb) {
205                 if ((value < 0) || (value > 1))
206                         return BadValue;
207                 pPriv->overlayCRTC = value;
208                 NVWriteCRTC(pNv, value, NV_CRTC_FSEL, NVReadCRTC(pNv, value, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
209                 NVWriteCRTC(pNv, !value, NV_CRTC_FSEL, NVReadCRTC(pNv, !value, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
210         } else
211                 return BadMatch;
212
213         NV10WriteOverlayParameters(pScrn);
214
215         return Success;
216 }
217
218 /**
219  * NV10GetOverlayPortAttribute
220  * 
221  * @param pScrn unused
222  * @param attribute attribute to be read
223  * @param value value of attribute will be stored in this pointer
224  * @param data port from which attribute will be read
225  * @return Success, if queried attribute exists
226  */
227 int
228 NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
229                           INT32 *value, pointer data)
230 {
231         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
232
233         if (attribute == xvBrightness)
234                 *value = pPriv->brightness;
235         else if (attribute == xvDoubleBuffer)
236                 *value = (pPriv->doubleBuffer) ? 1 : 0;
237         else if (attribute == xvContrast)
238                 *value = pPriv->contrast;
239         else if (attribute == xvSaturation)
240                 *value = pPriv->saturation;
241         else if (attribute == xvHue)
242                 *value = pPriv->hue;
243         else if (attribute == xvColorKey)
244                 *value = pPriv->colorKey;
245         else if (attribute == xvAutopaintColorKey)
246                 *value = (pPriv->autopaintColorKey) ? 1 : 0;
247         else if (attribute == xvITURBT709)
248                 *value = (pPriv->iturbt_709) ? 1 : 0;
249         else if (attribute == xvOnCRTCNb)
250                 *value = (pPriv->overlayCRTC) ? 1 : 0;
251         else
252                 return BadMatch;
253
254         return Success;
255 }
256
257 /**
258  * NV10StopOverlay
259  * Tell the hardware to stop the overlay
260  */
261 void
262 NV10StopOverlay (ScrnInfoPtr pScrn)
263 {
264     NVPtr pNv = NVPTR(pScrn);
265     nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
266 }
267
268 /** 
269  * NV10WriteOverlayParameters
270  * Tell the hardware about parameters that are too expensive to be set
271  * on every frame
272  */
273 void
274 NV10WriteOverlayParameters (ScrnInfoPtr pScrn)
275 {
276     NVPtr          pNv     = NVPTR(pScrn);
277     NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
278     int            satSine, satCosine;
279     double         angle;
280
281     angle = (double)pPriv->hue * 3.1415927 / 180.0;
282
283     satSine = pPriv->saturation * sin(angle);
284     if (satSine < -1024)
285         satSine = -1024;
286     satCosine = pPriv->saturation * cos(angle);
287     if (satCosine < -1024)
288         satCosine = -1024;
289
290     nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
291             pPriv->contrast);
292     nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
293             pPriv->contrast);
294     nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
295             (satCosine & 0xffff));
296     nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
297             (satCosine & 0xffff));
298     nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
299
300 }
301