nvbios: Add some valid register ranges for nv50.
[nouveau] / src / nv10_video_overlay.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           xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
39                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, int offset, int uvoffset, int id,
64                   int dstPitch, BoxPtr dstBox,
65                   int x1, int y1, int x2, int y2,
66                   short width, short height,
67                   short src_w, short src_h,
68                   short drw_w, short drw_h,
69                   RegionPtr clipBoxes)
70 {
71         NVPtr         pNv    = NVPTR(pScrn);
72         NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
73         int           buffer = pPriv->currentBuffer;
74
75         if (!pNv->randr12_enable) {
76                 if (pScrn->currentMode->Flags & V_DBLSCAN) {
77                         dstBox->y1 <<= 1;
78                         dstBox->y2 <<= 1;
79                         drw_h <<= 1;
80                 }
81         } else {
82                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
83                 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC];
84                 if (crtc->mode.Flags & V_DBLSCAN) {
85                         dstBox->y1 <<= 1;
86                         dstBox->y2 <<= 1;
87                         drw_h <<= 1;
88                 }
89         }
90
91         /* paint the color key */
92         if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
93                 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
94                 /* we always paint V4L's color key */
95                 if (!pPriv->grabbedByV4L)
96                         REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
97                 {
98                 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
99                 }
100         }
101
102         //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 >>
103         //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));
104
105         nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer)     , 0);
106         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer)     , offset);
107         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer)  , (height << 16) | width);
108         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
109                           ((y1 << 4) & 0xffff0000) | (x1 >> 12));
110         nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer)    , (src_w << 20) / drw_w);
111         nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer)    , (src_h << 20) / drw_h);
112         nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
113                           (dstBox->y1 << 16) | dstBox->x1);
114         nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
115                           ((dstBox->y2 - dstBox->y1) << 16) |
116                            (dstBox->x2 - dstBox->x1));
117
118         dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;   /* use color key */
119         if(id != FOURCC_UYVY)
120                 dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
121         if(pPriv->iturbt_709)
122                 dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
123
124         if( id == FOURCC_YV12 || id == FOURCC_I420 )
125                 dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
126
127         /* Those are important only for planar formats (NV12) */
128         if ( uvoffset )
129                 {
130                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
131                 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer), uvoffset);
132                 }
133
134         nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
135         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
136         nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 :  0x1);
137
138         pPriv->videoStatus = CLIENT_VIDEO_ON;
139 }
140
141 /**
142  * NV10SetOverlayPortAttribute
143  * sets the attribute "attribute" of port "data" to value "value"
144  * calls NVResetVideo(pScrn) to apply changes to hardware
145  * 
146  * @param pScrenInfo
147  * @param attribute attribute to set
148  * @param value value to which attribute is to be set
149  * @param data port from which the attribute is to be set
150  * 
151  * @return Success, if setting is successful
152  * BadValue/BadMatch, if value/attribute are invalid
153  * @see NVResetVideo(ScrnInfoPtr pScrn)
154  */
155 int
156 NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
157                           INT32 value, pointer data)
158 {
159         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
160         NVPtr         pNv   = NVPTR(pScrn);
161
162         if (attribute == xvBrightness) {
163                 if ((value < -512) || (value > 512))
164                         return BadValue;
165                 pPriv->brightness = value;
166         } else
167         if (attribute == xvDoubleBuffer) {
168                 if ((value < 0) || (value > 1))
169                         return BadValue;
170                 pPriv->doubleBuffer = value;
171         } else
172         if (attribute == xvContrast) {
173                 if ((value < 0) || (value > 8191))
174                         return BadValue;
175                 pPriv->contrast = value;
176         } else
177         if (attribute == xvHue) {
178                 value %= 360;
179                 if (value < 0)
180                         value += 360;
181                 pPriv->hue = value;
182         } else
183         if (attribute == xvSaturation) {
184                 if ((value < 0) || (value > 8191))
185                         return BadValue;
186                 pPriv->saturation = value;
187         } else
188         if (attribute == xvColorKey) {
189                 pPriv->colorKey = value;
190                 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
191         } else
192         if (attribute == xvAutopaintColorKey) {
193                 if ((value < 0) || (value > 1))
194                         return BadValue;
195                 pPriv->autopaintColorKey = value;
196         } else
197         if (attribute == xvITURBT709) {
198                 if ((value < 0) || (value > 1))
199                         return BadValue;
200                 pPriv->iturbt_709 = value;
201         } else
202         if (attribute == xvSetDefaults) {
203                 NVSetPortDefaults(pScrn, pPriv);
204         } else
205         if ( attribute == xvOnCRTCNb) {
206                 if ((value < 0) || (value > 1))
207                         return BadValue;
208                 pPriv->overlayCRTC = value;
209                 NVWriteCRTC(pNv, value, NV_CRTC_FSEL, NVReadCRTC(pNv, value, NV_CRTC_FSEL) | NV_CRTC_FSEL_OVERLAY);
210                 NVWriteCRTC(pNv, !value, NV_CRTC_FSEL, NVReadCRTC(pNv, !value, NV_CRTC_FSEL) & ~NV_CRTC_FSEL_OVERLAY);
211         } else
212                 return BadMatch;
213
214         NV10WriteOverlayParameters(pScrn);
215
216         return Success;
217 }
218
219 /**
220  * NV10GetOverlayPortAttribute
221  * 
222  * @param pScrn unused
223  * @param attribute attribute to be read
224  * @param value value of attribute will be stored in this pointer
225  * @param data port from which attribute will be read
226  * @return Success, if queried attribute exists
227  */
228 int
229 NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
230                           INT32 *value, pointer data)
231 {
232         NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
233
234         if (attribute == xvBrightness)
235                 *value = pPriv->brightness;
236         else if (attribute == xvDoubleBuffer)
237                 *value = (pPriv->doubleBuffer) ? 1 : 0;
238         else if (attribute == xvContrast)
239                 *value = pPriv->contrast;
240         else if (attribute == xvSaturation)
241                 *value = pPriv->saturation;
242         else if (attribute == xvHue)
243                 *value = pPriv->hue;
244         else if (attribute == xvColorKey)
245                 *value = pPriv->colorKey;
246         else if (attribute == xvAutopaintColorKey)
247                 *value = (pPriv->autopaintColorKey) ? 1 : 0;
248         else if (attribute == xvITURBT709)
249                 *value = (pPriv->iturbt_709) ? 1 : 0;
250         else if (attribute == xvOnCRTCNb)
251                 *value = (pPriv->overlayCRTC) ? 1 : 0;
252         else
253                 return BadMatch;
254
255         return Success;
256 }
257
258 /**
259  * NV10StopOverlay
260  * Tell the hardware to stop the overlay
261  */
262 void
263 NV10StopOverlay (ScrnInfoPtr pScrn)
264 {
265     NVPtr pNv = NVPTR(pScrn);
266     nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
267 }
268
269 /** 
270  * NV10WriteOverlayParameters
271  * Tell the hardware about parameters that are too expensive to be set
272  * on every frame
273  */
274 void
275 NV10WriteOverlayParameters (ScrnInfoPtr pScrn)
276 {
277     NVPtr          pNv     = NVPTR(pScrn);
278     NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
279     int            satSine, satCosine;
280     double         angle;
281
282     angle = (double)pPriv->hue * 3.1415927 / 180.0;
283
284     satSine = pPriv->saturation * sin(angle);
285     if (satSine < -1024)
286         satSine = -1024;
287     satCosine = pPriv->saturation * cos(angle);
288     if (satCosine < -1024)
289         satCosine = -1024;
290
291     nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
292             pPriv->contrast);
293     nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
294             pPriv->contrast);
295     nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
296             (satCosine & 0xffff));
297     nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
298             (satCosine & 0xffff));
299     nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
300
301 }
302