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