1 /***************************************************************************
3 Copyright 2000 Intel Corporation. All Rights Reserved.
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:
13 The above copyright notice and this permission notice (including the
14 next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
28 * i810_hwmc.c: i810 HWMC Driver
31 * Matt Sottek <matthew.j.sottek@intel.com>
43 #include "xf86_OSproc.h"
46 #include "xf86fbman.h"
47 #include "regionstr.h"
54 #include <X11/extensions/Xv.h>
55 #include <X11/extensions/XvMC.h>
56 #include "dixstruct.h"
59 int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
60 int *num_priv, long **priv );
61 void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
63 int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
64 int *num_priv, long **priv );
65 void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
67 int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
68 int *num_priv, long **priv );
69 void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
73 drm_context_t drmcontext;
75 unsigned int OverlayOffset;
76 unsigned int OverlaySize;
77 unsigned int SurfacesOffset;
78 unsigned int SurfacesSize;
81 } I810XvMCCreateContextRec;
84 static int yv12_subpicture_index_list[2] =
90 static XF86MCImageIDList yv12_subpicture_list =
93 yv12_subpicture_index_list
96 static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface =
99 XVMC_CHROMA_FORMAT_420,
106 XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
108 &yv12_subpicture_list
111 static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface =
114 XVMC_CHROMA_FORMAT_420,
121 XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
123 &yv12_subpicture_list
126 static XF86MCSurfaceInfoPtr ppSI[2] =
128 (XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface,
129 (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
132 /* List of subpicture types that we support */
133 static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
134 static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
136 static XF86ImagePtr i810_subpicture_list[2] =
138 (XF86ImagePtr)&ia44_subpicture,
139 (XF86ImagePtr)&ai44_subpicture
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.
146 * Surface and Subpicture - see above
147 * Function pointers to functions below
149 static XF86MCAdaptorRec pAdapt =
151 "I810 Video Overlay", /* name */
152 2, /* num_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
164 static XF86MCAdaptorPtr ppAdapt[1] =
166 (XF86MCAdaptorPtr)&pAdapt
169 /**************************************************************************
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.
179 * We need to allocate memory for the device depended adaptor record.
180 * This is what holds the pointers to all our device functions.
182 * We need to map the overlay registers into the drm.
184 * We need to map the surfaces into the drm.
190 * None, this calls the device independent screen initialization
195 **************************************************************************/
196 void I810InitMC(ScreenPtr pScreen)
198 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
199 I810Ptr pI810 = I810PTR(pScrn);
202 /* Clear the Surface Allocation */
203 for(i=0; i<I810_MAX_SURFACES; i++) {
204 pI810->surfaceAllocation[i] = 0;
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");
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");
218 xf86XvMCScreenInit(pScreen, 1, ppAdapt);
221 /**************************************************************************
223 * I810XvMCCreateContext
225 * Some info about the private data:
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.
230 * *priv = (long *) calloc (elements, sizeof(element))
231 * *num_priv = (elements * sizeof(element)) >> 2;
233 **************************************************************************/
235 int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
236 int *num_priv, long **priv )
238 I810Ptr pI810 = I810PTR(pScrn);
239 DRIInfoPtr pDRIInfo = pI810->pDRIInfo;
240 I810XvMCCreateContextRec *contextRec;
243 if(!pI810->directRenderingEnabled) {
244 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
245 "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
249 /* Context Already in use! */
250 if(pI810->xvmcContext) {
251 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
252 "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
256 *priv = calloc(1,sizeof(I810XvMCCreateContextRec));
257 contextRec = (I810XvMCCreateContextRec *)*priv;
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");
272 drmAuthMagic(pI810->drmSubFD, pContext->flags);
274 pI810->xvmcContext = contextRec->drmcontext;
275 contextRec->fbBase = pScrn->memPhysBase;
277 /* Overlay Regs are at 1024 offset into the Cursor Space */
278 contextRec->OverlayOffset = pI810->CursorStart;
279 contextRec->OverlaySize = 4096;
281 contextRec->SurfacesOffset = pI810->MC.Start;
282 contextRec->SurfacesSize = pI810->MC.Size;
283 strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9);
289 int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
290 int *num_priv, long **priv )
292 I810Ptr pI810 = I810PTR(pScrn);
295 *priv = (long *)calloc(2,sizeof(long));
298 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
299 "I810XvMCCreateSurface: Unable to allocate memory!\n");
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);
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);
335 int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
336 int *num_priv, long **priv )
338 I810Ptr pI810 = I810PTR(pScrn);
341 *priv = (long *)calloc(1,sizeof(long));
344 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
345 "I810XvMCCreateSubpicture: Unable to allocate memory!\n");
351 if(pI810->numSurfaces == 6) {
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);
361 if(pI810->numSurfaces == 7) {
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);
376 void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
378 I810Ptr pI810 = I810PTR(pScrn);
380 drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext);
381 pI810->xvmcContext = 0;
384 void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
386 I810Ptr pI810 = I810PTR(pScrn);
389 for(i=0; i<I810_MAX_SURFACES; i++) {
390 if(pI810->surfaceAllocation[i] == pSurf->surface_id) {
391 pI810->surfaceAllocation[i] = 0;
398 void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
400 I810Ptr pI810 = I810PTR(pScrn);
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;