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; 62e3d74329Smrg uint32_t colorKey; 63e3d74329Smrg uint32_t 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; 229e3d74329Smrg 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 408e3d74329Smrg unsigned char *fb = (uint8_t*)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 575e3d74329Smrguint32_t 576c582b7e3SmrgR128AllocateMemory( 577e3d74329Smrg ScrnInfoPtr pScrn, 578e3d74329Smrg void **mem_struct, 579e3d74329Smrg int size, 580e3d74329Smrg int align, 581e3d74329Smrg Bool need_accel 582c582b7e3Smrg){ 583e3d74329Smrg R128InfoPtr info = R128PTR(pScrn); 584e3d74329Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 585e3d74329Smrg Bool do_linear = !need_accel; 586e3d74329Smrg uint32_t offset = 0; 587e3d74329Smrg 588e3d74329Smrg#ifdef HAVE_XAA_H 589e3d74329Smrg if (!info->accel && need_accel) 590e3d74329Smrg do_linear = FALSE; 591e3d74329Smrg else 592e3d74329Smrg do_linear = TRUE; 593e3d74329Smrg#endif 594e3d74329Smrg#ifdef USE_EXA 595e3d74329Smrg if (info->ExaDriver) { 596e3d74329Smrg ExaOffscreenArea *area = *mem_struct; 597e3d74329Smrg 598e3d74329Smrg if (area != NULL) { 599e3d74329Smrg if (area->size >= size) return area->offset; 600c582b7e3Smrg 601e3d74329Smrg exaOffscreenFree(pScreen, area); 602e3d74329Smrg } 603e3d74329Smrg 604e3d74329Smrg area = exaOffscreenAlloc(pScreen, size, align, TRUE, NULL, NULL); 605e3d74329Smrg *mem_struct = area; 606e3d74329Smrg 607e3d74329Smrg if (area == NULL) return 0; 608e3d74329Smrg offset = area->offset; 609e3d74329Smrg } 610e3d74329Smrg#endif 611e3d74329Smrg if (!info->useEXA && do_linear) { 61242a55b46Smrg FBLinearPtr linear = *mem_struct; 61342a55b46Smrg int cpp = info->CurrentLayout.pixel_bytes; 614c582b7e3Smrg 615e3d74329Smrg /* XAA allocates in units of pixels at the screen bpp, so adjust size appropriately. */ 616e3d74329Smrg size = (size + cpp - 1) / cpp; 617e3d74329Smrg align = (align + cpp - 1) / cpp; 618c582b7e3Smrg 61942a55b46Smrg if(linear) { 620e3d74329Smrg if(linear->size >= size) 621e3d74329Smrg return linear->offset * cpp; 62242a55b46Smrg 623e3d74329Smrg if(xf86ResizeOffscreenLinear(linear, size)) 624e3d74329Smrg return linear->offset * cpp; 625c582b7e3Smrg 626e3d74329Smrg xf86FreeOffscreenLinear(linear); 62742a55b46Smrg } 628c582b7e3Smrg 629e3d74329Smrg linear = xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); 63042a55b46Smrg *mem_struct = linear; 631c582b7e3Smrg 63242a55b46Smrg if(!linear) { 633e3d74329Smrg int max_size; 634c582b7e3Smrg 635e3d74329Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, PRIORITY_EXTREME); 636e3d74329Smrg if(max_size < size) return 0; 637c582b7e3Smrg 638e3d74329Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 639e3d74329Smrg linear = xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); 640c582b7e3Smrg 641e3d74329Smrg *mem_struct = linear; 642e3d74329Smrg if(!linear) return 0; 64342a55b46Smrg } 64442a55b46Smrg 645e3d74329Smrg offset = linear->offset * cpp; 646e3d74329Smrg } 647c582b7e3Smrg 648e3d74329Smrg return offset; 649c582b7e3Smrg} 650c582b7e3Smrg 651c582b7e3Smrgstatic void 652c582b7e3SmrgR128DisplayVideo422( 653c582b7e3Smrg ScrnInfoPtr pScrn, 654c582b7e3Smrg int id, 655c582b7e3Smrg int offset, 656c582b7e3Smrg short width, short height, 657c582b7e3Smrg int pitch, 658c582b7e3Smrg int left, int right, int top, 659c582b7e3Smrg BoxPtr dstBox, 660c582b7e3Smrg short src_w, short src_h, 661c582b7e3Smrg short drw_w, short drw_h 662c582b7e3Smrg){ 663c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 664e3d74329Smrg R128EntPtr pR128Ent = R128EntPriv(pScrn); 665e3d74329Smrg xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]); 666e3d74329Smrg R128OutputPrivatePtr r128_output = output->driver_private; 667c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 668c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 669e3d74329Smrg 67042a55b46Smrg int v_inc, h_inc, step_by, tmp, v_inc_shift; 671c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 672c582b7e3Smrg int p1_v_accum_init; 673e3d74329Smrg Bool rmx_active = FALSE; 674c582b7e3Smrg 675c582b7e3Smrg R128ECP(pScrn, pPriv); 676c582b7e3Smrg 67742a55b46Smrg v_inc_shift = 20; 67842a55b46Smrg if (pScrn->currentMode->Flags & V_INTERLACE) 67942a55b46Smrg v_inc_shift++; 68042a55b46Smrg if (pScrn->currentMode->Flags & V_DBLSCAN) 68142a55b46Smrg v_inc_shift--; 6820496e070Smrg 683e3d74329Smrg if (r128_output->PanelYRes > 0) 684e3d74329Smrg rmx_active = INREG(R128_FP_VERT_STRETCH) & R128_VERT_STRETCH_ENABLE; 68542a55b46Smrg if (rmx_active) { 686e3d74329Smrg v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / r128_output->PanelYRes) << v_inc_shift) / drw_h; 68742a55b46Smrg } else { 68842a55b46Smrg v_inc = (src_h << v_inc_shift) / drw_h; 68942a55b46Smrg } 690c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 691c582b7e3Smrg step_by = 1; 692c582b7e3Smrg 693c582b7e3Smrg while(h_inc >= (2 << 12)) { 694c582b7e3Smrg step_by++; 695c582b7e3Smrg h_inc >>= 1; 696c582b7e3Smrg } 697c582b7e3Smrg 698c582b7e3Smrg /* keep everything in 16.16 */ 699c582b7e3Smrg 700c582b7e3Smrg offset += ((left >> 16) & ~7) << 1; 701c582b7e3Smrg 702c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 703c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 704c582b7e3Smrg ((tmp << 12) & 0xf0000000); 705c582b7e3Smrg 706c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 707c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 708c582b7e3Smrg ((tmp << 12) & 0x70000000); 709c582b7e3Smrg 710c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 711c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 712c582b7e3Smrg 713c582b7e3Smrg left = (left >> 16) & 7; 714c582b7e3Smrg 715c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 716c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 717c582b7e3Smrg 718c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 719c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 720c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 721c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 722c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 723c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 724c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 725c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 726c582b7e3Smrg left >>= 1; width >>= 1; 727c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16)); 728c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16)); 729c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0); 730c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 731c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0); 732c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 733c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 734c582b7e3Smrg 735c582b7e3Smrg if(id == FOURCC_UYVY) 736c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03); 737c582b7e3Smrg else 738c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03); 739c582b7e3Smrg 740c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 741c582b7e3Smrg} 742c582b7e3Smrg 743c582b7e3Smrgstatic void 744c582b7e3SmrgR128DisplayVideo420( 745c582b7e3Smrg ScrnInfoPtr pScrn, 746c582b7e3Smrg short width, short height, 747c582b7e3Smrg int pitch, 748c582b7e3Smrg int offset1, int offset2, int offset3, 749c582b7e3Smrg int left, int right, int top, 750c582b7e3Smrg BoxPtr dstBox, 751c582b7e3Smrg short src_w, short src_h, 752c582b7e3Smrg short drw_w, short drw_h 753c582b7e3Smrg){ 754c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 755e3d74329Smrg R128EntPtr pR128Ent = R128EntPriv(pScrn); 756e3d74329Smrg xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]); 757e3d74329Smrg R128OutputPrivatePtr r128_output = output->driver_private; 758c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 759c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 76042a55b46Smrg int v_inc, h_inc, step_by, tmp, leftUV, v_inc_shift; 761c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 762c582b7e3Smrg int p1_v_accum_init, p23_v_accum_init; 763e3d74329Smrg Bool rmx_active = FALSE; 76442a55b46Smrg 76542a55b46Smrg v_inc_shift = 20; 76642a55b46Smrg if (pScrn->currentMode->Flags & V_INTERLACE) 76742a55b46Smrg v_inc_shift++; 76842a55b46Smrg if (pScrn->currentMode->Flags & V_DBLSCAN) 76942a55b46Smrg v_inc_shift--; 7700496e070Smrg 771e3d74329Smrg if (r128_output->PanelYRes > 0) 772e3d74329Smrg rmx_active = INREG(R128_FP_VERT_STRETCH) & R128_VERT_STRETCH_ENABLE; 77342a55b46Smrg if (rmx_active) { 774e3d74329Smrg v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / r128_output->PanelYRes) << v_inc_shift) / drw_h; 77542a55b46Smrg } else { 77642a55b46Smrg v_inc = (src_h << v_inc_shift) / drw_h; 77742a55b46Smrg } 778c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 779c582b7e3Smrg step_by = 1; 780c582b7e3Smrg 781c582b7e3Smrg while(h_inc >= (2 << 12)) { 782c582b7e3Smrg step_by++; 783c582b7e3Smrg h_inc >>= 1; 784c582b7e3Smrg } 785c582b7e3Smrg 786c582b7e3Smrg /* keep everything in 16.16 */ 787c582b7e3Smrg 788c582b7e3Smrg offset1 += (left >> 16) & ~15; 789c582b7e3Smrg offset2 += (left >> 17) & ~15; 790c582b7e3Smrg offset3 += (left >> 17) & ~15; 791c582b7e3Smrg 792c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 793c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 794c582b7e3Smrg ((tmp << 12) & 0xf0000000); 795c582b7e3Smrg 796c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 797c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 798c582b7e3Smrg ((tmp << 12) & 0x70000000); 799c582b7e3Smrg 800c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 801c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 802c582b7e3Smrg 803c582b7e3Smrg tmp = ((top >> 1) & 0x0000ffff) + 0x00018000; 804c582b7e3Smrg p23_v_accum_init = ((tmp << 4) & 0x01ff8000) | 0x00000001; 805c582b7e3Smrg 806c582b7e3Smrg leftUV = (left >> 17) & 15; 807c582b7e3Smrg left = (left >> 16) & 15; 808c582b7e3Smrg 809c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 810c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 811c582b7e3Smrg 812c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 813c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 814c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 815c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 816c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 817c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 818c582b7e3Smrg src_h = (src_h + 1) >> 1; 819c582b7e3Smrg OUTREG(R128_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | ((src_h - 1) << 16)); 820c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 821c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1); 822c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 823c582b7e3Smrg width >>= 1; 824c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16)); 825c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16)); 826c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); 827c582b7e3Smrg OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, (offset2 & 0xfffffff0) | 0x00000001); 828c582b7e3Smrg OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, (offset3 & 0xfffffff0) | 0x00000001); 829c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 830c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); 831c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 832c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 833c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03); 834c582b7e3Smrg 835c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 836c582b7e3Smrg} 837c582b7e3Smrg 838c582b7e3Smrg 839c582b7e3Smrg 840c582b7e3Smrgstatic int 841c582b7e3SmrgR128PutImage( 842c582b7e3Smrg ScrnInfoPtr pScrn, 843c582b7e3Smrg short src_x, short src_y, 844c582b7e3Smrg short drw_x, short drw_y, 845c582b7e3Smrg short src_w, short src_h, 846c582b7e3Smrg short drw_w, short drw_h, 847c582b7e3Smrg int id, unsigned char* buf, 848c582b7e3Smrg short width, short height, 849c582b7e3Smrg Bool Sync, 850c582b7e3Smrg RegionPtr clipBoxes, pointer data, 851c582b7e3Smrg DrawablePtr pDraw 852c582b7e3Smrg){ 853c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 854c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 855e3d74329Smrg unsigned char *fb = (uint8_t*)info->FB; 856c582b7e3Smrg INT32 xa, xb, ya, yb; 857c582b7e3Smrg int new_size, offset, s1offset, s2offset, s3offset; 858c582b7e3Smrg int srcPitch, srcPitch2, dstPitch; 859c582b7e3Smrg int d1line, d2line, d3line, d1offset, d2offset, d3offset; 86042a55b46Smrg int top, left, npixels, nlines; 861c582b7e3Smrg BoxRec dstBox; 862e3d74329Smrg uint32_t tmp; 863e3d74329Smrg 864e3d74329Smrg /* Currently, the video is only visible on the first monitor. 865e3d74329Smrg * In the future we could try to make this smarter, or just implement 866e3d74329Smrg * textured video. */ 867e3d74329Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 868e3d74329Smrg xf86CrtcPtr crtc = xf86_config->crtc[0]; 869e3d74329Smrg 870c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 871c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 872e3d74329Smrg uint32_t config_cntl = INREG(R128_CONFIG_CNTL); 873c582b7e3Smrg 874c582b7e3Smrg /* We need to disable byte swapping, or the data gets mangled */ 875c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl & 876c582b7e3Smrg ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP)); 877c582b7e3Smrg#endif 878c582b7e3Smrg 879c582b7e3Smrg /* 880c582b7e3Smrg * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes 881c582b7e3Smrg * of the source. 882c582b7e3Smrg * 883c582b7e3Smrg * d1offset, d2offset, d3offset - byte offsets to the Y, U and V planes 884c582b7e3Smrg * of the destination. 885c582b7e3Smrg * 886c582b7e3Smrg * offset - byte offset within the framebuffer to where the destination 887c582b7e3Smrg * is stored. 888c582b7e3Smrg * 889c582b7e3Smrg * d1line, d2line, d3line - byte offsets within the destination to the 890c582b7e3Smrg * first displayed scanline in each plane. 891c582b7e3Smrg * 892c582b7e3Smrg */ 893c582b7e3Smrg 894c582b7e3Smrg if(src_w > (drw_w << 4)) 895c582b7e3Smrg drw_w = src_w >> 4; 896c582b7e3Smrg if(src_h > (drw_h << 4)) 897c582b7e3Smrg drw_h = src_h >> 4; 898c582b7e3Smrg 899c582b7e3Smrg /* Clip */ 900c582b7e3Smrg xa = src_x; 901c582b7e3Smrg xb = src_x + src_w; 902c582b7e3Smrg ya = src_y; 903c582b7e3Smrg yb = src_y + src_h; 904c582b7e3Smrg 905c582b7e3Smrg dstBox.x1 = drw_x; 906c582b7e3Smrg dstBox.x2 = drw_x + drw_w; 907c582b7e3Smrg dstBox.y1 = drw_y; 908c582b7e3Smrg dstBox.y2 = drw_y + drw_h; 909c582b7e3Smrg 910c582b7e3Smrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, 911c582b7e3Smrg clipBoxes, width, height)) 912c582b7e3Smrg return Success; 913c582b7e3Smrg 914e3d74329Smrg dstBox.x1 -= crtc->x; 915e3d74329Smrg dstBox.x2 -= crtc->x; 916e3d74329Smrg dstBox.y1 -= crtc->y; 917e3d74329Smrg dstBox.y2 -= crtc->y; 918c582b7e3Smrg 919c582b7e3Smrg switch(id) { 920c582b7e3Smrg case FOURCC_YV12: 921c582b7e3Smrg case FOURCC_I420: 922c582b7e3Smrg srcPitch = (width + 3) & ~3; 923c582b7e3Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 924c582b7e3Smrg dstPitch = (width + 31) & ~31; /* of luma */ 92542a55b46Smrg new_size = dstPitch * (height + (height >> 1)); 926c582b7e3Smrg s1offset = 0; 927c582b7e3Smrg s2offset = srcPitch * height; 928c582b7e3Smrg s3offset = (srcPitch2 * (height >> 1)) + s2offset; 929c582b7e3Smrg break; 930c582b7e3Smrg case FOURCC_UYVY: 931c582b7e3Smrg case FOURCC_YUY2: 932c582b7e3Smrg default: 933c582b7e3Smrg srcPitch = width << 1; 934c582b7e3Smrg srcPitch2 = 0; 935c582b7e3Smrg dstPitch = ((width << 1) + 15) & ~15; 93642a55b46Smrg new_size = dstPitch * height; 937c582b7e3Smrg s1offset = 0; 938c582b7e3Smrg s2offset = 0; 939c582b7e3Smrg s3offset = 0; 940c582b7e3Smrg break; 941c582b7e3Smrg } 942c582b7e3Smrg 943e3d74329Smrg pPriv->videoOffset = R128AllocateMemory(pScrn, &(pPriv->BufferHandle), 944e3d74329Smrg pPriv->doubleBuffer ? (new_size << 1) : new_size, 945e3d74329Smrg 64, FALSE); 946e3d74329Smrg 947e3d74329Smrg if (pPriv->videoOffset == 0) 948e3d74329Smrg return BadAlloc; 949c582b7e3Smrg 950c582b7e3Smrg pPriv->currentBuffer ^= 1; 951c582b7e3Smrg 952c582b7e3Smrg /* copy data */ 953c582b7e3Smrg top = ya >> 16; 954c582b7e3Smrg left = (xa >> 16) & ~1; 955c582b7e3Smrg npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; 956c582b7e3Smrg 95742a55b46Smrg offset = pPriv->videoOffset; 958c582b7e3Smrg if(pPriv->doubleBuffer) 95942a55b46Smrg offset += pPriv->currentBuffer * new_size; 960c582b7e3Smrg 961c582b7e3Smrg switch(id) { 962c582b7e3Smrg case FOURCC_YV12: 963c582b7e3Smrg case FOURCC_I420: 964c582b7e3Smrg d1line = top * dstPitch; 965c582b7e3Smrg d2line = (height * dstPitch) + ((top >> 1) * (dstPitch >> 1)); 966c582b7e3Smrg d3line = d2line + ((height >> 1) * (dstPitch >> 1)); 967c582b7e3Smrg 968c582b7e3Smrg top &= ~1; 969c582b7e3Smrg 970c582b7e3Smrg d1offset = (top * dstPitch) + left + offset; 971c582b7e3Smrg d2offset = d2line + (left >> 1) + offset; 972c582b7e3Smrg d3offset = d3line + (left >> 1) + offset; 973c582b7e3Smrg 974c582b7e3Smrg s1offset += (top * srcPitch) + left; 975c582b7e3Smrg tmp = ((top >> 1) * srcPitch2) + (left >> 1); 976c582b7e3Smrg s2offset += tmp; 977c582b7e3Smrg s3offset += tmp; 978c582b7e3Smrg if(id == FOURCC_YV12) { 979c582b7e3Smrg tmp = s2offset; 980c582b7e3Smrg s2offset = s3offset; 981c582b7e3Smrg s3offset = tmp; 982c582b7e3Smrg } 983c582b7e3Smrg 984c582b7e3Smrg nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; 985c582b7e3Smrg R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset, 986c582b7e3Smrg fb + d1offset, fb + d2offset, fb + d3offset, 987c582b7e3Smrg srcPitch, srcPitch2, dstPitch, nlines, npixels); 988c582b7e3Smrg break; 989c582b7e3Smrg case FOURCC_UYVY: 990c582b7e3Smrg case FOURCC_YUY2: 991c582b7e3Smrg default: 992c582b7e3Smrg left <<= 1; 993c582b7e3Smrg d1line = top * dstPitch; 994c582b7e3Smrg d2line = 0; 995c582b7e3Smrg d3line = 0; 996c582b7e3Smrg d1offset = d1line + left + offset; 997c582b7e3Smrg d2offset = 0; 998c582b7e3Smrg d3offset = 0; 999c582b7e3Smrg s1offset += (top * srcPitch) + left; 1000c582b7e3Smrg nlines = ((yb + 0xffff) >> 16) - top; 1001c582b7e3Smrg R128CopyData422(info, buf + s1offset, fb + d1offset, 1002c582b7e3Smrg srcPitch, dstPitch, nlines, npixels); 1003c582b7e3Smrg break; 1004c582b7e3Smrg } 1005c582b7e3Smrg 1006c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 1007c582b7e3Smrg /* restore byte swapping */ 1008c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl); 1009c582b7e3Smrg#endif 1010c582b7e3Smrg 1011c582b7e3Smrg /* update cliplist */ 1012c582b7e3Smrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 1013c582b7e3Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 1014c582b7e3Smrg /* draw these */ 1015c582b7e3Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 1016c582b7e3Smrg } 1017c582b7e3Smrg 1018c582b7e3Smrg 1019c582b7e3Smrg switch(id) { 1020c582b7e3Smrg case FOURCC_YV12: 1021c582b7e3Smrg case FOURCC_I420: 1022c582b7e3Smrg R128DisplayVideo420(pScrn, width, height, dstPitch, 1023c582b7e3Smrg offset + d1line, offset + d2line, offset + d3line, 1024c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 1025c582b7e3Smrg break; 1026c582b7e3Smrg case FOURCC_UYVY: 1027c582b7e3Smrg case FOURCC_YUY2: 1028c582b7e3Smrg default: 1029c582b7e3Smrg R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch, 1030c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 1031c582b7e3Smrg break; 1032c582b7e3Smrg } 1033c582b7e3Smrg 1034c582b7e3Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 1035c582b7e3Smrg 1036c582b7e3Smrg info->VideoTimerCallback = R128VideoTimerCallback; 1037c582b7e3Smrg 1038c582b7e3Smrg return Success; 1039c582b7e3Smrg} 1040c582b7e3Smrg 1041c582b7e3Smrg 1042c582b7e3Smrgstatic int 1043c582b7e3SmrgR128QueryImageAttributes( 1044c582b7e3Smrg ScrnInfoPtr pScrn, 1045c582b7e3Smrg int id, 1046c582b7e3Smrg unsigned short *w, unsigned short *h, 1047c582b7e3Smrg int *pitches, int *offsets 1048c582b7e3Smrg){ 1049c582b7e3Smrg int size, tmp; 1050c582b7e3Smrg 1051c582b7e3Smrg if(*w > MAXWIDTH) *w = MAXWIDTH; 1052c582b7e3Smrg if(*h > MAXHEIGHT) *h = MAXHEIGHT; 1053c582b7e3Smrg 1054c582b7e3Smrg *w = (*w + 1) & ~1; 1055c582b7e3Smrg if(offsets) offsets[0] = 0; 1056c582b7e3Smrg 1057c582b7e3Smrg switch(id) { 1058c582b7e3Smrg case FOURCC_YV12: 1059c582b7e3Smrg case FOURCC_I420: 1060c582b7e3Smrg *h = (*h + 1) & ~1; 1061c582b7e3Smrg size = (*w + 3) & ~3; 1062c582b7e3Smrg if(pitches) pitches[0] = size; 1063c582b7e3Smrg size *= *h; 1064c582b7e3Smrg if(offsets) offsets[1] = size; 1065c582b7e3Smrg tmp = ((*w >> 1) + 3) & ~3; 1066c582b7e3Smrg if(pitches) pitches[1] = pitches[2] = tmp; 1067c582b7e3Smrg tmp *= (*h >> 1); 1068c582b7e3Smrg size += tmp; 1069c582b7e3Smrg if(offsets) offsets[2] = size; 1070c582b7e3Smrg size += tmp; 1071c582b7e3Smrg break; 1072c582b7e3Smrg case FOURCC_UYVY: 1073c582b7e3Smrg case FOURCC_YUY2: 1074c582b7e3Smrg default: 1075c582b7e3Smrg size = *w << 1; 1076c582b7e3Smrg if(pitches) pitches[0] = size; 1077c582b7e3Smrg size *= *h; 1078c582b7e3Smrg break; 1079c582b7e3Smrg } 1080c582b7e3Smrg 1081c582b7e3Smrg return size; 1082c582b7e3Smrg} 1083c582b7e3Smrg 1084c582b7e3Smrgstatic void 1085c582b7e3SmrgR128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) 1086c582b7e3Smrg{ 1087c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1088c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 1089c582b7e3Smrg 1090c582b7e3Smrg if(pPriv->videoStatus & TIMER_MASK) { 1091c582b7e3Smrg if(pPriv->videoStatus & OFF_TIMER) { 1092c582b7e3Smrg if(pPriv->offTime < now) { 1093c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1094c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0); 1095c582b7e3Smrg pPriv->videoStatus = FREE_TIMER; 1096c582b7e3Smrg pPriv->freeTime = now + FREE_DELAY; 1097c582b7e3Smrg } 1098c582b7e3Smrg } else { /* FREE_TIMER */ 1099c582b7e3Smrg if(pPriv->freeTime < now) { 110042a55b46Smrg if(pPriv->BufferHandle) { 110142a55b46Smrg if (!info->useEXA) { 110242a55b46Smrg xf86FreeOffscreenLinear((FBLinearPtr) pPriv->BufferHandle); 110342a55b46Smrg } 110442a55b46Smrg#ifdef USE_EXA 110542a55b46Smrg else { 110642a55b46Smrg exaOffscreenFree(pScrn->pScreen, (ExaOffscreenArea *) pPriv->BufferHandle); 110742a55b46Smrg } 110842a55b46Smrg#endif 110942a55b46Smrg pPriv->BufferHandle = NULL; 1110c582b7e3Smrg } 1111c582b7e3Smrg pPriv->videoStatus = 0; 1112c582b7e3Smrg info->VideoTimerCallback = NULL; 1113c582b7e3Smrg } 1114c582b7e3Smrg } 1115c582b7e3Smrg } else /* shouldn't get here */ 1116c582b7e3Smrg info->VideoTimerCallback = NULL; 1117c582b7e3Smrg} 1118