1 /* 2 Copyright (c) 2002-04, Thomas Kurschel 3 4 5 Part of Radeon accelerant 6 7 CRTC <-> display routing 8 9 This stuff is highly ASIC dependant and is probably the most ASIC-specific 10 code of the entire project. 11 */ 12 13 #include "radeon_accelerant.h" 14 #include "mmio.h" 15 #include "dac_regs.h" 16 #include "fp_regs.h" 17 #include "crtc_regs.h" 18 #include "tv_out_regs.h" 19 #include "pll_regs.h" 20 #include "gpiopad_regs.h" 21 #include "pll_access.h" 22 #include "set_mode.h" 23 24 25 // read regs needed for display device routing 26 void Radeon_ReadMonitorRoutingRegs( 27 accelerator_info *ai, routing_regs *values ) 28 { 29 vuint8 *regs = ai->regs; 30 31 values->dac_cntl = INREG( regs, RADEON_DAC_CNTL ); 32 values->dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 ); 33 values->crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL ); 34 values->crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL ); 35 values->disp_output_cntl = INREG( regs, RADEON_DISP_OUTPUT_CNTL ); 36 values->pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL ); 37 values->vclk_ecp_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL ); 38 39 switch( ai->si->asic ) { 40 case rt_ve: 41 case rt_m6: 42 case rt_rv200: 43 case rt_m7: 44 case rt_rv250: 45 case rt_m9: 46 case rt_rv280: 47 case rt_m9plus: 48 case rt_rs100: 49 case rt_rs200: 50 values->disp_hw_debug = INREG( regs, RADEON_DISP_HW_DEBUG ); 51 break; 52 53 case rt_r200: 54 values->disp_tv_out_cntl = INREG( regs, RADEON_DISP_TV_OUT_CNTL ); 55 break; 56 57 case rt_r300: 58 case rt_r300_4p: 59 case rt_rv350: 60 case rt_m10: 61 case rt_rv360: 62 case rt_r350: 63 case rt_r360: 64 case rt_m11: 65 values->gpiopad_a = INREG( regs, RADEON_GPIOPAD_A ); 66 break; 67 68 case rt_r100: 69 break; 70 } 71 72 if( ai->si->asic > rt_r100 ) { 73 // register introduced after R100 74 values->tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL ); 75 } 76 77 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) 78 values->tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL ); 79 80 values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL ); 81 values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL ); 82 } 83 84 85 // setup register contents to proper CRTC <-> display device mapping 86 void Radeon_CalcMonitorRouting( 87 accelerator_info *ai, const impactv_params *tv_parameters, routing_regs *values ) 88 { 89 display_device_e display_devices[2], total_devices, controlled_devices; 90 91 if( ai->vc->used_crtc[0] ) 92 display_devices[0] = ai->si->crtc[0].chosen_displays; 93 else 94 display_devices[0] = dd_none; 95 96 if( ai->vc->used_crtc[1] ) 97 display_devices[1] = ai->si->crtc[1].chosen_displays; 98 else 99 display_devices[1] = dd_none; 100 101 total_devices = display_devices[0] | display_devices[1]; 102 controlled_devices = ai->vc->controlled_displays; 103 104 // enable 8 bit DAC 105 // (could be moved to boot initialization) 106 values->dac_cntl |= 107 RADEON_DAC_MASK_ALL | RADEON_DAC_VGA_ADR_EN | RADEON_DAC_8BIT_EN; 108 109 // enable frame buffer access and extended CRTC counter 110 // (again: something for boot init.) 111 values->crtc_ext_cntl = 112 RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN; 113 114 // set VGA signal style (not sure whether this affects 115 // CRTC1 or CRT-DAC, so we better always set it) 116 values->dac_cntl &= ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING); 117 values->dac_cntl |= RADEON_DAC_RANGE_CNTL_PS2; 118 119 // disable all the magic CRTC shadowing 120 values->fp_gen_cntl &= 121 ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN | 122 RADEON_FP_DFP_SYNC_SEL | 123 RADEON_FP_CRT_SYNC_SEL | 124 RADEON_FP_CRTC_LOCK_8DOT | 125 RADEON_FP_USE_SHADOW_EN | 126 RADEON_FP_CRTC_USE_SHADOW_VEND | 127 RADEON_FP_CRT_SYNC_ALT); 128 values->fp_gen_cntl |= 129 RADEON_FP_CRTC_DONT_SHADOW_VPAR | 130 RADEON_FP_CRTC_DONT_SHADOW_HEND; 131 132 // route VGA-DAC 133 if( (total_devices & dd_crt) != 0 ) { 134 int crtc_idx = (display_devices[1] & dd_crt) != 0; 135 136 // the CRT_ON flag seems to directly affect the CRT-DAC, _not_ the CRTC1 signal 137 values->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; 138 139 switch( ai->si->asic ) { 140 case rt_ve: 141 case rt_m6: 142 case rt_rv200: 143 case rt_m7: 144 case rt_rv250: 145 case rt_m9: 146 case rt_rv280: 147 case rt_m9plus: 148 case rt_rs100: 149 case rt_rs200: 150 values->dac_cntl2 &= ~RADEON_DAC_CLK_SEL_MASK; 151 values->dac_cntl2 |= crtc_idx == 0 ? 0 : RADEON_DAC_CLK_SEL_CRTC2; 152 break; 153 154 case rt_r200: 155 case rt_r300: 156 case rt_r300_4p: 157 case rt_rv350: 158 case rt_m10: 159 case rt_m11: 160 case rt_rv360: 161 case rt_r350: 162 case rt_r360: 163 values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; 164 values->disp_output_cntl |= 165 (crtc_idx == 0 ? 0 : RADEON_DISP_DAC_SOURCE_CRTC2); 166 break; 167 168 case rt_r100: 169 break; 170 } 171 172 } else if( (controlled_devices & dd_crt) != 0 ) { 173 values->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; 174 } 175 176 177 if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) { 178 // power down TV-DAC 179 // (but only if TV-Out _and_ TV-CRT is controlled by us) 180 // this will be undone if needed 181 values->tv_dac_cntl |= 182 RADEON_TV_DAC_CNTL_RDACPD | 183 RADEON_TV_DAC_CNTL_GDACPD | 184 RADEON_TV_DAC_CNTL_BDACPD; 185 } 186 187 188 // set CRT mode of TV-DAC if needed 189 // (doesn't work on r200, but there is no TV-DAC used for CRT anyway) 190 if( (total_devices & dd_tv_crt) != 0 ) { 191 // enable CRT via TV-DAC (ignored if TV-DAC is in TV-Out mode) 192 values->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; 193 194 values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK; 195 values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_CRT; 196 197 // enable TV-DAC and set PS2 signal level 198 values->tv_dac_cntl = 199 RADEON_TV_DAC_CNTL_NBLANK | 200 RADEON_TV_DAC_CNTL_NHOLD | 201 RADEON_TV_DAC_CNTL_STD_PS2 | 202 (8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) | 203 (2 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT); 204 205 // at least r300 needs magic bit set to switch between TV-CRT and TV-Out 206 switch( ai->si->asic ) { 207 case rt_r200: 208 case rt_r300: 209 case rt_r300_4p: 210 case rt_rv350: 211 case rt_m10: 212 case rt_m11: 213 case rt_rv360: 214 case rt_r350: 215 case rt_r360: 216 values->gpiopad_a |= 1; 217 break; 218 default: 219 ; 220 } 221 222 } else if( (controlled_devices & dd_tv_crt) != 0 ) { 223 values->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; 224 } 225 226 values->skip_tv_dac = false; 227 228 229 // disable forwarding data to TV-Out unit 230 // (will be enabled on demand later on) 231 if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) 232 values->dac_cntl &= ~RADEON_DAC_TVO_EN; 233 234 235 // set TV mode of TV-DAC if needed 236 if( (total_devices & (dd_ctv | dd_stv)) != 0 ) { 237 // see above 238 values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK; 239 values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_TV; 240 241 // at least r300 needs magic bit set to switch between TV-CRT and TV-Out 242 switch( ai->si->asic ) { 243 case rt_r200: 244 case rt_r300: 245 case rt_r300_4p: 246 case rt_rv350: 247 case rt_rv360: 248 case rt_m10: 249 case rt_m11: 250 case rt_r350: 251 case rt_r360: 252 values->gpiopad_a &= ~1; 253 break; 254 default: 255 ; 256 } 257 258 // the TV-DAC itself is under control of the TV-Out code 259 values->skip_tv_dac = true; 260 261 if( !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) { 262 // tell DAC to forward data to external chip 263 values->dac_cntl |= RADEON_DAC_TVO_EN; 264 265 // set Output Linear Transform Unit as source 266 // (TODO: is this unit initialized properly?) 267 // disable overlay sync (could be a good idea to enable it) 268 // set 8 BPP mode 269 values->disp_output_cntl &= 270 ~(RADEON_DISP_TV_SOURCE | 271 RADEON_DISP_TV_MODE_MASK | 272 RADEON_DISP_TV_YG_DITH_EN | 273 RADEON_DISP_TV_CBB_CRR_DITH_EN | 274 RADEON_DISP_TV_BIT_WIDTH | 275 RADEON_DISP_TV_SYNC_MODE_MASK | 276 RADEON_DISP_TV_SYNC_COLOR_MASK); 277 278 // enable dithering 279 values->disp_output_cntl |= 280 RADEON_DISP_TV_YG_DITH_EN | 281 RADEON_DISP_TV_CBB_CRR_DITH_EN; 282 283 // set output data format 284 values->disp_output_cntl |= tv_parameters->mode888 ? 285 RADEON_DISP_TV_MODE_888 : RADEON_DISP_TV_MODE_565; 286 287 switch( ai->si->asic ) { 288 case rt_r200: 289 // disable downfiltering and scaling, set RGB mode, 290 // don't transmit overlay indicator; 291 // I don't really know whether this is a good choice 292 values->disp_tv_out_cntl &= 293 (RADEON_DISP_TV_OUT_YG_FILTER_MASK | 294 RADEON_DISP_TV_OUT_YG_SAMPLE | 295 RADEON_DISP_TV_OUT_CrR_FILTER_MASK | 296 RADEON_DISP_TV_OUT_CrR_SAMPLE | 297 RADEON_DISP_TV_OUT_CbB_FILTER_MASK | 298 RADEON_DISP_TV_OUT_CbB_SAMPLE | 299 RADEON_DISP_TV_SUBSAMPLE_CNTL_MASK | 300 RADEON_DISP_TV_H_DOWNSCALE | 301 RADEON_DISP_TV_COLOR_SPACE | 302 RADEON_DISP_TV_DITH_MODE | 303 RADEON_DISP_TV_DATA_ZERO_SEL | 304 RADEON_DISP_TV_CLKO_SEL | 305 RADEON_DISP_TV_CLKO_OUT_EN | 306 RADEON_DISP_TV_DOWNSCALE_CNTL); 307 308 // enable TVOCLKO (is this needed?) 309 values->disp_tv_out_cntl |= RADEON_DISP_TV_CLKO_OUT_EN; 310 break; 311 312 default: 313 ; 314 } 315 } 316 317 } else if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) { 318 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) { 319 // disable clock of TV-out units 320 values->tv_master_cntl = 321 RADEON_TV_MASTER_CNTL_TV_ASYNC_RST | 322 RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST | 323 RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST | 324 RADEON_TV_MASTER_CNTL_TVCLK_ALWAYS_ONb; 325 } 326 } 327 328 // choose CRTC for TV-DAC 329 if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) { 330 int crtc_idx = (display_devices[1] & (dd_tv_crt | dd_ctv | dd_stv)) != 0; 331 332 switch( ai->si->asic ) { 333 case rt_ve: 334 case rt_m6: 335 case rt_rv200: 336 case rt_m7: 337 case rt_rv250: 338 case rt_m9: 339 case rt_rv280: 340 case rt_m9plus: 341 case rt_rs100: 342 case rt_rs200: 343 values->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; 344 // warning: meaning is wrong way around - 0 means crtc2, 1 means crtc1 345 values->disp_hw_debug |= crtc_idx == 0 ? RADEON_CRT2_DISP1_SEL : 0; 346 break; 347 348 case rt_r200: 349 // TV-Out data comes directly from CRTC (i.e. with Linear Transform Unit) 350 values->disp_output_cntl |= RADEON_DISP_TV_SOURCE; 351 // choose CRTC 352 values->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC; 353 values->disp_tv_out_cntl |= crtc_idx == 0 ? 0 : RADEON_DISP_TV_PATH_SRC; 354 break; 355 356 case rt_r300: 357 case rt_r300_4p: 358 case rt_rv350: 359 case rt_m10: 360 case rt_m11: 361 case rt_rv360: 362 case rt_r350: 363 case rt_r360: 364 values->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 365 values->disp_output_cntl |= 366 crtc_idx == 0 ? 0 : RADEON_DISP_TVDAC_SOURCE_CRTC2; 367 break; 368 369 case rt_r100: 370 break; 371 } 372 } 373 374 // choose clock source for (internal) TV-out unit 375 if( (total_devices & (dd_ctv | dd_stv)) != 0 ) { 376 int crtc_idx = (display_devices[1] & (dd_ctv | dd_stv)) != 0; 377 378 values->pixclks_cntl &= ~RADEON_PIXCLK_TV_SRC_SEL_MASK; 379 values->pixclks_cntl |= crtc_idx == 0 ? 380 RADEON_PIXCLK_TV_SRC_SEL_PIXCLK : RADEON_PIXCLK_TV_SRC_SEL_PIX2CLK; 381 } 382 383 // choose CRTC clock source; 384 // normally, CRTC1 uses PLL1 and CRTC2 uses PLL2, but if an external TV-Out 385 // chip is used, the clock is retrieved from this chip to stay in perfect sync 386 if( (display_devices[0] & (dd_ctv | dd_stv)) != 0 387 && !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) 388 { 389 // select BYTCLK input pin as pixel src 390 values->vclk_ecp_cntl &= 391 ~(RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_MASK | RADEON_VCLK_SRC_SEL_MASK); 392 393 values->vclk_ecp_cntl |= RADEON_VCLK_SRC_BYTE_CLK; 394 values->vclk_ecp_cntl |= 0 << RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_SHIFT; 395 396 // disable clock if pixel format in CRTC_GEN_CNTL is zero; 397 // disable (DAC?) during blank 398 values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb; 399 400 } else { 401 // select PLL as pixel clock 402 values->vclk_ecp_cntl &= ~RADEON_VCLK_SRC_SEL_MASK; 403 values->vclk_ecp_cntl |= RADEON_VCLK_SRC_PPLL_CLK; 404 405 // disable clock if pixel format in CRTC_GEN_CNTL is zero 406 values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb; 407 } 408 409 values->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; 410 if( (display_devices[1] & (dd_ctv | dd_stv)) != 0 411 && !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) 412 { 413 // r200 spec misses everything regarding second CRTC, so 414 // this is guessing 415 values->pixclks_cntl |= 2; 416 } else 417 values->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLL_CLK; 418 419 // choose CRTC for flat panel 420 if( (total_devices & (dd_lvds | dd_dvi)) != 0 ) { 421 int crtc_idx = (display_devices[1] & (dd_lvds | dd_dvi)) != 0; 422 423 values->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2; 424 values->fp_gen_cntl |= crtc_idx == 0 ? 0 : RADEON_FP_SEL_CRTC2; 425 } 426 427 // enable/disable RMX for crtc1 if there is a flat panel 428 // (TODO: this doesn't seem to work) 429 // !!! makes trouble on Radeon 9200 Mobility !?? 430 if( (display_devices[1] & (dd_lvds | dd_dvi)) != 0 ) { 431 values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; 432 values->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_RMX; 433 } 434 435 436 // choose CRTC for secondary flat panel 437 if( (total_devices & dd_dvi_ext) != 0 ) { 438 int crtc_idx = (display_devices[1] & (dd_dvi_ext)) != 0; 439 440 // TODO: this list looks a bit magic/wrong for me; I reckon ATI moved the 441 // bit starting with ASIC xxx, but I have no specs to verify that 442 switch( ai->si->asic ) { 443 case rt_r200: 444 case rt_r300: 445 case rt_r350: 446 case rt_rv350: 447 case rt_m10: 448 values->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_CRTC2; 449 values->fp2_gen_cntl |= 450 crtc_idx == 0 ? 0 : RADEON_FP2_SOURCE_SEL_CRTC2; 451 break; 452 453 default: 454 values->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; 455 values->fp2_gen_cntl |= 456 crtc_idx == 0 ? 0 : RADEON_FP2_SRC_SEL_CRTC2; 457 } 458 } 459 } 460 461 void Radeon_ProgramMonitorRouting( 462 accelerator_info *ai, routing_regs *values ) 463 { 464 vuint8 *regs = ai->regs; 465 466 OUTREG( regs, RADEON_DAC_CNTL, values->dac_cntl ); 467 OUTREG( regs, RADEON_DAC_CNTL2, values->dac_cntl2 ); 468 OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, values->crtc2_gen_cntl, 469 ~RADEON_CRTC2_CRT2_ON ); 470 OUTREG( regs, RADEON_DISP_OUTPUT_CNTL, values->disp_output_cntl ); 471 472 switch( ai->si->asic ) { 473 case rt_ve: 474 case rt_m6: 475 case rt_rv200: 476 case rt_m7: 477 case rt_rv250: 478 case rt_m9: 479 case rt_rv280: 480 case rt_m9plus: 481 case rt_rs100: 482 case rt_rs200: 483 OUTREG( regs, RADEON_DISP_HW_DEBUG, values->disp_hw_debug ); 484 break; 485 486 case rt_r200: 487 OUTREG( regs, RADEON_DISP_TV_OUT_CNTL, values->disp_tv_out_cntl ); 488 break; 489 490 case rt_r300: 491 case rt_r300_4p: 492 case rt_rv350: 493 case rt_m10: 494 case rt_m11: 495 case rt_rv360: 496 case rt_r350: 497 case rt_r360: 498 OUTREGP( regs, RADEON_GPIOPAD_A, values->gpiopad_a, ~1 ); 499 break; 500 501 case rt_r100: 502 break; 503 } 504 505 if( ai->si->asic > rt_r100 ) { 506 // register introduced after R100; 507 // only set it when necessary (more precisely: if TV-Out is used, 508 // this register is set by the TV-Out code) 509 if( !values->skip_tv_dac ) 510 OUTREG( regs, RADEON_TV_DAC_CNTL, values->tv_dac_cntl ); 511 } 512 513 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) 514 OUTREG( regs, RADEON_TV_MASTER_CNTL, values->tv_master_cntl ); 515 516 OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, ~( 517 RADEON_FP_SEL_CRTC2 | 518 RADEON_FP_RMX_HVSYNC_CONTROL_EN | 519 RADEON_FP_DFP_SYNC_SEL | 520 RADEON_FP_CRT_SYNC_SEL | 521 RADEON_FP_CRTC_LOCK_8DOT | 522 RADEON_FP_USE_SHADOW_EN | 523 RADEON_FP_CRTC_USE_SHADOW_VEND | 524 RADEON_FP_CRT_SYNC_ALT | 525 RADEON_FP_CRTC_DONT_SHADOW_VPAR | 526 RADEON_FP_CRTC_DONT_SHADOW_HEND )); 527 528 529 OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl, 530 ~(RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 )); 531 532 if( ai->vc->used_crtc[0] ) { 533 Radeon_OUTPLLP( ai->regs, ai->si->asic, 534 RADEON_VCLK_ECP_CNTL, values->vclk_ecp_cntl, 535 ~RADEON_VCLK_SRC_SEL_MASK ); 536 } 537 538 if( ai->vc->used_crtc[1] ) { 539 Radeon_OUTPLLP( ai->regs, ai->si->asic, 540 RADEON_PIXCLKS_CNTL, values->pixclks_cntl, 541 ~RADEON_PIX2CLK_SRC_SEL_MASK ); 542 } 543 544 Radeon_OUTPLLP( ai->regs, ai->si->asic, 545 RADEON_PIXCLKS_CNTL, values->pixclks_cntl, 546 ~RADEON_PIXCLK_TV_SRC_SEL_MASK ); 547 548 // enable/disable CRTC1 549 if( ai->vc->assigned_crtc[0] ) { 550 uint32 crtc_gen_cntl; 551 552 crtc_gen_cntl = INREG( regs, RADEON_CRTC_GEN_CNTL ); 553 554 if( ai->vc->used_crtc[0] ) { 555 crtc_gen_cntl |= RADEON_CRTC_EN; 556 } else { 557 crtc_gen_cntl &= ~RADEON_CRTC_EN; 558 crtc_gen_cntl &= ~RADEON_CRTC_PIX_WIDTH_MASK; 559 } 560 561 OUTREGP( regs, RADEON_CRTC_GEN_CNTL, crtc_gen_cntl, 562 ~(RADEON_CRTC_PIX_WIDTH_MASK | RADEON_CRTC_EN) ); 563 } 564 565 // enable/disable CRTC2 566 if( ai->vc->assigned_crtc[1] ) { 567 uint32 crtc2_gen_cntl; 568 569 crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL ); 570 571 if( ai->vc->used_crtc[1] ) { 572 crtc2_gen_cntl |= RADEON_CRTC2_EN; 573 } else { 574 crtc2_gen_cntl &= ~RADEON_CRTC2_EN; 575 crtc2_gen_cntl &= ~RADEON_CRTC2_PIX_WIDTH_MASK; 576 } 577 578 OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl, 579 ~(RADEON_CRTC2_PIX_WIDTH_MASK | RADEON_CRTC2_EN) ); 580 } 581 582 // XFree says that crtc_ext_cntl must be restored after CRTC2 in dual-screen mode 583 OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl, 584 RADEON_CRTC_VSYNC_DIS | 585 RADEON_CRTC_HSYNC_DIS | 586 RADEON_CRTC_DISPLAY_DIS ); 587 } 588 589 590 // internal version of SetupDefaultMonitorRouting; 591 // input and output are written to local variables 592 void assignDefaultMonitorRoute( 593 accelerator_info *ai, 594 display_device_e display_devices, int whished_num_heads, bool use_laptop_panel, 595 display_device_e *crtc1, display_device_e *crtc2 ) 596 { 597 virtual_card *vc = ai->vc; 598 display_device_e crtc1_displays = 0, crtc2_displays = 0; 599 600 SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d", 601 display_devices, whished_num_heads ); 602 603 // restrict to allowed devices 604 display_devices &= ai->vc->controlled_displays; 605 606 // if CRTC1 is not ours, we cannot use flat panels 607 if( !ai->vc->assigned_crtc[0] ) { 608 display_devices &= ~(dd_lvds | dd_dvi); 609 } 610 611 SHOW_FLOW( 2, "after restriction: %x", display_devices ); 612 613 // flat panels get always connected to CRTC1 because its RMX unit 614 if( (display_devices & dd_lvds) != 0 ) { 615 // if user requests it, laptop panels are always used 616 if( use_laptop_panel ) { 617 crtc1_displays |= dd_lvds; 618 619 } else { 620 // if he doesn't request it, we try to not use it 621 display_device_e tmp_crtc1, tmp_crtc2; 622 int effective_num_heads; 623 624 // determine routing with laptop panel ignored 625 assignDefaultMonitorRoute( ai, display_devices & ~dd_lvds, 626 whished_num_heads, use_laptop_panel, &tmp_crtc1, &tmp_crtc2 ); 627 628 effective_num_heads = (tmp_crtc1 != 0) + (tmp_crtc2 != 0); 629 630 // only use laptop panel if we cannot satisfy the requested 631 // number of heads without it 632 if( effective_num_heads < whished_num_heads ) 633 crtc1_displays |= dd_lvds; 634 } 635 636 } else if( (display_devices & dd_dvi) != 0 ) 637 crtc1_displays |= dd_dvi; 638 639 // TV-Out gets always connected to crtc2... 640 if( (display_devices & dd_stv) != 0 ) 641 crtc2_displays |= dd_stv; 642 else if( (display_devices & dd_ctv) != 0 ) 643 crtc2_displays |= dd_ctv; 644 645 // ...but if there is no crtc2, they win on crtc1; 646 // if the user connects both a flat panel and a TV, he usually 647 // wants to use the TV 648 if( !vc->assigned_crtc[1] && crtc2_displays != 0 ) { 649 crtc1_displays = crtc2_displays; 650 crtc2_displays = dd_none; 651 } 652 653 // if internal TV-Out is used, the DAC cannot drive a CRT at the same time 654 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ) && (display_devices & (dd_stv | dd_ctv)) != 0 ) 655 display_devices &= ~dd_tv_crt; 656 657 // CRT on CRT-DAC gets any spare CRTC; 658 // if there is none, it can share CRTC with TV-Out; 659 // this sharing may be dangerous as TV-Out uses strange timings, so 660 // we should perhaps forbid sharing 661 if( (display_devices & dd_crt) != 0 ) { 662 if( crtc1_displays == 0 && vc->assigned_crtc[0] ) 663 crtc1_displays |= dd_crt; 664 else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] ) 665 crtc2_displays |= dd_crt; 666 else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] ) 667 crtc1_displays |= dd_crt; 668 else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] ) 669 crtc2_displays |= dd_crt; 670 } 671 672 // same applies to CRT on TV-DAC; 673 // if we cannot find a CRTC, we could clone the content of the CRT-DAC, 674 // but I doubt that you really want two CRTs showing the same 675 if( (display_devices & dd_tv_crt) != 0 ) { 676 if( crtc1_displays == 0 && vc->assigned_crtc[0] ) 677 crtc1_displays |= dd_tv_crt; 678 else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] ) 679 crtc2_displays |= dd_tv_crt; 680 else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] ) 681 crtc1_displays |= dd_tv_crt; 682 else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] ) 683 crtc2_displays |= dd_tv_crt; 684 } 685 686 SHOW_FLOW( 3, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays ); 687 688 *crtc1 = crtc1_displays; 689 *crtc2 = crtc2_displays; 690 } 691 692 // Setup sensible default monitor routing 693 // whished_num_heads - number of independant heads current display mode would need 694 // use_laptop_panel - if true, always use laptop panel 695 void Radeon_SetupDefaultMonitorRouting( 696 accelerator_info *ai, int whished_num_heads, bool use_laptop_panel ) 697 { 698 virtual_card *vc = ai->vc; 699 shared_info *si = ai->si; 700 display_device_e display_devices = vc->connected_displays; 701 702 SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d, use_laptop_panel=%d", 703 display_devices, whished_num_heads, use_laptop_panel ); 704 705 // ignore TV if standard is set to "off" 706 if( vc->tv_standard == ts_off ) 707 display_devices &= ~(dd_ctv | dd_stv); 708 709 assignDefaultMonitorRoute( 710 ai, display_devices, whished_num_heads, use_laptop_panel, 711 &si->crtc[0].chosen_displays, &si->crtc[1].chosen_displays ); 712 713 /* si->crtc[0].chosen_displays = dd_none; 714 si->crtc[1].chosen_displays = dd_tv_crt;*/ 715 716 /*vc->used_crtc[0] = si->crtc[0].chosen_displays != dd_none; 717 vc->used_crtc[1] = si->crtc[1].chosen_displays != dd_none;*/ 718 719 SHOW_FLOW( 2, "num_crtc: %d, CRTC1 (%s): 0x%x, CRTC2 (%s): 0x%x", 720 si->num_crtc, 721 vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[0].chosen_displays, 722 vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[1].chosen_displays ); 723 } 724