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