r128_video.c revision 0496e070
1c582b7e3Smrg 2c582b7e3Smrg#ifdef HAVE_CONFIG_H 3c582b7e3Smrg#include "config.h" 4c582b7e3Smrg#endif 5c582b7e3Smrg 6c582b7e3Smrg#include <string.h> 7c582b7e3Smrg 8c582b7e3Smrg#include "r128.h" 9c582b7e3Smrg#include "r128_reg.h" 10c582b7e3Smrg 1142a55b46Smrg#ifdef R128DRI 12c582b7e3Smrg#include "r128_common.h" 13c582b7e3Smrg#include "r128_sarea.h" 14c582b7e3Smrg#endif 15c582b7e3Smrg 16c582b7e3Smrg#include "xf86.h" 17c582b7e3Smrg#include "dixstruct.h" 18c582b7e3Smrg 19c582b7e3Smrg#include <X11/extensions/Xv.h> 20c582b7e3Smrg#include "fourcc.h" 21c582b7e3Smrg 22c582b7e3Smrg#define OFF_DELAY 250 /* milliseconds */ 23c582b7e3Smrg#define FREE_DELAY 15000 24c582b7e3Smrg 25c582b7e3Smrg#define OFF_TIMER 0x01 26c582b7e3Smrg#define FREE_TIMER 0x02 27c582b7e3Smrg#define CLIENT_VIDEO_ON 0x04 28c582b7e3Smrg 29c582b7e3Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 30c582b7e3Smrg 31c582b7e3Smrgstatic XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr); 32c582b7e3Smrgstatic int R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 33c582b7e3Smrgstatic int R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 34c582b7e3Smrgstatic void R128StopVideo(ScrnInfoPtr, pointer, Bool); 35c582b7e3Smrgstatic void R128QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, 36c582b7e3Smrg unsigned int *, unsigned int *, pointer); 37c582b7e3Smrgstatic int R128PutImage(ScrnInfoPtr, short, short, short, short, short, 38c582b7e3Smrg short, short, short, int, unsigned char*, short, 39c582b7e3Smrg short, Bool, RegionPtr, pointer, DrawablePtr); 40c582b7e3Smrgstatic int R128QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 41c582b7e3Smrg unsigned short *, int *, int *); 42c582b7e3Smrg 43c582b7e3Smrg 44c582b7e3Smrgstatic void R128ResetVideo(ScrnInfoPtr); 45c582b7e3Smrg 46c582b7e3Smrgstatic void R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now); 47c582b7e3Smrg 48c582b7e3Smrg 49c582b7e3Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 50c582b7e3Smrg 51c582b7e3Smrgstatic Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; 52c582b7e3Smrg 53c582b7e3Smrg 54c582b7e3Smrgtypedef struct { 55c582b7e3Smrg int brightness; 56c582b7e3Smrg int saturation; 57c582b7e3Smrg Bool doubleBuffer; 58c582b7e3Smrg unsigned char currentBuffer; 5942a55b46Smrg void* BufferHandle; 6042a55b46Smrg int videoOffset; 61c582b7e3Smrg RegionRec clip; 62c582b7e3Smrg CARD32 colorKey; 63c582b7e3Smrg CARD32 videoStatus; 64c582b7e3Smrg Time offTime; 65c582b7e3Smrg Time freeTime; 66c582b7e3Smrg int ecp_div; 67c582b7e3Smrg} R128PortPrivRec, *R128PortPrivPtr; 68c582b7e3Smrg 69c582b7e3Smrgstatic void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv) 70c582b7e3Smrg{ 71c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 72c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 73c582b7e3Smrg int dot_clock = info->ModeReg.dot_clock_freq; 74c582b7e3Smrg 75c582b7e3Smrg if (dot_clock < 12500) pPriv->ecp_div = 0; 76c582b7e3Smrg else if (dot_clock < 25000) pPriv->ecp_div = 1; 77c582b7e3Smrg else pPriv->ecp_div = 2; 78c582b7e3Smrg 79c582b7e3Smrg OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, pPriv->ecp_div<<8, ~R128_ECP_DIV_MASK); 80c582b7e3Smrg} 81c582b7e3Smrg 82c582b7e3Smrgvoid R128InitVideo(ScreenPtr pScreen) 83c582b7e3Smrg{ 8442a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 85c582b7e3Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 86c582b7e3Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 87c582b7e3Smrg int num_adaptors; 88c582b7e3Smrg 89c582b7e3Smrg newAdaptor = R128SetupImageVideo(pScreen); 90c582b7e3Smrg 91c582b7e3Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 92c582b7e3Smrg 93c582b7e3Smrg if(newAdaptor) { 94c582b7e3Smrg if(!num_adaptors) { 95c582b7e3Smrg num_adaptors = 1; 96c582b7e3Smrg adaptors = &newAdaptor; 97c582b7e3Smrg } else { 98c582b7e3Smrg newAdaptors = /* need to free this someplace */ 9942a55b46Smrg malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 100c582b7e3Smrg if(newAdaptors) { 101c582b7e3Smrg memcpy(newAdaptors, adaptors, num_adaptors * 102c582b7e3Smrg sizeof(XF86VideoAdaptorPtr)); 103c582b7e3Smrg newAdaptors[num_adaptors] = newAdaptor; 104c582b7e3Smrg adaptors = newAdaptors; 105c582b7e3Smrg num_adaptors++; 106c582b7e3Smrg } 107c582b7e3Smrg } 108c582b7e3Smrg } 109c582b7e3Smrg 110c582b7e3Smrg if(num_adaptors) 111c582b7e3Smrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 112c582b7e3Smrg 113c582b7e3Smrg if(newAdaptors) 11442a55b46Smrg free(newAdaptors); 115c582b7e3Smrg} 116c582b7e3Smrg 117c582b7e3Smrg#define MAXWIDTH 2048 118c582b7e3Smrg#define MAXHEIGHT 2048 119c582b7e3Smrg 120c582b7e3Smrg/* client libraries expect an encoding */ 121c582b7e3Smrgstatic XF86VideoEncodingRec DummyEncoding = 122c582b7e3Smrg{ 123c582b7e3Smrg 0, 124c582b7e3Smrg "XV_IMAGE", 125c582b7e3Smrg MAXWIDTH, MAXHEIGHT, 126c582b7e3Smrg {1, 1} 127c582b7e3Smrg}; 128c582b7e3Smrg 129c582b7e3Smrg#define NUM_FORMATS 12 130c582b7e3Smrg 131c582b7e3Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = 132c582b7e3Smrg{ 133c582b7e3Smrg {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, 134c582b7e3Smrg {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, 135c582b7e3Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 136c582b7e3Smrg {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 137c582b7e3Smrg}; 138c582b7e3Smrg 139c582b7e3Smrg 140c582b7e3Smrg#define NUM_ATTRIBUTES 4 141c582b7e3Smrg 142c582b7e3Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 143c582b7e3Smrg{ 144c582b7e3Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 145c582b7e3Smrg {XvSettable | XvGettable, -64, 63, "XV_BRIGHTNESS"}, 146c582b7e3Smrg {XvSettable | XvGettable, 0, 31, "XV_SATURATION"}, 147c582b7e3Smrg {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} 148c582b7e3Smrg}; 149c582b7e3Smrg 150c582b7e3Smrg#define NUM_IMAGES 4 151c582b7e3Smrg 152c582b7e3Smrgstatic XF86ImageRec Images[NUM_IMAGES] = 153c582b7e3Smrg{ 154c582b7e3Smrg XVIMAGE_YUY2, 155c582b7e3Smrg XVIMAGE_UYVY, 156c582b7e3Smrg XVIMAGE_YV12, 157c582b7e3Smrg XVIMAGE_I420 158c582b7e3Smrg}; 159c582b7e3Smrg 160c582b7e3Smrgstatic void 161c582b7e3SmrgR128ResetVideo(ScrnInfoPtr pScrn) 162c582b7e3Smrg{ 163c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 164c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 165c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 166c582b7e3Smrg 167c582b7e3Smrg 168c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x80000000); 169c582b7e3Smrg OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0); 170c582b7e3Smrg OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ 171c582b7e3Smrg OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f); 172c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 173c582b7e3Smrg (pPriv->saturation << 8) | 174c582b7e3Smrg (pPriv->saturation << 16)); 175c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_MSK, (1 << pScrn->depth) - 1); 176c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); 177c582b7e3Smrg OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE); 178c582b7e3Smrg OUTREG(R128_OV0_TEST, 0); 179c582b7e3Smrg} 180c582b7e3Smrg 181c582b7e3Smrg 182c582b7e3Smrgstatic XF86VideoAdaptorPtr 183c582b7e3SmrgR128AllocAdaptor(ScrnInfoPtr pScrn) 184c582b7e3Smrg{ 185c582b7e3Smrg XF86VideoAdaptorPtr adapt; 186c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 187c582b7e3Smrg R128PortPrivPtr pPriv; 188c582b7e3Smrg 189c582b7e3Smrg if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 190c582b7e3Smrg return NULL; 191c582b7e3Smrg 19242a55b46Smrg if(!(pPriv = calloc(1, sizeof(R128PortPrivRec) + sizeof(DevUnion)))) 193c582b7e3Smrg { 19442a55b46Smrg free(adapt); 195c582b7e3Smrg return NULL; 196c582b7e3Smrg } 197c582b7e3Smrg 198c582b7e3Smrg adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 199c582b7e3Smrg adapt->pPortPrivates[0].ptr = (pointer)pPriv; 200c582b7e3Smrg 201c582b7e3Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 202c582b7e3Smrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 203c582b7e3Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 204c582b7e3Smrg xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 205c582b7e3Smrg 206c582b7e3Smrg pPriv->colorKey = info->videoKey; 207c582b7e3Smrg pPriv->doubleBuffer = TRUE; 208c582b7e3Smrg pPriv->videoStatus = 0; 209c582b7e3Smrg pPriv->brightness = 0; 210c582b7e3Smrg pPriv->saturation = 16; 211c582b7e3Smrg pPriv->currentBuffer = 0; 212c582b7e3Smrg R128ECP(pScrn, pPriv); 213c582b7e3Smrg 214c582b7e3Smrg return adapt; 215c582b7e3Smrg} 216c582b7e3Smrg 217c582b7e3Smrgstatic XF86VideoAdaptorPtr 218c582b7e3SmrgR128SetupImageVideo(ScreenPtr pScreen) 219c582b7e3Smrg{ 22042a55b46Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 221c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 222c582b7e3Smrg R128PortPrivPtr pPriv; 223c582b7e3Smrg XF86VideoAdaptorPtr adapt; 224c582b7e3Smrg 225c582b7e3Smrg if(!(adapt = R128AllocAdaptor(pScrn))) 226c582b7e3Smrg return NULL; 227c582b7e3Smrg 228c582b7e3Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 229c582b7e3Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 230c582b7e3Smrg adapt->name = "ATI Rage128 Video Overlay"; 231c582b7e3Smrg adapt->nEncodings = 1; 232c582b7e3Smrg adapt->pEncodings = &DummyEncoding; 233c582b7e3Smrg adapt->nFormats = NUM_FORMATS; 234c582b7e3Smrg adapt->pFormats = Formats; 235c582b7e3Smrg adapt->nPorts = 1; 236c582b7e3Smrg adapt->nAttributes = NUM_ATTRIBUTES; 237c582b7e3Smrg adapt->pAttributes = Attributes; 238c582b7e3Smrg adapt->nImages = NUM_IMAGES; 239c582b7e3Smrg adapt->pImages = Images; 240c582b7e3Smrg adapt->PutVideo = NULL; 241c582b7e3Smrg adapt->PutStill = NULL; 242c582b7e3Smrg adapt->GetVideo = NULL; 243c582b7e3Smrg adapt->GetStill = NULL; 244c582b7e3Smrg adapt->StopVideo = R128StopVideo; 245c582b7e3Smrg adapt->SetPortAttribute = R128SetPortAttribute; 246c582b7e3Smrg adapt->GetPortAttribute = R128GetPortAttribute; 247c582b7e3Smrg adapt->QueryBestSize = R128QueryBestSize; 248c582b7e3Smrg adapt->PutImage = R128PutImage; 249c582b7e3Smrg adapt->QueryImageAttributes = R128QueryImageAttributes; 250c582b7e3Smrg 251c582b7e3Smrg info->adaptor = adapt; 252c582b7e3Smrg 253c582b7e3Smrg pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr); 254c582b7e3Smrg REGION_NULL(pScreen, &(pPriv->clip)); 255c582b7e3Smrg 256c582b7e3Smrg R128ResetVideo(pScrn); 257c582b7e3Smrg 258c582b7e3Smrg return adapt; 259c582b7e3Smrg} 260c582b7e3Smrg 261c582b7e3Smrgstatic void 262c582b7e3SmrgR128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 263c582b7e3Smrg{ 264c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 265c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 266c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 267c582b7e3Smrg 268c582b7e3Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 269c582b7e3Smrg 270c582b7e3Smrg if(cleanup) { 271c582b7e3Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 272c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0); 273c582b7e3Smrg } 27442a55b46Smrg if(pPriv->BufferHandle) { 27542a55b46Smrg if (!info->useEXA) { 27642a55b46Smrg xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle); 27742a55b46Smrg } 27842a55b46Smrg#ifdef USE_EXA 27942a55b46Smrg else { 28042a55b46Smrg exaOffscreenFree(pScrn->pScreen, (ExaOffscreenArea *) pPriv->BufferHandle); 28142a55b46Smrg } 28242a55b46Smrg#endif 28342a55b46Smrg pPriv->BufferHandle = NULL; 284c582b7e3Smrg } 285c582b7e3Smrg pPriv->videoStatus = 0; 286c582b7e3Smrg } else { 287c582b7e3Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 288c582b7e3Smrg pPriv->videoStatus |= OFF_TIMER; 289c582b7e3Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 290c582b7e3Smrg } 291c582b7e3Smrg } 292c582b7e3Smrg} 293c582b7e3Smrg 294c582b7e3Smrgstatic int 295c582b7e3SmrgR128SetPortAttribute( 296c582b7e3Smrg ScrnInfoPtr pScrn, 297c582b7e3Smrg Atom attribute, 298c582b7e3Smrg INT32 value, 299c582b7e3Smrg pointer data 300c582b7e3Smrg){ 301c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 302c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 303c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 304c582b7e3Smrg 305c582b7e3Smrg if(attribute == xvBrightness) { 306c582b7e3Smrg if((value < -64) || (value > 63)) 307c582b7e3Smrg return BadValue; 308c582b7e3Smrg pPriv->brightness = value; 309c582b7e3Smrg 310c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 311c582b7e3Smrg (pPriv->saturation << 8) | 312c582b7e3Smrg (pPriv->saturation << 16)); 313c582b7e3Smrg } else 314c582b7e3Smrg if(attribute == xvSaturation) { 315c582b7e3Smrg if((value < 0) || (value > 31)) 316c582b7e3Smrg return BadValue; 317c582b7e3Smrg pPriv->saturation = value; 318c582b7e3Smrg 319c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 320c582b7e3Smrg (pPriv->saturation << 8) | 321c582b7e3Smrg (pPriv->saturation << 16)); 322c582b7e3Smrg } else 323c582b7e3Smrg if(attribute == xvDoubleBuffer) { 324c582b7e3Smrg if((value < 0) || (value > 1)) 325c582b7e3Smrg return BadValue; 326c582b7e3Smrg pPriv->doubleBuffer = value; 327c582b7e3Smrg } else 328c582b7e3Smrg if(attribute == xvColorKey) { 329c582b7e3Smrg pPriv->colorKey = value; 330c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); 331c582b7e3Smrg 332c582b7e3Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 333c582b7e3Smrg } else return BadMatch; 334c582b7e3Smrg 335c582b7e3Smrg return Success; 336c582b7e3Smrg} 337c582b7e3Smrg 338c582b7e3Smrgstatic int 339c582b7e3SmrgR128GetPortAttribute( 340c582b7e3Smrg ScrnInfoPtr pScrn, 341c582b7e3Smrg Atom attribute, 342c582b7e3Smrg INT32 *value, 343c582b7e3Smrg pointer data 344c582b7e3Smrg){ 345c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 346c582b7e3Smrg 347c582b7e3Smrg if(attribute == xvBrightness) { 348c582b7e3Smrg *value = pPriv->brightness; 349c582b7e3Smrg } else 350c582b7e3Smrg if(attribute == xvSaturation) { 351c582b7e3Smrg *value = pPriv->saturation; 352c582b7e3Smrg } else 353c582b7e3Smrg if(attribute == xvDoubleBuffer) { 354c582b7e3Smrg *value = pPriv->doubleBuffer ? 1 : 0; 355c582b7e3Smrg } else 356c582b7e3Smrg if(attribute == xvColorKey) { 357c582b7e3Smrg *value = pPriv->colorKey; 358c582b7e3Smrg } else return BadMatch; 359c582b7e3Smrg 360c582b7e3Smrg return Success; 361c582b7e3Smrg} 362c582b7e3Smrg 363c582b7e3Smrg 364c582b7e3Smrgstatic void 365c582b7e3SmrgR128QueryBestSize( 366c582b7e3Smrg ScrnInfoPtr pScrn, 367c582b7e3Smrg Bool motion, 368c582b7e3Smrg short vid_w, short vid_h, 369c582b7e3Smrg short drw_w, short drw_h, 370c582b7e3Smrg unsigned int *p_w, unsigned int *p_h, 371c582b7e3Smrg pointer data 372c582b7e3Smrg){ 373c582b7e3Smrg if(vid_w > (drw_w << 4)) 374c582b7e3Smrg drw_w = vid_w >> 4; 375c582b7e3Smrg if(vid_h > (drw_h << 4)) 376c582b7e3Smrg drw_h = vid_h >> 4; 377c582b7e3Smrg 378c582b7e3Smrg *p_w = drw_w; 379c582b7e3Smrg *p_h = drw_h; 380c582b7e3Smrg} 381c582b7e3Smrg 382c582b7e3Smrg 383c582b7e3Smrg/* 384c582b7e3Smrg * 385c582b7e3Smrg * R128DMA - abuse the texture blit ioctl to transfer rectangular blocks 386c582b7e3Smrg * 387c582b7e3Smrg * The block is split into 'passes' pieces of 'hpass' lines which fit entirely 388c582b7e3Smrg * into an indirect buffer 389c582b7e3Smrg * 390c582b7e3Smrg */ 391c582b7e3Smrg 39242a55b46SmrgBool 393c582b7e3SmrgR128DMA( 394c582b7e3Smrg R128InfoPtr info, 395c582b7e3Smrg unsigned char *src, 396c582b7e3Smrg unsigned char *dst, 397c582b7e3Smrg int srcPitch, 398c582b7e3Smrg int dstPitch, 399c582b7e3Smrg int h, 400c582b7e3Smrg int w 401c582b7e3Smrg){ 402c582b7e3Smrg 40342a55b46Smrg#ifdef R128DRI 404c582b7e3Smrg 405c582b7e3Smrg#define BUFSIZE (R128_BUFFER_SIZE - R128_HOSTDATA_BLIT_OFFSET) 406c582b7e3Smrg#define MAXPASSES (MAXHEIGHT/(BUFSIZE/(MAXWIDTH*2))+1) 407c582b7e3Smrg 408c582b7e3Smrg unsigned char *fb = (CARD8*)info->FB; 409c582b7e3Smrg unsigned char *buf; 410c582b7e3Smrg int err=-1, i, idx, offset, hpass, passes, srcpassbytes, dstpassbytes; 411c582b7e3Smrg int sizes[MAXPASSES], list[MAXPASSES]; 412c582b7e3Smrg drmDMAReq req; 413c582b7e3Smrg drmR128Blit blit; 414c582b7e3Smrg 415c582b7e3Smrg /* Verify conditions and bail out as early as possible */ 416c582b7e3Smrg if (!info->directRenderingEnabled || !info->DMAForXv) 417c582b7e3Smrg return FALSE; 418c582b7e3Smrg 419c582b7e3Smrg if ((hpass = min(h,(BUFSIZE/w))) == 0) 420c582b7e3Smrg return FALSE; 421c582b7e3Smrg 422c582b7e3Smrg if ((passes = (h+hpass-1)/hpass) > MAXPASSES) 423c582b7e3Smrg return FALSE; 424c582b7e3Smrg 425c582b7e3Smrg /* Request indirect buffers */ 426c582b7e3Smrg srcpassbytes = w*hpass; 427c582b7e3Smrg 428c582b7e3Smrg req.context = info->drmCtx; 429c582b7e3Smrg req.send_count = 0; 430c582b7e3Smrg req.send_list = NULL; 431c582b7e3Smrg req.send_sizes = NULL; 432c582b7e3Smrg req.flags = DRM_DMA_LARGER_OK; 433c582b7e3Smrg req.request_count = passes; 434c582b7e3Smrg req.request_size = srcpassbytes + R128_HOSTDATA_BLIT_OFFSET; 435c582b7e3Smrg req.request_list = &list[0]; 436c582b7e3Smrg req.request_sizes = &sizes[0]; 437c582b7e3Smrg req.granted_count = 0; 438c582b7e3Smrg 439c582b7e3Smrg if (drmDMA(info->drmFD, &req)) 440c582b7e3Smrg return FALSE; 441c582b7e3Smrg 442c582b7e3Smrg if (req.granted_count < passes) { 443c582b7e3Smrg drmFreeBufs(info->drmFD, req.granted_count, req.request_list); 444c582b7e3Smrg return FALSE; 445c582b7e3Smrg } 446c582b7e3Smrg 447c582b7e3Smrg /* Copy parts of the block into buffers and fire them */ 448c582b7e3Smrg dstpassbytes = hpass*dstPitch; 449c582b7e3Smrg dstPitch /= 8; 450c582b7e3Smrg 451c582b7e3Smrg for (i=0, offset=dst-fb; i<passes; i++, offset+=dstpassbytes) { 452c582b7e3Smrg if (i == (passes-1) && (h % hpass) != 0) { 453c582b7e3Smrg hpass = h % hpass; 454c582b7e3Smrg srcpassbytes = w*hpass; 455c582b7e3Smrg } 456c582b7e3Smrg 457c582b7e3Smrg idx = req.request_list[i]; 458c582b7e3Smrg buf = (unsigned char *) info->buffers->list[idx].address + R128_HOSTDATA_BLIT_OFFSET; 459c582b7e3Smrg 460c582b7e3Smrg if (srcPitch == w) { 461c582b7e3Smrg memcpy(buf, src, srcpassbytes); 462c582b7e3Smrg src += srcpassbytes; 463c582b7e3Smrg } else { 464c582b7e3Smrg int count = hpass; 465c582b7e3Smrg while(count--) { 466c582b7e3Smrg memcpy(buf, src, w); 467c582b7e3Smrg src += srcPitch; 468c582b7e3Smrg buf += w; 469c582b7e3Smrg } 470c582b7e3Smrg } 471c582b7e3Smrg 472c582b7e3Smrg blit.idx = idx; 473c582b7e3Smrg blit.offset = offset; 474c582b7e3Smrg blit.pitch = dstPitch; 475c582b7e3Smrg blit.format = (R128_DATATYPE_CI8 >> 16); 476c582b7e3Smrg blit.x = (offset % 32); 477c582b7e3Smrg blit.y = 0; 478c582b7e3Smrg blit.width = w; 479c582b7e3Smrg blit.height = hpass; 480c582b7e3Smrg 481c582b7e3Smrg if ((err = drmCommandWrite(info->drmFD, DRM_R128_BLIT, 482c582b7e3Smrg &blit, sizeof(drmR128Blit))) < 0) 483c582b7e3Smrg break; 484c582b7e3Smrg } 485c582b7e3Smrg 486c582b7e3Smrg drmFreeBufs(info->drmFD, req.granted_count, req.request_list); 487c582b7e3Smrg 488c582b7e3Smrg return (err==0) ? TRUE : FALSE; 489c582b7e3Smrg 490c582b7e3Smrg#else 491c582b7e3Smrg 49242a55b46Smrg /* This is to avoid cluttering the rest of the code with '#ifdef R128DRI' */ 493c582b7e3Smrg return FALSE; 494c582b7e3Smrg 49542a55b46Smrg#endif /* R128DRI */ 496c582b7e3Smrg 497c582b7e3Smrg} 498c582b7e3Smrg 499c582b7e3Smrg 500c582b7e3Smrgstatic void 501c582b7e3SmrgR128CopyData422( 502c582b7e3Smrg R128InfoPtr info, 503c582b7e3Smrg unsigned char *src, 504c582b7e3Smrg unsigned char *dst, 505c582b7e3Smrg int srcPitch, 506c582b7e3Smrg int dstPitch, 507c582b7e3Smrg int h, 508c582b7e3Smrg int w 509c582b7e3Smrg){ 510c582b7e3Smrg w <<= 1; 511c582b7e3Smrg 512c582b7e3Smrg /* Attempt data transfer with DMA and fall back to memcpy */ 513c582b7e3Smrg 514c582b7e3Smrg if (!R128DMA(info, src, dst, srcPitch, dstPitch, h, w)) { 515c582b7e3Smrg while(h--) { 516c582b7e3Smrg memcpy(dst, src, w); 517c582b7e3Smrg src += srcPitch; 518c582b7e3Smrg dst += dstPitch; 519c582b7e3Smrg } 520c582b7e3Smrg } 521c582b7e3Smrg} 522c582b7e3Smrg 523c582b7e3Smrgstatic void 524c582b7e3SmrgR128CopyData420( 525c582b7e3Smrg R128InfoPtr info, 526c582b7e3Smrg unsigned char *src1, 527c582b7e3Smrg unsigned char *src2, 528c582b7e3Smrg unsigned char *src3, 529c582b7e3Smrg unsigned char *dst1, 530c582b7e3Smrg unsigned char *dst2, 531c582b7e3Smrg unsigned char *dst3, 532c582b7e3Smrg int srcPitch, 533c582b7e3Smrg int srcPitch2, 534c582b7e3Smrg int dstPitch, 535c582b7e3Smrg int h, 536c582b7e3Smrg int w 537c582b7e3Smrg){ 538c582b7e3Smrg int count; 539c582b7e3Smrg 540c582b7e3Smrg /* Attempt data transfer with DMA and fall back to memcpy */ 541c582b7e3Smrg 542c582b7e3Smrg if (!R128DMA(info, src1, dst1, srcPitch, dstPitch, h, w)) { 543c582b7e3Smrg count = h; 544c582b7e3Smrg while(count--) { 545c582b7e3Smrg memcpy(dst1, src1, w); 546c582b7e3Smrg src1 += srcPitch; 547c582b7e3Smrg dst1 += dstPitch; 548c582b7e3Smrg } 549c582b7e3Smrg } 550c582b7e3Smrg 551c582b7e3Smrg w >>= 1; 552c582b7e3Smrg h >>= 1; 553c582b7e3Smrg dstPitch >>= 1; 554c582b7e3Smrg 555c582b7e3Smrg if (!R128DMA(info, src2, dst2, srcPitch2, dstPitch, h, w)) { 556c582b7e3Smrg count = h; 557c582b7e3Smrg while(count--) { 558c582b7e3Smrg memcpy(dst2, src2, w); 559c582b7e3Smrg src2 += srcPitch2; 560c582b7e3Smrg dst2 += dstPitch; 561c582b7e3Smrg } 562c582b7e3Smrg } 563c582b7e3Smrg 564c582b7e3Smrg if (!R128DMA(info, src3, dst3, srcPitch2, dstPitch, h, w)) { 565c582b7e3Smrg count = h; 566c582b7e3Smrg while(count--) { 567c582b7e3Smrg memcpy(dst3, src3, w); 568c582b7e3Smrg src3 += srcPitch2; 569c582b7e3Smrg dst3 += dstPitch; 570c582b7e3Smrg } 571c582b7e3Smrg } 572c582b7e3Smrg} 573c582b7e3Smrg 574c582b7e3Smrg 57542a55b46Smrgstatic CARD32 576c582b7e3SmrgR128AllocateMemory( 577c582b7e3Smrg ScrnInfoPtr pScrn, 57842a55b46Smrg void **mem_struct, 579c582b7e3Smrg int size 580c582b7e3Smrg){ 58142a55b46Smrg R128InfoPtr info = R128PTR(pScrn); 58242a55b46Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 58342a55b46Smrg int offset = 0; 584c582b7e3Smrg 58542a55b46Smrg if(!info->useEXA) { 58642a55b46Smrg FBLinearPtr linear = *mem_struct; 58742a55b46Smrg int cpp = info->CurrentLayout.pixel_bytes; 588c582b7e3Smrg 58942a55b46Smrg /* XAA allocates in units of pixels at the screen bpp, so adjust size appropriately. */ 59042a55b46Smrg size = (size + cpp - 1) / cpp; 591c582b7e3Smrg 59242a55b46Smrg if(linear) { 59342a55b46Smrg if(linear->size >= size) 59442a55b46Smrg return linear->offset * cpp; 59542a55b46Smrg 59642a55b46Smrg if(xf86ResizeOffscreenLinear(linear, size)) 59742a55b46Smrg return linear->offset * cpp; 598c582b7e3Smrg 59942a55b46Smrg xf86FreeOffscreenLinear(linear); 60042a55b46Smrg } 601c582b7e3Smrg 60242a55b46Smrg 60342a55b46Smrg linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 604c582b7e3Smrg NULL, NULL, NULL); 60542a55b46Smrg *mem_struct = linear; 606c582b7e3Smrg 60742a55b46Smrg if(!linear) { 60842a55b46Smrg int max_size; 609c582b7e3Smrg 61042a55b46Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, 611c582b7e3Smrg PRIORITY_EXTREME); 612c582b7e3Smrg 61342a55b46Smrg if(max_size < size) 61442a55b46Smrg return 0; 615c582b7e3Smrg 61642a55b46Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 61742a55b46Smrg linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 618c582b7e3Smrg NULL, NULL, NULL); 61942a55b46Smrg 62042a55b46Smrg if(!linear) return 0; 62142a55b46Smrg } 62242a55b46Smrg 62342a55b46Smrg offset = linear->offset * cpp; 62442a55b46Smrg } 62542a55b46Smrg#ifdef USE_EXA 62642a55b46Smrg else { 62742a55b46Smrg /* EXA support based on mga driver */ 62842a55b46Smrg ExaOffscreenArea *area = *mem_struct; 62942a55b46Smrg 63042a55b46Smrg if(area) { 63142a55b46Smrg if(area->size >= size) 63242a55b46Smrg return area->offset; 63342a55b46Smrg 63442a55b46Smrg exaOffscreenFree(pScrn->pScreen, area); 63542a55b46Smrg } 63642a55b46Smrg 63742a55b46Smrg area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, NULL, NULL); 63842a55b46Smrg *mem_struct = area; 63942a55b46Smrg 64042a55b46Smrg if(!area) return 0; 64142a55b46Smrg 64242a55b46Smrg offset = area->offset; 643c582b7e3Smrg } 64442a55b46Smrg#endif 645c582b7e3Smrg 64642a55b46Smrg return offset; 647c582b7e3Smrg} 648c582b7e3Smrg 649c582b7e3Smrgstatic void 650c582b7e3SmrgR128DisplayVideo422( 651c582b7e3Smrg ScrnInfoPtr pScrn, 652c582b7e3Smrg int id, 653c582b7e3Smrg int offset, 654c582b7e3Smrg short width, short height, 655c582b7e3Smrg int pitch, 656c582b7e3Smrg int left, int right, int top, 657c582b7e3Smrg BoxPtr dstBox, 658c582b7e3Smrg short src_w, short src_h, 659c582b7e3Smrg short drw_w, short drw_h 660c582b7e3Smrg){ 661c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 662c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 663c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 66442a55b46Smrg int v_inc, h_inc, step_by, tmp, v_inc_shift; 665c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 666c582b7e3Smrg int p1_v_accum_init; 66742a55b46Smrg Bool rmx_active; 668c582b7e3Smrg 669c582b7e3Smrg R128ECP(pScrn, pPriv); 670c582b7e3Smrg 67142a55b46Smrg v_inc_shift = 20; 67242a55b46Smrg if (pScrn->currentMode->Flags & V_INTERLACE) 67342a55b46Smrg v_inc_shift++; 67442a55b46Smrg if (pScrn->currentMode->Flags & V_DBLSCAN) 67542a55b46Smrg v_inc_shift--; 6760496e070Smrg 67742a55b46Smrg rmx_active = INREG(R128_FP_VERT_STRETCH) & R128_VERT_STRETCH_ENABLE; 67842a55b46Smrg if (rmx_active) { 67942a55b46Smrg v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; 68042a55b46Smrg } else { 68142a55b46Smrg v_inc = (src_h << v_inc_shift) / drw_h; 68242a55b46Smrg } 683c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 684c582b7e3Smrg step_by = 1; 685c582b7e3Smrg 686c582b7e3Smrg while(h_inc >= (2 << 12)) { 687c582b7e3Smrg step_by++; 688c582b7e3Smrg h_inc >>= 1; 689c582b7e3Smrg } 690c582b7e3Smrg 691c582b7e3Smrg /* keep everything in 16.16 */ 692c582b7e3Smrg 693c582b7e3Smrg offset += ((left >> 16) & ~7) << 1; 694c582b7e3Smrg 695c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 696c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 697c582b7e3Smrg ((tmp << 12) & 0xf0000000); 698c582b7e3Smrg 699c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 700c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 701c582b7e3Smrg ((tmp << 12) & 0x70000000); 702c582b7e3Smrg 703c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 704c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 705c582b7e3Smrg 706c582b7e3Smrg left = (left >> 16) & 7; 707c582b7e3Smrg 708c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 709c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 710c582b7e3Smrg 711c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 712c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 713c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 714c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 715c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 716c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 717c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 718c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 719c582b7e3Smrg left >>= 1; width >>= 1; 720c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16)); 721c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16)); 722c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0); 723c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 724c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0); 725c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 726c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 727c582b7e3Smrg 728c582b7e3Smrg if(id == FOURCC_UYVY) 729c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03); 730c582b7e3Smrg else 731c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03); 732c582b7e3Smrg 733c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 734c582b7e3Smrg} 735c582b7e3Smrg 736c582b7e3Smrgstatic void 737c582b7e3SmrgR128DisplayVideo420( 738c582b7e3Smrg ScrnInfoPtr pScrn, 739c582b7e3Smrg short width, short height, 740c582b7e3Smrg int pitch, 741c582b7e3Smrg int offset1, int offset2, int offset3, 742c582b7e3Smrg int left, int right, int top, 743c582b7e3Smrg BoxPtr dstBox, 744c582b7e3Smrg short src_w, short src_h, 745c582b7e3Smrg short drw_w, short drw_h 746c582b7e3Smrg){ 747c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 748c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 749c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 75042a55b46Smrg int v_inc, h_inc, step_by, tmp, leftUV, v_inc_shift; 751c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 752c582b7e3Smrg int p1_v_accum_init, p23_v_accum_init; 75342a55b46Smrg Bool rmx_active; 75442a55b46Smrg 75542a55b46Smrg v_inc_shift = 20; 75642a55b46Smrg if (pScrn->currentMode->Flags & V_INTERLACE) 75742a55b46Smrg v_inc_shift++; 75842a55b46Smrg if (pScrn->currentMode->Flags & V_DBLSCAN) 75942a55b46Smrg v_inc_shift--; 7600496e070Smrg 76142a55b46Smrg rmx_active = INREG(R128_FP_VERT_STRETCH) & R128_VERT_STRETCH_ENABLE; 76242a55b46Smrg if (rmx_active) { 76342a55b46Smrg v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; 76442a55b46Smrg } else { 76542a55b46Smrg v_inc = (src_h << v_inc_shift) / drw_h; 76642a55b46Smrg } 767c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 768c582b7e3Smrg step_by = 1; 769c582b7e3Smrg 770c582b7e3Smrg while(h_inc >= (2 << 12)) { 771c582b7e3Smrg step_by++; 772c582b7e3Smrg h_inc >>= 1; 773c582b7e3Smrg } 774c582b7e3Smrg 775c582b7e3Smrg /* keep everything in 16.16 */ 776c582b7e3Smrg 777c582b7e3Smrg offset1 += (left >> 16) & ~15; 778c582b7e3Smrg offset2 += (left >> 17) & ~15; 779c582b7e3Smrg offset3 += (left >> 17) & ~15; 780c582b7e3Smrg 781c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 782c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 783c582b7e3Smrg ((tmp << 12) & 0xf0000000); 784c582b7e3Smrg 785c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 786c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 787c582b7e3Smrg ((tmp << 12) & 0x70000000); 788c582b7e3Smrg 789c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 790c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 791c582b7e3Smrg 792c582b7e3Smrg tmp = ((top >> 1) & 0x0000ffff) + 0x00018000; 793c582b7e3Smrg p23_v_accum_init = ((tmp << 4) & 0x01ff8000) | 0x00000001; 794c582b7e3Smrg 795c582b7e3Smrg leftUV = (left >> 17) & 15; 796c582b7e3Smrg left = (left >> 16) & 15; 797c582b7e3Smrg 798c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 799c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 800c582b7e3Smrg 801c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 802c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 803c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 804c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 805c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 806c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 807c582b7e3Smrg src_h = (src_h + 1) >> 1; 808c582b7e3Smrg OUTREG(R128_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | ((src_h - 1) << 16)); 809c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 810c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1); 811c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 812c582b7e3Smrg width >>= 1; 813c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16)); 814c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16)); 815c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); 816c582b7e3Smrg OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, (offset2 & 0xfffffff0) | 0x00000001); 817c582b7e3Smrg OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, (offset3 & 0xfffffff0) | 0x00000001); 818c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 819c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); 820c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 821c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 822c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03); 823c582b7e3Smrg 824c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 825c582b7e3Smrg} 826c582b7e3Smrg 827c582b7e3Smrg 828c582b7e3Smrg 829c582b7e3Smrgstatic int 830c582b7e3SmrgR128PutImage( 831c582b7e3Smrg ScrnInfoPtr pScrn, 832c582b7e3Smrg short src_x, short src_y, 833c582b7e3Smrg short drw_x, short drw_y, 834c582b7e3Smrg short src_w, short src_h, 835c582b7e3Smrg short drw_w, short drw_h, 836c582b7e3Smrg int id, unsigned char* buf, 837c582b7e3Smrg short width, short height, 838c582b7e3Smrg Bool Sync, 839c582b7e3Smrg RegionPtr clipBoxes, pointer data, 840c582b7e3Smrg DrawablePtr pDraw 841c582b7e3Smrg){ 842c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 843c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 844c582b7e3Smrg unsigned char *fb = (CARD8*)info->FB; 845c582b7e3Smrg INT32 xa, xb, ya, yb; 846c582b7e3Smrg int new_size, offset, s1offset, s2offset, s3offset; 847c582b7e3Smrg int srcPitch, srcPitch2, dstPitch; 848c582b7e3Smrg int d1line, d2line, d3line, d1offset, d2offset, d3offset; 84942a55b46Smrg int top, left, npixels, nlines; 850c582b7e3Smrg BoxRec dstBox; 851c582b7e3Smrg CARD32 tmp; 852c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 853c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 854c582b7e3Smrg CARD32 config_cntl = INREG(R128_CONFIG_CNTL); 855c582b7e3Smrg 856c582b7e3Smrg /* We need to disable byte swapping, or the data gets mangled */ 857c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl & 858c582b7e3Smrg ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP)); 859c582b7e3Smrg#endif 860c582b7e3Smrg 861c582b7e3Smrg /* 862c582b7e3Smrg * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes 863c582b7e3Smrg * of the source. 864c582b7e3Smrg * 865c582b7e3Smrg * d1offset, d2offset, d3offset - byte offsets to the Y, U and V planes 866c582b7e3Smrg * of the destination. 867c582b7e3Smrg * 868c582b7e3Smrg * offset - byte offset within the framebuffer to where the destination 869c582b7e3Smrg * is stored. 870c582b7e3Smrg * 871c582b7e3Smrg * d1line, d2line, d3line - byte offsets within the destination to the 872c582b7e3Smrg * first displayed scanline in each plane. 873c582b7e3Smrg * 874c582b7e3Smrg */ 875c582b7e3Smrg 876c582b7e3Smrg if(src_w > (drw_w << 4)) 877c582b7e3Smrg drw_w = src_w >> 4; 878c582b7e3Smrg if(src_h > (drw_h << 4)) 879c582b7e3Smrg drw_h = src_h >> 4; 880c582b7e3Smrg 881c582b7e3Smrg /* Clip */ 882c582b7e3Smrg xa = src_x; 883c582b7e3Smrg xb = src_x + src_w; 884c582b7e3Smrg ya = src_y; 885c582b7e3Smrg yb = src_y + src_h; 886c582b7e3Smrg 887c582b7e3Smrg dstBox.x1 = drw_x; 888c582b7e3Smrg dstBox.x2 = drw_x + drw_w; 889c582b7e3Smrg dstBox.y1 = drw_y; 890c582b7e3Smrg dstBox.y2 = drw_y + drw_h; 891c582b7e3Smrg 892c582b7e3Smrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, 893c582b7e3Smrg clipBoxes, width, height)) 894c582b7e3Smrg return Success; 895c582b7e3Smrg 896c582b7e3Smrg dstBox.x1 -= pScrn->frameX0; 897c582b7e3Smrg dstBox.x2 -= pScrn->frameX0; 898c582b7e3Smrg dstBox.y1 -= pScrn->frameY0; 899c582b7e3Smrg dstBox.y2 -= pScrn->frameY0; 900c582b7e3Smrg 901c582b7e3Smrg switch(id) { 902c582b7e3Smrg case FOURCC_YV12: 903c582b7e3Smrg case FOURCC_I420: 904c582b7e3Smrg srcPitch = (width + 3) & ~3; 905c582b7e3Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 906c582b7e3Smrg dstPitch = (width + 31) & ~31; /* of luma */ 90742a55b46Smrg new_size = dstPitch * (height + (height >> 1)); 908c582b7e3Smrg s1offset = 0; 909c582b7e3Smrg s2offset = srcPitch * height; 910c582b7e3Smrg s3offset = (srcPitch2 * (height >> 1)) + s2offset; 911c582b7e3Smrg break; 912c582b7e3Smrg case FOURCC_UYVY: 913c582b7e3Smrg case FOURCC_YUY2: 914c582b7e3Smrg default: 915c582b7e3Smrg srcPitch = width << 1; 916c582b7e3Smrg srcPitch2 = 0; 917c582b7e3Smrg dstPitch = ((width << 1) + 15) & ~15; 91842a55b46Smrg new_size = dstPitch * height; 919c582b7e3Smrg s1offset = 0; 920c582b7e3Smrg s2offset = 0; 921c582b7e3Smrg s3offset = 0; 922c582b7e3Smrg break; 923c582b7e3Smrg } 924c582b7e3Smrg 92542a55b46Smrg if(!(pPriv->videoOffset = R128AllocateMemory(pScrn, &(pPriv->BufferHandle), 926c582b7e3Smrg pPriv->doubleBuffer ? (new_size << 1) : new_size))) 927c582b7e3Smrg { 928c582b7e3Smrg return BadAlloc; 929c582b7e3Smrg } 930c582b7e3Smrg 931c582b7e3Smrg pPriv->currentBuffer ^= 1; 932c582b7e3Smrg 933c582b7e3Smrg /* copy data */ 934c582b7e3Smrg top = ya >> 16; 935c582b7e3Smrg left = (xa >> 16) & ~1; 936c582b7e3Smrg npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; 937c582b7e3Smrg 93842a55b46Smrg offset = pPriv->videoOffset; 939c582b7e3Smrg if(pPriv->doubleBuffer) 94042a55b46Smrg offset += pPriv->currentBuffer * new_size; 941c582b7e3Smrg 942c582b7e3Smrg switch(id) { 943c582b7e3Smrg case FOURCC_YV12: 944c582b7e3Smrg case FOURCC_I420: 945c582b7e3Smrg d1line = top * dstPitch; 946c582b7e3Smrg d2line = (height * dstPitch) + ((top >> 1) * (dstPitch >> 1)); 947c582b7e3Smrg d3line = d2line + ((height >> 1) * (dstPitch >> 1)); 948c582b7e3Smrg 949c582b7e3Smrg top &= ~1; 950c582b7e3Smrg 951c582b7e3Smrg d1offset = (top * dstPitch) + left + offset; 952c582b7e3Smrg d2offset = d2line + (left >> 1) + offset; 953c582b7e3Smrg d3offset = d3line + (left >> 1) + offset; 954c582b7e3Smrg 955c582b7e3Smrg s1offset += (top * srcPitch) + left; 956c582b7e3Smrg tmp = ((top >> 1) * srcPitch2) + (left >> 1); 957c582b7e3Smrg s2offset += tmp; 958c582b7e3Smrg s3offset += tmp; 959c582b7e3Smrg if(id == FOURCC_YV12) { 960c582b7e3Smrg tmp = s2offset; 961c582b7e3Smrg s2offset = s3offset; 962c582b7e3Smrg s3offset = tmp; 963c582b7e3Smrg } 964c582b7e3Smrg 965c582b7e3Smrg nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; 966c582b7e3Smrg R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset, 967c582b7e3Smrg fb + d1offset, fb + d2offset, fb + d3offset, 968c582b7e3Smrg srcPitch, srcPitch2, dstPitch, nlines, npixels); 969c582b7e3Smrg break; 970c582b7e3Smrg case FOURCC_UYVY: 971c582b7e3Smrg case FOURCC_YUY2: 972c582b7e3Smrg default: 973c582b7e3Smrg left <<= 1; 974c582b7e3Smrg d1line = top * dstPitch; 975c582b7e3Smrg d2line = 0; 976c582b7e3Smrg d3line = 0; 977c582b7e3Smrg d1offset = d1line + left + offset; 978c582b7e3Smrg d2offset = 0; 979c582b7e3Smrg d3offset = 0; 980c582b7e3Smrg s1offset += (top * srcPitch) + left; 981c582b7e3Smrg nlines = ((yb + 0xffff) >> 16) - top; 982c582b7e3Smrg R128CopyData422(info, buf + s1offset, fb + d1offset, 983c582b7e3Smrg srcPitch, dstPitch, nlines, npixels); 984c582b7e3Smrg break; 985c582b7e3Smrg } 986c582b7e3Smrg 987c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 988c582b7e3Smrg /* restore byte swapping */ 989c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl); 990c582b7e3Smrg#endif 991c582b7e3Smrg 992c582b7e3Smrg /* update cliplist */ 993c582b7e3Smrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 994c582b7e3Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 995c582b7e3Smrg /* draw these */ 996c582b7e3Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 997c582b7e3Smrg } 998c582b7e3Smrg 999c582b7e3Smrg 1000c582b7e3Smrg switch(id) { 1001c582b7e3Smrg case FOURCC_YV12: 1002c582b7e3Smrg case FOURCC_I420: 1003c582b7e3Smrg R128DisplayVideo420(pScrn, width, height, dstPitch, 1004c582b7e3Smrg offset + d1line, offset + d2line, offset + d3line, 1005c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 1006c582b7e3Smrg break; 1007c582b7e3Smrg case FOURCC_UYVY: 1008c582b7e3Smrg case FOURCC_YUY2: 1009c582b7e3Smrg default: 1010c582b7e3Smrg R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch, 1011c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 1012c582b7e3Smrg break; 1013c582b7e3Smrg } 1014c582b7e3Smrg 1015c582b7e3Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 1016c582b7e3Smrg 1017c582b7e3Smrg info->VideoTimerCallback = R128VideoTimerCallback; 1018c582b7e3Smrg 1019c582b7e3Smrg return Success; 1020c582b7e3Smrg} 1021c582b7e3Smrg 1022c582b7e3Smrg 1023c582b7e3Smrgstatic int 1024c582b7e3SmrgR128QueryImageAttributes( 1025c582b7e3Smrg ScrnInfoPtr pScrn, 1026c582b7e3Smrg int id, 1027c582b7e3Smrg unsigned short *w, unsigned short *h, 1028c582b7e3Smrg int *pitches, int *offsets 1029c582b7e3Smrg){ 1030c582b7e3Smrg int size, tmp; 1031c582b7e3Smrg 1032c582b7e3Smrg if(*w > MAXWIDTH) *w = MAXWIDTH; 1033c582b7e3Smrg if(*h > MAXHEIGHT) *h = MAXHEIGHT; 1034c582b7e3Smrg 1035c582b7e3Smrg *w = (*w + 1) & ~1; 1036c582b7e3Smrg if(offsets) offsets[0] = 0; 1037c582b7e3Smrg 1038c582b7e3Smrg switch(id) { 1039c582b7e3Smrg case FOURCC_YV12: 1040c582b7e3Smrg case FOURCC_I420: 1041c582b7e3Smrg *h = (*h + 1) & ~1; 1042c582b7e3Smrg size = (*w + 3) & ~3; 1043c582b7e3Smrg if(pitches) pitches[0] = size; 1044c582b7e3Smrg size *= *h; 1045c582b7e3Smrg if(offsets) offsets[1] = size; 1046c582b7e3Smrg tmp = ((*w >> 1) + 3) & ~3; 1047c582b7e3Smrg if(pitches) pitches[1] = pitches[2] = tmp; 1048c582b7e3Smrg tmp *= (*h >> 1); 1049c582b7e3Smrg size += tmp; 1050c582b7e3Smrg if(offsets) offsets[2] = size; 1051c582b7e3Smrg size += tmp; 1052c582b7e3Smrg break; 1053c582b7e3Smrg case FOURCC_UYVY: 1054c582b7e3Smrg case FOURCC_YUY2: 1055c582b7e3Smrg default: 1056c582b7e3Smrg size = *w << 1; 1057c582b7e3Smrg if(pitches) pitches[0] = size; 1058c582b7e3Smrg size *= *h; 1059c582b7e3Smrg break; 1060c582b7e3Smrg } 1061c582b7e3Smrg 1062c582b7e3Smrg return size; 1063c582b7e3Smrg} 1064c582b7e3Smrg 1065c582b7e3Smrgstatic void 1066c582b7e3SmrgR128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) 1067c582b7e3Smrg{ 1068c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1069c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 1070c582b7e3Smrg 1071c582b7e3Smrg if(pPriv->videoStatus & TIMER_MASK) { 1072c582b7e3Smrg if(pPriv->videoStatus & OFF_TIMER) { 1073c582b7e3Smrg if(pPriv->offTime < now) { 1074c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1075c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0); 1076c582b7e3Smrg pPriv->videoStatus = FREE_TIMER; 1077c582b7e3Smrg pPriv->freeTime = now + FREE_DELAY; 1078c582b7e3Smrg } 1079c582b7e3Smrg } else { /* FREE_TIMER */ 1080c582b7e3Smrg if(pPriv->freeTime < now) { 108142a55b46Smrg if(pPriv->BufferHandle) { 108242a55b46Smrg if (!info->useEXA) { 108342a55b46Smrg xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle); 108442a55b46Smrg } 108542a55b46Smrg#ifdef USE_EXA 108642a55b46Smrg else { 108742a55b46Smrg exaOffscreenFree(pScrn->pScreen, (ExaOffscreenArea *) pPriv->BufferHandle); 108842a55b46Smrg } 108942a55b46Smrg#endif 109042a55b46Smrg pPriv->BufferHandle = NULL; 1091c582b7e3Smrg } 1092c582b7e3Smrg pPriv->videoStatus = 0; 1093c582b7e3Smrg info->VideoTimerCallback = NULL; 1094c582b7e3Smrg } 1095c582b7e3Smrg } 1096c582b7e3Smrg } else /* shouldn't get here */ 1097c582b7e3Smrg info->VideoTimerCallback = NULL; 1098c582b7e3Smrg} 1099