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