radeon_video.c revision 40732134
1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include <stdlib.h> 7#include <string.h> 8#include <stdio.h> 9#include <math.h> 10 11#include "radeon.h" 12#include "radeon_reg.h" 13#include "radeon_macros.h" 14#include "radeon_probe.h" 15#include "radeon_video.h" 16 17#include "xf86.h" 18#include "dixstruct.h" 19#include "atipciids.h" 20#include "xf86fbman.h" 21 22#include <X11/extensions/Xv.h> 23#include "fourcc.h" 24 25#include "theatre_detect.h" 26#include "theatre_reg.h" 27#include "fi1236.h" 28#include "msp3430.h" 29#include "tda9885.h" 30 31#define OFF_DELAY 250 /* milliseconds */ 32#define FREE_DELAY 15000 33 34#define OFF_TIMER 0x01 35#define FREE_TIMER 0x02 36#define CLIENT_VIDEO_ON 0x04 37 38#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 39 40/* capture config constants */ 41#define BUF_TYPE_FIELD 0 42#define BUF_TYPE_ALTERNATING 1 43#define BUF_TYPE_FRAME 2 44 45 46#define BUF_MODE_SINGLE 0 47#define BUF_MODE_DOUBLE 1 48#define BUF_MODE_TRIPLE 2 49/* CAP0_CONFIG values */ 50 51#define FORMAT_BROOKTREE 0 52#define FORMAT_CCIR656 1 53#define FORMAT_ZV 2 54#define FORMAT_VIP16 3 55#define FORMAT_TRANSPORT 4 56 57#define ENABLE_RADEON_CAPTURE_WEAVE (RADEON_CAP0_CONFIG_CONTINUOS \ 58 | (BUF_MODE_DOUBLE <<7) \ 59 | (BUF_TYPE_FRAME << 4) \ 60 | ( (pPriv->theatre !=NULL)?(FORMAT_CCIR656<<23):(FORMAT_BROOKTREE<<23)) \ 61 | RADEON_CAP0_CONFIG_HORZ_DECIMATOR \ 62 | (pPriv->capture_vbi_data ? RADEON_CAP0_CONFIG_VBI_EN : 0) \ 63 | RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422) 64 65#define ENABLE_RADEON_CAPTURE_BOB (RADEON_CAP0_CONFIG_CONTINUOS \ 66 | (BUF_MODE_SINGLE <<7) \ 67 | (BUF_TYPE_ALTERNATING << 4) \ 68 | ( (pPriv->theatre !=NULL)?(FORMAT_CCIR656<<23):(FORMAT_BROOKTREE<<23)) \ 69 | RADEON_CAP0_CONFIG_HORZ_DECIMATOR \ 70 | (pPriv->capture_vbi_data ? RADEON_CAP0_CONFIG_VBI_EN : 0) \ 71 | RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422) 72 73 74static void RADEONInitOffscreenImages(ScreenPtr); 75 76static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr); 77static int RADEONPutImage(ScrnInfoPtr, short, short, short, short, short, 78 short, short, short, int, unsigned char*, short, 79 short, Bool, RegionPtr, pointer, 80 DrawablePtr); 81static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); 82static int RADEONPutVideo(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, 83 short src_w, short src_h, short drw_w, short drw_h, 84 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw); 85 86static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv); 87static void RADEON_RT_SetEncoding(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); 88static void RADEON_MSP_SetEncoding(RADEONPortPrivPtr pPriv); 89static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv); 90static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv); 91 92static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; 93static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; 94static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; 95static Atom xvGamma, xvColorspace; 96static Atom xvCRTC; 97static Atom xvEncoding, xvFrequency, xvVolume, xvMute, 98 xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation, 99 xvTunerStatus, xvSAP, xvOverlayDeinterlacingMethod, 100 xvLocationID, xvDeviceID, xvInstanceID, xvDumpStatus, 101 xvAdjustment; 102 103static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; 104 105#define GET_PORT_PRIVATE(pScrn) \ 106 (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 107 108static void 109radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) 110{ 111 dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; 112 dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; 113 dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; 114 dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; 115 116 if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) 117 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 118} 119 120static void 121radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) 122{ 123 if (crtc->enabled) { 124 crtc_box->x1 = crtc->x; 125 crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); 126 crtc_box->y1 = crtc->y; 127 crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); 128 } else 129 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; 130} 131 132static int 133radeon_box_area(BoxPtr box) 134{ 135 return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); 136} 137 138xf86CrtcPtr 139radeon_pick_best_crtc(ScrnInfoPtr pScrn, 140 int x1, int x2, int y1, int y2) 141{ 142 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 143 int coverage, best_coverage, c; 144 BoxRec box, crtc_box, cover_box; 145 RROutputPtr primary_output = NULL; 146 xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL; 147 148 box.x1 = x1; 149 box.x2 = x2; 150 box.y1 = y1; 151 box.y2 = y2; 152 best_coverage = 0; 153 154 /* Prefer the CRTC of the primary output */ 155 if (dixPrivateKeyRegistered(rrPrivKey)) { 156 primary_output = RRFirstOutput(pScrn->pScreen); 157 } 158 if (primary_output && primary_output->crtc) 159 primary_crtc = primary_output->crtc->devPrivate; 160 161 for (c = 0; c < xf86_config->num_crtc; c++) { 162 xf86CrtcPtr crtc = xf86_config->crtc[c]; 163 radeon_crtc_box(crtc, &crtc_box); 164 radeon_box_intersect(&cover_box, &crtc_box, &box); 165 coverage = radeon_box_area(&cover_box); 166 if (coverage > best_coverage || 167 (coverage == best_coverage && crtc == primary_crtc)) { 168 best_crtc = crtc; 169 best_coverage = coverage; 170 } 171 } 172 return best_crtc; 173} 174 175#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER 176static xf86CrtcPtr 177radeon_covering_crtc(ScrnInfoPtr pScrn, 178 BoxPtr box, 179 xf86CrtcPtr desired, 180 BoxPtr crtc_box_ret) 181{ 182 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 183 xf86CrtcPtr crtc, best_crtc; 184 int coverage, best_coverage; 185 int c; 186 BoxRec crtc_box, cover_box; 187 188 best_crtc = NULL; 189 best_coverage = 0; 190 crtc_box_ret->x1 = 0; 191 crtc_box_ret->x2 = 0; 192 crtc_box_ret->y1 = 0; 193 crtc_box_ret->y2 = 0; 194 for (c = 0; c < xf86_config->num_crtc; c++) { 195 crtc = xf86_config->crtc[c]; 196 radeon_crtc_box(crtc, &crtc_box); 197 radeon_box_intersect(&cover_box, &crtc_box, box); 198 coverage = radeon_box_area(&cover_box); 199 if (coverage && crtc == desired) { 200 *crtc_box_ret = crtc_box; 201 return crtc; 202 } else if (coverage > best_coverage) { 203 *crtc_box_ret = crtc_box; 204 best_crtc = crtc; 205 best_coverage = coverage; 206 } 207 } 208 return best_crtc; 209} 210 211static Bool 212radeon_crtc_clip_video_helper(ScrnInfoPtr pScrn, 213 xf86CrtcPtr *crtc_ret, 214 xf86CrtcPtr desired_crtc, 215 BoxPtr dst, 216 INT32 *xa, 217 INT32 *xb, 218 INT32 *ya, 219 INT32 *yb, 220 RegionPtr reg, 221 INT32 width, 222 INT32 height) 223{ 224 Bool ret; 225 RegionRec crtc_region_local; 226 RegionPtr crtc_region = reg; 227 228 /* 229 * For overlay video, compute the relevant CRTC and 230 * clip video to that 231 */ 232 if (crtc_ret) { 233 BoxRec crtc_box; 234 xf86CrtcPtr crtc = radeon_covering_crtc(pScrn, dst, 235 desired_crtc, 236 &crtc_box); 237 238 if (crtc) { 239 REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); 240 crtc_region = &crtc_region_local; 241 REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); 242 } 243 *crtc_ret = crtc; 244 } 245 246 ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, 247 crtc_region, width, height); 248 249 if (crtc_region != reg) 250 REGION_UNINIT (pScreen, &crtc_region_local); 251 252 return ret; 253} 254#endif 255 256static Bool 257radeon_crtc_clip_video(ScrnInfoPtr pScrn, 258 xf86CrtcPtr *crtc_ret, 259 xf86CrtcPtr desired_crtc, 260 BoxPtr dst, 261 INT32 *xa, 262 INT32 *xb, 263 INT32 *ya, 264 INT32 *yb, 265 RegionPtr reg, 266 INT32 width, 267 INT32 height) 268{ 269#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER 270 return radeon_crtc_clip_video_helper(pScrn, crtc_ret, desired_crtc, 271 dst, xa, xb, ya, yb, 272 reg, width, height); 273#else 274 return xf86_crtc_clip_video_helper(pScrn, crtc_ret, desired_crtc, 275 dst, xa, xb, ya, yb, 276 reg, width, height); 277#endif 278} 279 280void RADEONInitVideo(ScreenPtr pScreen) 281{ 282 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 283 RADEONInfoPtr info = RADEONPTR(pScrn); 284 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 285 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 286 XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; 287 int num_adaptors; 288 289 /* no overlay or 3D on RN50 */ 290 if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) 291 return; 292 293 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 294 newAdaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); 295 if (newAdaptors == NULL) 296 return; 297 298 memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 299 adaptors = newAdaptors; 300 301 if (!IS_AVIVO_VARIANT && !info->kms_enabled) { 302 overlayAdaptor = RADEONSetupImageVideo(pScreen); 303 if (overlayAdaptor != NULL) { 304 adaptors[num_adaptors++] = overlayAdaptor; 305 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n"); 306 } else 307 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up overlay video\n"); 308 RADEONInitOffscreenImages(pScreen); 309 } 310 311 if ((info->ChipFamily < CHIP_FAMILY_RS400) 312#ifdef XF86DRI 313 || (info->directRenderingEnabled) 314#endif 315 ) { 316 texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen); 317 if (texturedAdaptor != NULL) { 318 adaptors[num_adaptors++] = texturedAdaptor; 319 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); 320 } else 321 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n"); 322 } else 323 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textured video requires CP on R5xx/R6xx/R7xx/IGP\n"); 324 325 if(num_adaptors) 326 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 327 328 if(texturedAdaptor) { 329 XF86MCAdaptorPtr xvmcAdaptor = RADEONCreateAdaptorXvMC(pScreen, texturedAdaptor->name); 330 if(xvmcAdaptor) { 331 if(!xf86XvMCScreenInit(pScreen, 1, &xvmcAdaptor)) 332 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] Failed to initialize extension.\n"); 333 else 334 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[XvMC] Extension initialized.\n"); 335 } 336 } 337 338 if(newAdaptors) 339 free(newAdaptors); 340 341} 342 343/* client libraries expect an encoding */ 344static XF86VideoEncodingRec DummyEncoding = 345{ 346 0, 347 "XV_IMAGE", 348 2047, 2047, 349 {1, 1} 350}; 351 352 /* the picture is interlaced - hence the half-heights */ 353 354static XF86VideoEncodingRec 355InputVideoEncodings[] = 356{ 357 { 0, "XV_IMAGE", 2047,2047,{1,1}}, 358 { 1, "pal-composite", 720, 288, { 1, 50 }}, 359 { 2, "pal-tuner", 720, 288, { 1, 50 }}, 360 { 3, "pal-svideo", 720, 288, { 1, 50 }}, 361 { 4, "ntsc-composite", 640, 240, { 1001, 60000 }}, 362 { 5, "ntsc-tuner", 640, 240, { 1001, 60000 }}, 363 { 6, "ntsc-svideo", 640, 240, { 1001, 60000 }}, 364 { 7, "secam-composite", 720, 288, { 1, 50 }}, 365 { 8, "secam-tuner", 720, 288, { 1, 50 }}, 366 { 9, "secam-svideo", 720, 288, { 1, 50 }}, 367 { 10,"pal_60-composite", 768, 288, { 1, 50 }}, 368 { 11,"pal_60-tuner", 768, 288, { 1, 50 }}, 369 { 12,"pal_60-svideo", 768, 288, { 1, 50 }} 370}; 371 372 373#define NUM_FORMATS 12 374 375static XF86VideoFormatRec Formats[NUM_FORMATS] = 376{ 377 {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, 378 {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, 379 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 380 {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 381}; 382 383 384#if 0 385#define NUM_ATTRIBUTES 9+6 386 387static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 388{ 389 {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, 390 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 391 {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"}, 392 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 393 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 394 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 395 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 396 {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"}, 397 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 398 {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, 399 {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, 400 {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, 401 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 402 {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, 403 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 404}; 405 406#endif 407 408#define NUM_ATTRIBUTES 22 409#define NUM_DEC_ATTRIBUTES (NUM_ATTRIBUTES+12) 410 411static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] = 412{ 413 { XvGettable, 0, ~0, "XV_DEVICE_ID"}, 414 { XvGettable, 0, ~0, "XV_LOCATION_ID"}, 415 { XvGettable, 0, ~0, "XV_INSTANCE_ID"}, 416 {XvSettable , 0, 1, "XV_DUMP_STATUS"}, 417 {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, 418 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 419 {XvSettable | XvGettable, 0, ~0,"XV_COLORKEY"}, 420 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 421 {XvSettable | XvGettable, 0, 255, "XV_OVERLAY_ALPHA"}, 422 {XvSettable | XvGettable, 0, 255, "XV_GRAPHICS_ALPHA"}, 423 {XvSettable | XvGettable, 0, 1, "XV_ALPHA_MODE"}, 424 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 425 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 426 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 427 {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"}, 428 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, 429 {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, 430 {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, 431 {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, 432 {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, 433 {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, 434 {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, 435 436 {XvSettable | XvGettable, -1000, 1000, "XV_DEC_BRIGHTNESS"}, 437 {XvSettable | XvGettable, -1000, 1000, "XV_DEC_CONTRAST"}, 438 {XvSettable | XvGettable, -1000, 1000, "XV_DEC_SATURATION"}, 439 {XvSettable | XvGettable, -1000, 1000, "XV_DEC_HUE"}, 440 {XvSettable | XvGettable, 0, 2, "XV_OVERLAY_DEINTERLACING_METHOD"}, 441 {XvSettable | XvGettable, 0, 12, "XV_ENCODING"}, 442 {XvSettable | XvGettable, 0, -1, "XV_FREQ"}, 443 { XvGettable, -1000, 1000, "XV_TUNER_STATUS"}, 444 {XvSettable | XvGettable, -1000, 1000, "XV_VOLUME"}, 445 {XvSettable | XvGettable, 0, 1, "XV_MUTE"}, 446 {XvSettable | XvGettable, 0, 1, "XV_SAP"}, 447 {XvSettable | XvGettable, 0, 0x1F, "XV_DEBUG_ADJUSTMENT"}, 448 { 0, 0, 0, NULL} /* just a place holder so I don't have to be fancy with commas */ 449}; 450 451 452#define INCLUDE_RGB_FORMATS 1 453 454#if INCLUDE_RGB_FORMATS 455 456#define NUM_IMAGES 8 457 458/* Note: GUIDs are bogus... - but nothing uses them anyway */ 459 460#define FOURCC_RGBA32 0x41424752 461 462#define XVIMAGE_RGBA32(byte_order) \ 463 { \ 464 FOURCC_RGBA32, \ 465 XvRGB, \ 466 byte_order, \ 467 { 'R', 'G', 'B', 'A', \ 468 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 469 32, \ 470 XvPacked, \ 471 1, \ 472 32, 0x00FF0000, 0x0000FF00, 0x000000FF, \ 473 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 474 {'A', 'R', 'G', 'B', \ 475 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 476 XvTopToBottom \ 477 } 478 479#define FOURCC_RGB24 0x00000000 480 481#define XVIMAGE_RGB24 \ 482 { \ 483 FOURCC_RGB24, \ 484 XvRGB, \ 485 LSBFirst, \ 486 { 'R', 'G', 'B', 0, \ 487 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 488 24, \ 489 XvPacked, \ 490 1, \ 491 24, 0x00FF0000, 0x0000FF00, 0x000000FF, \ 492 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 493 { 'R', 'G', 'B', \ 494 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 495 XvTopToBottom \ 496 } 497 498#define FOURCC_RGBT16 0x54424752 499 500#define XVIMAGE_RGBT16(byte_order) \ 501 { \ 502 FOURCC_RGBT16, \ 503 XvRGB, \ 504 byte_order, \ 505 { 'R', 'G', 'B', 'T', \ 506 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 507 16, \ 508 XvPacked, \ 509 1, \ 510 16, 0x00007C00, 0x000003E0, 0x0000001F, \ 511 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 512 {'A', 'R', 'G', 'B', \ 513 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 514 XvTopToBottom \ 515 } 516 517#define FOURCC_RGB16 0x32424752 518 519#define XVIMAGE_RGB16(byte_order) \ 520 { \ 521 FOURCC_RGB16, \ 522 XvRGB, \ 523 byte_order, \ 524 { 'R', 'G', 'B', 0x00, \ 525 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 526 16, \ 527 XvPacked, \ 528 1, \ 529 16, 0x0000F800, 0x000007E0, 0x0000001F, \ 530 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 531 {'R', 'G', 'B', \ 532 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 533 XvTopToBottom \ 534 } 535 536static XF86ImageRec Images[NUM_IMAGES] = 537{ 538#if X_BYTE_ORDER == X_BIG_ENDIAN 539 XVIMAGE_RGBA32(MSBFirst), 540 XVIMAGE_RGBT16(MSBFirst), 541 XVIMAGE_RGB16(MSBFirst), 542#else 543 XVIMAGE_RGBA32(LSBFirst), 544 XVIMAGE_RGBT16(LSBFirst), 545 XVIMAGE_RGB16(LSBFirst), 546#endif 547 XVIMAGE_RGB24, 548 XVIMAGE_YUY2, 549 XVIMAGE_UYVY, 550 XVIMAGE_YV12, 551 XVIMAGE_I420 552}; 553 554#else 555 556#define NUM_IMAGES 4 557 558static XF86ImageRec Images[NUM_IMAGES] = 559{ 560 XVIMAGE_YUY2, 561 XVIMAGE_UYVY, 562 XVIMAGE_YV12, 563 XVIMAGE_I420 564}; 565 566#endif 567 568/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */ 569static REF_TRANSFORM trans[2] = 570{ 571 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */ 572 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */ 573}; 574 575/* Gamma curve definition for preset gammas */ 576typedef struct tagGAMMA_CURVE_R100 577{ 578 uint32_t GAMMA_0_F_SLOPE; 579 uint32_t GAMMA_0_F_OFFSET; 580 uint32_t GAMMA_10_1F_SLOPE; 581 uint32_t GAMMA_10_1F_OFFSET; 582 uint32_t GAMMA_20_3F_SLOPE; 583 uint32_t GAMMA_20_3F_OFFSET; 584 uint32_t GAMMA_40_7F_SLOPE; 585 uint32_t GAMMA_40_7F_OFFSET; 586 uint32_t GAMMA_380_3BF_SLOPE; 587 uint32_t GAMMA_380_3BF_OFFSET; 588 uint32_t GAMMA_3C0_3FF_SLOPE; 589 uint32_t GAMMA_3C0_3FF_OFFSET; 590 float OvGammaCont; 591} GAMMA_CURVE_R100; 592 593typedef struct tagGAMMA_CURVE_R200 594{ 595 uint32_t GAMMA_0_F_SLOPE; 596 uint32_t GAMMA_0_F_OFFSET; 597 uint32_t GAMMA_10_1F_SLOPE; 598 uint32_t GAMMA_10_1F_OFFSET; 599 uint32_t GAMMA_20_3F_SLOPE; 600 uint32_t GAMMA_20_3F_OFFSET; 601 uint32_t GAMMA_40_7F_SLOPE; 602 uint32_t GAMMA_40_7F_OFFSET; 603 uint32_t GAMMA_80_BF_SLOPE; 604 uint32_t GAMMA_80_BF_OFFSET; 605 uint32_t GAMMA_C0_FF_SLOPE; 606 uint32_t GAMMA_C0_FF_OFFSET; 607 uint32_t GAMMA_100_13F_SLOPE; 608 uint32_t GAMMA_100_13F_OFFSET; 609 uint32_t GAMMA_140_17F_SLOPE; 610 uint32_t GAMMA_140_17F_OFFSET; 611 uint32_t GAMMA_180_1BF_SLOPE; 612 uint32_t GAMMA_180_1BF_OFFSET; 613 uint32_t GAMMA_1C0_1FF_SLOPE; 614 uint32_t GAMMA_1C0_1FF_OFFSET; 615 uint32_t GAMMA_200_23F_SLOPE; 616 uint32_t GAMMA_200_23F_OFFSET; 617 uint32_t GAMMA_240_27F_SLOPE; 618 uint32_t GAMMA_240_27F_OFFSET; 619 uint32_t GAMMA_280_2BF_SLOPE; 620 uint32_t GAMMA_280_2BF_OFFSET; 621 uint32_t GAMMA_2C0_2FF_SLOPE; 622 uint32_t GAMMA_2C0_2FF_OFFSET; 623 uint32_t GAMMA_300_33F_SLOPE; 624 uint32_t GAMMA_300_33F_OFFSET; 625 uint32_t GAMMA_340_37F_SLOPE; 626 uint32_t GAMMA_340_37F_OFFSET; 627 uint32_t GAMMA_380_3BF_SLOPE; 628 uint32_t GAMMA_380_3BF_OFFSET; 629 uint32_t GAMMA_3C0_3FF_SLOPE; 630 uint32_t GAMMA_3C0_3FF_OFFSET; 631 float OvGammaCont; 632} GAMMA_CURVE_R200; 633 634 635/* Preset gammas */ 636static GAMMA_CURVE_R100 gamma_curve_r100[8] = 637{ 638 /* Gamma 1.0 */ 639 {0x100, 0x0, 640 0x100, 0x20, 641 0x100, 0x40, 642 0x100, 0x80, 643 0x100, 0x100, 644 0x100, 0x100, 645 1.0}, 646 /* Gamma 0.85 */ 647 {0x75, 0x0, 648 0xA2, 0xF, 649 0xAC, 0x23, 650 0xC6, 0x4E, 651 0x129, 0xD6, 652 0x12B, 0xD5, 653 1.0}, 654 /* Gamma 1.1 */ 655 {0x180, 0x0, 656 0x13C, 0x30, 657 0x13C, 0x57, 658 0x123, 0xA5, 659 0xEA, 0x116, 660 0xEA, 0x116, 661 0.9913}, 662 /* Gamma 1.2 */ 663 {0x21B, 0x0, 664 0x16D, 0x43, 665 0x172, 0x71, 666 0x13D, 0xCD, 667 0xD9, 0x128, 668 0xD6, 0x12A, 669 0.9827}, 670 /* Gamma 1.45 */ 671 {0x404, 0x0, 672 0x1B9, 0x81, 673 0x1EE, 0xB8, 674 0x16A, 0x133, 675 0xB7, 0x14B, 676 0xB2, 0x14E, 677 0.9567}, 678 /* Gamma 1.7 */ 679 {0x658, 0x0, 680 0x1B5, 0xCB, 681 0x25F, 0x102, 682 0x181, 0x199, 683 0x9C, 0x165, 684 0x98, 0x167, 685 0.9394}, 686 /* Gamma 2.2 */ 687 {0x7FF, 0x0, 688 0x625, 0x100, 689 0x1E4, 0x1C4, 690 0x1BD, 0x23D, 691 0x79, 0x187, 692 0x76, 0x188, 693 0.9135}, 694 /* Gamma 2.5 */ 695 {0x7FF, 0x0, 696 0x7FF, 0x100, 697 0x2AD, 0x200, 698 0x1A2, 0x2AB, 699 0x6E, 0x194, 700 0x67, 0x197, 701 0.9135} 702}; 703 704static GAMMA_CURVE_R200 gamma_curve_r200[8] = 705 { 706 /* Gamma 1.0 */ 707 {0x00000100, 0x00000000, 708 0x00000100, 0x00000020, 709 0x00000100, 0x00000040, 710 0x00000100, 0x00000080, 711 0x00000100, 0x00000100, 712 0x00000100, 0x00000100, 713 0x00000100, 0x00000200, 714 0x00000100, 0x00000200, 715 0x00000100, 0x00000300, 716 0x00000100, 0x00000300, 717 0x00000100, 0x00000400, 718 0x00000100, 0x00000400, 719 0x00000100, 0x00000500, 720 0x00000100, 0x00000500, 721 0x00000100, 0x00000600, 722 0x00000100, 0x00000600, 723 0x00000100, 0x00000700, 724 0x00000100, 0x00000700, 725 1.0}, 726 /* Gamma 0.85 */ 727 {0x0000001D, 0x00000000, 728 0x00000028, 0x0000000F, 729 0x00000056, 0x00000023, 730 0x000000C5, 0x0000004E, 731 0x000000DA, 0x000000B0, 732 0x000000E6, 0x000000AA, 733 0x000000F1, 0x00000190, 734 0x000000F9, 0x0000018C, 735 0x00000101, 0x00000286, 736 0x00000108, 0x00000282, 737 0x0000010D, 0x0000038A, 738 0x00000113, 0x00000387, 739 0x00000118, 0x0000049A, 740 0x0000011C, 0x00000498, 741 0x00000120, 0x000005B4, 742 0x00000124, 0x000005B2, 743 0x00000128, 0x000006D6, 744 0x0000012C, 0x000006D5, 745 1.0}, 746 /* Gamma 1.1 */ 747 {0x00000060, 0x00000000, 748 0x0000004F, 0x00000030, 749 0x0000009C, 0x00000057, 750 0x00000121, 0x000000A5, 751 0x00000113, 0x00000136, 752 0x0000010B, 0x0000013A, 753 0x00000105, 0x00000245, 754 0x00000100, 0x00000247, 755 0x000000FD, 0x00000348, 756 0x000000F9, 0x00000349, 757 0x000000F6, 0x00000443, 758 0x000000F4, 0x00000444, 759 0x000000F2, 0x00000538, 760 0x000000F0, 0x00000539, 761 0x000000EE, 0x00000629, 762 0x000000EC, 0x00000629, 763 0x000000EB, 0x00000716, 764 0x000000E9, 0x00000717, 765 0.9913}, 766 /* Gamma 1.2 */ 767 {0x00000087, 0x00000000, 768 0x0000005B, 0x00000043, 769 0x000000B7, 0x00000071, 770 0x0000013D, 0x000000CD, 771 0x00000121, 0x0000016B, 772 0x00000113, 0x00000172, 773 0x00000107, 0x00000286, 774 0x000000FF, 0x0000028A, 775 0x000000F8, 0x00000389, 776 0x000000F2, 0x0000038B, 777 0x000000ED, 0x0000047D, 778 0x000000E9, 0x00000480, 779 0x000000E5, 0x00000568, 780 0x000000E1, 0x0000056A, 781 0x000000DE, 0x0000064B, 782 0x000000DB, 0x0000064D, 783 0x000000D9, 0x00000728, 784 0x000000D6, 0x00000729, 785 0.9827}, 786 /* Gamma 1.45 */ 787 {0x00000101, 0x00000000, 788 0x0000006E, 0x00000081, 789 0x000000F7, 0x000000B8, 790 0x0000016E, 0x00000133, 791 0x00000139, 0x000001EA, 792 0x0000011B, 0x000001F9, 793 0x00000105, 0x00000314, 794 0x000000F6, 0x0000031C, 795 0x000000E9, 0x00000411, 796 0x000000DF, 0x00000417, 797 0x000000D7, 0x000004F6, 798 0x000000CF, 0x000004F9, 799 0x000000C9, 0x000005C9, 800 0x000000C4, 0x000005CC, 801 0x000000BF, 0x0000068F, 802 0x000000BA, 0x00000691, 803 0x000000B6, 0x0000074B, 804 0x000000B2, 0x0000074D, 805 0.9567}, 806 /* Gamma 1.7 */ 807 {0x00000196, 0x00000000, 808 0x0000006D, 0x000000CB, 809 0x0000012F, 0x00000102, 810 0x00000187, 0x00000199, 811 0x00000144, 0x0000025b, 812 0x00000118, 0x00000273, 813 0x000000FE, 0x0000038B, 814 0x000000E9, 0x00000395, 815 0x000000DA, 0x0000047E, 816 0x000000CE, 0x00000485, 817 0x000000C3, 0x00000552, 818 0x000000BB, 0x00000556, 819 0x000000B3, 0x00000611, 820 0x000000AC, 0x00000614, 821 0x000000A7, 0x000006C1, 822 0x000000A1, 0x000006C3, 823 0x0000009D, 0x00000765, 824 0x00000098, 0x00000767, 825 0.9394}, 826 /* Gamma 2.2 */ 827 {0x000001FF, 0x00000000, 828 0x0000018A, 0x00000100, 829 0x000000F1, 0x000001C5, 830 0x000001D6, 0x0000023D, 831 0x00000124, 0x00000328, 832 0x00000116, 0x0000032F, 833 0x000000E2, 0x00000446, 834 0x000000D3, 0x0000044D, 835 0x000000BC, 0x00000520, 836 0x000000B0, 0x00000526, 837 0x000000A4, 0x000005D6, 838 0x0000009B, 0x000005DB, 839 0x00000092, 0x00000676, 840 0x0000008B, 0x00000679, 841 0x00000085, 0x00000704, 842 0x00000080, 0x00000707, 843 0x0000007B, 0x00000787, 844 0x00000076, 0x00000789, 845 0.9135}, 846 /* Gamma 2.5 */ 847 {0x000001FF, 0x00000000, 848 0x000001FF, 0x00000100, 849 0x00000159, 0x000001FF, 850 0x000001AC, 0x000002AB, 851 0x0000012F, 0x00000381, 852 0x00000101, 0x00000399, 853 0x000000D9, 0x0000049A, 854 0x000000C3, 0x000004A5, 855 0x000000AF, 0x00000567, 856 0x000000A1, 0x0000056E, 857 0x00000095, 0x00000610, 858 0x0000008C, 0x00000614, 859 0x00000084, 0x000006A0, 860 0x0000007D, 0x000006A4, 861 0x00000077, 0x00000721, 862 0x00000071, 0x00000723, 863 0x0000006D, 0x00000795, 864 0x00000068, 0x00000797, 865 0.9135} 866}; 867 868static void 869RADEONSetOverlayGamma(ScrnInfoPtr pScrn, uint32_t gamma) 870{ 871 RADEONInfoPtr info = RADEONPTR(pScrn); 872 unsigned char *RADEONMMIO = info->MMIO; 873 874 /* Set gamma */ 875 RADEONWaitForIdleMMIO(pScrn); 876 877 if (info->ChipFamily < CHIP_FAMILY_R200) { 878 uint32_t ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & ~RADEON_SCALER_GAMMA_SEL_MASK; 879 OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (gamma << 5)); 880 } 881 882 /* Load gamma curve adjustments */ 883 if (info->ChipFamily >= CHIP_FAMILY_R200) { 884 OUTREG(RADEON_OV0_GAMMA_000_00F, 885 (gamma_curve_r200[gamma].GAMMA_0_F_OFFSET << 0x00000000) | 886 (gamma_curve_r200[gamma].GAMMA_0_F_SLOPE << 0x00000010)); 887 OUTREG(RADEON_OV0_GAMMA_010_01F, 888 (gamma_curve_r200[gamma].GAMMA_10_1F_OFFSET << 0x00000000) | 889 (gamma_curve_r200[gamma].GAMMA_10_1F_SLOPE << 0x00000010)); 890 OUTREG(RADEON_OV0_GAMMA_020_03F, 891 (gamma_curve_r200[gamma].GAMMA_20_3F_OFFSET << 0x00000000) | 892 (gamma_curve_r200[gamma].GAMMA_20_3F_SLOPE << 0x00000010)); 893 OUTREG(RADEON_OV0_GAMMA_040_07F, 894 (gamma_curve_r200[gamma].GAMMA_40_7F_OFFSET << 0x00000000) | 895 (gamma_curve_r200[gamma].GAMMA_40_7F_SLOPE << 0x00000010)); 896 OUTREG(RADEON_OV0_GAMMA_080_0BF, 897 (gamma_curve_r200[gamma].GAMMA_80_BF_OFFSET << 0x00000000) | 898 (gamma_curve_r200[gamma].GAMMA_80_BF_SLOPE << 0x00000010)); 899 OUTREG(RADEON_OV0_GAMMA_0C0_0FF, 900 (gamma_curve_r200[gamma].GAMMA_C0_FF_OFFSET << 0x00000000) | 901 (gamma_curve_r200[gamma].GAMMA_C0_FF_SLOPE << 0x00000010)); 902 OUTREG(RADEON_OV0_GAMMA_100_13F, 903 (gamma_curve_r200[gamma].GAMMA_100_13F_OFFSET << 0x00000000) | 904 (gamma_curve_r200[gamma].GAMMA_100_13F_SLOPE << 0x00000010)); 905 OUTREG(RADEON_OV0_GAMMA_140_17F, 906 (gamma_curve_r200[gamma].GAMMA_140_17F_OFFSET << 0x00000000) | 907 (gamma_curve_r200[gamma].GAMMA_140_17F_SLOPE << 0x00000010)); 908 OUTREG(RADEON_OV0_GAMMA_180_1BF, 909 (gamma_curve_r200[gamma].GAMMA_180_1BF_OFFSET << 0x00000000) | 910 (gamma_curve_r200[gamma].GAMMA_180_1BF_SLOPE << 0x00000010)); 911 OUTREG(RADEON_OV0_GAMMA_1C0_1FF, 912 (gamma_curve_r200[gamma].GAMMA_1C0_1FF_OFFSET << 0x00000000) | 913 (gamma_curve_r200[gamma].GAMMA_1C0_1FF_SLOPE << 0x00000010)); 914 OUTREG(RADEON_OV0_GAMMA_200_23F, 915 (gamma_curve_r200[gamma].GAMMA_200_23F_OFFSET << 0x00000000) | 916 (gamma_curve_r200[gamma].GAMMA_200_23F_SLOPE << 0x00000010)); 917 OUTREG(RADEON_OV0_GAMMA_240_27F, 918 (gamma_curve_r200[gamma].GAMMA_240_27F_OFFSET << 0x00000000) | 919 (gamma_curve_r200[gamma].GAMMA_240_27F_SLOPE << 0x00000010)); 920 OUTREG(RADEON_OV0_GAMMA_280_2BF, 921 (gamma_curve_r200[gamma].GAMMA_280_2BF_OFFSET << 0x00000000) | 922 (gamma_curve_r200[gamma].GAMMA_280_2BF_SLOPE << 0x00000010)); 923 OUTREG(RADEON_OV0_GAMMA_2C0_2FF, 924 (gamma_curve_r200[gamma].GAMMA_2C0_2FF_OFFSET << 0x00000000) | 925 (gamma_curve_r200[gamma].GAMMA_2C0_2FF_SLOPE << 0x00000010)); 926 OUTREG(RADEON_OV0_GAMMA_300_33F, 927 (gamma_curve_r200[gamma].GAMMA_300_33F_OFFSET << 0x00000000) | 928 (gamma_curve_r200[gamma].GAMMA_300_33F_SLOPE << 0x00000010)); 929 OUTREG(RADEON_OV0_GAMMA_340_37F, 930 (gamma_curve_r200[gamma].GAMMA_340_37F_OFFSET << 0x00000000) | 931 (gamma_curve_r200[gamma].GAMMA_340_37F_SLOPE << 0x00000010)); 932 OUTREG(RADEON_OV0_GAMMA_380_3BF, 933 (gamma_curve_r200[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) | 934 (gamma_curve_r200[gamma].GAMMA_380_3BF_SLOPE << 0x00000010)); 935 OUTREG(RADEON_OV0_GAMMA_3C0_3FF, 936 (gamma_curve_r200[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) | 937 (gamma_curve_r200[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010)); 938 } else { 939 OUTREG(RADEON_OV0_GAMMA_000_00F, 940 (gamma_curve_r100[gamma].GAMMA_0_F_OFFSET << 0x00000000) | 941 (gamma_curve_r100[gamma].GAMMA_0_F_SLOPE << 0x00000010)); 942 OUTREG(RADEON_OV0_GAMMA_010_01F, 943 (gamma_curve_r100[gamma].GAMMA_10_1F_OFFSET << 0x00000000) | 944 (gamma_curve_r100[gamma].GAMMA_10_1F_SLOPE << 0x00000010)); 945 OUTREG(RADEON_OV0_GAMMA_020_03F, 946 (gamma_curve_r100[gamma].GAMMA_20_3F_OFFSET << 0x00000000) | 947 (gamma_curve_r100[gamma].GAMMA_20_3F_SLOPE << 0x00000010)); 948 OUTREG(RADEON_OV0_GAMMA_040_07F, 949 (gamma_curve_r100[gamma].GAMMA_40_7F_OFFSET << 0x00000000) | 950 (gamma_curve_r100[gamma].GAMMA_40_7F_SLOPE << 0x00000010)); 951 OUTREG(RADEON_OV0_GAMMA_380_3BF, 952 (gamma_curve_r100[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) | 953 (gamma_curve_r100[gamma].GAMMA_380_3BF_SLOPE << 0x00000010)); 954 OUTREG(RADEON_OV0_GAMMA_3C0_3FF, 955 (gamma_curve_r100[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) | 956 (gamma_curve_r100[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010)); 957 } 958 959} 960 961static uint32_t 962RADEONTranslateUserGamma(uint32_t user_gamma) 963{ 964 /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */ 965 if (user_gamma <= 925) /* 0.85 */ 966 return 1; 967 else if (user_gamma <= 1050) /* 1.0 */ 968 return 0; 969 else if (user_gamma <= 1150) /* 1.1 */ 970 return 2; 971 else if (user_gamma <= 1325) /* 1.2 */ 972 return 3; 973 else if (user_gamma <= 1575) /* 1.45 */ 974 return 4; 975 else if (user_gamma <= 1950) /* 1.7 */ 976 return 5; 977 else if (user_gamma <= 2350) /* 2.2 */ 978 return 6; 979 else if (user_gamma > 2350) /* 2.5 */ 980 return 7; 981 else 982 return 0; 983} 984 985 986/**************************************************************************** 987 * SetTransform * 988 * Function: Calculates and sets color space transform from supplied * 989 * reference transform, gamma, brightness, contrast, hue and * 990 * saturation. * 991 * Inputs: bright - brightness * 992 * cont - contrast * 993 * sat - saturation * 994 * hue - hue * 995 * red_intensity - intensity of red component * 996 * green_intensity - intensity of green component * 997 * blue_intensity - intensity of blue component * 998 * ref - index to the table of refernce transforms * 999 * user_gamma - gamma value x 1000 (e.g., 1200 = gamma of 1.2) * 1000 * Outputs: NONE * 1001 ****************************************************************************/ 1002 1003static void RADEONSetTransform (ScrnInfoPtr pScrn, 1004 float bright, 1005 float cont, 1006 float sat, 1007 float hue, 1008 float red_intensity, 1009 float green_intensity, 1010 float blue_intensity, 1011 uint32_t ref, 1012 uint32_t user_gamma) 1013{ 1014 RADEONInfoPtr info = RADEONPTR(pScrn); 1015 unsigned char *RADEONMMIO = info->MMIO; 1016 float OvHueSin, OvHueCos; 1017 float CAdjLuma, CAdjOff; 1018 float CAdjRCb, CAdjRCr; 1019 float CAdjGCb, CAdjGCr; 1020 float CAdjBCb, CAdjBCr; 1021 float RedAdj,GreenAdj,BlueAdj; 1022 float OvLuma, OvROff, OvGOff, OvBOff; 1023 float OvRCb, OvRCr; 1024 float OvGCb, OvGCr; 1025 float OvBCb, OvBCr; 1026 float Loff = 64.0; 1027 float Coff = 512.0f; 1028 1029 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff; 1030 uint32_t dwOvRCb, dwOvRCr; 1031 uint32_t dwOvGCb, dwOvGCr; 1032 uint32_t dwOvBCb, dwOvBCr; 1033 uint32_t gamma = 0; 1034 1035 if (ref >= 2) 1036 return; 1037 1038 /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */ 1039 gamma = RADEONTranslateUserGamma(user_gamma); 1040 1041 if (gamma >= 8) 1042 return; 1043 1044 OvHueSin = sin(hue); 1045 OvHueCos = cos(hue); 1046 1047 CAdjLuma = cont * trans[ref].RefLuma; 1048 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0; 1049 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0; 1050 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0; 1051 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0; 1052 1053 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr; 1054 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr; 1055 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr); 1056 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr); 1057 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb; 1058 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb; 1059 1060#if 0 /* default constants */ 1061 CAdjLuma = 1.16455078125; 1062 1063 CAdjRCb = 0.0; 1064 CAdjRCr = 1.59619140625; 1065 CAdjGCb = -0.39111328125; 1066 CAdjGCr = -0.8125; 1067 CAdjBCb = 2.01708984375; 1068 CAdjBCr = 0; 1069#endif 1070 1071 OvLuma = CAdjLuma * gamma_curve_r100[gamma].OvGammaCont; 1072 OvRCb = CAdjRCb * gamma_curve_r100[gamma].OvGammaCont; 1073 OvRCr = CAdjRCr * gamma_curve_r100[gamma].OvGammaCont; 1074 OvGCb = CAdjGCb * gamma_curve_r100[gamma].OvGammaCont; 1075 OvGCr = CAdjGCr * gamma_curve_r100[gamma].OvGammaCont; 1076 OvBCb = CAdjBCb * gamma_curve_r100[gamma].OvGammaCont; 1077 OvBCr = CAdjBCr * gamma_curve_r100[gamma].OvGammaCont; 1078 OvROff = RedAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont - 1079 OvLuma * Loff - (OvRCb + OvRCr) * Coff; 1080 OvGOff = GreenAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont - 1081 OvLuma * Loff - (OvGCb + OvGCr) * Coff; 1082 OvBOff = BlueAdj + CAdjOff * gamma_curve_r100[gamma].OvGammaCont - 1083 OvLuma * Loff - (OvBCb + OvBCr) * Coff; 1084#if 0 /* default constants */ 1085 OvROff = -888.5; 1086 OvGOff = 545; 1087 OvBOff = -1104; 1088#endif 1089 1090 OvROff = ClipValue(OvROff, -2048.0, 2047.5); 1091 OvGOff = ClipValue(OvGOff, -2048.0, 2047.5); 1092 OvBOff = ClipValue(OvBOff, -2048.0, 2047.5); 1093 dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff; 1094 dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff; 1095 dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff; 1096 1097 if(info->ChipFamily == CHIP_FAMILY_RADEON) 1098 { 1099 dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17; 1100 dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1; 1101 dwOvRCr = (((INT32)(OvRCr * 2048.0))&0x7fff)<<17; 1102 dwOvGCb = (((INT32)(OvGCb * 2048.0))&0x7fff)<<1; 1103 dwOvGCr = (((INT32)(OvGCr * 2048.0))&0x7fff)<<17; 1104 dwOvBCb = (((INT32)(OvBCb * 2048.0))&0x7fff)<<1; 1105 dwOvBCr = (((INT32)(OvBCr * 2048.0))&0x7fff)<<17; 1106 } 1107 else 1108 { 1109 dwOvLuma = (((INT32)(OvLuma * 256.0))&0xfff)<<20; 1110 dwOvRCb = (((INT32)(OvRCb * 256.0))&0xfff)<<4; 1111 dwOvRCr = (((INT32)(OvRCr * 256.0))&0xfff)<<20; 1112 dwOvGCb = (((INT32)(OvGCb * 256.0))&0xfff)<<4; 1113 dwOvGCr = (((INT32)(OvGCr * 256.0))&0xfff)<<20; 1114 dwOvBCb = (((INT32)(OvBCb * 256.0))&0xfff)<<4; 1115 dwOvBCr = (((INT32)(OvBCr * 256.0))&0xfff)<<20; 1116 } 1117 1118 /* set gamma */ 1119 RADEONSetOverlayGamma(pScrn, gamma); 1120 1121 /* color transforms */ 1122 OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma); 1123 OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr); 1124 OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma); 1125 OUTREG(RADEON_OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr); 1126 OUTREG(RADEON_OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma); 1127 OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr); 1128} 1129 1130static void RADEONSetOverlayAlpha(ScrnInfoPtr pScrn, int ov_alpha, int gr_alpha, int alpha_mode) 1131{ 1132 RADEONInfoPtr info = RADEONPTR(pScrn); 1133 unsigned char *RADEONMMIO = info->MMIO; 1134 1135 if (alpha_mode == 0) { /* key mode */ 1136 OUTREG(RADEON_OV0_KEY_CNTL, 1137 RADEON_GRAPHIC_KEY_FN_EQ | /* what does this do? */ 1138 RADEON_VIDEO_KEY_FN_FALSE | /* what does this do? */ 1139 RADEON_CMP_MIX_OR); 1140 /* crtc 1 */ 1141 OUTREG(RADEON_DISP_MERGE_CNTL, 1142 (RADEON_DISP_ALPHA_MODE_KEY & 1143 RADEON_DISP_ALPHA_MODE_MASK) | 1144 ((gr_alpha << 0x00000010) & 1145 RADEON_DISP_GRPH_ALPHA_MASK) | 1146 ((ov_alpha << 0x00000018) & 1147 RADEON_DISP_OV0_ALPHA_MASK)); 1148 /* crtc 2 */ 1149 OUTREG(RADEON_DISP2_MERGE_CNTL, 1150 (RADEON_DISP_ALPHA_MODE_KEY & 1151 RADEON_DISP_ALPHA_MODE_MASK) | 1152 ((gr_alpha << 0x00000010) & 1153 RADEON_DISP_GRPH_ALPHA_MASK) | 1154 ((ov_alpha << 0x00000018) & 1155 RADEON_DISP_OV0_ALPHA_MASK)); 1156 } else { /* global mode */ 1157 OUTREG(RADEON_OV0_KEY_CNTL, 1158 RADEON_GRAPHIC_KEY_FN_FALSE | /* what does this do? */ 1159 RADEON_VIDEO_KEY_FN_FALSE | /* what does this do? */ 1160 RADEON_CMP_MIX_AND); 1161 /* crtc 2 */ 1162 OUTREG(RADEON_DISP2_MERGE_CNTL, 1163 (RADEON_DISP_ALPHA_MODE_GLOBAL & 1164 RADEON_DISP_ALPHA_MODE_MASK) | 1165 ((gr_alpha << 0x00000010) & 1166 RADEON_DISP_GRPH_ALPHA_MASK) | 1167 ((ov_alpha << 0x00000018) & 1168 RADEON_DISP_OV0_ALPHA_MASK)); 1169 /* crtc 1 */ 1170 OUTREG(RADEON_DISP_MERGE_CNTL, 1171 (RADEON_DISP_ALPHA_MODE_GLOBAL & 1172 RADEON_DISP_ALPHA_MODE_MASK) | 1173 ((gr_alpha << 0x00000010) & 1174 RADEON_DISP_GRPH_ALPHA_MASK) | 1175 ((ov_alpha << 0x00000018) & 1176 RADEON_DISP_OV0_ALPHA_MASK)); 1177 } 1178 /* per-pixel mode - RADEON_DISP_ALPHA_MODE_PER_PIXEL */ 1179 /* not yet supported */ 1180} 1181 1182static void RADEONSetColorKey(ScrnInfoPtr pScrn, uint32_t colorKey) 1183{ 1184 RADEONInfoPtr info = RADEONPTR(pScrn); 1185 unsigned char *RADEONMMIO = info->MMIO; 1186 uint32_t min, max; 1187 uint8_t r, g, b; 1188 1189 if (info->CurrentLayout.depth > 8) 1190 { 1191 uint32_t rbits, gbits, bbits; 1192 1193 rbits = (colorKey & pScrn->mask.red) >> pScrn->offset.red; 1194 gbits = (colorKey & pScrn->mask.green) >> pScrn->offset.green; 1195 bbits = (colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 1196 1197 r = rbits << (8 - pScrn->weight.red); 1198 g = gbits << (8 - pScrn->weight.green); 1199 b = bbits << (8 - pScrn->weight.blue); 1200 } 1201 else 1202 { 1203 uint32_t bits; 1204 1205 bits = colorKey & ((1 << info->CurrentLayout.depth) - 1); 1206 r = bits; 1207 g = bits; 1208 b = bits; 1209 } 1210 min = (r << 16) | (g << 8) | (b); 1211 max = (0xff << 24) | (r << 16) | (g << 8) | (b); 1212 1213 RADEONWaitForFifo(pScrn, 2); 1214 OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, max); 1215 OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min); 1216} 1217 1218void 1219RADEONResetVideo(ScrnInfoPtr pScrn) 1220{ 1221 RADEONInfoPtr info = RADEONPTR(pScrn); 1222 unsigned char *RADEONMMIO = info->MMIO; 1223 RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 1224 char tmp[200]; 1225 1226 /* this function is called from ScreenInit. pScreen is used 1227 by XAA internally, but not valid until ScreenInit finishs. 1228 */ 1229 if (info->accelOn && pScrn->pScreen) 1230 RADEON_SYNC(info, pScrn); 1231 1232 /* this is done here because each time the server is reset these 1233 could change.. Otherwise they remain constant */ 1234 xvInstanceID = MAKE_ATOM("XV_INSTANCE_ID"); 1235 xvDeviceID = MAKE_ATOM("XV_DEVICE_ID"); 1236 xvLocationID = MAKE_ATOM("XV_LOCATION_ID"); 1237 xvDumpStatus = MAKE_ATOM("XV_DUMP_STATUS"); 1238 1239 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 1240 xvSaturation = MAKE_ATOM("XV_SATURATION"); 1241 xvColor = MAKE_ATOM("XV_COLOR"); 1242 xvContrast = MAKE_ATOM("XV_CONTRAST"); 1243 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 1244 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 1245 xvHue = MAKE_ATOM("XV_HUE"); 1246 xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY"); 1247 xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY"); 1248 xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY"); 1249 xvGamma = MAKE_ATOM("XV_GAMMA"); 1250 xvColorspace = MAKE_ATOM("XV_COLORSPACE"); 1251 1252 xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 1253 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); 1254 xvCRTC = MAKE_ATOM("XV_CRTC"); 1255 1256 xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); 1257 xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); 1258 xvAlphaMode = MAKE_ATOM("XV_ALPHA_MODE"); 1259 1260 xvOverlayDeinterlacingMethod = MAKE_ATOM("XV_OVERLAY_DEINTERLACING_METHOD"); 1261 1262 xvDecBrightness = MAKE_ATOM("XV_DEC_BRIGHTNESS"); 1263 xvDecSaturation = MAKE_ATOM("XV_DEC_SATURATION"); 1264 xvDecColor = MAKE_ATOM("XV_DEC_COLOR"); 1265 xvDecContrast = MAKE_ATOM("XV_DEC_CONTRAST"); 1266 xvDecHue = MAKE_ATOM("XV_DEC_HUE"); 1267 1268 xvEncoding = MAKE_ATOM("XV_ENCODING"); 1269 xvFrequency = MAKE_ATOM("XV_FREQ"); 1270 xvTunerStatus = MAKE_ATOM("XV_TUNER_STATUS"); 1271 xvVolume = MAKE_ATOM("XV_VOLUME"); 1272 xvMute = MAKE_ATOM("XV_MUTE"); 1273 xvSAP = MAKE_ATOM("XV_SAP"); 1274 1275 xvAdjustment = MAKE_ATOM("XV_DEBUG_ADJUSTMENT"); 1276 1277 sprintf(tmp, "RXXX:%d.%d.%d", PCI_DEV_VENDOR_ID(info->PciInfo), 1278 PCI_DEV_DEVICE_ID(info->PciInfo), PCI_DEV_REVISION(info->PciInfo)); 1279 pPriv->device_id = MAKE_ATOM(tmp); 1280 sprintf(tmp, "PCI:%02d:%02d.%d", PCI_DEV_BUS(info->PciInfo), 1281 PCI_DEV_DEV(info->PciInfo), PCI_DEV_FUNC(info->PciInfo)); 1282 pPriv->location_id = MAKE_ATOM(tmp); 1283 sprintf(tmp, "INSTANCE:%d", pScrn->scrnIndex); 1284 pPriv->instance_id = MAKE_ATOM(tmp); 1285 1286 OUTREG(RADEON_OV0_SCALE_CNTL, RADEON_SCALER_SOFT_RESET); 1287 OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ 1288 OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0); 1289 OUTREG(RADEON_OV0_FILTER_CNTL, RADEON_FILTER_PROGRAMMABLE_COEF); 1290 OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ | 1291 RADEON_VIDEO_KEY_FN_FALSE | 1292 RADEON_CMP_MIX_OR); 1293 OUTREG(RADEON_OV0_TEST, 0); 1294 OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND); 1295 OUTREG(RADEON_CAP0_TRIG_CNTL, 0); 1296 RADEONSetColorKey(pScrn, pPriv->colorKey); 1297 1298 if (info->ChipFamily == CHIP_FAMILY_RADEON) { 1299 1300 OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000); 1301 OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e); 1302 OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0); 1303 OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442); 1304 OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040); 1305 OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); 1306 1307 } else { 1308 1309 OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000); 1310 OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e); 1311 OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a2f9da); 1312 OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442); 1313 OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046); 1314 OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); 1315 } 1316 /* 1317 * Set default Gamma ramp: 1318 * 1319 * Of 18 segments for gamma curve, all segments in R200 (and 1320 * newer) are programmable, while only lower 4 and upper 2 1321 * segments are programmable in the older Radeons. 1322 */ 1323 1324 RADEONSetOverlayGamma(pScrn, 0); /* gamma = 1.0 */ 1325 1326 if(pPriv->VIP!=NULL){ 1327 RADEONVIP_reset(pScrn,pPriv); 1328 } 1329 1330 if(pPriv->theatre != NULL) { 1331 xf86_InitTheatre(pPriv->theatre); 1332/* xf86_ResetTheatreRegsForNoTVout(pPriv->theatre); */ 1333 } 1334 1335 if(pPriv->i2c != NULL){ 1336 RADEONResetI2C(pScrn, pPriv); 1337 } 1338} 1339 1340static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) 1341{ 1342 RADEONInfoPtr info = RADEONPTR(pScrn); 1343 RADEONPLLPtr pll = &(info->pll); 1344 TheatrePtr t; 1345 1346 uint8_t a; 1347 int i; 1348 1349 pPriv->theatre = NULL; 1350 1351 if(!info->MM_TABLE_valid && 1352 !((info->RageTheatreCrystal>=0) && 1353 (info->RageTheatreTunerPort>=0) && (info->RageTheatreCompositePort>=0) && 1354 (info->RageTheatreSVideoPort>=0))) 1355 { 1356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no multimedia table present, disabling Rage Theatre.\n"); 1357 return; 1358 } 1359 1360 /* Go and find Rage Theatre, if it exists */ 1361 1362 if (info->IsMobility) 1363 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility, not scanning for Rage Theatre\n"); 1364 else 1365 pPriv->theatre=xf86_DetectTheatre(pPriv->VIP); 1366 1367 if(pPriv->theatre==NULL)return; 1368 1369 /* just a matter of convenience */ 1370 t=pPriv->theatre; 1371 1372 t->video_decoder_type=info->video_decoder_type; 1373 1374 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "video decoder type is 0x%04x (BIOS value) versus 0x%04x (current PLL setting)\n", 1375 t->video_decoder_type, pll->xclk); 1376 1377 if(info->MM_TABLE_valid){ 1378 for(i=0;i<5;i++){ 1379 a=info->MM_TABLE.input[i]; 1380 1381 switch(a & 0x3){ 1382 case 1: 1383 t->wTunerConnector=i; 1384 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Tuner is on port %d\n",i); 1385 break; 1386 case 2: if(a & 0x4){ 1387 t->wComp0Connector=RT_COMP2; 1388 } else { 1389 t->wComp0Connector=RT_COMP1; 1390 } 1391 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %u\n", (unsigned)t->wComp0Connector); 1392 break; 1393 case 3: if(a & 0x4){ 1394 t->wSVideo0Connector=RT_YCR_COMP4; 1395 } else { 1396 t->wSVideo0Connector=RT_YCF_COMP4; 1397 } 1398 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %u\n", (unsigned)t->wSVideo0Connector); 1399 break; 1400 default: 1401 break; 1402 } 1403 } 1404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%u, composite=%u, svideo=%u\n", 1405 (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); 1406 1407 } 1408 1409 if(info->RageTheatreTunerPort>=0)t->wTunerConnector=info->RageTheatreTunerPort; 1410 if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort; 1411 if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort; 1412 1413 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%u, composite=%u, svideo=%u\n", 1414 (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); 1415 1416 switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){ 1417 case 2700: 1418 t->video_decoder_type=RT_FREF_2700; 1419 break; 1420 case 2950: 1421 t->video_decoder_type=RT_FREF_2950; 1422 break; 1423 default: 1424 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1425 "Unsupported reference clock frequency, Rage Theatre disabled\n"); 1426 t->theatre_num=-1; 1427 free(pPriv->theatre); 1428 pPriv->theatre = NULL; 1429 return; 1430 } 1431 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "video decoder type used: 0x%04x\n", t->video_decoder_type); 1432} 1433 1434static XF86VideoAdaptorPtr 1435RADEONAllocAdaptor(ScrnInfoPtr pScrn) 1436{ 1437 XF86VideoAdaptorPtr adapt; 1438 RADEONInfoPtr info = RADEONPTR(pScrn); 1439 RADEONPortPrivPtr pPriv; 1440 uint32_t dot_clock; 1441 int ecp; 1442 1443 if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 1444 return NULL; 1445 1446 if(!(pPriv = calloc(1, sizeof(RADEONPortPrivRec) + sizeof(DevUnion)))) 1447 { 1448 free(adapt); 1449 return NULL; 1450 } 1451 1452 adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 1453 adapt->pPortPrivates[0].ptr = (pointer)pPriv; 1454 1455 pPriv->colorKey = info->videoKey; 1456 pPriv->doubleBuffer = TRUE; 1457 pPriv->videoStatus = 0; 1458 pPriv->brightness = 0; 1459 pPriv->transform_index = 0; 1460 pPriv->saturation = 0; 1461 pPriv->contrast = 0; 1462 pPriv->red_intensity = 0; 1463 pPriv->green_intensity = 0; 1464 pPriv->blue_intensity = 0; 1465 pPriv->hue = 0; 1466 pPriv->currentBuffer = 0; 1467 pPriv->autopaint_colorkey = TRUE; 1468 pPriv->gamma = 1000; 1469 pPriv->desired_crtc = NULL; 1470 1471 pPriv->ov_alpha = 255; 1472 pPriv->gr_alpha = 255; 1473 pPriv->alpha_mode = 0; 1474 1475 /* TV-in stuff */ 1476 pPriv->video_stream_active = FALSE; 1477 pPriv->encoding = 4; 1478 pPriv->frequency = 1000; 1479 pPriv->volume = -1000; 1480 pPriv->mute = TRUE; 1481 pPriv->v = 0; 1482 pPriv->overlay_deinterlacing_method = METHOD_BOB; 1483 pPriv->capture_vbi_data = 0; 1484 pPriv->dec_brightness = 0; 1485 pPriv->dec_saturation = 0; 1486 pPriv->dec_contrast = 0; 1487 pPriv->dec_hue = 0; 1488 1489 1490 /* 1491 * Unlike older Mach64 chips, RADEON has only two ECP settings: 1492 * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) 1493 * for higher clocks, sure makes life nicer 1494 */ 1495 dot_clock = info->ModeReg->dot_clock_freq; 1496 1497 if (dot_clock < 17500) 1498 info->ecp_div = 0; 1499 else 1500 info->ecp_div = 1; 1501 ecp = (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (info->ecp_div << 8); 1502 1503 if (info->IsIGP) { 1504 /* Force the overlay clock on for integrated chips 1505 */ 1506 ecp |= (1<<18); 1507 } 1508 1509 OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, ecp); 1510 1511 1512 /* Decide on tuner type */ 1513 if((info->tunerType<0) && (info->MM_TABLE_valid)) { 1514 pPriv->tuner_type = info->MM_TABLE.tuner_type; 1515 } else 1516 pPriv->tuner_type = info->tunerType; 1517 1518 /* Initialize I2C bus */ 1519 RADEONInitI2C(pScrn, pPriv); 1520 if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv); 1521 1522 1523 #if 0 /* this is just here for easy debugging - normally off */ 1524 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Scanning I2C Bus\n"); 1525 for(i=0;i<255;i+=2) 1526 if(RADEONProbeAddress(pPriv->i2c, i)) 1527 xf86DrvMsg(pScrn->scrnIndex, X_INFO, " found device at address 0x%02x\n", i); 1528 #endif 1529 1530 /* resetting the VIP bus causes problems with some mobility chips. 1531 * we don't support video in on any mobility chips at the moment anyway 1532 */ 1533 /* Initialize VIP bus */ 1534 if (!info->IsMobility) 1535 RADEONVIP_init(pScrn, pPriv); 1536 1537 info->adaptor = adapt; 1538 info->xv_max_width = 2047; 1539 info->xv_max_height = 2047; 1540 1541 if(!xf86LoadSubModule(pScrn,"theatre_detect")) 1542 { 1543 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre detect module\n"); 1544 goto skip_theatre; 1545 } 1546 RADEONSetupTheatre(pScrn, pPriv); 1547 1548 /* 1549 * Now load the correspondind theatre chip based on what has been detected. 1550 */ 1551 if (pPriv->theatre) 1552 { 1553 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Going to load the corresponding theatre module\n"); 1554 switch (pPriv->theatre->theatre_id) 1555 { 1556 case RT100_ATI_ID: 1557 { 1558 if(!xf86LoadSubModule(pScrn,"theatre")) 1559 { 1560 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre module\n"); 1561 free(pPriv->theatre); 1562 goto skip_theatre; 1563 } 1564 break; 1565 } 1566 case RT200_ATI_ID: 1567 { 1568 if(!xf86LoadSubModule(pScrn,"theatre200")) 1569 { 1570 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre module\n"); 1571 free(pPriv->theatre); 1572 goto skip_theatre; 1573 } 1574 pPriv->theatre->microc_path = info->RageTheatreMicrocPath; 1575 pPriv->theatre->microc_type = info->RageTheatreMicrocType; 1576 break; 1577 } 1578 default: 1579 { 1580 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unknown Theatre chip\n"); 1581 free(pPriv->theatre); 1582 goto skip_theatre; 1583 } 1584 } 1585 } 1586 1587 if(pPriv->theatre!=NULL) 1588 { 1589 xf86_InitTheatre(pPriv->theatre); 1590 if(pPriv->theatre->mode == MODE_UNINITIALIZED) 1591 { 1592 free(pPriv->theatre); 1593 pPriv->theatre = NULL; 1594 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Rage Theatre disabled\n"); 1595 /* Here the modules must be unloaded */ 1596 goto skip_theatre; 1597 } 1598 } 1599 1600 if(pPriv->theatre!=NULL){ 1601 xf86_ResetTheatreRegsForNoTVout(pPriv->theatre); 1602 xf86_RT_SetTint(pPriv->theatre, pPriv->dec_hue); 1603 xf86_RT_SetSaturation(pPriv->theatre, pPriv->dec_saturation); 1604 xf86_RT_SetSharpness(pPriv->theatre, RT_NORM_SHARPNESS); 1605 xf86_RT_SetContrast(pPriv->theatre, pPriv->dec_contrast); 1606 xf86_RT_SetBrightness(pPriv->theatre, pPriv->dec_brightness); 1607 1608 RADEON_RT_SetEncoding(pScrn, pPriv); 1609 } 1610 1611skip_theatre: 1612 1613 return adapt; 1614} 1615 1616static XF86VideoAdaptorPtr 1617RADEONSetupImageVideo(ScreenPtr pScreen) 1618{ 1619 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1620 RADEONPortPrivPtr pPriv; 1621 XF86VideoAdaptorPtr adapt; 1622 1623 if(!(adapt = RADEONAllocAdaptor(pScrn))) 1624 return NULL; 1625 1626 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 1627 adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; 1628 adapt->name = "ATI Radeon Video Overlay"; 1629 adapt->nEncodings = 1; 1630 adapt->pEncodings = &DummyEncoding; 1631 adapt->nFormats = NUM_FORMATS; 1632 adapt->pFormats = Formats; 1633 adapt->nPorts = 1; 1634 adapt->nAttributes = NUM_ATTRIBUTES; 1635 adapt->pAttributes = Attributes; 1636 adapt->nImages = NUM_IMAGES; 1637 adapt->pImages = Images; 1638 adapt->PutVideo = NULL; 1639 adapt->PutStill = NULL; 1640 adapt->GetVideo = NULL; 1641 adapt->GetStill = NULL; 1642 adapt->StopVideo = RADEONStopVideo; 1643 adapt->SetPortAttribute = RADEONSetPortAttribute; 1644 adapt->GetPortAttribute = RADEONGetPortAttribute; 1645 adapt->QueryBestSize = RADEONQueryBestSize; 1646 adapt->PutImage = RADEONPutImage; 1647 adapt->QueryImageAttributes = RADEONQueryImageAttributes; 1648 1649 pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr); 1650 REGION_NULL(pScreen, &(pPriv->clip)); 1651 1652 pPriv->textured = FALSE; 1653 1654 if(pPriv->theatre != NULL) { 1655 /* video decoder is present, extend capabilities */ 1656 adapt->nEncodings = 13; 1657 adapt->pEncodings = InputVideoEncodings; 1658 adapt->type |= XvVideoMask; 1659 adapt->nAttributes = NUM_DEC_ATTRIBUTES; 1660 adapt->PutVideo = RADEONPutVideo; 1661 } 1662 1663 RADEONResetVideo(pScrn); 1664 1665 return adapt; 1666} 1667 1668void 1669RADEONFreeVideoMemory(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) 1670{ 1671 RADEONInfoPtr info = RADEONPTR(pScrn); 1672 1673 if (pPriv->video_memory != NULL) { 1674 radeon_legacy_free_memory(pScrn, pPriv->video_memory); 1675 pPriv->video_memory = NULL; 1676 1677 if (info->cs && pPriv->textured) { 1678 pPriv->src_bo[0] = NULL; 1679 radeon_legacy_free_memory(pScrn, pPriv->src_bo[1]); 1680 pPriv->src_bo[1] = NULL; 1681 } 1682 } 1683} 1684 1685void 1686RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 1687{ 1688 RADEONInfoPtr info = RADEONPTR(pScrn); 1689 unsigned char *RADEONMMIO = info->MMIO; 1690 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 1691 1692 if (pPriv->textured) { 1693 if (cleanup) { 1694 RADEONFreeVideoMemory(pScrn, pPriv); 1695 } 1696 return; 1697 } 1698 1699 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1700 1701 if(cleanup) { 1702 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 1703 RADEONWaitForFifo(pScrn, 2); 1704 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 1705 } 1706 if(pPriv->video_stream_active){ 1707 RADEONWaitForFifo(pScrn, 2); 1708 OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND); 1709 OUTREG(RADEON_CAP0_TRIG_CNTL, 0); 1710 RADEONResetVideo(pScrn); 1711 pPriv->video_stream_active = FALSE; 1712 if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE); 1713 if(pPriv->uda1380 != NULL) xf86_uda1380_mute(pPriv->uda1380, TRUE); 1714 if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); 1715 } 1716 RADEONFreeVideoMemory(pScrn, pPriv); 1717 pPriv->videoStatus = 0; 1718 } else { 1719 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 1720 pPriv->videoStatus |= OFF_TIMER; 1721 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 1722 } 1723 } 1724} 1725 1726int 1727RADEONSetPortAttribute(ScrnInfoPtr pScrn, 1728 Atom attribute, 1729 INT32 value, 1730 pointer data) 1731{ 1732 RADEONInfoPtr info = RADEONPTR(pScrn); 1733 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 1734 Bool setTransform = FALSE; 1735 Bool setAlpha = FALSE; 1736 unsigned char *RADEONMMIO = info->MMIO; 1737 1738 RADEON_SYNC(info, pScrn); 1739 1740 if(attribute == xvAutopaintColorkey) 1741 { 1742 pPriv->autopaint_colorkey = ClipValue (value, 0, 1); 1743 } 1744 else if(attribute == xvSetDefaults) 1745 { 1746 pPriv->autopaint_colorkey = TRUE; 1747 pPriv->brightness = 0; 1748 pPriv->saturation = 0; 1749 pPriv->contrast = 0; 1750 pPriv->hue = 0; 1751 pPriv->red_intensity = 0; 1752 pPriv->green_intensity = 0; 1753 pPriv->blue_intensity = 0; 1754 pPriv->gamma = 1000; 1755 pPriv->transform_index = 0; 1756 pPriv->doubleBuffer = FALSE; 1757 pPriv->ov_alpha = 255; 1758 pPriv->gr_alpha = 255; 1759 pPriv->alpha_mode = 0; 1760 1761 /* It is simpler to call itself */ 1762 RADEONSetPortAttribute(pScrn, xvDecBrightness, 0, data); 1763 RADEONSetPortAttribute(pScrn, xvDecSaturation, 0, data); 1764 RADEONSetPortAttribute(pScrn, xvDecContrast, 0, data); 1765 RADEONSetPortAttribute(pScrn, xvDecHue, 0, data); 1766 1767 RADEONSetPortAttribute(pScrn, xvVolume, -1000, data); 1768 RADEONSetPortAttribute(pScrn, xvMute, 1, data); 1769 RADEONSetPortAttribute(pScrn, xvSAP, 0, data); 1770 RADEONSetPortAttribute(pScrn, xvDoubleBuffer, 1, data); 1771 1772 setTransform = TRUE; 1773 setAlpha = TRUE; 1774 } 1775 else if(attribute == xvBrightness) 1776 { 1777 pPriv->brightness = ClipValue (value, -1000, 1000); 1778 setTransform = TRUE; 1779 } 1780 else if((attribute == xvSaturation) || (attribute == xvColor)) 1781 { 1782 pPriv->saturation = ClipValue (value, -1000, 1000); 1783 setTransform = TRUE; 1784 } 1785 else if(attribute == xvContrast) 1786 { 1787 pPriv->contrast = ClipValue (value, -1000, 1000); 1788 setTransform = TRUE; 1789 } 1790 else if(attribute == xvHue) 1791 { 1792 pPriv->hue = ClipValue (value, -1000, 1000); 1793 setTransform = TRUE; 1794 } 1795 else if(attribute == xvRedIntensity) 1796 { 1797 pPriv->red_intensity = ClipValue (value, -1000, 1000); 1798 setTransform = TRUE; 1799 } 1800 else if(attribute == xvGreenIntensity) 1801 { 1802 pPriv->green_intensity = ClipValue (value, -1000, 1000); 1803 setTransform = TRUE; 1804 } 1805 else if(attribute == xvBlueIntensity) 1806 { 1807 pPriv->blue_intensity = ClipValue (value, -1000, 1000); 1808 setTransform = TRUE; 1809 } 1810 else if(attribute == xvGamma) 1811 { 1812 pPriv->gamma = ClipValue (value, 100, 10000); 1813 setTransform = TRUE; 1814 } 1815 else if(attribute == xvColorspace) 1816 { 1817 pPriv->transform_index = ClipValue (value, 0, 1); 1818 setTransform = TRUE; 1819 } 1820 else if(attribute == xvDoubleBuffer) 1821 { 1822 pPriv->doubleBuffer = ClipValue (value, 0, 1); 1823 } 1824 else if(attribute == xvColorKey) 1825 { 1826 pPriv->colorKey = value; 1827 RADEONSetColorKey (pScrn, pPriv->colorKey); 1828 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1829 } 1830 else if(attribute == xvCRTC) 1831 { 1832 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1833 if ((value < -1) || (value > xf86_config->num_crtc)) 1834 return BadValue; 1835 if (value < 0) 1836 pPriv->desired_crtc = NULL; 1837 else 1838 pPriv->desired_crtc = xf86_config->crtc[value]; 1839 } 1840 else if(attribute == xvOvAlpha) 1841 { 1842 pPriv->ov_alpha = ClipValue (value, 0, 255); 1843 setAlpha = TRUE; 1844 } 1845 else if(attribute == xvGrAlpha) 1846 { 1847 pPriv->gr_alpha = ClipValue (value, 0, 255); 1848 setAlpha = TRUE; 1849 } 1850 else if(attribute == xvAlphaMode) 1851 { 1852 pPriv->alpha_mode = ClipValue (value, 0, 1); 1853 setAlpha = TRUE; 1854 } 1855 else if(attribute == xvDecBrightness) 1856 { 1857 pPriv->dec_brightness = value; 1858 if(pPriv->theatre!=NULL) xf86_RT_SetBrightness(pPriv->theatre, pPriv->dec_brightness); 1859 } 1860 else if((attribute == xvDecSaturation) || (attribute == xvDecColor)) 1861 { 1862 if(value<-1000)value = -1000; 1863 if(value>1000)value = 1000; 1864 pPriv->dec_saturation = value; 1865 if(pPriv->theatre != NULL)xf86_RT_SetSaturation(pPriv->theatre, value); 1866 } 1867 else if(attribute == xvDecContrast) 1868 { 1869 pPriv->dec_contrast = value; 1870 if(pPriv->theatre != NULL)xf86_RT_SetContrast(pPriv->theatre, value); 1871 } 1872 else if(attribute == xvDecHue) 1873 { 1874 pPriv->dec_hue = value; 1875 if(pPriv->theatre != NULL)xf86_RT_SetTint(pPriv->theatre, value); 1876 } 1877 else if(attribute == xvEncoding) 1878 { 1879 pPriv->encoding = value; 1880 if(pPriv->video_stream_active) 1881 { 1882 if(pPriv->theatre != NULL) RADEON_RT_SetEncoding(pScrn, pPriv); 1883 if(pPriv->msp3430 != NULL) RADEON_MSP_SetEncoding(pPriv); 1884 if(pPriv->tda9885 != NULL) RADEON_TDA9885_SetEncoding(pPriv); 1885 if(pPriv->fi1236 != NULL) RADEON_FI1236_SetEncoding(pPriv); 1886 if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); 1887 /* put more here to actually change it */ 1888 } 1889 } 1890 else if(attribute == xvFrequency) 1891 { 1892 pPriv->frequency = value; 1893 /* mute volume if it was not muted before */ 1894 if((pPriv->msp3430!=NULL)&& !pPriv->mute)xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE); 1895 if((pPriv->uda1380!=NULL)&& !pPriv->mute)xf86_uda1380_mute(pPriv->uda1380, TRUE); 1896 if(pPriv->fi1236 != NULL) xf86_TUNER_set_frequency(pPriv->fi1236, value); 1897/* if(pPriv->theatre != NULL) RADEON_RT_SetEncoding(pScrn, pPriv); */ 1898 if((pPriv->msp3430 != NULL) && (pPriv->msp3430->recheck)) 1899 xf86_InitMSP3430(pPriv->msp3430); 1900 if((pPriv->msp3430 != NULL)&& !pPriv->mute) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_VOLUME(pPriv->volume)); 1901 if((pPriv->uda1380 != NULL)&& !pPriv->mute) xf86_uda1380_setvolume(pPriv->uda1380, pPriv->volume); 1902 } 1903 else if(attribute == xvMute) 1904 { 1905 pPriv->mute = value; 1906 if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume)); 1907 if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); 1908 if(pPriv->uda1380 != NULL) xf86_uda1380_mute(pPriv->uda1380, pPriv->mute); 1909 } 1910 else if(attribute == xvSAP) 1911 { 1912 pPriv->sap_channel = value; 1913 if(pPriv->msp3430 != NULL) xf86_MSP3430SetSAP(pPriv->msp3430, pPriv->sap_channel?4:3); 1914 } 1915 else if(attribute == xvVolume) 1916 { 1917 if(value<-1000)value = -1000; 1918 if(value>1000)value = 1000; 1919 pPriv->volume = value; 1920 pPriv->mute = FALSE; 1921 if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_VOLUME(value)); 1922 if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); 1923 if(pPriv->uda1380 != NULL) xf86_uda1380_setvolume(pPriv->uda1380, value); 1924 } 1925 else if(attribute == xvOverlayDeinterlacingMethod) 1926 { 1927 if(value<0)value = 0; 1928 if(value>2)value = 2; 1929 pPriv->overlay_deinterlacing_method = value; 1930 switch(pPriv->overlay_deinterlacing_method){ 1931 case METHOD_BOB: 1932 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA); 1933 break; 1934 case METHOD_SINGLE: 1935 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xEEEEE | (9<<28)); 1936 break; 1937 case METHOD_WEAVE: 1938 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0x0); 1939 break; 1940 default: 1941 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA); 1942 } 1943 } 1944 else if(attribute == xvDumpStatus) 1945 { 1946 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode flags 0x%08x: %s%s\n", 1947 pScrn->currentMode->Flags, 1948 pScrn->currentMode->Flags & V_INTERLACE ? " interlaced" : "" , 1949 pScrn->currentMode->Flags & V_DBLSCAN ? " doublescan" : "" 1950 ); 1951 if(pPriv->tda9885 != NULL){ 1952 xf86_tda9885_getstatus(pPriv->tda9885); 1953 xf86_tda9885_dumpstatus(pPriv->tda9885); 1954 } 1955 if(pPriv->fi1236!=NULL){ 1956 xf86_fi1236_dump_status(pPriv->fi1236); 1957 } 1958 } 1959 else if(attribute == xvAdjustment) 1960 { 1961 pPriv->adjustment=value; 1962 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %u\n", 1963 (unsigned)pPriv->adjustment); 1964 if(pPriv->tda9885!=0){ 1965 pPriv->tda9885->top_adjustment=value; 1966 RADEON_TDA9885_SetEncoding(pPriv); 1967 } 1968 } 1969 else 1970 return BadMatch; 1971 1972 if (setTransform) 1973 { 1974 RADEONSetTransform(pScrn, 1975 RTFBrightness(pPriv->brightness), 1976 RTFContrast(pPriv->contrast), 1977 RTFSaturation(pPriv->saturation), 1978 RTFHue(pPriv->hue), 1979 RTFIntensity(pPriv->red_intensity), 1980 RTFIntensity(pPriv->green_intensity), 1981 RTFIntensity(pPriv->blue_intensity), 1982 pPriv->transform_index, 1983 pPriv->gamma); 1984 } 1985 1986 if (setAlpha) 1987 { 1988 RADEONSetOverlayAlpha(pScrn, pPriv->ov_alpha, pPriv->gr_alpha, pPriv->alpha_mode); 1989 } 1990 1991 return Success; 1992} 1993 1994int 1995RADEONGetPortAttribute(ScrnInfoPtr pScrn, 1996 Atom attribute, 1997 INT32 *value, 1998 pointer data) 1999{ 2000 RADEONInfoPtr info = RADEONPTR(pScrn); 2001 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 2002 2003 if (info->accelOn) RADEON_SYNC(info, pScrn); 2004 2005 if(attribute == xvAutopaintColorkey) 2006 *value = pPriv->autopaint_colorkey; 2007 else if(attribute == xvBrightness) 2008 *value = pPriv->brightness; 2009 else if((attribute == xvSaturation) || (attribute == xvColor)) 2010 *value = pPriv->saturation; 2011 else if(attribute == xvContrast) 2012 *value = pPriv->contrast; 2013 else if(attribute == xvHue) 2014 *value = pPriv->hue; 2015 else if(attribute == xvRedIntensity) 2016 *value = pPriv->red_intensity; 2017 else if(attribute == xvGreenIntensity) 2018 *value = pPriv->green_intensity; 2019 else if(attribute == xvBlueIntensity) 2020 *value = pPriv->blue_intensity; 2021 else if(attribute == xvGamma) 2022 *value = pPriv->gamma; 2023 else if(attribute == xvColorspace) 2024 *value = pPriv->transform_index; 2025 else if(attribute == xvDoubleBuffer) 2026 *value = pPriv->doubleBuffer ? 1 : 0; 2027 else if(attribute == xvColorKey) 2028 *value = pPriv->colorKey; 2029 else if(attribute == xvCRTC) { 2030 int c; 2031 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2032 for (c = 0; c < xf86_config->num_crtc; c++) 2033 if (xf86_config->crtc[c] == pPriv->desired_crtc) 2034 break; 2035 if (c == xf86_config->num_crtc) 2036 c = -1; 2037 *value = c; 2038 } 2039 else if(attribute == xvOvAlpha) 2040 *value = pPriv->ov_alpha; 2041 else if(attribute == xvGrAlpha) 2042 *value = pPriv->gr_alpha; 2043 else if(attribute == xvAlphaMode) 2044 *value = pPriv->alpha_mode; 2045 else if(attribute == xvDecBrightness) 2046 *value = pPriv->dec_brightness; 2047 else if((attribute == xvDecSaturation) || (attribute == xvDecColor)) 2048 *value = pPriv->dec_saturation; 2049 else if(attribute == xvDecContrast) 2050 *value = pPriv->dec_contrast; 2051 else if(attribute == xvDecHue) 2052 *value = pPriv->dec_hue; 2053 else if(attribute == xvEncoding) 2054 *value = pPriv->encoding; 2055 else if(attribute == xvFrequency) 2056 *value = pPriv->frequency; 2057 else 2058 if(attribute == xvTunerStatus) { 2059 if(pPriv->fi1236==NULL){ 2060 *value=TUNER_OFF; 2061 } else 2062 { 2063 *value = xf86_TUNER_get_afc_hint(pPriv->fi1236); 2064 } 2065 } 2066 else if(attribute == xvMute) 2067 *value = pPriv->mute; 2068 else if(attribute == xvSAP) 2069 *value = pPriv->sap_channel; 2070 else if(attribute == xvVolume) 2071 *value = pPriv->volume; 2072 else if(attribute == xvOverlayDeinterlacingMethod) 2073 *value = pPriv->overlay_deinterlacing_method; 2074 else if(attribute == xvDeviceID) 2075 *value = pPriv->device_id; 2076 else if(attribute == xvLocationID) 2077 *value = pPriv->location_id; 2078 else if(attribute == xvInstanceID) 2079 *value = pPriv->instance_id; 2080 else if(attribute == xvAdjustment) 2081 *value = pPriv->adjustment; 2082 else 2083 return BadMatch; 2084 2085 return Success; 2086} 2087 2088void 2089RADEONQueryBestSize( 2090 ScrnInfoPtr pScrn, 2091 Bool motion, 2092 short vid_w, short vid_h, 2093 short drw_w, short drw_h, 2094 unsigned int *p_w, unsigned int *p_h, 2095 pointer data 2096){ 2097 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 2098 2099 if (!pPriv->textured) { 2100 if (vid_w > (drw_w << 4)) 2101 drw_w = vid_w >> 4; 2102 if (vid_h > (drw_h << 4)) 2103 drw_h = vid_h >> 4; 2104 } 2105 2106 *p_w = drw_w; 2107 *p_h = drw_h; 2108} 2109 2110static struct { 2111 double range; 2112 signed char coeff[5][4]; 2113 } TapCoeffs[]= 2114 { 2115 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2116 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2117 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2118 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2119 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2120 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2121 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2122 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2123 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2124 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2125 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2126 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2127 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2128 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2129 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2130 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2131 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2132 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2133 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2134 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2135 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2136 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2137 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2138 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2139 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2140 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, 2141 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }}, 2142 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, 2143 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, 2144 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, 2145 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }}, 2146 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2147 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2148 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2149 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2150 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2151 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2152 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2153 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2154 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, 2155 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, 2156 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, 2157 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, 2158 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, 2159 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, 2160 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, 2161 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, 2162 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, 2163 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, 2164 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, 2165 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, 2166 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, 2167 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }}, 2168 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }}, 2169 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, 2170 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, 2171 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, 2172 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }}, 2173 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, 2174 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, 2175 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, 2176 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, 2177 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, 2178 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2179 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2180 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2181 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2182 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2183 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2184 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, 2185 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, 2186 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, 2187 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, 2188 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, 2189 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}, 2190 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }} 2191 }; 2192 2193void 2194RADEONCopyData( 2195 ScrnInfoPtr pScrn, 2196 unsigned char *src, 2197 unsigned char *dst, 2198 unsigned int srcPitch, 2199 unsigned int dstPitch, 2200 unsigned int h, 2201 unsigned int w, 2202 unsigned int bpp 2203){ 2204 RADEONInfoPtr info = RADEONPTR(pScrn); 2205 2206 /* Get the byte-swapping right for big endian systems */ 2207 if ( bpp == 2 ) { 2208 w *= 2; 2209 bpp = 1; 2210 } 2211 2212#ifdef XF86DRI 2213 2214 if ( info->directRenderingEnabled && info->DMAForXv ) 2215 { 2216 uint8_t *buf; 2217 uint32_t bufPitch, dstPitchOff; 2218 int x, y; 2219 unsigned int hpass; 2220 2221 RADEONHostDataParams( pScrn, dst, dstPitch, bpp, &dstPitchOff, &x, &y ); 2222 2223 while ( (buf = RADEONHostDataBlit( pScrn, bpp, w, dstPitchOff, &bufPitch, 2224 x, &y, &h, &hpass )) ) 2225 { 2226 RADEONHostDataBlitCopyPass( pScrn, bpp, buf, src, hpass, bufPitch, 2227 srcPitch ); 2228 src += hpass * srcPitch; 2229 } 2230 2231 FLUSH_RING(); 2232 2233 return; 2234 } 2235 else 2236#endif /* XF86DRI */ 2237 { 2238 int swap = RADEON_HOST_DATA_SWAP_NONE; 2239 2240#if X_BYTE_ORDER == X_BIG_ENDIAN 2241 if (info->kms_enabled) { 2242 switch(bpp) { 2243 case 2: 2244 swap = RADEON_HOST_DATA_SWAP_16BIT; 2245 break; 2246 case 4: 2247 swap = RADEON_HOST_DATA_SWAP_32BIT; 2248 break; 2249 } 2250 } else { 2251 switch (pScrn->bitsPerPixel) { 2252 case 16: 2253 swap = RADEON_HOST_DATA_SWAP_16BIT; 2254 break; 2255 case 32: 2256 swap = RADEON_HOST_DATA_SWAP_32BIT; 2257 break; 2258 } 2259 } 2260#endif 2261 2262 w *= bpp; 2263 2264 if (dstPitch == w && dstPitch == srcPitch) 2265 RADEONCopySwap(dst, src, h * dstPitch, swap); 2266 else { 2267 while (h--) { 2268 RADEONCopySwap(dst, src, w, swap); 2269 src += srcPitch; 2270 dst += dstPitch; 2271 } 2272 } 2273 } 2274} 2275 2276static void 2277RADEONCopyRGB24Data( 2278 ScrnInfoPtr pScrn, 2279 unsigned char *src, 2280 unsigned char *dst, 2281 unsigned int srcPitch, 2282 unsigned int dstPitch, 2283 unsigned int h, 2284 unsigned int w 2285){ 2286 uint32_t *dptr; 2287 uint8_t *sptr; 2288 int i,j; 2289 RADEONInfoPtr info = RADEONPTR(pScrn); 2290#ifdef XF86DRI 2291 2292 if ( info->directRenderingEnabled && info->DMAForXv ) 2293 { 2294 uint32_t bufPitch, dstPitchOff; 2295 int x, y; 2296 unsigned int hpass; 2297 2298 RADEONHostDataParams( pScrn, dst, dstPitch, 4, &dstPitchOff, &x, &y ); 2299 2300 while ( (dptr = ( uint32_t* )RADEONHostDataBlit( pScrn, 4, w, dstPitchOff, 2301 &bufPitch, x, &y, &h, 2302 &hpass )) ) 2303 { 2304 for( j = 0; j < hpass; j++ ) 2305 { 2306 sptr = src; 2307 2308 for ( i = 0 ; i < w; i++, sptr += 3 ) 2309 { 2310 dptr[i] = (sptr[2] << 16) | (sptr[1] << 8) | sptr[0]; 2311 } 2312 2313 src += srcPitch; 2314 dptr += bufPitch / 4; 2315 } 2316 } 2317 2318 FLUSH_RING(); 2319 2320 return; 2321 } 2322 else 2323#endif /* XF86DRI */ 2324 { 2325#if X_BYTE_ORDER == X_BIG_ENDIAN 2326 unsigned char *RADEONMMIO = info->MMIO; 2327 2328 if (!info->kms_enabled) 2329 OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl & 2330 ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP)); 2331#endif 2332 2333 for (j = 0; j < h; j++) { 2334 dptr = (uint32_t *)(dst + j * dstPitch); 2335 sptr = src + j * srcPitch; 2336 2337 for (i = 0; i < w; i++, sptr += 3) { 2338 dptr[i] = cpu_to_le32((sptr[2] << 16) | (sptr[1] << 8) | sptr[0]); 2339 } 2340 } 2341 2342#if X_BYTE_ORDER == X_BIG_ENDIAN 2343 if (!info->kms_enabled) { 2344 /* restore byte swapping */ 2345 OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); 2346 } 2347#endif 2348 } 2349} 2350 2351 2352#ifdef XF86DRI 2353static void RADEON_420_422( 2354 unsigned int *d, 2355 unsigned char *s1, 2356 unsigned char *s2, 2357 unsigned char *s3, 2358 unsigned int n 2359) 2360{ 2361 while ( n ) { 2362 *(d++) = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); 2363 s1+=2; s2++; s3++; 2364 n--; 2365 } 2366} 2367#endif 2368 2369void 2370RADEONCopyMungedData( 2371 ScrnInfoPtr pScrn, 2372 unsigned char *src1, 2373 unsigned char *src2, 2374 unsigned char *src3, 2375 unsigned char *dst1, 2376 unsigned int srcPitch, 2377 unsigned int srcPitch2, 2378 unsigned int dstPitch, 2379 unsigned int h, 2380 unsigned int w 2381){ 2382 RADEONInfoPtr info = RADEONPTR(pScrn); 2383#ifdef XF86DRI 2384 2385 if ( info->directRenderingEnabled && info->DMAForXv ) 2386 { 2387 uint8_t *buf; 2388 uint32_t y = 0, bufPitch, dstPitchOff; 2389 int blitX, blitY; 2390 unsigned int hpass; 2391 2392 /* XXX Fix endian flip on R300 */ 2393 2394 RADEONHostDataParams( pScrn, dst1, dstPitch, 4, &dstPitchOff, &blitX, &blitY ); 2395 2396 while ( (buf = RADEONHostDataBlit( pScrn, 4, w/2, dstPitchOff, &bufPitch, 2397 blitX, &blitY, &h, &hpass )) ) 2398 { 2399 while ( hpass-- ) 2400 { 2401 RADEON_420_422( (unsigned int *) buf, src1, src2, src3, 2402 bufPitch / 4 ); 2403 src1 += srcPitch; 2404 if ( y & 1 ) 2405 { 2406 src2 += srcPitch2; 2407 src3 += srcPitch2; 2408 } 2409 buf += bufPitch; 2410 y++; 2411 } 2412 } 2413 2414 FLUSH_RING(); 2415 } 2416 else 2417#endif /* XF86DRI */ 2418 { 2419 uint32_t *dst; 2420 uint8_t *s1, *s2, *s3; 2421 int i, j; 2422 2423#if X_BYTE_ORDER == X_BIG_ENDIAN 2424 unsigned char *RADEONMMIO = info->MMIO; 2425 2426 if (!info->kms_enabled) 2427 OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl & 2428 ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP)); 2429#endif 2430 2431 w /= 2; 2432 2433 for( j = 0; j < h; j++ ) 2434 { 2435 dst = (pointer)dst1; 2436 s1 = src1; s2 = src2; s3 = src3; 2437 i = w; 2438 while( i > 4 ) 2439 { 2440 dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24)); 2441 dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24)); 2442 dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24)); 2443 dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24)); 2444 dst += 4; s2 += 4; s3 += 4; s1 += 8; 2445 i -= 4; 2446 } 2447 while( i-- ) 2448 { 2449 dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24)); 2450 dst++; s2++; s3++; 2451 s1 += 2; 2452 } 2453 2454 dst1 += dstPitch; 2455 src1 += srcPitch; 2456 if( j & 1 ) 2457 { 2458 src2 += srcPitch2; 2459 src3 += srcPitch2; 2460 } 2461 } 2462#if X_BYTE_ORDER == X_BIG_ENDIAN 2463 if (!info->kms_enabled) { 2464 /* restore byte swapping */ 2465 OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); 2466 } 2467#endif 2468 } 2469} 2470 2471static void 2472RADEONDisplayVideo( 2473 ScrnInfoPtr pScrn, 2474 xf86CrtcPtr crtc, 2475 RADEONPortPrivPtr pPriv, 2476 int id, 2477 int base_offset, 2478 int offset1, int offset2, 2479 int offset3, int offset4, 2480 int offset5, int offset6, 2481 short width, short height, 2482 int pitch, 2483 int left, int right, int top, 2484 BoxPtr dstBox, 2485 short src_w, short src_h, 2486 short drw_w, short drw_h, 2487 int deinterlacing_method 2488){ 2489 RADEONInfoPtr info = RADEONPTR(pScrn); 2490 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2491 unsigned char *RADEONMMIO = info->MMIO; 2492 uint32_t v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp; 2493 double h_inc_d; 2494 int p1_h_accum_init, p23_h_accum_init; 2495 int p1_v_accum_init, p23_v_accum_init; 2496 int p23_blank_lines; 2497 int ecp_div; 2498 int v_inc_shift; 2499 int y_mult; 2500 int x_off; 2501 int y_off; 2502 uint32_t scaler_src; 2503 uint32_t dot_clock; 2504 int is_rgb; 2505 int is_planar; 2506 int i; 2507 uint32_t scale_cntl; 2508 double dsr; 2509 int tap_set; 2510 int predownscale=0; 2511 int src_w_d; 2512 int leftuv = 0; 2513 DisplayModePtr mode; 2514 RADEONOutputPrivatePtr radeon_output; 2515 xf86OutputPtr output; 2516 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 2517 2518 is_rgb=0; is_planar=0; 2519 switch(id){ 2520 case FOURCC_I420: 2521 case FOURCC_YV12: 2522 is_planar=1; 2523 break; 2524 case FOURCC_RGBA32: 2525 case FOURCC_RGB24: 2526 case FOURCC_RGBT16: 2527 case FOURCC_RGB16: 2528 is_rgb=1; 2529 break; 2530 default: 2531 break; 2532 } 2533 2534 /* Here we need to find ecp_div again, as the user may have switched resolutions 2535 but only call OUTPLL/INPLL if needed since it may cause a 10ms delay due to 2536 workarounds for chip erratas */ 2537 2538 /* Figure out which head we are on for dot clock */ 2539 if (radeon_crtc->crtc_id == 1) 2540 dot_clock = info->ModeReg->dot_clock_freq_2; 2541 else 2542 dot_clock = info->ModeReg->dot_clock_freq; 2543 2544 if (dot_clock < 17500) 2545 ecp_div = 0; 2546 else 2547 ecp_div = 1; 2548 2549 if (ecp_div != info->ecp_div) { 2550 info->ecp_div = ecp_div; 2551 OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, 2552 (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8)); 2553 } 2554 2555 /* I suspect we may need a usleep after writing to the PLL. if you play a video too soon 2556 after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey 2557 on the right edge video output. 2558 Is this still the case? Might have been chips which need the errata, 2559 there is now plenty of usleep after INPLL/OUTPLL for those...*/ 2560 2561 v_inc_shift = 20; 2562 y_mult = 1; 2563 2564 mode = &crtc->mode; 2565 2566 if (mode->Flags & V_INTERLACE) 2567 v_inc_shift++; 2568 if (mode->Flags & V_DBLSCAN) { 2569 v_inc_shift--; 2570 y_mult = 2; 2571 } 2572 2573 v_inc = (src_h << v_inc_shift) / drw_h; 2574 2575 for (i = 0; i < xf86_config->num_output; i++) { 2576 output = xf86_config->output[i]; 2577 if (output->crtc == crtc) { 2578 radeon_output = output->driver_private; 2579 if (radeon_output->Flags & RADEON_USE_RMX) 2580 v_inc = ((src_h * mode->CrtcVDisplay / 2581 radeon_output->native_mode.PanelYRes) << v_inc_shift) / drw_h; 2582 break; 2583 } 2584 } 2585 2586 h_inc = (1 << (12 + ecp_div)); 2587 2588 step_by_y = 1; 2589 step_by_uv = step_by_y; 2590 2591 src_w_d = src_w; 2592#if 0 2593 /* XXX this does not appear to work */ 2594 /* if the source width was larger than what would fit in overlay scaler increase step_by values */ 2595 i=src_w; 2596 while(i>info->overlay_scaler_buffer_width){ 2597 step_by_y++; 2598 step_by_uv++; 2599 h_inc >>=1; 2600 i=i/2; 2601 } 2602#else 2603 /* predownscale instead (yes this hurts quality) - will only work for widths up 2604 to 2 times the overlay_scaler_buffer_width, should be enough */ 2605 if (src_w_d > info->overlay_scaler_buffer_width) { 2606 src_w_d /= 2; /* odd widths? */ 2607 predownscale = 1; 2608 } 2609#endif 2610 2611 h_inc_d = src_w_d; 2612 h_inc_d = h_inc_d/drw_w; 2613 /* we could do a tad better - but why 2614 bother when this concerns downscaling and the code is so much more 2615 hairy */ 2616 while(h_inc*h_inc_d >= (2 << 12)) { 2617 if(!is_rgb && (((h_inc+h_inc/2)*h_inc_d)<(2<<12))){ 2618 step_by_uv = step_by_y+1; 2619 break; 2620 } 2621 step_by_y++; 2622 step_by_uv = step_by_y; 2623 h_inc >>= 1; 2624 } 2625 2626 h_inc_uv = h_inc>>(step_by_uv-step_by_y); 2627 h_inc = h_inc * h_inc_d; 2628 h_inc_uv = h_inc_uv * h_inc_d; 2629 /* info->overlay_scaler_buffer_width is magic number - maximum line length the overlay scaler can fit 2630 in the buffer for 2 tap filtering */ 2631 /* the only place it is documented in is in ATI source code */ 2632 /* we need twice as much space for 4 tap filtering.. */ 2633 /* under special circumstances turn on 4 tap filtering */ 2634 /* disable this code for now as it has a DISASTROUS effect on image quality when upscaling 2635 at least on rv250 (only as long as the drw_w*2 <=... requirement is still met of course) */ 2636#if 0 2637 if(!is_rgb && (step_by_y==1) && (step_by_uv==1) && (h_inc < (1<<12)) 2638 && (deinterlacing_method!=METHOD_WEAVE) 2639 && (drw_w*2 <= info->overlay_scaler_buffer_width)){ 2640 step_by_y=0; 2641 step_by_uv=1; 2642 h_inc_uv = h_inc; 2643 } 2644#endif 2645 2646 /* Make the overlay base address as close to the buffers as possible to 2647 * prevent the buffer offsets from exceeding the hardware limit of 128 MB. 2648 * The base address must be aligned to a multiple of 4 MB. 2649 */ 2650 base_offset = ((info->fbLocation + base_offset) & (~0 << 22)) - 2651 info->fbLocation; 2652 2653 offset1 -= base_offset; 2654 offset2 -= base_offset; 2655 offset3 -= base_offset; 2656 offset4 -= base_offset; 2657 offset5 -= base_offset; 2658 offset6 -= base_offset; 2659 2660 /* keep everything in 16.16 */ 2661 2662 if (is_planar) { 2663 offset1 += ((left >> 16) & ~15); 2664 offset2 += ((left >> 16) & ~31) >> 1; 2665 offset3 += ((left >> 16) & ~31) >> 1; 2666 offset4 += ((left >> 16) & ~15); 2667 offset5 += ((left >> 16) & ~31) >> 1; 2668 offset6 += ((left >> 16) & ~31) >> 1; 2669 offset2 |= RADEON_VIF_BUF0_PITCH_SEL; 2670 offset3 |= RADEON_VIF_BUF0_PITCH_SEL; 2671 offset5 |= RADEON_VIF_BUF0_PITCH_SEL; 2672 offset6 |= RADEON_VIF_BUF0_PITCH_SEL; 2673 } 2674 else { 2675 /* is this really correct for non-2-byte formats? */ 2676 offset1 += ((left >> 16) & ~7) << 1; 2677 offset2 += ((left >> 16) & ~7) << 1; 2678 offset3 += ((left >> 16) & ~7) << 1; 2679 offset4 += ((left >> 16) & ~7) << 1; 2680 offset5 += ((left >> 16) & ~7) << 1; 2681 offset6 += ((left >> 16) & ~7) << 1; 2682 } 2683 2684 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 2685 p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 2686 ((tmp << 12) & 0xf0000000); 2687 2688 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc_uv << 2); 2689 p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 2690 ((tmp << 12) & 0x70000000); 2691 2692 tmp = (top & 0x0000ffff) + 0x00018000; 2693 p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 2694 (((deinterlacing_method!=METHOD_WEAVE)&&!is_rgb)?0x03:0x01); 2695 2696 if (is_planar) { 2697 p23_v_accum_init = ((tmp << 4) & 0x03ff8000) | 2698 ((deinterlacing_method != METHOD_WEAVE) ? 0x03 : 0x01); 2699 p23_blank_lines = (((src_h >> 1) - 1) << 16); 2700 } 2701 else { 2702 p23_v_accum_init = 0; 2703 p23_blank_lines = 0; 2704 } 2705 2706 if (is_planar) { 2707 leftuv = ((left >> 16) >> 1) & 15; 2708 left = (left >> 16) & 15; 2709 } 2710 else { 2711 left = (left >> 16) & 7; 2712 if (!is_rgb) 2713 leftuv = left >> 1; 2714 } 2715 2716 RADEONWaitForFifo(pScrn, 2); 2717 OUTREG(RADEON_OV0_REG_LOAD_CNTL, RADEON_REG_LD_CTL_LOCK); 2718 if (info->accelOn) RADEON_SYNC(info, pScrn); 2719 while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_LOCK_READBACK)); 2720 2721 RADEONWaitForFifo(pScrn, 10); 2722 OUTREG(RADEON_OV0_H_INC, h_inc | ((is_rgb? h_inc_uv: (h_inc_uv >> 1)) << 16)); 2723 OUTREG(RADEON_OV0_STEP_BY, step_by_y | (step_by_uv << 8) | 2724 predownscale << 4 | predownscale << 12); 2725 2726 x_off = 8; 2727 y_off = 0; 2728 2729 if (IS_R300_VARIANT || 2730 (info->ChipFamily == CHIP_FAMILY_R200)) 2731 x_off = 0; 2732 2733 /* needed to make the overlay work on crtc1 in leftof and above modes */ 2734 /* XXX: may need to adjust x_off/y_off for dualhead like mergedfb -- need to test */ 2735 /* 2736 if (srel == radeonLeftOf) { 2737 x_off -= mode->CrtcHDisplay; 2738 } 2739 if (srel == radeonAbove) { 2740 y_off -= mode->CrtcVDisplay; 2741 } 2742 */ 2743 2744 /* Put the hardware overlay on CRTC2: 2745 * 2746 * Since one hardware overlay can not be displayed on two heads 2747 * at the same time, we might need to consider using software 2748 * rendering for the second head. 2749 */ 2750 2751 if (radeon_crtc->crtc_id == 1) { 2752 x_off = 0; 2753 OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | 2754 ((dstBox->y1*y_mult) << 16))); 2755 OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 + x_off) | 2756 ((dstBox->y2*y_mult) << 16))); 2757 scaler_src = RADEON_SCALER_CRTC_SEL; 2758 } else { 2759 OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) | 2760 (((dstBox->y1*y_mult) + y_off) << 16))); 2761 OUTREG(RADEON_OV0_Y_X_END, ((dstBox->x2 + x_off) | 2762 (((dstBox->y2*y_mult) + y_off) << 16))); 2763 scaler_src = 0; 2764 } 2765 2766 /* program the tap coefficients for better downscaling quality. 2767 Could do slightly better by using hardcoded coefficients for one axis 2768 in case only the other axis is downscaled (see RADEON_OV0_FILTER_CNTL) */ 2769 dsr=(double)(1<<0xC)/h_inc; 2770 if(dsr<0.25)dsr=0.25; 2771 if(dsr>1.0)dsr=1.0; 2772 tap_set=(int)((dsr-0.25)*100); 2773 for(i=0;i<5;i++){ 2774 OUTREG(RADEON_OV0_FOUR_TAP_COEF_0+i*4, (TapCoeffs[tap_set].coeff[i][0] &0xf) | 2775 ((TapCoeffs[tap_set].coeff[i][1] &0x7f)<<8) | 2776 ((TapCoeffs[tap_set].coeff[i][2] &0x7f)<<16) | 2777 ((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24)); 2778 } 2779 2780 RADEONWaitForFifo(pScrn, 11); 2781 OUTREG(RADEON_OV0_V_INC, v_inc); 2782 OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 2783 OUTREG(RADEON_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | p23_blank_lines); 2784 OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch); 2785 OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, is_planar ? pitch >> 1 : pitch); 2786 OUTREG(RADEON_OV0_P1_X_START_END, (src_w + left - 1) | (left << 16)); 2787 if (!is_rgb) 2788 src_w >>= 1; 2789 OUTREG(RADEON_OV0_P2_X_START_END, (src_w + leftuv - 1) | (leftuv << 16)); 2790 OUTREG(RADEON_OV0_P3_X_START_END, (src_w + leftuv - 1) | (leftuv << 16)); 2791 if (info->ModeReg->ov0_base_addr != (info->fbLocation + base_offset)) { 2792 ErrorF("Changing OV0_BASE_ADDR from 0x%08x to 0x%08x\n", 2793 info->ModeReg->ov0_base_addr, (uint32_t)info->fbLocation + base_offset); 2794 info->ModeReg->ov0_base_addr = info->fbLocation + base_offset; 2795 OUTREG(RADEON_OV0_BASE_ADDR, info->ModeReg->ov0_base_addr); 2796 } 2797 OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1); 2798 OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2); 2799 OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3); 2800 2801 RADEONWaitForFifo(pScrn, 9); 2802 OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset4); 2803 OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset5); 2804 OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset6); 2805 OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 2806 OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 2807 OUTREG(RADEON_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); 2808 OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 2809 2810 scale_cntl = RADEON_SCALER_ADAPTIVE_DEINT | RADEON_SCALER_DOUBLE_BUFFER 2811 | RADEON_SCALER_ENABLE | RADEON_SCALER_SMART_SWITCH | (0x7f<<16) | scaler_src; 2812 switch(id){ 2813 case FOURCC_UYVY: 2814 scale_cntl |= RADEON_SCALER_SOURCE_YVYU422; 2815 break; 2816 case FOURCC_RGB24: 2817 case FOURCC_RGBA32: 2818 scale_cntl |= RADEON_SCALER_SOURCE_32BPP | RADEON_SCALER_LIN_TRANS_BYPASS; 2819 break; 2820 case FOURCC_RGB16: 2821 scale_cntl |= RADEON_SCALER_SOURCE_16BPP | RADEON_SCALER_LIN_TRANS_BYPASS; 2822 break; 2823 case FOURCC_RGBT16: 2824 scale_cntl |= RADEON_SCALER_SOURCE_15BPP | RADEON_SCALER_LIN_TRANS_BYPASS; 2825 break; 2826 case FOURCC_YV12: 2827 case FOURCC_I420: 2828 scale_cntl |= RADEON_SCALER_SOURCE_YUV12; 2829 break; 2830 case FOURCC_YUY2: 2831 default: 2832 scale_cntl |= RADEON_SCALER_SOURCE_VYUY422 2833 | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); 2834 break; 2835 } 2836 2837 if (info->ChipFamily < CHIP_FAMILY_R200) { 2838 scale_cntl &= ~RADEON_SCALER_GAMMA_SEL_MASK; 2839 scale_cntl |= ((RADEONTranslateUserGamma(pPriv->gamma)) << 5); 2840 } 2841 2842 OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl); 2843 OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); 2844} 2845 2846 2847static void 2848RADEONFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes) 2849{ 2850#if HAVE_XV_DRAWABLE_HELPER 2851 xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes); 2852#else 2853 xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes); 2854#endif 2855} 2856 2857 2858static int 2859RADEONPutImage( 2860 ScrnInfoPtr pScrn, 2861 short src_x, short src_y, 2862 short drw_x, short drw_y, 2863 short src_w, short src_h, 2864 short drw_w, short drw_h, 2865 int id, unsigned char* buf, 2866 short width, short height, 2867 Bool Sync, 2868 RegionPtr clipBoxes, pointer data, 2869 DrawablePtr pDraw 2870){ 2871 RADEONInfoPtr info = RADEONPTR(pScrn); 2872 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 2873 INT32 xa, xb, ya, yb; 2874 unsigned char *dst_start; 2875 int new_size, offset, s2offset, s3offset; 2876 int srcPitch, srcPitch2, dstPitch; 2877 int d2line, d3line; 2878 int top, left, npixels, nlines, bpp; 2879 int idconv = id; 2880 BoxRec dstBox; 2881 uint32_t tmp; 2882 xf86CrtcPtr crtc; 2883 2884 /* 2885 * s2offset, s3offset - byte offsets into U and V plane of the 2886 * source where copying starts. Y plane is 2887 * done by editing "buf". 2888 * 2889 * offset - byte offset to the first line of the destination. 2890 * 2891 * dst_start - byte address to the first displayed pel. 2892 * 2893 */ 2894 2895 /* make the compiler happy */ 2896 s2offset = s3offset = srcPitch2 = 0; 2897 d2line = d3line = 0; 2898 2899 if(src_w > (drw_w << 4)) 2900 drw_w = src_w >> 4; 2901 if(src_h > (drw_h << 4)) 2902 drw_h = src_h >> 4; 2903 2904 /* Clip */ 2905 xa = src_x; 2906 xb = src_x + src_w; 2907 ya = src_y; 2908 yb = src_y + src_h; 2909 2910 dstBox.x1 = drw_x; 2911 dstBox.x2 = drw_x + drw_w; 2912 dstBox.y1 = drw_y; 2913 dstBox.y2 = drw_y + drw_h; 2914 2915 if (!radeon_crtc_clip_video(pScrn, &crtc, pPriv->desired_crtc, 2916 &dstBox, &xa, &xb, &ya, &yb, 2917 clipBoxes, width, height)) 2918 return Success; 2919 2920 if (!crtc) { 2921 if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 2922 unsigned char *RADEONMMIO = info->MMIO; 2923 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 2924 pPriv->videoStatus &= ~CLIENT_VIDEO_ON; 2925 } 2926 return Success; 2927 } 2928 2929 dstBox.x1 -= crtc->x; 2930 dstBox.x2 -= crtc->x; 2931 dstBox.y1 -= crtc->y; 2932 dstBox.y2 -= crtc->y; 2933 2934 bpp = pScrn->bitsPerPixel >> 3; 2935 2936 switch(id) { 2937 case FOURCC_RGB24: 2938 dstPitch = width * 4; 2939 srcPitch = width * 3; 2940 break; 2941 case FOURCC_RGBA32: 2942 dstPitch = width * 4; 2943 srcPitch = width * 4; 2944 break; 2945 case FOURCC_RGB16: 2946 case FOURCC_RGBT16: 2947 dstPitch = width * 2; 2948 srcPitch = RADEON_ALIGN(width * 2, 4); 2949 break; 2950 case FOURCC_YV12: 2951 case FOURCC_I420: 2952 /* it seems rs4xx chips (all of them???) either can't handle planar 2953 yuv at all or would need some unknown different setup. */ 2954 if ((info->ChipFamily != CHIP_FAMILY_RS400) && 2955 (info->ChipFamily != CHIP_FAMILY_RS480)) { 2956 /* need 16bytes alignment for u,v plane, so 2 times that for width 2957 but blitter needs 64bytes alignment. 128byte is a waste but dstpitch 2958 for uv planes needs to be dstpitch yplane >> 1 for now. */ 2959 dstPitch = (RADEON_ALIGN(width, 128)); 2960 srcPitch = RADEON_ALIGN(width, 4); 2961 } 2962 else { 2963 dstPitch = width * 2; 2964 srcPitch = RADEON_ALIGN(width, 4); 2965 idconv = FOURCC_YUY2; 2966 } 2967 break; 2968 case FOURCC_UYVY: 2969 case FOURCC_YUY2: 2970 default: 2971 dstPitch = width * 2; 2972 srcPitch = width * 2; 2973 break; 2974 } 2975 2976#ifdef XF86DRI 2977 if (info->directRenderingEnabled && info->DMAForXv) { 2978 /* The upload blit only supports multiples of 64 bytes */ 2979 dstPitch = RADEON_ALIGN(dstPitch, 64); 2980 } else 2981#endif 2982 /* The overlay only supports multiples of 16 bytes */ 2983 dstPitch = RADEON_ALIGN(dstPitch, 16); 2984 2985 new_size = dstPitch * height; 2986 if (idconv == FOURCC_YV12 || id == FOURCC_I420) { 2987 new_size += (dstPitch >> 1) * (RADEON_ALIGN(height, 2)); 2988 } 2989 pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, &pPriv->video_memory, 2990 (pPriv->doubleBuffer ? 2991 (new_size * 2) : new_size), 64, 2992 RADEON_GEM_DOMAIN_VRAM); 2993 if (pPriv->video_offset == 0) 2994 return BadAlloc; 2995 2996 pPriv->currentBuffer ^= 1; 2997 2998 /* copy data */ 2999 top = ya >> 16; 3000 left = (xa >> 16) & ~1; 3001 npixels = ((xb + 0xffff) >> 16) - left; 3002 3003 offset = (pPriv->video_offset) + (top * dstPitch); 3004 3005 if(pPriv->doubleBuffer) { 3006 unsigned char *RADEONMMIO = info->MMIO; 3007 3008 /* Wait for last flip to take effect */ 3009 while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_FLIP_READBACK)); 3010 3011 offset += pPriv->currentBuffer * new_size; 3012 } 3013 3014 dst_start = info->FB + offset; 3015 3016 switch(id) { 3017 case FOURCC_YV12: 3018 case FOURCC_I420: 3019 if (id == idconv) { 3020 /* meh. Such a mess just for someone who wants to watch half the video clipped */ 3021 top &= ~1; 3022 /* odd number of pixels? That may not work correctly */ 3023 srcPitch2 = RADEON_ALIGN(width >> 1, 4); 3024 /* odd number of lines? Maybe... */ 3025 s2offset = srcPitch * (RADEON_ALIGN(height, 2)); 3026 s3offset = s2offset + srcPitch2 * ((height + 1) >> 1); 3027 s2offset += (top >> 1) * srcPitch2 + (left >> 1); 3028 s3offset += (top >> 1) * srcPitch2 + (left >> 1); 3029 d2line = (height * dstPitch); 3030 d3line = d2line + ((height + 1) >> 1) * (dstPitch >> 1); 3031 nlines = ((yb + 0xffff) >> 16) - top; 3032 d2line += (top >> 1) * (dstPitch >> 1) - (top * dstPitch); 3033 d3line += (top >> 1) * (dstPitch >> 1) - (top * dstPitch); 3034 if(id == FOURCC_YV12) { 3035 tmp = s2offset; 3036 s2offset = s3offset; 3037 s3offset = tmp; 3038 } 3039 RADEONCopyData(pScrn, buf + (top * srcPitch) + left, dst_start + left, 3040 srcPitch, dstPitch, nlines, npixels, 1); 3041 RADEONCopyData(pScrn, buf + s2offset, dst_start + d2line + (left >> 1), 3042 srcPitch2, dstPitch >> 1, (nlines + 1) >> 1, npixels >> 1, 1); 3043 RADEONCopyData(pScrn, buf + s3offset, dst_start + d3line + (left >> 1), 3044 srcPitch2, dstPitch >> 1, (nlines + 1) >> 1, npixels >> 1, 1); 3045 } 3046 else { 3047 s2offset = srcPitch * height; 3048 srcPitch2 = RADEON_ALIGN(width >> 1, 4); 3049 s3offset = (srcPitch2 * (height >> 1)) + s2offset; 3050 top &= ~1; 3051 dst_start += left << 1; 3052 tmp = ((top >> 1) * srcPitch2) + (left >> 1); 3053 s2offset += tmp; 3054 s3offset += tmp; 3055 if(id == FOURCC_I420) { 3056 tmp = s2offset; 3057 s2offset = s3offset; 3058 s3offset = tmp; 3059 } 3060 nlines = ((yb + 0xffff) >> 16) - top; 3061 RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left, 3062 buf + s2offset, buf + s3offset, dst_start, 3063 srcPitch, srcPitch2, dstPitch, nlines, npixels); 3064 } 3065 break; 3066 case FOURCC_RGBT16: 3067 case FOURCC_RGB16: 3068 case FOURCC_UYVY: 3069 case FOURCC_YUY2: 3070 default: 3071 left <<= 1; 3072 buf += (top * srcPitch) + left; 3073 nlines = ((yb + 0xffff) >> 16) - top; 3074 dst_start += left; 3075 RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 2); 3076 break; 3077 case FOURCC_RGBA32: 3078 buf += (top * srcPitch) + left*4; 3079 nlines = ((yb + 0xffff) >> 16) - top; 3080 dst_start += left*4; 3081 RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 4); 3082 break; 3083 case FOURCC_RGB24: 3084 buf += (top * srcPitch) + left*3; 3085 nlines = ((yb + 0xffff) >> 16) - top; 3086 dst_start += left*4; 3087 RADEONCopyRGB24Data(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels); 3088 break; 3089 } 3090 3091 /* update cliplist */ 3092 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) 3093 { 3094 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 3095 /* draw these */ 3096 if(pPriv->autopaint_colorkey) 3097 RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); 3098 } 3099 3100 /* FIXME: someone should look at these offsets, I don't think it makes sense how 3101 they are handled throughout the source. */ 3102 RADEONDisplayVideo(pScrn, crtc, pPriv, idconv, pPriv->video_offset, offset, 3103 offset + d2line, offset + d3line, offset, offset + d2line, 3104 offset + d3line, width, height, dstPitch, xa, xb, ya, 3105 &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB); 3106 3107 pPriv->videoStatus = CLIENT_VIDEO_ON; 3108 3109 info->VideoTimerCallback = RADEONVideoTimerCallback; 3110 3111 return Success; 3112} 3113 3114 3115int 3116RADEONQueryImageAttributes( 3117 ScrnInfoPtr pScrn, 3118 int id, 3119 unsigned short *w, unsigned short *h, 3120 int *pitches, int *offsets 3121){ 3122 const RADEONInfoRec * const info = RADEONPTR(pScrn); 3123 int size, tmp; 3124 3125 if(*w > info->xv_max_width) *w = info->xv_max_width; 3126 if(*h > info->xv_max_height) *h = info->xv_max_height; 3127 3128 *w = RADEON_ALIGN(*w, 2); 3129 if(offsets) offsets[0] = 0; 3130 3131 switch(id) { 3132 case FOURCC_YV12: 3133 case FOURCC_I420: 3134 *h = RADEON_ALIGN(*h, 2); 3135 size = RADEON_ALIGN(*w, 4); 3136 if(pitches) pitches[0] = size; 3137 size *= *h; 3138 if(offsets) offsets[1] = size; 3139 tmp = RADEON_ALIGN(*w >> 1, 4); 3140 if(pitches) pitches[1] = pitches[2] = tmp; 3141 tmp *= (*h >> 1); 3142 size += tmp; 3143 if(offsets) offsets[2] = size; 3144 size += tmp; 3145 break; 3146 case FOURCC_RGBA32: 3147 size = *w << 2; 3148 if(pitches) pitches[0] = size; 3149 size *= *h; 3150 break; 3151 case FOURCC_RGB24: 3152 size = *w * 3; 3153 if(pitches) pitches[0] = size; 3154 size *= *h; 3155 break; 3156 case FOURCC_RGBT16: 3157 case FOURCC_RGB16: 3158 case FOURCC_UYVY: 3159 case FOURCC_YUY2: 3160 default: 3161 size = *w << 1; 3162 if(pitches) pitches[0] = size; 3163 size *= *h; 3164 break; 3165 } 3166 3167 return size; 3168} 3169 3170static void 3171RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) 3172{ 3173 RADEONInfoPtr info = RADEONPTR(pScrn); 3174 RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 3175 3176 if(pPriv->videoStatus & TIMER_MASK) { 3177 if(pPriv->videoStatus & OFF_TIMER) { 3178 if(pPriv->offTime < now) { 3179 unsigned char *RADEONMMIO = info->MMIO; 3180 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 3181 pPriv->videoStatus = FREE_TIMER; 3182 pPriv->freeTime = now + FREE_DELAY; 3183 } 3184 } else { /* FREE_TIMER */ 3185 if(pPriv->freeTime < now) { 3186 RADEONFreeVideoMemory(pScrn, pPriv); 3187 pPriv->videoStatus = 0; 3188 info->VideoTimerCallback = NULL; 3189 } 3190 } 3191 } else /* shouldn't get here */ 3192 info->VideoTimerCallback = NULL; 3193} 3194 3195/****************** Offscreen stuff ***************/ 3196typedef struct { 3197 void *surface_memory; 3198 Bool isOn; 3199} OffscreenPrivRec, * OffscreenPrivPtr; 3200 3201static int 3202RADEONAllocateSurface( 3203 ScrnInfoPtr pScrn, 3204 int id, 3205 unsigned short w, 3206 unsigned short h, 3207 XF86SurfacePtr surface 3208){ 3209 int offset, pitch, size; 3210 OffscreenPrivPtr pPriv; 3211 void *surface_memory = NULL; 3212 if((w > 1024) || (h > 1024)) 3213 return BadAlloc; 3214 3215 w = RADEON_ALIGN(w, 2); 3216 pitch = RADEON_ALIGN(w << 1, 16); 3217 size = pitch * h; 3218 3219 offset = radeon_legacy_allocate_memory(pScrn, &surface_memory, size, 64, 3220 RADEON_GEM_DOMAIN_VRAM); 3221 if (offset == 0) 3222 return BadAlloc; 3223 3224 surface->width = w; 3225 surface->height = h; 3226 3227 if(!(surface->pitches = malloc(sizeof(int)))) { 3228 radeon_legacy_free_memory(pScrn, surface_memory); 3229 return BadAlloc; 3230 } 3231 if(!(surface->offsets = malloc(sizeof(int)))) { 3232 free(surface->pitches); 3233 radeon_legacy_free_memory(pScrn, surface_memory); 3234 return BadAlloc; 3235 } 3236 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 3237 free(surface->pitches); 3238 free(surface->offsets); 3239 radeon_legacy_free_memory(pScrn, surface_memory); 3240 return BadAlloc; 3241 } 3242 3243 pPriv->surface_memory = surface_memory; 3244 pPriv->isOn = FALSE; 3245 3246 surface->pScrn = pScrn; 3247 surface->id = id; 3248 surface->pitches[0] = pitch; 3249 surface->offsets[0] = offset; 3250 surface->devPrivate.ptr = (pointer)pPriv; 3251 3252 return Success; 3253} 3254 3255static int 3256RADEONStopSurface( 3257 XF86SurfacePtr surface 3258){ 3259 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 3260 RADEONInfoPtr info = RADEONPTR(surface->pScrn); 3261 unsigned char *RADEONMMIO = info->MMIO; 3262 3263 if(pPriv->isOn) { 3264 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 3265 pPriv->isOn = FALSE; 3266 } 3267 return Success; 3268} 3269 3270 3271static int 3272RADEONFreeSurface( 3273 XF86SurfacePtr surface 3274){ 3275 ScrnInfoPtr pScrn = surface->pScrn; 3276 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 3277 3278 if(pPriv->isOn) 3279 RADEONStopSurface(surface); 3280 radeon_legacy_free_memory(pScrn, pPriv->surface_memory); 3281 pPriv->surface_memory = NULL; 3282 free(surface->pitches); 3283 free(surface->offsets); 3284 free(surface->devPrivate.ptr); 3285 3286 return Success; 3287} 3288 3289static int 3290RADEONGetSurfaceAttribute( 3291 ScrnInfoPtr pScrn, 3292 Atom attribute, 3293 INT32 *value 3294){ 3295 return RADEONGetPortAttribute(pScrn, attribute, value, 3296 (pointer)(GET_PORT_PRIVATE(pScrn))); 3297} 3298 3299static int 3300RADEONSetSurfaceAttribute( 3301 ScrnInfoPtr pScrn, 3302 Atom attribute, 3303 INT32 value 3304){ 3305 return RADEONSetPortAttribute(pScrn, attribute, value, 3306 (pointer)(GET_PORT_PRIVATE(pScrn))); 3307} 3308 3309 3310static int 3311RADEONDisplaySurface( 3312 XF86SurfacePtr surface, 3313 short src_x, short src_y, 3314 short drw_x, short drw_y, 3315 short src_w, short src_h, 3316 short drw_w, short drw_h, 3317 RegionPtr clipBoxes 3318){ 3319 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 3320 ScrnInfoPtr pScrn = surface->pScrn; 3321 RADEONInfoPtr info = RADEONPTR(pScrn); 3322 RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr; 3323 3324 INT32 xa, ya, xb, yb; 3325 BoxRec dstBox; 3326 xf86CrtcPtr crtc; 3327 3328 if (src_w > (drw_w << 4)) 3329 drw_w = src_w >> 4; 3330 if (src_h > (drw_h << 4)) 3331 drw_h = src_h >> 4; 3332 3333 xa = src_x; 3334 xb = src_x + src_w; 3335 ya = src_y; 3336 yb = src_y + src_h; 3337 3338 dstBox.x1 = drw_x; 3339 dstBox.x2 = drw_x + drw_w; 3340 dstBox.y1 = drw_y; 3341 dstBox.y2 = drw_y + drw_h; 3342 3343 if (!radeon_crtc_clip_video(pScrn, &crtc, portPriv->desired_crtc, 3344 &dstBox, &xa, &xb, &ya, &yb, clipBoxes, 3345 surface->width, surface->height)) 3346 return Success; 3347 3348 if (!crtc) { 3349 if (pPriv->isOn) { 3350 unsigned char *RADEONMMIO = info->MMIO; 3351 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 3352 pPriv->isOn = FALSE; 3353 } 3354 return Success; 3355 } 3356 3357 dstBox.x1 -= crtc->x; 3358 dstBox.x2 -= crtc->x; 3359 dstBox.y1 -= crtc->y; 3360 dstBox.y2 -= crtc->y; 3361 3362#if 0 3363 /* this isn't needed */ 3364 RADEONResetVideo(pScrn); 3365#endif 3366 RADEONDisplayVideo(pScrn, crtc, portPriv, surface->id, 3367 surface->offsets[0], surface->offsets[0], 3368 surface->offsets[0], surface->offsets[0], 3369 surface->offsets[0], surface->offsets[0], 3370 surface->offsets[0], surface->width, surface->height, 3371 surface->pitches[0], xa, xb, ya, &dstBox, src_w, src_h, 3372 drw_w, drw_h, METHOD_BOB); 3373 3374 if (portPriv->autopaint_colorkey) 3375 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 3376 3377 pPriv->isOn = TRUE; 3378 /* we've prempted the XvImage stream so set its free timer */ 3379 if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 3380 REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 3381 UpdateCurrentTime(); 3382 portPriv->videoStatus = FREE_TIMER; 3383 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 3384 info->VideoTimerCallback = RADEONVideoTimerCallback; 3385 } 3386 3387 return Success; 3388} 3389 3390 3391static void 3392RADEONInitOffscreenImages(ScreenPtr pScreen) 3393{ 3394/* ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3395 RADEONInfoPtr info = RADEONPTR(pScrn); */ 3396 XF86OffscreenImagePtr offscreenImages; 3397 /* need to free this someplace */ 3398 3399 if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 3400 return; 3401 3402 offscreenImages[0].image = &Images[0]; 3403 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| 3404 VIDEO_CLIP_TO_VIEWPORT*/; 3405 offscreenImages[0].alloc_surface = RADEONAllocateSurface; 3406 offscreenImages[0].free_surface = RADEONFreeSurface; 3407 offscreenImages[0].display = RADEONDisplaySurface; 3408 offscreenImages[0].stop = RADEONStopSurface; 3409 offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute; 3410 offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute; 3411 offscreenImages[0].max_width = 2047; 3412 offscreenImages[0].max_height = 2047; 3413 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 3414 offscreenImages[0].attributes = Attributes; 3415 3416 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 3417} 3418 3419 /* TV-in functions */ 3420 3421static int 3422RADEONPutVideo( 3423 ScrnInfoPtr pScrn, 3424 short src_x, short src_y, 3425 short drw_x, short drw_y, 3426 short src_w, short src_h, 3427 short drw_w, short drw_h, 3428 RegionPtr clipBoxes, pointer data, 3429 DrawablePtr pDraw 3430){ 3431 RADEONInfoPtr info = RADEONPTR(pScrn); 3432 RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; 3433 unsigned char *RADEONMMIO = info->MMIO; 3434 INT32 xa, xb, ya, yb, top; 3435 unsigned int pitch, new_size, alloc_size; 3436 unsigned int offset1, offset2, offset3, offset4, s2offset, s3offset; 3437 unsigned int vbi_offset0, vbi_offset1; 3438 int srcPitch, srcPitch2, dstPitch; 3439 int bpp; 3440 BoxRec dstBox; 3441 uint32_t id, display_base; 3442 int width, height; 3443 int mult; 3444 int vbi_line_width, vbi_start, vbi_end; 3445 xf86CrtcPtr crtc; 3446 3447 RADEON_SYNC(info, pScrn); 3448 /* 3449 * s2offset, s3offset - byte offsets into U and V plane of the 3450 * source where copying starts. Y plane is 3451 * done by editing "buf". 3452 * 3453 * offset - byte offset to the first line of the destination. 3454 * 3455 * dst_start - byte address to the first displayed pel. 3456 * 3457 */ 3458 3459 /* make the compiler happy */ 3460 s2offset = s3offset = srcPitch2 = 0; 3461 3462 if(src_w > (drw_w << 4)) 3463 drw_w = src_w >> 4; 3464 if(src_h > (drw_h << 4)) 3465 drw_h = src_h >> 4; 3466 3467 /* Clip */ 3468 xa = src_x; 3469 xb = src_x + src_w; 3470 ya = src_y; 3471 yb = src_y + src_h; 3472 3473 dstBox.x1 = drw_x; 3474 dstBox.x2 = drw_x + drw_w; 3475 dstBox.y1 = drw_y; 3476 dstBox.y2 = drw_y + drw_h; 3477 3478 width = InputVideoEncodings[pPriv->encoding].width; 3479 height = InputVideoEncodings[pPriv->encoding].height; 3480 3481 vbi_line_width = 798*2; 3482 if(width<=640) 3483 vbi_line_width = 0x640; /* 1600 actually */ 3484 else 3485 vbi_line_width = 2000; /* might need adjustment */ 3486 3487 if (!radeon_crtc_clip_video(pScrn, &crtc, pPriv->desired_crtc, 3488 &dstBox, &xa, &xb, &ya, &yb, 3489 clipBoxes, width, height)) 3490 return Success; 3491 3492 if (!crtc) { 3493 if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 3494 unsigned char *RADEONMMIO = info->MMIO; 3495 OUTREG(RADEON_OV0_SCALE_CNTL, 0); 3496 pPriv->videoStatus &= ~CLIENT_VIDEO_ON; 3497 } 3498 return Success; 3499 } 3500 3501 dstBox.x1 -= crtc->x; 3502 dstBox.x2 -= crtc->x; 3503 dstBox.y1 -= crtc->y; 3504 dstBox.y2 -= crtc->y; 3505 3506 bpp = pScrn->bitsPerPixel >> 3; 3507 pitch = bpp * pScrn->displayWidth; 3508 3509 switch(pPriv->overlay_deinterlacing_method){ 3510 case METHOD_BOB: 3511 case METHOD_SINGLE: 3512 mult=2; 3513 break; 3514 case METHOD_WEAVE: 3515 case METHOD_ADAPTIVE: 3516 mult=4; 3517 break; 3518 default: 3519 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Internal error: PutVideo\n"); 3520 mult=4; 3521 } 3522 3523 id = FOURCC_YUY2; 3524 3525 top = ya>>16; 3526#if 0 3527 /* setting the ID above makes this useful - needs revisiting */ 3528 switch(id) { 3529 case FOURCC_YV12: 3530 case FOURCC_I420: 3531 top &= ~1; 3532 dstPitch = RADEON_ALIGN(width << 1, 16); 3533 srcPitch = RADEON_ALIGN(width, 4); 3534 s2offset = srcPitch * height; 3535 srcPitch2 = RADEON_ALIGN(width >> 1, 4); 3536 s3offset = (srcPitch2 * (height >> 1)) + s2offset; 3537 break; 3538 case FOURCC_UYVY: 3539 case FOURCC_YUY2: 3540 default: 3541 dstPitch = RADEON_ALIGN(width<<1, 16); 3542 srcPitch = (width<<1); 3543 break; 3544 } 3545#else 3546 dstPitch = RADEON_ALIGN(width << 1, 16); 3547 srcPitch = (width<<1); 3548#endif 3549 3550 new_size = dstPitch * height; 3551 new_size = new_size + 0x1f; /* for aligning */ 3552 alloc_size = new_size * mult; 3553 if (pPriv->capture_vbi_data) 3554 alloc_size += 2 * 2 * vbi_line_width * 21; 3555 3556 pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, &pPriv->video_memory, 3557 (pPriv->doubleBuffer ? 3558 (new_size * 2) : new_size), 64, 3559 RADEON_GEM_DOMAIN_GTT); 3560 if (pPriv->video_offset == 0) 3561 return BadAlloc; 3562 3563/* I have suspicion that capture engine must be active _before_ Rage Theatre 3564 is being manipulated with.. */ 3565 3566 RADEONWaitForIdleMMIO(pScrn); 3567 display_base=INREG(RADEON_DISPLAY_BASE_ADDR); 3568 3569/* RADEONWaitForFifo(pScrn, 15); */ 3570 3571 switch(pPriv->overlay_deinterlacing_method){ 3572 case METHOD_BOB: 3573 case METHOD_SINGLE: 3574 offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10); 3575 offset2 = RADEON_ALIGN(pPriv->video_offset + new_size, 0x10); 3576 offset3 = offset1; 3577 offset4 = offset2; 3578 break; 3579 case METHOD_WEAVE: 3580 offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10); 3581 offset2 = offset1+dstPitch; 3582 offset3 = RADEON_ALIGN(pPriv->video_offset + 2 * new_size, 0x10); 3583 offset4 = offset3+dstPitch; 3584 break; 3585 default: 3586 offset1 = RADEON_ALIGN(pPriv->video_offset, 0x10); 3587 offset2 = RADEON_ALIGN(pPriv->video_offset + new_size, 0x10); 3588 offset3 = offset1; 3589 offset4 = offset2; 3590 } 3591 3592 OUTREG(RADEON_CAP0_BUF0_OFFSET, offset1+display_base); 3593 OUTREG(RADEON_CAP0_BUF0_EVEN_OFFSET, offset2+display_base); 3594 OUTREG(RADEON_CAP0_BUF1_OFFSET, offset3+display_base); 3595 OUTREG(RADEON_CAP0_BUF1_EVEN_OFFSET, offset4+display_base); 3596 3597 OUTREG(RADEON_CAP0_ONESHOT_BUF_OFFSET, offset1+display_base); 3598 3599 if(pPriv->capture_vbi_data){ 3600 if ((pPriv->encoding==2)||(pPriv->encoding==8)) { 3601 /* PAL, SECAM */ 3602 vbi_start = 5; 3603 vbi_end = 21; 3604 } else { 3605 /* NTSC */ 3606 vbi_start = 8; 3607 vbi_end = 20; 3608 } 3609 3610 vbi_offset0 = RADEON_ALIGN(pPriv->video_offset + mult * new_size * bpp, 0x10); 3611 vbi_offset1 = vbi_offset0 + dstPitch*20; 3612 OUTREG(RADEON_CAP0_VBI0_OFFSET, vbi_offset0+display_base); 3613 OUTREG(RADEON_CAP0_VBI1_OFFSET, vbi_offset1+display_base); 3614 OUTREG(RADEON_CAP0_VBI2_OFFSET, 0); 3615 OUTREG(RADEON_CAP0_VBI3_OFFSET, 0); 3616 OUTREG(RADEON_CAP0_VBI_V_WINDOW, vbi_start | (vbi_end<<16)); 3617 OUTREG(RADEON_CAP0_VBI_H_WINDOW, 0 | (vbi_line_width)<<16); 3618 } 3619 3620 OUTREG(RADEON_CAP0_BUF_PITCH, dstPitch*mult/2); 3621 OUTREG(RADEON_CAP0_H_WINDOW, (2*width)<<16); 3622 OUTREG(RADEON_CAP0_V_WINDOW, (((height)+pPriv->v-1)<<16)|(pPriv->v-1)); 3623 if(mult==2){ 3624 OUTREG(RADEON_CAP0_CONFIG, ENABLE_RADEON_CAPTURE_BOB); 3625 } else { 3626 OUTREG(RADEON_CAP0_CONFIG, ENABLE_RADEON_CAPTURE_WEAVE); 3627 } 3628 OUTREG(RADEON_CAP0_DEBUG, 0); 3629 3630 OUTREG(RADEON_VID_BUFFER_CONTROL, (1<<16) | 0x01); 3631 OUTREG(RADEON_TEST_DEBUG_CNTL, 0); 3632 3633 if(! pPriv->video_stream_active) 3634 { 3635 3636 RADEONWaitForIdleMMIO(pScrn); 3637 OUTREG(RADEON_VIDEOMUX_CNTL, INREG(RADEON_VIDEOMUX_CNTL)|1 ); 3638 OUTREG(RADEON_CAP0_PORT_MODE_CNTL, (pPriv->theatre!=NULL)? 1: 0); 3639 OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_PCLK); 3640 OUTREG(RADEON_CAP0_TRIG_CNTL, 0x11); 3641 if(pPriv->theatre != NULL) 3642 { 3643 RADEON_RT_SetEncoding(pScrn, pPriv); 3644 } 3645 if(pPriv->msp3430 != NULL) RADEON_MSP_SetEncoding(pPriv); 3646 if(pPriv->tda9885 != NULL) RADEON_TDA9885_SetEncoding(pPriv); 3647 if(pPriv->fi1236 != NULL) RADEON_FI1236_SetEncoding(pPriv); 3648 if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv); 3649 } 3650 3651 3652 /* update cliplist */ 3653 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 3654 REGION_COPY(pScreen, &pPriv->clip, clipBoxes); 3655 /* draw these */ 3656 if(pPriv->autopaint_colorkey) 3657 RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); 3658 } 3659 3660 RADEONDisplayVideo(pScrn, crtc, pPriv, id, pPriv->video_offset, 3661 offset1+top*srcPitch, offset2+top*srcPitch, 3662 offset3+top*srcPitch, offset4+top*srcPitch, 3663 offset1+top*srcPitch, offset2+top*srcPitch, width, height, 3664 dstPitch*mult/2, xa, xb, ya, &dstBox, src_w, src_h*mult/2, 3665 drw_w, drw_h, pPriv->overlay_deinterlacing_method); 3666 3667 RADEONWaitForFifo(pScrn, 1); 3668 OUTREG(RADEON_OV0_REG_LOAD_CNTL, RADEON_REG_LD_CTL_LOCK); 3669 RADEONWaitForIdleMMIO(pScrn); 3670 while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_LOCK_READBACK)); 3671 3672 3673 switch(pPriv->overlay_deinterlacing_method){ 3674 case METHOD_BOB: 3675 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA); 3676 OUTREG(RADEON_OV0_AUTO_FLIP_CNTL,0 /*| RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD*/ 3677 |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN); 3678 break; 3679 case METHOD_SINGLE: 3680 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xEEEEE | (9<<28)); 3681 OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 3682 |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN); 3683 break; 3684 case METHOD_WEAVE: 3685 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0x11111 | (9<<28)); 3686 OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0 |RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 3687 | RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN 3688 /* |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN */ 3689 /*|RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN */ 3690 |RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE); 3691 break; 3692 default: 3693 OUTREG(RADEON_OV0_DEINTERLACE_PATTERN, 0xAAAAA); 3694 OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 3695 |RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN); 3696 } 3697 3698 3699 RADEONWaitForIdleMMIO(pScrn); 3700 OUTREG (RADEON_OV0_AUTO_FLIP_CNTL, (INREG (RADEON_OV0_AUTO_FLIP_CNTL) ^ RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE )); 3701 OUTREG (RADEON_OV0_AUTO_FLIP_CNTL, (INREG (RADEON_OV0_AUTO_FLIP_CNTL) ^ RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE )); 3702 3703 OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); 3704 3705#if 0 3706 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "OV0_FLAG_CNTL=0x%08x\n", INREG(RADEON_OV0_FLAG_CNTL)); 3707/* OUTREG(RADEON_OV0_FLAG_CNTL, 8); */ 3708 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "OV0_VID_BUFFER_CNTL=0x%08x\n", INREG(RADEON_VID_BUFFER_CONTROL)); 3709 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CAP0_BUF_STATUS=0x%08x\n", INREG(RADEON_CAP0_BUF_STATUS)); 3710 3711/* OUTREG(RADEON_OV0_SCALE_CNTL, 0x417f1B00); */ 3712#endif 3713 3714 pPriv->videoStatus = CLIENT_VIDEO_ON; 3715 pPriv->video_stream_active = TRUE; 3716 3717 info->VideoTimerCallback = RADEONVideoTimerCallback; 3718 3719 return Success; 3720} 3721 /* miscellaneous TV-in helper functions */ 3722 3723static void RADEON_board_setmisc(RADEONPortPrivPtr pPriv) 3724{ 3725 /* Adjust PAL/SECAM constants for FI1216MF tuner */ 3726 if((((pPriv->tuner_type & 0xf)==5) || 3727 ((pPriv->tuner_type & 0xf)==11)|| 3728 ((pPriv->tuner_type & 0xf)==14)) 3729 && (pPriv->fi1236!=NULL)) 3730 { 3731 if((pPriv->encoding>=1)&&(pPriv->encoding<=3)) /*PAL*/ 3732 { 3733 pPriv->fi1236->parm.band_low = 0xA1; 3734 pPriv->fi1236->parm.band_mid = 0x91; 3735 pPriv->fi1236->parm.band_high = 0x31; 3736 } 3737 if((pPriv->encoding>=7)&&(pPriv->encoding<=9)) /*SECAM*/ 3738 { 3739 pPriv->fi1236->parm.band_low = 0xA3; 3740 pPriv->fi1236->parm.band_mid = 0x93; 3741 pPriv->fi1236->parm.band_high = 0x33; 3742 } 3743 } 3744 3745} 3746 3747static void RADEON_RT_SetEncoding(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) 3748{ 3749int width, height; 3750RADEONWaitForIdleMMIO(pScrn); 3751 3752/* Disable VBI capture for anything but TV tuner */ 3753switch(pPriv->encoding){ 3754 case 2: 3755 case 5: 3756 case 8: 3757 pPriv->capture_vbi_data=1; 3758 break; 3759 default: 3760 pPriv->capture_vbi_data=0; 3761 } 3762 3763switch(pPriv->encoding){ 3764 case 1: 3765 xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0); 3766 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL); 3767 pPriv->v=25; 3768 break; 3769 case 2: 3770 xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0); 3771 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL); 3772 pPriv->v=25; 3773 break; 3774 case 3: 3775 xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0); 3776 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL); 3777 pPriv->v=25; 3778 break; 3779 case 4: 3780 xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE,0); 3781 xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE); 3782 pPriv->v=23; 3783 break; 3784 case 5: 3785 xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0); 3786 xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE); 3787 pPriv->v=23; 3788 break; 3789 case 6: 3790 xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0); 3791 xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE); 3792 pPriv->v=23; 3793 break; 3794 case 7: 3795 xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE, 0); 3796 xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE); 3797 pPriv->v=25; 3798 break; 3799 case 8: 3800 xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0); 3801 xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE); 3802 pPriv->v=25; 3803 break; 3804 case 9: 3805 xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0); 3806 xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE); 3807 pPriv->v=25; 3808 break; 3809 case 10: 3810 xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0); 3811 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60); 3812 pPriv->v=25; 3813 break; 3814 case 11: 3815 xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0); 3816 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60); 3817 pPriv->v=25; 3818 break; 3819 case 12: 3820 xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0); 3821 xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60); 3822 pPriv->v=25; 3823 break; 3824 default: 3825 pPriv->v=0; 3826 return; 3827 } 3828xf86_RT_SetInterlace(pPriv->theatre, 1); 3829width = InputVideoEncodings[pPriv->encoding].width; 3830height = InputVideoEncodings[pPriv->encoding].height; 3831xf86_RT_SetOutputVideoSize(pPriv->theatre, width, height*2, 0, pPriv->capture_vbi_data); 3832} 3833 3834static void RADEON_MSP_SetEncoding(RADEONPortPrivPtr pPriv) 3835{ 3836xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE); 3837switch(pPriv->encoding){ 3838 case 1: 3839 pPriv->msp3430->standard = MSP3430_PAL; 3840 pPriv->msp3430->connector = MSP3430_CONNECTOR_3; 3841 break; 3842 case 2: 3843 pPriv->msp3430->standard = MSP3430_PAL; 3844 pPriv->msp3430->connector = MSP3430_CONNECTOR_1; 3845 break; 3846 case 3: 3847 pPriv->msp3430->standard = MSP3430_PAL; 3848 pPriv->msp3430->connector = MSP3430_CONNECTOR_2; 3849 break; 3850 case 4: 3851 pPriv->msp3430->standard = MSP3430_NTSC; 3852 pPriv->msp3430->connector = MSP3430_CONNECTOR_3; 3853 break; 3854 case 5: 3855 pPriv->msp3430->standard = MSP3430_NTSC; 3856 pPriv->msp3430->connector = MSP3430_CONNECTOR_1; 3857 break; 3858 case 6: 3859 pPriv->msp3430->standard = MSP3430_NTSC; 3860 pPriv->msp3430->connector = MSP3430_CONNECTOR_2; 3861 break; 3862 case 7: 3863 pPriv->msp3430->standard = MSP3430_SECAM; 3864 pPriv->msp3430->connector = MSP3430_CONNECTOR_3; 3865 break; 3866 case 8: 3867 pPriv->msp3430->standard = MSP3430_SECAM; 3868 pPriv->msp3430->connector = MSP3430_CONNECTOR_1; 3869 break; 3870 case 9: 3871 pPriv->msp3430->standard = MSP3430_SECAM; 3872 pPriv->msp3430->connector = MSP3430_CONNECTOR_2; 3873 break; 3874 case 10: 3875 pPriv->msp3430->standard = MSP3430_SECAM; 3876 pPriv->msp3430->connector = MSP3430_CONNECTOR_3; 3877 break; 3878 case 11: 3879 pPriv->msp3430->standard = MSP3430_SECAM; 3880 pPriv->msp3430->connector = MSP3430_CONNECTOR_1; 3881 break; 3882 case 12: 3883 pPriv->msp3430->standard = MSP3430_SECAM; 3884 pPriv->msp3430->connector = MSP3430_CONNECTOR_2; 3885 break; 3886 default: 3887 return; 3888 } 3889xf86_InitMSP3430(pPriv->msp3430); 3890xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume)); 3891} 3892 3893static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv) 3894{ 3895TDA9885Ptr t=pPriv->tda9885; 3896 3897switch(pPriv->encoding){ 3898 /* PAL */ 3899 case 1: 3900 case 2: 3901 case 3: 3902 t->standard_video_if=2; 3903 t->standard_sound_carrier=1; 3904 t->modulation=2; /* negative FM */ 3905 break; 3906 /* NTSC */ 3907 case 4: 3908 case 5: 3909 case 6: 3910 t->standard_video_if=1; 3911 t->standard_sound_carrier=0; 3912 t->modulation=2; /* negative FM */ 3913 break; 3914 /* SECAM */ 3915 case 7: 3916 case 8: 3917 case 9: 3918 case 10: 3919 case 11: 3920 case 12: 3921 t->standard_video_if=0; 3922 t->standard_sound_carrier=3; 3923 t->modulation=0; /* positive AM */ 3924 break; 3925 default: 3926 return; 3927 } 3928xf86_tda9885_setparameters(pPriv->tda9885); 3929xf86_tda9885_getstatus(pPriv->tda9885); 3930xf86_tda9885_dumpstatus(pPriv->tda9885); 3931} 3932 3933static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv) 3934{ 3935/* at the moment this only affect MT2032 */ 3936switch(pPriv->encoding){ 3937 /* PAL */ 3938 case 1: 3939 case 2: 3940 case 3: 3941 pPriv->fi1236->video_if=38.900; 3942 break; 3943 /* NTSC */ 3944 case 4: 3945 case 5: 3946 case 6: 3947 pPriv->fi1236->video_if=45.7812; 3948 pPriv->fi1236->video_if=45.750; 3949 pPriv->fi1236->video_if=45.125; 3950 break; 3951 /* SECAM */ 3952 case 7: 3953 case 8: 3954 case 9: 3955 case 10: 3956 case 11: 3957 case 12: 3958 pPriv->fi1236->video_if=58.7812; 3959 break; 3960 default: 3961 return; 3962 } 3963} 3964 3965