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