take two
[profile/ivi/xorg-x11-drv-intel.git] / src / legacy / i810 / i810_hwmc.c
1 /***************************************************************************
2
3 Copyright 2000 Intel Corporation.  All Rights Reserved.
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sub license, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12
13 The above copyright notice and this permission notice (including the
14 next paragraph) shall be included in all copies or substantial portions
15 of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23 THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 **************************************************************************/
26
27 /*
28  * i810_hwmc.c: i810 HWMC Driver
29  *
30  * Authors:
31  *      Matt Sottek <matthew.j.sottek@intel.com>
32  *
33  *
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <string.h>
41
42 #include "xf86.h"
43 #include "xf86_OSproc.h"
44 #include "compiler.h"
45 #include "xf86Pci.h"
46 #include "xf86fbman.h"
47 #include "regionstr.h"
48
49 #include "i810.h"
50 #include "i810_dri.h"
51
52 #include "xf86xv.h"
53 #include "xf86xvmc.h"
54 #include <X11/extensions/Xv.h>
55 #include <X11/extensions/XvMC.h>
56 #include "dixstruct.h"
57 #include "fourcc.h"
58
59 int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
60                            int *num_priv, long **priv );
61 void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
62
63 int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
64                            int *num_priv, long **priv );
65 void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
66
67 int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
68                                int *num_priv, long **priv );
69 void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
70
71
72 typedef struct {
73   drm_context_t drmcontext;
74   unsigned int fbBase;
75   unsigned int OverlayOffset;
76   unsigned int OverlaySize;
77   unsigned int SurfacesOffset;
78   unsigned int SurfacesSize;
79   char busIdString[10];
80   char pad[2];
81 } I810XvMCCreateContextRec;
82
83
84 static int yv12_subpicture_index_list[2] = 
85 {
86   FOURCC_IA44,
87   FOURCC_AI44
88 };
89
90 static XF86MCImageIDList yv12_subpicture_list =
91 {
92   2,
93   yv12_subpicture_index_list
94 };
95  
96 static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface =
97 {
98     FOURCC_YV12,  
99     XVMC_CHROMA_FORMAT_420,
100     0,
101     720,
102     576,
103     720,
104     576,
105     XVMC_MPEG_2,
106     XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
107     XVMC_INTRA_UNSIGNED,
108     &yv12_subpicture_list
109 };
110
111 static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface =
112 {
113     FOURCC_YV12,  
114     XVMC_CHROMA_FORMAT_420,
115     0,
116     720,
117     576,
118     720,
119     576,
120     XVMC_MPEG_1,
121     XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
122     XVMC_INTRA_UNSIGNED,
123     &yv12_subpicture_list
124 };
125
126 static XF86MCSurfaceInfoPtr ppSI[2] = 
127 {
128     (XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface,
129     (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
130 };
131
132 /* List of subpicture types that we support */
133 static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
134 static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
135
136 static XF86ImagePtr i810_subpicture_list[2] =
137 {
138   (XF86ImagePtr)&ia44_subpicture,
139   (XF86ImagePtr)&ai44_subpicture
140 };
141
142 /* Fill in the device dependent adaptor record. 
143  * This is named "I810 Video Overlay" because this code falls under the
144  * XV extenstion, the name must match or it won't be used.
145  *
146  * Surface and Subpicture - see above
147  * Function pointers to functions below
148  */
149 static XF86MCAdaptorRec pAdapt = 
150 {
151   "I810 Video Overlay",         /* name */
152   2,                            /* num_surfaces */
153   ppSI,                         /* surfaces */
154   2,                            /* num_subpictures */
155   i810_subpicture_list,         /* subpictures */
156   (xf86XvMCCreateContextProcPtr)I810XvMCCreateContext,
157   (xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext,
158   (xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface,
159   (xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface,
160   (xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture,
161   (xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture
162 };
163
164 static XF86MCAdaptorPtr ppAdapt[1] = 
165 {
166         (XF86MCAdaptorPtr)&pAdapt
167 };
168
169 /**************************************************************************
170  *
171  *  I810InitMC
172  *
173  *  Initialize the hardware motion compenstation extention for this 
174  *  hardware. The initialization routines want the address of the pointers
175  *  to the structures, not the address of the structures. This means we
176  *  allocate (or create static?) the pointer memory and pass that 
177  *  address. This seems a little convoluted.
178  *
179  *  We need to allocate memory for the device depended adaptor record. 
180  *  This is what holds the pointers to all our device functions.
181  *
182  *  We need to map the overlay registers into the drm.
183  *
184  *  We need to map the surfaces into the drm.
185  *
186  *  Inputs:
187  *    Screen pointer
188  *
189  *  Outputs:
190  *    None, this calls the device independent screen initialization 
191  *    function.
192  *
193  *  Revisions:
194  *  
195  **************************************************************************/
196 void I810InitMC(ScreenPtr pScreen)
197 {
198   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
199   I810Ptr pI810 = I810PTR(pScrn);
200   int i;
201
202   /* Clear the Surface Allocation */
203   for(i=0; i<I810_MAX_SURFACES; i++) {
204         pI810->surfaceAllocation[i] = 0;
205   }  
206
207   /* Cursor is at a page boundary, Overlay regs are not, don't forget */
208   if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->CursorStart,
209                 4096, DRM_AGP, 0, (drmAddress) &pI810->overlay_map) < 0) {
210     xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
211     return;
212   }
213   if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->MC.Start,
214                 pI810->MC.Size, DRM_AGP, 0, (drmAddress) &pI810->mc_map) < 0) {
215     xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n");
216     return;
217   }
218   xf86XvMCScreenInit(pScreen, 1, ppAdapt);
219 }
220
221 /**************************************************************************
222  *
223  *  I810XvMCCreateContext
224  *
225  *  Some info about the private data:
226  *
227  *  Set *num_priv to the number of 32bit words that make up the size of
228  *  of the data that priv will point to.
229  *
230  *  *priv = (long *) calloc (elements, sizeof(element))
231  *  *num_priv = (elements * sizeof(element)) >> 2;
232  *
233  **************************************************************************/
234
235 int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
236                             int *num_priv, long **priv )
237 {
238   I810Ptr pI810 = I810PTR(pScrn);
239   DRIInfoPtr pDRIInfo = pI810->pDRIInfo;
240   I810XvMCCreateContextRec *contextRec;
241
242
243   if(!pI810->directRenderingEnabled) {
244     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
245         "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
246     return BadAlloc;
247   }
248
249   /* Context Already in use! */
250   if(pI810->xvmcContext) {
251     xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
252         "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
253     return BadAlloc;
254   }
255
256   *priv = calloc(1,sizeof(I810XvMCCreateContextRec));
257   contextRec = (I810XvMCCreateContextRec *)*priv;
258
259   if(!*priv) {
260     *num_priv = 0;
261     return BadAlloc;
262   }
263
264   *num_priv = sizeof(I810XvMCCreateContextRec) >> 2;
265   if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
266     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
267         "I810XvMCCreateContext: Unable to create DRMContext!\n");
268     free(*priv);
269     return BadAlloc;
270   }
271
272   drmAuthMagic(pI810->drmSubFD, pContext->flags);
273
274   pI810->xvmcContext = contextRec->drmcontext;
275   contextRec->fbBase = pScrn->memPhysBase;
276
277   /* Overlay Regs are at 1024 offset into the Cursor Space */
278   contextRec->OverlayOffset = pI810->CursorStart;
279   contextRec->OverlaySize = 4096;
280
281   contextRec->SurfacesOffset = pI810->MC.Start;
282   contextRec->SurfacesSize = pI810->MC.Size;
283   strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9);
284
285   return Success;
286 }
287
288
289 int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
290                            int *num_priv, long **priv )
291 {
292   I810Ptr pI810 = I810PTR(pScrn);
293   int i;
294
295   *priv = (long *)calloc(2,sizeof(long));
296
297   if(!*priv) {
298     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
299         "I810XvMCCreateSurface: Unable to allocate memory!\n");
300     *num_priv = 0;
301     return BadAlloc;
302   }
303   *num_priv = 2;
304
305   /* Surface Arrangement is different based on 6 or 7 Surfaces */
306   if(pI810->numSurfaces == 6) {
307      for(i=0; i<pI810->numSurfaces; i++) {
308        if(!pI810->surfaceAllocation[i]) {
309          pI810->surfaceAllocation[i] = pSurf->surface_id;
310          /* Y data starts at 2MB offset, each surface is 576k */
311          (*priv)[0] = (2*1024*1024 + 576*1024 * i);
312          /* UV data starts at 0 offset, each set is 288k */
313          (*priv)[1] = (576*512 * i);
314          return Success;
315        }
316      }
317   }
318   if(pI810->numSurfaces == 7) {
319      for(i=0; i<pI810->numSurfaces; i++) {
320        if(!pI810->surfaceAllocation[i]) {
321          pI810->surfaceAllocation[i] = pSurf->surface_id;
322          /* Y data starts at 2.5MB offset, each surface is 576k */
323          (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
324          /* UV data starts at 0 offset, each set is 288k */
325          (*priv)[1] = (576*512 * i);
326          return Success;
327        }
328      }
329   }
330   (*priv)[0] = 0;
331   (*priv)[1] = 0;
332   return BadAlloc;
333 }
334
335 int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
336                               int *num_priv, long **priv )
337 {
338   I810Ptr pI810 = I810PTR(pScrn);
339   int i;
340
341   *priv = (long *)calloc(1,sizeof(long));
342
343   if(!*priv) {
344     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
345         "I810XvMCCreateSubpicture: Unable to allocate memory!\n");
346     *num_priv = 0;
347     return BadAlloc;
348   }
349   *num_priv = 1;
350
351   if(pI810->numSurfaces == 6) {
352      for(i=6; i<8; i++) {
353        if(!pI810->surfaceAllocation[i]) {
354          pI810->surfaceAllocation[i] = pSubp->subpicture_id;
355          /* Subpictures are after the Y surfaces in memory */ 
356          (*priv)[0] = (2*1024*1024 + 576*1024 * i);
357          return Success;
358        }
359      }
360   }
361   if(pI810->numSurfaces == 7) {
362      for(i=7; i<9; i++) {
363          if(!pI810->surfaceAllocation[i]) {
364          pI810->surfaceAllocation[i] = pSubp->subpicture_id;
365          /* Subpictures are after the Y surfaces in memory */
366          (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
367          return Success;
368        }
369      }
370   }
371
372   (*priv)[0] = 0;
373   return BadAlloc;
374 }
375
376 void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
377 {
378   I810Ptr pI810 = I810PTR(pScrn);
379
380   drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext);
381   pI810->xvmcContext = 0;
382 }
383
384 void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
385 {
386   I810Ptr pI810 = I810PTR(pScrn);
387   int i;
388
389   for(i=0; i<I810_MAX_SURFACES; i++) {
390     if(pI810->surfaceAllocation[i] == pSurf->surface_id) {
391       pI810->surfaceAllocation[i] = 0;
392       return;
393     }
394   }
395   return;
396 }
397
398 void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
399 {
400   I810Ptr pI810 = I810PTR(pScrn);
401   int i;
402
403   for(i=pI810->numSurfaces; i<I810_MAX_SURFACES + I810_MAX_SUBPICTURES; i++) {
404     if(pI810->surfaceAllocation[i] == pSubp->subpicture_id) {
405       pI810->surfaceAllocation[i] = 0;
406       return;
407     }
408   }
409   return;
410 }
411
412
413
414
415
416