1 /* 2 Copyright (c) 2002-2004, Thomas Kurschel 3 4 5 Part of Radeon accelerant 6 7 Sets display modes, colour palette and handles DPMS 8 */ 9 10 11 #include "GlobalData.h" 12 #include "generic.h" 13 #include <sys/ioctl.h> 14 #include "radeon_regs.h" 15 #include "mmio.h" 16 #include "crtc_regs.h" 17 #include <GraphicsDefs.h> 18 19 #include "crtc_regs.h" 20 #include "overlay_regs.h" 21 #include "rbbm_regs.h" 22 #include "dac_regs.h" 23 24 #include "set_mode.h" 25 26 #include <string.h> 27 28 29 // round virtual width up to next valid size 30 uint32 Radeon_RoundVWidth( 31 int virtual_width, int bpp ) 32 { 33 // we have to make both the CRTC and the accelerator happy: 34 // - the CRTC wants virtual width in pixels to be a multiple of 8 35 // - the accelerator expects width in bytes to be a multiple of 64 36 37 // to put that together, width (in bytes) must be a multiple of the least 38 // common nominator of bytes-per-pixel*8 (CRTC) and 64 (accelerator); 39 40 // if bytes-per-pixel is a power of two and less than 8, the LCM is 64; 41 // almost all colour depth satisfy that apart from 24 bit; in this case, 42 // the LCM is 64*3=192 43 44 // after dividing by bytes-per-pixel we get pixels: in first case, 45 // width must be multiple of 64/bytes-per-pixel; in second case, 46 // width must be multiple of 64*3/3=64 47 48 if( bpp != 3 ) 49 return (virtual_width + 64/bpp - 1) & ~(64/bpp - 1); 50 else 51 return (virtual_width + 63) & ~63; 52 } 53 54 55 // list of registers that must be reset before display mode switch 56 // to avoid interferences 57 static struct { 58 uint16 reg; 59 uint32 val; 60 } common_regs[] = { 61 { RADEON_OVR_CLR, 0 }, 62 { RADEON_OVR_WID_LEFT_RIGHT, 0 }, 63 { RADEON_OVR_WID_TOP_BOTTOM, 0 }, 64 { RADEON_OV0_SCALE_CNTL, 0 }, // disable overlay 65 { RADEON_SUBPIC_CNTL, 0 }, 66 { RADEON_I2C_CNTL_1, 0 }, 67 }; 68 69 70 static void Radeon_InitCommonRegs( 71 accelerator_info *ai ) 72 { 73 vuint8 *regs = ai->regs; 74 uint i; 75 76 for( i = 0; i < sizeof( common_regs) / sizeof( common_regs[0] ); ++i ) 77 OUTREG( regs, common_regs[i].reg, common_regs[i].val ); 78 79 // enable extended display modes 80 OUTREGP( regs, RADEON_CRTC_GEN_CNTL, 81 RADEON_CRTC_EXT_DISP_EN, ~RADEON_CRTC_EXT_DISP_EN ); 82 83 // disable flat panel auto-centering 84 // (if we have a CRT on CRTC1, this must be disabled; 85 // if we have a flat panel on CRTC1, we setup CRTC manually, not 86 // using the auto-centre, automatic-sync-override magic) 87 OUTREG( regs, RADEON_CRTC_MORE_CNTL, 0 ); 88 } 89 90 91 // set display mode of one head; 92 // port restrictions, like fixed-sync TFTs connected to it, are taken care of 93 void Radeon_SetMode( 94 accelerator_info *ai, crtc_info *crtc, display_mode *mode, impactv_params *tv_params ) 95 { 96 virtual_card *vc = ai->vc; 97 shared_info *si = ai->si; 98 vuint8 *regs = ai->regs; 99 int format; 100 int bpp; 101 display_device_e disp_devices; 102 fp_info *fp_info; 103 104 crtc_regs crtc_values; 105 pll_regs pll_values; 106 fp_regs fp_values; 107 impactv_regs impactv_values; 108 uint32 surface_cntl; 109 110 bool internal_tv_encoder; 111 pll_dividers dividers; 112 113 crtc->mode = *mode; 114 115 // don't destroy passed values, use our copy instead 116 mode = &crtc->mode; 117 118 disp_devices = crtc->chosen_displays; 119 fp_info = &si->flatpanels[crtc->flatpanel_port]; 120 121 // if using an flat panel or LCD, maximum resolution 122 // is determined by the physical resolution; 123 // also, all timing is fixed 124 if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) { 125 if( mode->timing.h_display > fp_info->panel_xres ) 126 mode->timing.h_display = fp_info->panel_xres; 127 if( mode->timing.v_display > fp_info->panel_yres ) 128 mode->timing.v_display = fp_info->panel_yres; 129 130 mode->timing.h_total = mode->timing.h_display + fp_info->h_blank; 131 mode->timing.h_sync_start = mode->timing.h_display + fp_info->h_over_plus; 132 mode->timing.h_sync_end = mode->timing.h_sync_start + fp_info->h_sync_width; 133 mode->timing.v_total = mode->timing.v_display + fp_info->v_blank; 134 mode->timing.v_sync_start = mode->timing.v_display + fp_info->v_over_plus; 135 mode->timing.v_sync_end = mode->timing.v_sync_start + fp_info->v_sync_width; 136 137 mode->timing.pixel_clock = fp_info->dot_clock; 138 } 139 140 // TV-out supports at most 1024x768 141 if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) { 142 if( mode->timing.h_display > 1024 ) 143 mode->timing.h_display = 1024; 144 145 if( mode->timing.v_display > 768 ) 146 mode->timing.v_display = 768; 147 } 148 149 // if using TV-Out, the timing of the source signal must be tweaked to 150 // get proper timing 151 internal_tv_encoder = IS_INTERNAL_TV_OUT( si->tv_chip ); 152 153 // we need higher accuracy then Be thought of 154 mode->timing.pixel_clock *= 1000; 155 156 // TV stuff must be done first as it tweaks the display mode 157 if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) { 158 display_mode tweaked_mode; 159 160 Radeon_CalcImpacTVParams( 161 &si->pll, tv_params, vc->tv_standard, internal_tv_encoder, 162 mode, &tweaked_mode ); 163 164 *mode = tweaked_mode; 165 } 166 167 Radeon_GetFormat( mode->space, &format, &bpp ); 168 169 vc->bpp = bpp; 170 vc->datatype = format; 171 172 // time to read original register content 173 // lock hardware so noone bothers us 174 Radeon_WaitForIdle( ai, true ); 175 176 if( (disp_devices & (dd_dvi | dd_lvds | dd_dvi_ext)) != 0 ) { 177 if( crtc->crtc_idx == 0 ) 178 Radeon_ReadRMXRegisters( ai, &fp_values ); 179 180 Radeon_ReadFPRegisters( ai, &fp_values ); 181 } 182 183 if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) { 184 // some register's content isn't created from scratch but 185 // only modified, so we need the original content first 186 if( internal_tv_encoder ) 187 Radeon_InternalTVOutReadRegisters( ai, &impactv_values ); 188 else 189 Radeon_TheatreReadTVRegisters( ai, &impactv_values ); 190 } 191 192 193 // calculate all hardware register values 194 Radeon_CalcCRTCRegisters( ai, crtc, mode, &crtc_values ); 195 196 surface_cntl = RADEON_SURF_TRANSLATION_DIS; 197 198 if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) { 199 Radeon_CalcImpacTVRegisters( ai, mode, tv_params, &impactv_values, 200 crtc->crtc_idx, internal_tv_encoder, vc->tv_standard, disp_devices ); 201 } 202 203 if( (disp_devices & (dd_stv | dd_ctv)) == 0 ) 204 Radeon_CalcCRTPLLDividers( &si->pll, mode, ÷rs ); 205 else 206 dividers = tv_params->crt_dividers; 207 208 Radeon_CalcPLLRegisters( mode, ÷rs, &pll_values ); 209 210 // for first CRTC1, we need to setup RMX properly 211 if( crtc->crtc_idx == 0 ) 212 Radeon_CalcRMXRegisters( fp_info, mode, 213 (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0, 214 &fp_values ); 215 216 if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) 217 Radeon_CalcFPRegisters( ai, crtc, fp_info, &crtc_values, &fp_values ); 218 219 // we don't use pixel clock anymore, so it can be reset to Be's kHz 220 mode->timing.pixel_clock /= 1000; 221 222 // write values to registers 223 224 Radeon_InitCommonRegs( ai ); 225 226 Radeon_ProgramCRTCRegisters( ai, crtc->crtc_idx, &crtc_values ); 227 228 OUTREG( regs, RADEON_SURFACE_CNTL, surface_cntl ); 229 230 if( crtc->crtc_idx == 0 ) 231 Radeon_ProgramRMXRegisters( ai, &fp_values ); 232 233 if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) 234 Radeon_ProgramFPRegisters( ai, crtc, fp_info, &fp_values ); 235 236 //if( mode->timing.pixel_clock ) 237 Radeon_ProgramPLL( ai, crtc->crtc_idx, &pll_values ); 238 239 if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) { 240 if( internal_tv_encoder ) 241 Radeon_InternalTVOutProgramRegisters( ai, &impactv_values ); 242 else 243 Radeon_TheatreProgramTVRegisters( ai, &impactv_values ); 244 } 245 246 crtc->active_displays = disp_devices; 247 248 // programming is over, so hardware can be used again 249 RELEASE_BEN( si->cp.lock ); 250 251 // overlay must be setup again after modeswitch (whoever was using it) 252 // TBD: this won't work if another virtual card was using it, 253 // but currently, virtual cards don't work anyway... 254 si->active_overlay.crtc_idx = -1; 255 } 256 257 258 // enable or disable VBlank interrupts 259 void Radeon_EnableIRQ( 260 accelerator_info *ai, bool enable ) 261 { 262 shared_info *si = ai->si; 263 uint32 int_cntl, int_mask; 264 265 int_cntl = INREG( ai->regs, RADEON_GEN_INT_CNTL ); 266 int_mask = 267 RADEON_CRTC_VBLANK_MASK 268 | (si->num_crtc > 1 ? RADEON_CRTC2_VBLANK_MASK : 0); 269 270 if( enable ) 271 int_cntl |= int_mask; 272 else 273 int_cntl &= ~int_mask; 274 275 OUTREG( ai->regs, RADEON_GEN_INT_CNTL, int_cntl ); 276 277 if( enable ) { 278 // on enable, we have to acknowledge all IRQs as the graphics card 279 // waits for that before it issues further IRQs 280 OUTREG( ai->regs, RADEON_GEN_INT_STATUS, int_cntl ); 281 } 282 283 si->enable_virtual_irq = enable; 284 } 285 286 287 // public function: set display mode 288 status_t SET_DISPLAY_MODE( 289 display_mode *mode_in ) 290 { 291 virtual_card *vc = ai->vc; 292 shared_info *si = ai->si; 293 display_mode bounds, mode; 294 295 mode = bounds = *mode_in; 296 297 ACQUIRE_BEN( si->engine.lock ); 298 299 SHOW_FLOW( 2, "width=%d, height=%d", mode.timing.h_display, mode.timing.v_display ); 300 301 // check mode and tweak parameters so we can program hardware 302 // without any further checks 303 if( PROPOSE_DISPLAY_MODE( &mode, &bounds, &bounds ) == B_ERROR ) { 304 SHOW_ERROR0( 2, "invalid mode" ); 305 306 RELEASE_BEN( si->engine.lock ); 307 return B_ERROR; 308 } 309 310 // already done by propose_display_mode, but it was undone on return; 311 // do this before equality check to recognize changes of multi-monitor mode 312 Radeon_DetectMultiMode( vc, &mode ); 313 314 // mode switches can take quite long and are visible, 315 // so avoid them if possible 316 if( memcmp( &mode, &vc->mode, sizeof( display_mode )) == 0 && 317 !vc->enforce_mode_change ) { 318 RELEASE_BEN( si->engine.lock ); 319 return B_OK; 320 } 321 322 // this flag was set when some internal parameter has changed that 323 // affects effective display mode 324 vc->enforce_mode_change = false; 325 326 // make sure, we don't get disturbed 327 //Radeon_Finish( ai ); 328 Radeon_EnableIRQ( ai, false ); 329 330 // free cursor and framebuffer memory 331 { 332 radeon_free_mem fm; 333 334 fm.magic = RADEON_PRIVATE_DATA_MAGIC; 335 fm.memory_type = mt_local; 336 fm.global = true; 337 338 if( vc->cursor.mem_handle ) { 339 fm.handle = vc->cursor.mem_handle; 340 ioctl( ai->fd, RADEON_FREE_MEM, &fm ); 341 } 342 343 if( vc->fb_mem_handle ) { 344 fm.handle = vc->fb_mem_handle; 345 ioctl( ai->fd, RADEON_FREE_MEM, &fm ); 346 } 347 } 348 349 memcpy( &vc->mode, &mode, sizeof( display_mode )); 350 351 // verify hardware restrictions *after* saving mode 352 // e.g. if you want a span mode but have one monitor disconnected, 353 // configuration shouldn't be touched, so you can continue working 354 // with two monitors later on just like nothing has happened 355 Radeon_VerifyMultiMode( vc, si, &mode ); 356 357 // set main flags 358 vc->independant_heads = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none; 359 360 if( si->num_crtc > 1 ) 361 vc->independant_heads += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none; 362 363 vc->different_heads = Radeon_DifferentPorts( &mode ); 364 SHOW_FLOW( 2, "independant heads: %d, different heads: %d", 365 vc->independant_heads, vc->different_heads ); 366 vc->scroll = mode.flags & B_SCROLL; 367 SHOW_FLOW( 2, "scrolling %s", vc->scroll ? "enabled" : "disabled" ); 368 369 // allocate frame buffer and cursor image memory 370 { 371 radeon_alloc_mem am; 372 int format, bpp; 373 374 // alloc cursor memory 375 am.magic = RADEON_PRIVATE_DATA_MAGIC; 376 am.size = 1024; 377 am.memory_type = mt_local; 378 am.global = true; 379 380 if( ioctl( ai->fd, RADEON_ALLOC_MEM, &am ) == B_OK ) { 381 vc->cursor.mem_handle = am.handle; 382 vc->cursor.fb_offset = am.offset; 383 } else { 384 // too bad that we are out of mem -> set reasonable values as 385 // it's too late to give up (ouch!) 386 SHOW_ERROR0( 2, "no memory for cursor image!" ); 387 vc->cursor.mem_handle = 0; 388 vc->cursor.fb_offset = 0; 389 } 390 391 vc->cursor.data = si->local_mem + vc->cursor.fb_offset; 392 393 // alloc frame buffer 394 Radeon_GetFormat( mode.space, &format, &bpp ); 395 vc->pitch = Radeon_RoundVWidth( mode.virtual_width, bpp ) * bpp; 396 am.size = vc->pitch * mode.virtual_height; 397 398 if( ioctl( ai->fd, RADEON_ALLOC_MEM, &am ) == B_OK ) { 399 vc->fb_mem_handle = am.handle; 400 vc->fb_offset = am.offset; 401 } else { 402 // ouch again - set reasonable values 403 SHOW_ERROR0( 2, "no memory for frame buffer!" ); 404 vc->fb_mem_handle = 0; 405 vc->fb_offset = 1024; 406 } 407 408 vc->fbc.frame_buffer = si->local_mem + vc->fb_offset; 409 vc->fbc.frame_buffer_dma = (void *)((uint8 *)si->framebuffer_pci + vc->fb_offset); 410 vc->fbc.bytes_per_row = vc->pitch; 411 412 SHOW_FLOW( 0, "frame buffer CPU-address=%x, phys-address=%x", 413 vc->fbc.frame_buffer, vc->fbc.frame_buffer_dma ); 414 } 415 416 // multi-screen stuff 417 Radeon_InitMultiModeVars( ai, &mode ); 418 419 // GO! 420 421 { 422 routing_regs routing_values; 423 impactv_params tv_params; 424 425 // we first switch off all output, so the monitor(s) won't get invalid signals 426 if( vc->assigned_crtc[0] ) { 427 // overwrite list of active displays to switch off displays 428 // someone else turned on 429 si->crtc[0].active_displays = vc->controlled_displays; 430 Radeon_SetDPMS( ai, 0, B_DPMS_SUSPEND ); 431 } 432 if( vc->assigned_crtc[1] ) { 433 si->crtc[1].active_displays = vc->controlled_displays; 434 Radeon_SetDPMS( ai, 1, B_DPMS_SUSPEND ); 435 } 436 437 // mark crtc that will be used from now on 438 vc->used_crtc[0] = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none; 439 vc->used_crtc[1] = vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none; 440 441 // then change the mode 442 if( vc->used_crtc[0] ) 443 Radeon_SetMode( ai, &si->crtc[0], &mode, &tv_params ); 444 if( vc->used_crtc[1] ) 445 Radeon_SetMode( ai, &si->crtc[1], &mode, &tv_params ); 446 447 // setup signal routing 448 Radeon_ReadMonitorRoutingRegs( ai, &routing_values ); 449 Radeon_CalcMonitorRouting( ai, &tv_params, &routing_values ); 450 Radeon_ProgramMonitorRouting( ai, &routing_values ); 451 452 // finally, switch display(s) on 453 if( vc->used_crtc[0] ) 454 Radeon_SetDPMS( ai, 0, B_DPMS_ON ); 455 if( vc->used_crtc[1] ) 456 Radeon_SetDPMS( ai, 1, B_DPMS_ON ); 457 458 OUTREGP( ai->regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS ); 459 } 460 461 SHOW_FLOW( 3, "pitch=%ld", vc->pitch ); 462 463 // we'll modify bits of this reg, so save it for async access 464 si->dac_cntl2 = INREG( ai->regs, RADEON_DAC_CNTL2 ); 465 466 // setup 2D registers 467 Radeon_Init2D( ai ); 468 // setup position of framebuffer for 2D commands 469 Radeon_FillStateBuffer( ai, vc->datatype ); 470 471 // remember that 2D accelerator is not prepared for any virtual card 472 si->active_vc = -1; 473 474 // first move to well-defined position (to setup CRTC offset) 475 Radeon_MoveDisplay( ai, 0, 0 ); 476 // then to (probably faulty) user-defined pos 477 Radeon_MoveDisplay( ai, mode.h_display_start, mode.v_display_start ); 478 479 // set standard palette in direct-colour modes 480 if( vc->used_crtc[0] ) 481 Radeon_InitPalette( ai, 0 ); 482 if( vc->used_crtc[1] ) 483 Radeon_InitPalette( ai, 1 ); 484 485 // initialize cursor data 486 if( vc->used_crtc[0] ) 487 Radeon_SetCursorColors( ai, 0 ); 488 if( vc->used_crtc[1] ) 489 Radeon_SetCursorColors( ai, 1 ); 490 491 // sync should be settled now, so we can reenable IRQs 492 Radeon_EnableIRQ( ai, true ); 493 494 RELEASE_BEN( si->engine.lock ); 495 496 // !! all this must be done after lock has been 497 // released to avoid dead-lock !! 498 // TBD: any invalid intermediate states? 499 500 // move_cursor sets all cursor-related variables and registers 501 vc->cursor.is_visible = false; 502 MOVE_CURSOR( 0, 0 ); 503 504 return B_OK; 505 } 506