radeon_tv.c revision 209ff23f
1/* 2 * Integrated TV out support based on the GATOS code by 3 * Federico Ulivi <fulivi@lycos.com> 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif 9 10#include <string.h> 11#include <stdio.h> 12 13/* X and server generic header files */ 14#include "xf86.h" 15#include "xf86_OSproc.h" 16#include "vgaHW.h" 17#include "xf86Modes.h" 18 19/* Driver data structures */ 20#include "radeon.h" 21#include "radeon_reg.h" 22#include "radeon_macros.h" 23#include "radeon_probe.h" 24#include "radeon_version.h" 25#include "radeon_tv.h" 26 27/********************************************************************** 28 * 29 * ModeConstants 30 * 31 * Storage of constants related to a single video mode 32 * 33 **********************************************************************/ 34 35typedef struct 36{ 37 uint16_t horResolution; 38 uint16_t verResolution; 39 TVStd standard; 40 uint16_t horTotal; 41 uint16_t verTotal; 42 uint16_t horStart; 43 uint16_t horSyncStart; 44 uint16_t verSyncStart; 45 unsigned defRestart; 46 uint16_t crtcPLL_N; 47 uint8_t crtcPLL_M; 48 uint8_t crtcPLL_postDiv; 49 unsigned pixToTV; 50} TVModeConstants; 51 52static const uint16_t hor_timing_NTSC[] = 53{ 54 0x0007, 55 0x003f, 56 0x0263, 57 0x0a24, 58 0x2a6b, 59 0x0a36, 60 0x126d, /* H_TABLE_POS1 */ 61 0x1bfe, 62 0x1a8f, /* H_TABLE_POS2 */ 63 0x1ec7, 64 0x3863, 65 0x1bfe, 66 0x1bfe, 67 0x1a2a, 68 0x1e95, 69 0x0e31, 70 0x201b, 71 0 72}; 73 74static const uint16_t vert_timing_NTSC[] = 75{ 76 0x2001, 77 0x200d, 78 0x1006, 79 0x0c06, 80 0x1006, 81 0x1818, 82 0x21e3, 83 0x1006, 84 0x0c06, 85 0x1006, 86 0x1817, 87 0x21d4, 88 0x0002, 89 0 90}; 91 92static const uint16_t hor_timing_PAL[] = 93{ 94 0x0007, 95 0x0058, 96 0x027c, 97 0x0a31, 98 0x2a77, 99 0x0a95, 100 0x124f, /* H_TABLE_POS1 */ 101 0x1bfe, 102 0x1b22, /* H_TABLE_POS2 */ 103 0x1ef9, 104 0x387c, 105 0x1bfe, 106 0x1bfe, 107 0x1b31, 108 0x1eb5, 109 0x0e43, 110 0x201b, 111 0 112}; 113 114static const uint16_t vert_timing_PAL[] = 115{ 116 0x2001, 117 0x200c, 118 0x1005, 119 0x0c05, 120 0x1005, 121 0x1401, 122 0x1821, 123 0x2240, 124 0x1005, 125 0x0c05, 126 0x1005, 127 0x1401, 128 0x1822, 129 0x2230, 130 0x0002, 131 0 132}; 133 134/********************************************************************** 135 * 136 * availableModes 137 * 138 * Table of all allowed modes for tv output 139 * 140 **********************************************************************/ 141static const TVModeConstants availableTVModes[] = 142{ 143 { 144 800, /* horResolution */ 145 600, /* verResolution */ 146 TV_STD_NTSC, /* standard */ 147 990, /* horTotal */ 148 740, /* verTotal */ 149 813, /* horStart */ 150 824, /* horSyncStart */ 151 632, /* verSyncStart */ 152 625592, /* defRestart */ 153 592, /* crtcPLL_N */ 154 91, /* crtcPLL_M */ 155 4, /* crtcPLL_postDiv */ 156 1022, /* pixToTV */ 157 }, 158 { 159 800, /* horResolution */ 160 600, /* verResolution */ 161 TV_STD_PAL, /* standard */ 162 1144, /* horTotal */ 163 706, /* verTotal */ 164 812, /* horStart */ 165 824, /* horSyncStart */ 166 669, /* verSyncStart */ 167 696700, /* defRestart */ 168 1382, /* crtcPLL_N */ 169 231, /* crtcPLL_M */ 170 4, /* crtcPLL_postDiv */ 171 759, /* pixToTV */ 172 } 173}; 174 175#define N_AVAILABLE_MODES (sizeof(availableModes) / sizeof(availableModes[ 0 ])) 176 177static long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; 178static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; 179static long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; 180static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; 181 182 183static void 184RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests, 185 unsigned nWaitLoops, unsigned cntThreshold) 186{ 187 RADEONInfoPtr info = RADEONPTR(pScrn); 188 unsigned char *RADEONMMIO = info->MMIO; 189 uint32_t savePLLTest; 190 unsigned i; 191 unsigned j; 192 193 OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); 194 195 savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL); 196 197 OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B); 198 199 /* XXX: these should probably be OUTPLL to avoid various PLL errata */ 200 201 OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); 202 203 for (i = 0; i < nTests; i++) { 204 OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); 205 206 for (j = 0; j < nWaitLoops; j++) 207 if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold) 208 break; 209 } 210 211 OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest); 212 213 OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); 214} 215 216/* Write to TV FIFO RAM */ 217static void 218RADEONWriteTVFIFO(ScrnInfoPtr pScrn, uint16_t addr, 219 uint32_t value) 220{ 221 RADEONInfoPtr info = RADEONPTR(pScrn); 222 unsigned char *RADEONMMIO = info->MMIO; 223 uint32_t tmp; 224 int i = 0; 225 226 OUTREG(RADEON_TV_HOST_WRITE_DATA, value); 227 228 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); 229 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); 230 231 do { 232 tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); 233 if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) 234 break; 235 i++; 236 } 237 while (i < 10000); 238 /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/ 239 240 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); 241} 242 243/* Read from TV FIFO RAM */ 244static uint32_t 245RADEONReadTVFIFO(ScrnInfoPtr pScrn, uint16_t addr) 246{ 247 RADEONInfoPtr info = RADEONPTR(pScrn); 248 unsigned char *RADEONMMIO = info->MMIO; 249 uint32_t tmp; 250 int i = 0; 251 252 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); 253 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); 254 255 do { 256 tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); 257 if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) 258 break; 259 i++; 260 } 261 while (i < 10000); 262 /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/ 263 264 OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); 265 266 return INREG(RADEON_TV_HOST_READ_DATA); 267} 268 269/* Get FIFO addresses of horizontal & vertical code timing tables from 270 * settings of uv_adr register. 271 */ 272static uint16_t 273RADEONGetHTimingTablesAddr(uint32_t tv_uv_adr) 274{ 275 uint16_t hTable; 276 277 switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { 278 case 0: 279 hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; 280 break; 281 case 1: 282 hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; 283 break; 284 case 2: 285 hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; 286 break; 287 default: 288 /* Of course, this should never happen */ 289 hTable = 0; 290 break; 291 } 292 return hTable; 293} 294 295static uint16_t 296RADEONGetVTimingTablesAddr(uint32_t tv_uv_adr) 297{ 298 uint16_t vTable; 299 300 switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { 301 case 0: 302 vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; 303 break; 304 case 1: 305 vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; 306 break; 307 case 2: 308 vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; 309 break; 310 default: 311 /* Of course, this should never happen */ 312 vTable = 0; 313 break; 314 } 315 return vTable; 316} 317 318/* Restore horizontal/vertical timing code tables */ 319static void 320RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore) 321{ 322 RADEONInfoPtr info = RADEONPTR(pScrn); 323 unsigned char *RADEONMMIO = info->MMIO; 324 uint16_t hTable; 325 uint16_t vTable; 326 uint32_t tmp; 327 unsigned i; 328 329 OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr); 330 hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr); 331 vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr); 332 333 for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) { 334 tmp = ((uint32_t)restore->h_code_timing[ i ] << 14) | ((uint32_t)restore->h_code_timing[ i + 1 ]); 335 RADEONWriteTVFIFO(pScrn, hTable, tmp); 336 if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0) 337 break; 338 } 339 340 for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) { 341 tmp = ((uint32_t)restore->v_code_timing[ i + 1 ] << 14) | ((uint32_t)restore->v_code_timing[ i ]); 342 RADEONWriteTVFIFO(pScrn, vTable, tmp); 343 if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0) 344 break; 345 } 346} 347 348/* restore TV PLLs */ 349static void 350RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 351{ 352 353 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); 354 OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl); 355 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); 356 357 RADEONWaitPLLLock(pScrn, 200, 800, 135); 358 359 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); 360 361 RADEONWaitPLLLock(pScrn, 300, 160, 27); 362 RADEONWaitPLLLock(pScrn, 200, 800, 135); 363 364 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf); 365 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); 366 367 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); 368 OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); 369} 370 371/* Restore TV horizontal/vertical settings */ 372static void 373RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 374{ 375 RADEONInfoPtr info = RADEONPTR(pScrn); 376 unsigned char *RADEONMMIO = info->MMIO; 377 378 OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl); 379 380 OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal); 381 OUTREG(RADEON_TV_HDISP, restore->tv_hdisp); 382 OUTREG(RADEON_TV_HSTART, restore->tv_hstart); 383 384 OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal); 385 OUTREG(RADEON_TV_VDISP, restore->tv_vdisp); 386 387 OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal); 388 389 OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1); 390 OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2); 391 392 OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl); 393 OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl); 394 OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl); 395} 396 397/* restore TV RESTART registers */ 398static void 399RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore) 400{ 401 RADEONInfoPtr info = RADEONPTR(pScrn); 402 unsigned char *RADEONMMIO = info->MMIO; 403 404 OUTREG(RADEON_TV_FRESTART, restore->tv_frestart); 405 OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart); 406 OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart); 407} 408 409/* restore tv standard & output muxes */ 410static void 411RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore) 412{ 413 RADEONInfoPtr info = RADEONPTR(pScrn); 414 unsigned char *RADEONMMIO = info->MMIO; 415 416 OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl); 417 418 OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); 419 420 OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1); 421 OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2); 422 423 OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl); 424 425 OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl); 426} 427 428/* Restore TV out regs */ 429void 430RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) 431{ 432 RADEONInfoPtr info = RADEONPTR(pScrn); 433 unsigned char *RADEONMMIO = info->MMIO; 434 435 ErrorF("Entering Restore TV\n"); 436 437 OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl 438 | RADEON_TV_ASYNC_RST 439 | RADEON_CRT_ASYNC_RST 440 | RADEON_TV_FIFO_ASYNC_RST)); 441 442 /* Temporarily turn the TV DAC off */ 443 OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK) 444 | RADEON_TV_DAC_BGSLEEP 445 | RADEON_TV_DAC_RDACPD 446 | RADEON_TV_DAC_GDACPD 447 | RADEON_TV_DAC_BDACPD)); 448 449 ErrorF("Restore TV PLL\n"); 450 RADEONRestoreTVPLLRegisters(pScrn, restore); 451 452 ErrorF("Restore TVHV\n"); 453 RADEONRestoreTVHVRegisters(pScrn, restore); 454 455 OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl 456 | RADEON_TV_ASYNC_RST 457 | RADEON_CRT_ASYNC_RST)); 458 459 ErrorF("Restore TV Restarts\n"); 460 RADEONRestoreTVRestarts(pScrn, restore); 461 462 ErrorF("Restore Timing Tables\n"); 463 RADEONRestoreTVTimingTables(pScrn, restore); 464 465 466 OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl 467 | RADEON_TV_ASYNC_RST)); 468 469 ErrorF("Restore TV standard\n"); 470 RADEONRestoreTVOutputStd(pScrn, restore); 471 472 OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); 473 474 OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings); 475 OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings); 476 477 OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); 478 479 ErrorF("Leaving Restore TV\n"); 480} 481 482/* Save horizontal/vertical timing code tables */ 483static void 484RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save) 485{ 486 RADEONInfoPtr info = RADEONPTR(pScrn); 487 unsigned char *RADEONMMIO = info->MMIO; 488 uint16_t hTable; 489 uint16_t vTable; 490 uint32_t tmp; 491 unsigned i; 492 493 save->tv_uv_adr = INREG(RADEON_TV_UV_ADR); 494 hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr); 495 vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr); 496 497 /* 498 * Reset FIFO arbiter in order to be able to access FIFO RAM 499 */ 500 501 OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST 502 | RADEON_CRT_ASYNC_RST 503 | RADEON_RESTART_PHASE_FIX 504 | RADEON_CRT_FIFO_CE_EN 505 | RADEON_TV_FIFO_CE_EN 506 | RADEON_TV_ON)); 507 508 /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/ 509 510 ErrorF("saveTimingTables: reading timing tables\n"); 511 512 for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) { 513 tmp = RADEONReadTVFIFO(pScrn, hTable--); 514 save->h_code_timing[ i ] = (uint16_t)((tmp >> 14) & 0x3fff); 515 save->h_code_timing[ i + 1 ] = (uint16_t)(tmp & 0x3fff); 516 517 if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0) 518 break; 519 } 520 521 for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) { 522 tmp = RADEONReadTVFIFO(pScrn, vTable++); 523 save->v_code_timing[ i ] = (uint16_t)(tmp & 0x3fff); 524 save->v_code_timing[ i + 1 ] = (uint16_t)((tmp >> 14) & 0x3fff); 525 526 if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0) 527 break; 528 } 529} 530 531/* read TV regs */ 532void 533RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) 534{ 535 RADEONInfoPtr info = RADEONPTR(pScrn); 536 unsigned char *RADEONMMIO = info->MMIO; 537 538 ErrorF("Entering TV Save\n"); 539 540 save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL); 541 save->tv_frestart = INREG(RADEON_TV_FRESTART); 542 save->tv_hrestart = INREG(RADEON_TV_HRESTART); 543 save->tv_vrestart = INREG(RADEON_TV_VRESTART); 544 save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS); 545 save->tv_hdisp = INREG(RADEON_TV_HDISP); 546 save->tv_hstart = INREG(RADEON_TV_HSTART); 547 save->tv_htotal = INREG(RADEON_TV_HTOTAL); 548 save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS); 549 save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); 550 save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL); 551 save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1); 552 save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2); 553 save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); 554 save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL); 555 save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL); 556 save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); 557 save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL); 558 save->tv_vdisp = INREG(RADEON_TV_VDISP); 559 save->tv_ftotal = INREG(RADEON_TV_FTOTAL); 560 save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1); 561 save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2); 562 save->tv_vtotal = INREG(RADEON_TV_VTOTAL); 563 save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL); 564 save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL); 565 save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL); 566 567 save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL); 568 save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1); 569 570 ErrorF("Save TV timing tables\n"); 571 572 RADEONSaveTVTimingTables(pScrn, save); 573 574 ErrorF("TV Save done\n"); 575} 576 577 578/* Compute F,V,H restarts from default restart position and hPos & vPos 579 * Return TRUE when code timing table was changed 580 */ 581static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save, 582 DisplayModePtr mode) 583{ 584 RADEONOutputPrivatePtr radeon_output = output->driver_private; 585 int restart; 586 unsigned hTotal; 587 unsigned vTotal; 588 unsigned fTotal; 589 int vOffset; 590 int hOffset; 591 uint16_t p1; 592 uint16_t p2; 593 Bool hChanged; 594 uint16_t hInc; 595 const TVModeConstants *constPtr; 596 597 /* FIXME: need to revisit this when we add more modes */ 598 if (radeon_output->tvStd == TV_STD_NTSC || 599 radeon_output->tvStd == TV_STD_NTSC_J || 600 radeon_output->tvStd == TV_STD_PAL_M) 601 constPtr = &availableTVModes[0]; 602 else 603 constPtr = &availableTVModes[1]; 604 605 hTotal = constPtr->horTotal; 606 vTotal = constPtr->verTotal; 607 608 if (radeon_output->tvStd == TV_STD_NTSC || 609 radeon_output->tvStd == TV_STD_NTSC_J || 610 radeon_output->tvStd == TV_STD_PAL_M || 611 radeon_output->tvStd == TV_STD_PAL_60) 612 fTotal = NTSC_TV_VFTOTAL + 1; 613 else 614 fTotal = PAL_TV_VFTOTAL + 1; 615 616 /* Adjust positions 1&2 in hor. code timing table */ 617 hOffset = radeon_output->hPos * H_POS_UNIT; 618 619 if (radeon_output->tvStd == TV_STD_NTSC || 620 radeon_output->tvStd == TV_STD_NTSC_J || 621 radeon_output->tvStd == TV_STD_PAL_M) { 622 /* improve image centering */ 623 hOffset -= 50; 624 p1 = hor_timing_NTSC[ H_TABLE_POS1 ]; 625 p2 = hor_timing_NTSC[ H_TABLE_POS2 ]; 626 } else { 627 p1 = hor_timing_PAL[ H_TABLE_POS1 ]; 628 p2 = hor_timing_PAL[ H_TABLE_POS2 ]; 629 } 630 631 632 p1 = (uint16_t)((int)p1 + hOffset); 633 p2 = (uint16_t)((int)p2 - hOffset); 634 635 hChanged = (p1 != save->h_code_timing[ H_TABLE_POS1 ] || 636 p2 != save->h_code_timing[ H_TABLE_POS2 ]); 637 638 save->h_code_timing[ H_TABLE_POS1 ] = p1; 639 save->h_code_timing[ H_TABLE_POS2 ] = p2; 640 641 /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ 642 hOffset = (hOffset * (int)(constPtr->pixToTV)) / 1000; 643 644 /* Adjust restart */ 645 restart = constPtr->defRestart; 646 647 /* 648 * Convert vPos TV lines to n. of CRTC pixels 649 * Be verrrrry careful when mixing signed & unsigned values in C.. 650 */ 651 if (radeon_output->tvStd == TV_STD_NTSC || 652 radeon_output->tvStd == TV_STD_NTSC_J || 653 radeon_output->tvStd == TV_STD_PAL_M || 654 radeon_output->tvStd == TV_STD_PAL_60) 655 vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(NTSC_TV_LINES_PER_FRAME); 656 else 657 vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(PAL_TV_LINES_PER_FRAME); 658 659 restart -= vOffset + hOffset; 660 661 ErrorF("computeRestarts: def = %u, h = %d, v = %d, p1=%04x, p2=%04x, restart = %d\n", 662 constPtr->defRestart , radeon_output->hPos , radeon_output->vPos , p1 , p2 , restart); 663 664 save->tv_hrestart = restart % hTotal; 665 restart /= hTotal; 666 save->tv_vrestart = restart % vTotal; 667 restart /= vTotal; 668 save->tv_frestart = restart % fTotal; 669 670 ErrorF("computeRestarts: F/H/V=%u,%u,%u\n", 671 (unsigned)save->tv_frestart, (unsigned)save->tv_vrestart, 672 (unsigned)save->tv_hrestart); 673 674 /* Compute H_INC from hSize */ 675 if (radeon_output->tvStd == TV_STD_NTSC || 676 radeon_output->tvStd == TV_STD_NTSC_J || 677 radeon_output->tvStd == TV_STD_PAL_M) 678 hInc = (uint16_t)((int)(constPtr->horResolution * 4096 * NTSC_TV_CLOCK_T) / 679 (radeon_output->hSize * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); 680 else 681 hInc = (uint16_t)((int)(constPtr->horResolution * 4096 * PAL_TV_CLOCK_T) / 682 (radeon_output->hSize * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); 683 684 save->tv_timing_cntl = (save->tv_timing_cntl & ~RADEON_H_INC_MASK) | 685 ((uint32_t)hInc << RADEON_H_INC_SHIFT); 686 687 ErrorF("computeRestarts: hSize=%d,hInc=%u\n" , radeon_output->hSize , hInc); 688 689 return hChanged; 690} 691 692/* intit TV-out regs */ 693void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save, 694 DisplayModePtr mode, BOOL IsPrimary) 695{ 696 ScrnInfoPtr pScrn = output->scrn; 697 RADEONOutputPrivatePtr radeon_output = output->driver_private; 698 RADEONInfoPtr info = RADEONPTR(pScrn); 699 unsigned i; 700 unsigned long vert_space, flicker_removal; 701 uint32_t tmp; 702 const TVModeConstants *constPtr; 703 const uint16_t *hor_timing; 704 const uint16_t *vert_timing; 705 706 707 /* FIXME: need to revisit this when we add more modes */ 708 if (radeon_output->tvStd == TV_STD_NTSC || 709 radeon_output->tvStd == TV_STD_NTSC_J || 710 radeon_output->tvStd == TV_STD_PAL_M) 711 constPtr = &availableTVModes[0]; 712 else 713 constPtr = &availableTVModes[1]; 714 715 save->tv_crc_cntl = 0; 716 717 save->tv_gain_limit_settings = (0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | 718 (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT); 719 720 save->tv_hdisp = constPtr->horResolution - 1; 721 save->tv_hstart = constPtr->horStart; 722 save->tv_htotal = constPtr->horTotal - 1; 723 724 save->tv_linear_gain_settings = (0x100 << RADEON_UV_GAIN_SHIFT) | 725 (0x100 << RADEON_Y_GAIN_SHIFT); 726 727 save->tv_master_cntl = (RADEON_VIN_ASYNC_RST 728 | RADEON_CRT_FIFO_CE_EN 729 | RADEON_TV_FIFO_CE_EN 730 | RADEON_TV_ON); 731 732 if (!IS_R300_VARIANT) 733 save->tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; 734 735 if (radeon_output->tvStd == TV_STD_NTSC || 736 radeon_output->tvStd == TV_STD_NTSC_J) 737 save->tv_master_cntl |= RADEON_RESTART_PHASE_FIX; 738 739 save->tv_modulator_cntl1 = RADEON_SLEW_RATE_LIMIT 740 | RADEON_SYNC_TIP_LEVEL 741 | RADEON_YFLT_EN 742 | RADEON_UVFLT_EN 743 | (6 << RADEON_CY_FILT_BLEND_SHIFT); 744 745 if (radeon_output->tvStd == TV_STD_NTSC || 746 radeon_output->tvStd == TV_STD_NTSC_J) { 747 save->tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) 748 | (0x3b << RADEON_BLANK_LEVEL_SHIFT); 749 save->tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | 750 ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 751 } else if (radeon_output->tvStd == TV_STD_SCART_PAL) { 752 save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; 753 save->tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | 754 ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 755 } else { 756 save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN 757 | (0x3b << RADEON_SET_UP_LEVEL_SHIFT) 758 | (0x3b << RADEON_BLANK_LEVEL_SHIFT); 759 save->tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | 760 ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); 761 } 762 763 save->pll_test_cntl = 0; 764 765 save->tv_pre_dac_mux_cntl = (RADEON_Y_RED_EN 766 | RADEON_C_GRN_EN 767 | RADEON_CMP_BLU_EN 768 | RADEON_DAC_DITHER_EN); 769 770 save->tv_rgb_cntl = (RADEON_RGB_DITHER_EN 771 | RADEON_TVOUT_SCALE_EN 772 | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) 773 | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)); 774 775 if (IsPrimary) { 776 if (radeon_output->Flags & RADEON_USE_RMX) 777 save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; 778 else 779 save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; 780 } else { 781 save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; 782 } 783 784 save->tv_sync_cntl = RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE; 785 786 save->tv_sync_size = constPtr->horResolution + 8; 787 788 if (radeon_output->tvStd == TV_STD_NTSC || 789 radeon_output->tvStd == TV_STD_NTSC_J || 790 radeon_output->tvStd == TV_STD_PAL_M || 791 radeon_output->tvStd == TV_STD_PAL_60) 792 vert_space = constPtr->verTotal * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; 793 else 794 vert_space = constPtr->verTotal * 2 * 10000 / PAL_TV_LINES_PER_FRAME; 795 796 save->tv_vscaler_cntl1 = RADEON_Y_W_EN; 797 save->tv_vscaler_cntl1 = 798 (save->tv_vscaler_cntl1 & 0xe3ff0000) | (vert_space * (1 << FRAC_BITS) / 10000); 799 save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; 800 if (constPtr->horResolution == 1024) 801 save->tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); 802 else 803 save->tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); 804 805 if (radeon_output->tvStd == TV_STD_NTSC || 806 radeon_output->tvStd == TV_STD_NTSC_J || 807 radeon_output->tvStd == TV_STD_PAL_M || 808 radeon_output->tvStd == TV_STD_PAL_60) 809 flicker_removal = 810 (float) constPtr->verTotal * 2.0 / NTSC_TV_LINES_PER_FRAME + 0.5; 811 else 812 flicker_removal = 813 (float) constPtr->verTotal * 2.0 / PAL_TV_LINES_PER_FRAME + 0.5; 814 815 if (flicker_removal < 3) 816 flicker_removal = 3; 817 for (i = 0; i < 6; ++i) { 818 if (flicker_removal == SLOPE_limit[i]) 819 break; 820 } 821 save->tv_y_saw_tooth_cntl = 822 (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + 5001) / 10000 / 8 823 | ((SLOPE_value[i] * (1 << (FRAC_BITS - 1)) / 8) << 16); 824 save->tv_y_fall_cntl = 825 (YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | 826 RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / 827 1024; 828 save->tv_y_rise_cntl = 829 RADEON_Y_RISE_PING_PONG 830 | (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; 831 832 save->tv_vscaler_cntl2 = ((save->tv_vscaler_cntl2 & 0x00fffff0) 833 | (0x10 << 24) 834 | RADEON_DITHER_MODE 835 | RADEON_Y_OUTPUT_DITHER_EN 836 | RADEON_UV_OUTPUT_DITHER_EN 837 | RADEON_UV_TO_BUF_DITHER_EN); 838 839 tmp = (save->tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; 840 tmp = ((16384 * 256 * 10) / tmp + 5) / 10; 841 tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; 842 save->tv_timing_cntl = tmp; 843 844 if (radeon_output->tvStd == TV_STD_NTSC || 845 radeon_output->tvStd == TV_STD_NTSC_J || 846 radeon_output->tvStd == TV_STD_PAL_M || 847 radeon_output->tvStd == TV_STD_PAL_60) 848 save->tv_dac_cntl = radeon_output->ntsc_tvdac_adj; 849 else 850 save->tv_dac_cntl = radeon_output->pal_tvdac_adj; 851 852 save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD); 853 854 if (radeon_output->tvStd == TV_STD_NTSC || 855 radeon_output->tvStd == TV_STD_NTSC_J) 856 save->tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; 857 else 858 save->tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; 859 860#if 0 861 /* needs fixes for r4xx */ 862 save->tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | RADEON_TV_DAC_GDACPD 863 | RADEON_TV_DAC_BDACPD); 864 865 if (radeon_output->MonType == MT_CTV) { 866 save->tv_dac_cntl &= ~RADEON_TV_DAC_BDACPD; 867 } 868 869 if (radeon_output->MonType == MT_STV) { 870 save->tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | 871 RADEON_TV_DAC_GDACPD); 872 } 873#endif 874 875 if (radeon_output->tvStd == TV_STD_NTSC || 876 radeon_output->tvStd == TV_STD_NTSC_J) 877 save->tv_pll_cntl = (NTSC_TV_PLL_M & RADEON_TV_M0LO_MASK) | 878 (((NTSC_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | 879 ((NTSC_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | 880 (((NTSC_TV_PLL_N >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | 881 ((NTSC_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); 882 else 883 save->tv_pll_cntl = (PAL_TV_PLL_M & RADEON_TV_M0LO_MASK) | 884 (((PAL_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | 885 ((PAL_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | 886 (((PAL_TV_PLL_N >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | 887 ((PAL_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); 888 889 save->tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK)<< RADEON_TVPCP_SHIFT) | 890 ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | 891 ((1 & RADEON_TVPDC_MASK)<< RADEON_TVPDC_SHIFT) | 892 RADEON_TVCLK_SRC_SEL_TVPLL | 893 RADEON_TVPLL_TEST_DIS); 894 895 save->tv_upsamp_and_gain_cntl = RADEON_YUPSAMP_EN | RADEON_UVUPSAMP_EN; 896 897 save->tv_uv_adr = 0xc8; 898 899 save->tv_vdisp = constPtr->verResolution - 1; 900 901 if (radeon_output->tvStd == TV_STD_NTSC || 902 radeon_output->tvStd == TV_STD_NTSC_J || 903 radeon_output->tvStd == TV_STD_PAL_M || 904 radeon_output->tvStd == TV_STD_PAL_60) 905 save->tv_ftotal = NTSC_TV_VFTOTAL; 906 else 907 save->tv_ftotal = PAL_TV_VFTOTAL; 908 909 save->tv_vtotal = constPtr->verTotal - 1; 910 911 if (radeon_output->tvStd == TV_STD_NTSC || 912 radeon_output->tvStd == TV_STD_NTSC_J || 913 radeon_output->tvStd == TV_STD_PAL_M) { 914 hor_timing = hor_timing_NTSC; 915 } else { 916 hor_timing = hor_timing_PAL; 917 } 918 919 if (radeon_output->tvStd == TV_STD_NTSC || 920 radeon_output->tvStd == TV_STD_NTSC_J || 921 radeon_output->tvStd == TV_STD_PAL_M || 922 radeon_output->tvStd == TV_STD_PAL_60) { 923 vert_timing = vert_timing_NTSC; 924 } else { 925 vert_timing = vert_timing_PAL; 926 } 927 928 for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { 929 if ((save->h_code_timing[ i ] = hor_timing[ i ]) == 0) 930 break; 931 } 932 933 for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { 934 if ((save->v_code_timing[ i ] = vert_timing[ i ]) == 0) 935 break; 936 } 937 938 /* 939 * This must be called AFTER loading timing tables as they are modified by this function 940 */ 941 RADEONInitTVRestarts(output, save, mode); 942 943 save->dac_cntl &= ~RADEON_DAC_TVO_EN; 944 945 if (IS_R300_VARIANT) 946 save->gpiopad_a = info->SavedReg->gpiopad_a & ~1; 947 948 if (IsPrimary) { 949 save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 950 save->disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC 951 | RADEON_DISP_TV_SOURCE_CRTC); 952 if (info->ChipFamily >= CHIP_FAMILY_R200) { 953 save->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; 954 } else { 955 save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; 956 } 957 } else { 958 save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; 959 save->disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; 960 961 if (info->ChipFamily >= CHIP_FAMILY_R200) { 962 save->disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; 963 } else { 964 save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; 965 } 966 } 967} 968 969 970/* Set hw registers for a new h/v position & h size */ 971void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode) 972{ 973 ScrnInfoPtr pScrn = output->scrn; 974 RADEONInfoPtr info = RADEONPTR(pScrn); 975 unsigned char *RADEONMMIO = info->MMIO; 976 Bool reloadTable; 977 RADEONSavePtr restore = info->ModeReg; 978 979 reloadTable = RADEONInitTVRestarts(output, restore, mode); 980 981 RADEONRestoreTVRestarts(pScrn, restore); 982 983 OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); 984 985 if (reloadTable) { 986 OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl 987 | RADEON_TV_ASYNC_RST 988 | RADEON_CRT_ASYNC_RST 989 | RADEON_RESTART_PHASE_FIX); 990 991 RADEONRestoreTVTimingTables(pScrn, restore); 992 993 OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); 994 } 995} 996 997void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, 998 DisplayModePtr mode, xf86OutputPtr output) 999{ 1000 const TVModeConstants *constPtr; 1001 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1002 1003 /* FIXME: need to revisit this when we add more modes */ 1004 if (radeon_output->tvStd == TV_STD_NTSC || 1005 radeon_output->tvStd == TV_STD_NTSC_J || 1006 radeon_output->tvStd == TV_STD_PAL_M) 1007 constPtr = &availableTVModes[0]; 1008 else 1009 constPtr = &availableTVModes[1]; 1010 1011 save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | 1012 (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); 1013 1014 save->crtc_h_sync_strt_wid = (save->crtc_h_sync_strt_wid 1015 & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | 1016 (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | 1017 (constPtr->horSyncStart & 7); 1018 1019 save->crtc_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | 1020 ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); 1021 1022 save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | 1023 ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); 1024 1025} 1026 1027void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, 1028 DisplayModePtr mode, xf86OutputPtr output) 1029{ 1030 unsigned postDiv; 1031 const TVModeConstants *constPtr; 1032 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1033 1034 /* FIXME: need to revisit this when we add more modes */ 1035 if (radeon_output->tvStd == TV_STD_NTSC || 1036 radeon_output->tvStd == TV_STD_NTSC_J || 1037 radeon_output->tvStd == TV_STD_PAL_M) 1038 constPtr = &availableTVModes[0]; 1039 else 1040 constPtr = &availableTVModes[1]; 1041 1042 save->htotal_cntl = (constPtr->horTotal & 0x7 /*0xf*/) | RADEON_HTOT_CNTL_VGA_EN; 1043 1044 save->ppll_ref_div = constPtr->crtcPLL_M; 1045 1046 switch (constPtr->crtcPLL_postDiv) { 1047 case 1: 1048 postDiv = 0; 1049 break; 1050 case 2: 1051 postDiv = 1; 1052 break; 1053 case 3: 1054 postDiv = 4; 1055 break; 1056 case 4: 1057 postDiv = 2; 1058 break; 1059 case 6: 1060 postDiv = 6; 1061 break; 1062 case 8: 1063 postDiv = 3; 1064 break; 1065 case 12: 1066 postDiv = 7; 1067 break; 1068 case 16: 1069 default: 1070 postDiv = 5; 1071 break; 1072 } 1073 1074 save->ppll_div_3 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); 1075 1076 save->pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); 1077 save->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; 1078 1079} 1080 1081void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, 1082 DisplayModePtr mode, xf86OutputPtr output) 1083{ 1084 const TVModeConstants *constPtr; 1085 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1086 1087 /* FIXME: need to revisit this when we add more modes */ 1088 if (radeon_output->tvStd == TV_STD_NTSC || 1089 radeon_output->tvStd == TV_STD_NTSC_J || 1090 radeon_output->tvStd == TV_STD_PAL_M) 1091 constPtr = &availableTVModes[0]; 1092 else 1093 constPtr = &availableTVModes[1]; 1094 1095 save->crtc2_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | 1096 (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); 1097 1098 save->crtc2_h_sync_strt_wid = (save->crtc2_h_sync_strt_wid 1099 & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | 1100 (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | 1101 (constPtr->horSyncStart & 7); 1102 1103 save->crtc2_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | 1104 ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); 1105 1106 save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | 1107 ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); 1108 1109} 1110 1111void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, 1112 DisplayModePtr mode, xf86OutputPtr output) 1113{ 1114 unsigned postDiv; 1115 const TVModeConstants *constPtr; 1116 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1117 1118 /* FIXME: need to revisit this when we add more modes */ 1119 if (radeon_output->tvStd == TV_STD_NTSC || 1120 radeon_output->tvStd == TV_STD_NTSC_J || 1121 radeon_output->tvStd == TV_STD_PAL_M) 1122 constPtr = &availableTVModes[0]; 1123 else 1124 constPtr = &availableTVModes[1]; 1125 1126 save->htotal_cntl2 = (constPtr->horTotal & 0x7); /* 0xf */ 1127 1128 save->p2pll_ref_div = constPtr->crtcPLL_M; 1129 1130 switch (constPtr->crtcPLL_postDiv) { 1131 case 1: 1132 postDiv = 0; 1133 break; 1134 case 2: 1135 postDiv = 1; 1136 break; 1137 case 3: 1138 postDiv = 4; 1139 break; 1140 case 4: 1141 postDiv = 2; 1142 break; 1143 case 6: 1144 postDiv = 6; 1145 break; 1146 case 8: 1147 postDiv = 3; 1148 break; 1149 case 12: 1150 postDiv = 7; 1151 break; 1152 case 16: 1153 default: 1154 postDiv = 5; 1155 break; 1156 } 1157 1158 save->p2pll_div_0 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); 1159 1160 save->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; 1161 save->pixclks_cntl |= (RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 1162 | RADEON_PIXCLK_TV_SRC_SEL); 1163 1164} 1165