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