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