1 /* 2 Copyright 1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 5 Other authors: 6 Mark Watson, 7 Apsed, 8 Rudolf Cornelissen 11/2002-5/2006 9 */ 10 11 #define MODULE_BIT 0x00200000 12 13 #include "acc_std.h" 14 15 /* 16 Enable/Disable interrupts. Just a wrapper around the 17 ioctl() to the kernel driver. 18 */ 19 static void interrupt_enable(bool flag) 20 { 21 status_t result; 22 gx00_set_bool_state sbs; 23 24 if (si->ps.int_assigned) 25 { 26 /* set the magic number so the driver knows we're for real */ 27 sbs.magic = GX00_PRIVATE_DATA_MAGIC; 28 sbs.do_it = flag; 29 /* contact driver and get a pointer to the registers and shared data */ 30 result = ioctl(fd, GX00_RUN_INTERRUPTS, &sbs, sizeof(sbs)); 31 } 32 } 33 34 /* First validate the mode, then call lots of bit banging stuff to set the mode(s)! */ 35 status_t SET_DISPLAY_MODE(display_mode *mode_to_set) 36 { 37 /* BOUNDS WARNING: 38 * It's impossible to deviate whatever small amount in a display_mode if the lower 39 * and upper limits are the same! 40 * Besides: 41 * BeOS (tested R5.0.3PE) is failing BWindowScreen::SetFrameBuffer() if PROPOSEMODE 42 * returns B_BAD_VALUE! 43 * Which means PROPOSEMODE should not return that on anything except on 44 * deviations for: 45 * display_mode.virtual_width; 46 * display_mode.virtual_height; 47 * display_mode.timing.h_display; 48 * display_mode.timing.v_display; 49 * So: 50 * We don't use bounds here by making sure bounds and target are the same struct! 51 * (See the call to PROPOSE_DISPLAY_MODE below) */ 52 display_mode /*bounds,*/ target; 53 54 uint8 colour_depth1 = 32; 55 status_t result; 56 uint32 startadd,startadd_right; 57 58 /* Adjust mode to valid one and fail if invalid */ 59 target /*= bounds*/ = *mode_to_set; 60 /* show the mode bits */ 61 LOG(1, ("SETMODE: (ENTER) initial modeflags: $%08x\n", target.flags)); 62 LOG(1, ("SETMODE: requested target pixelclock %dkHz\n", target.timing.pixel_clock)); 63 LOG(1, ("SETMODE: requested virtual_width %d, virtual_height %d\n", 64 target.virtual_width, target.virtual_height)); 65 66 /* See BOUNDS WARNING above... */ 67 if (PROPOSE_DISPLAY_MODE(&target, &target, &target) == B_ERROR) return B_ERROR; 68 69 /* overlay engine, cursor and MOVE_DISPLAY need to know the status even when 70 * in singlehead mode */ 71 si->switched_crtcs = false; 72 73 /* disable interrupts using the kernel driver */ 74 interrupt_enable(false); 75 76 /* then turn off screen(s) */ 77 gx00_crtc_dpms(false, false, false); 78 if (si->ps.secondary_head) 79 { 80 g400_crtc2_dpms(false, false, false); 81 } 82 else 83 { 84 /* on singlehead cards with TVout program the MAVEN as well */ 85 if (si->ps.tvout) gx00_maven_dpms(false, false, false); 86 } 87 88 /*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/ 89 startadd = (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer; 90 91 /* calculate and set new mode bytes_per_row */ 92 gx00_general_validate_pic_size (&target, &si->fbc.bytes_per_row, &si->acc_mode); 93 94 /*Perform the very long mode switch!*/ 95 if (target.flags & DUALHEAD_BITS) /*if some dualhead mode*/ 96 { 97 uint8 colour_depth2 = colour_depth1; 98 99 /* init display mode for secondary head */ 100 display_mode target2 = target; 101 102 LOG(1,("SETMODE: setting DUALHEAD mode\n")); 103 104 /* set the pixel clock PLL(s) */ 105 LOG(8,("SETMODE: target clock %dkHz\n",target.timing.pixel_clock)); 106 if (gx00_dac_set_pix_pll(target) == B_ERROR) 107 LOG(8,("SETMODE: error setting pixel clock (internal DAC)\n")); 108 109 /* we do not need to set the pixelclock here for a head that's in TVout mode */ 110 if (!(target2.flags & TV_BITS)) 111 { 112 LOG(8,("SETMODE: target2 clock %dkHz\n",target2.timing.pixel_clock)); 113 if (gx00_maven_set_vid_pll(target2) == B_ERROR) 114 LOG(8,("SETMODE: error setting pixel clock (MAVEN)\n")); 115 } 116 117 /*set the colour depth for CRTC1 and the DAC */ 118 switch(target.space) 119 { 120 case B_RGB16_LITTLE: 121 colour_depth1 = 16; 122 gx00_dac_mode(BPP16, 1.0); 123 gx00_crtc_depth(BPP16); 124 break; 125 case B_RGB32_LITTLE: 126 colour_depth1 = 32; 127 gx00_dac_mode(BPP32, 1.0); 128 gx00_crtc_depth(BPP32); 129 break; 130 } 131 /*set the colour depth for CRTC2 and the MAVEN */ 132 switch(target2.space) 133 { 134 case B_RGB16_LITTLE: 135 colour_depth2 = 16; 136 gx00_maven_mode(BPP16, 1.0); 137 g400_crtc2_depth(BPP16); 138 break; 139 case B_RGB32_LITTLE: 140 colour_depth2 = 32; 141 gx00_maven_mode(BPP32DIR, 1.0); 142 g400_crtc2_depth(BPP32DIR); 143 break; 144 } 145 146 /* check if we are doing interlaced TVout mode */ 147 si->interlaced_tv_mode = false; 148 if ((target2.flags & TV_BITS) && (si->ps.card_type >= G450)) 149 si->interlaced_tv_mode = true; 150 151 /*set the display(s) pitches*/ 152 gx00_crtc_set_display_pitch (); 153 //fixme: seperate for real dualhead modes: 154 //we need a secondary si->fbc! 155 g400_crtc2_set_display_pitch (); 156 157 /*work out where the "right" screen starts*/ 158 startadd_right=startadd+(target.timing.h_display * (colour_depth1 >> 3)); 159 160 /* calculate needed MAVEN-CRTC delay: formula valid for straight-through CRTC's */ 161 si->crtc_delay = 44; 162 if (colour_depth2 == 16) si->crtc_delay += 0; 163 164 /* set the outputs */ 165 switch (si->ps.card_type) 166 { 167 case G400: 168 case G400MAX: 169 /* setup vertical timing adjust for crtc connected to the MAVEN: 170 * assuming connected straight through. */ 171 /* (extra "blanking" line for MAVEN hardware design fault) */ 172 target2.timing.v_display++; 173 174 switch (target.flags & DUALHEAD_BITS) 175 { 176 case DUALHEAD_ON: 177 case DUALHEAD_CLONE: 178 gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN); 179 si->switched_crtcs = false; 180 break; 181 case DUALHEAD_SWITCH: 182 if (i2c_sec_tv_adapter() == B_OK) 183 { 184 /* Don't switch CRTC's because MAVEN YUV is impossible then, 185 * and primary head output will be limited to 135Mhz pixelclock. */ 186 LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n")); 187 gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN); 188 si->switched_crtcs = true; 189 } 190 else 191 { 192 /* This limits the pixelclocks on both heads to 135Mhz, 193 * but you can use overlay on the other output now. */ 194 LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n")); 195 gx00_general_dac_select(DS_CRTC1MAVEN_CRTC2DAC); 196 si->switched_crtcs = false; 197 /* re-calculate MAVEN-CRTC delay: formula valid for crossed CRTC's */ 198 si->crtc_delay = 17; 199 if (colour_depth1 == 16) si->crtc_delay += 4; 200 /* re-setup vertical timing adjust for crtc connected to the MAVEN: 201 * cross connected. */ 202 /* (extra "blanking" line for MAVEN hardware design fault) */ 203 target.timing.v_display++; 204 target2.timing.v_display--; 205 } 206 break; 207 } 208 break; 209 case G450: 210 case G550: 211 if (!si->ps.primary_dvi) 212 /* output connector use is always 'straight-through' */ 213 //fixme: re-evaluate when DVI is setup... 214 { 215 switch (target.flags & DUALHEAD_BITS) 216 { 217 case DUALHEAD_ON: 218 case DUALHEAD_CLONE: 219 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 220 si->switched_crtcs = false; 221 break; 222 case DUALHEAD_SWITCH: 223 if (i2c_sec_tv_adapter() == B_OK) 224 { 225 /* Don't switch CRTC's because MAVEN YUV and TVout is impossible then, 226 * and primary head output will be limited to 235Mhz pixelclock. */ 227 LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n")); 228 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 229 si->switched_crtcs = true; 230 } 231 else 232 { 233 /* This limits the pixelclocks on both heads to 235Mhz, 234 * but you can use overlay on the other output now. */ 235 LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n")); 236 gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1); 237 si->switched_crtcs = false; 238 } 239 break; 240 } 241 } 242 else 243 /* output connector use is cross-linked if no TV cable connected! */ 244 //fixme: re-evaluate when DVI is setup... 245 { 246 switch (target.flags & DUALHEAD_BITS) 247 { 248 case DUALHEAD_ON: 249 case DUALHEAD_CLONE: 250 if (i2c_sec_tv_adapter() == B_OK) 251 { 252 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 253 si->switched_crtcs = false; 254 } 255 else 256 { 257 /* This limits the pixelclocks on both heads to 235Mhz, 258 * but you can use overlay on the other output now. */ 259 gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1); 260 si->switched_crtcs = false; 261 } 262 break; 263 case DUALHEAD_SWITCH: 264 if (i2c_sec_tv_adapter() == B_OK) 265 { 266 /* Don't switch CRTC's because MAVEN YUV and TVout is impossible then, 267 * and primary head output will be limited to 235Mhz pixelclock. */ 268 LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n")); 269 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 270 si->switched_crtcs = true; 271 } 272 else 273 { 274 LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n")); 275 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 276 si->switched_crtcs = false; 277 } 278 break; 279 } 280 } 281 break; 282 default: 283 break; 284 } 285 286 if (si->switched_crtcs) 287 { 288 uint32 temp = startadd; 289 startadd = startadd_right; 290 startadd_right = temp; 291 } 292 293 /*Tell card what memory to display*/ 294 switch (target.flags & DUALHEAD_BITS) 295 { 296 case DUALHEAD_ON: 297 case DUALHEAD_SWITCH: 298 gx00_crtc_set_display_start(startadd,colour_depth1); 299 g400_crtc2_set_display_start(startadd_right,colour_depth2); 300 break; 301 case DUALHEAD_CLONE: 302 gx00_crtc_set_display_start(startadd,colour_depth1); 303 g400_crtc2_set_display_start(startadd,colour_depth2); 304 break; 305 } 306 307 /* set the timing */ 308 gx00_crtc_set_timing(target); 309 /* we do not need to setup CRTC2 here for a head that's in TVout mode */ 310 if (!(target2.flags & TV_BITS)) result = g400_crtc2_set_timing(target2); 311 312 /* TVout support: setup CRTC2 and it's pixelclock */ 313 if (si->ps.tvout && (target2.flags & TV_BITS)) maventv_init(target2); 314 } 315 else /* single head mode */ 316 { 317 status_t status; 318 int colour_mode = BPP32; 319 320 switch(target.space) 321 { 322 case B_CMAP8: 323 colour_depth1 = 8; 324 colour_mode = BPP8; 325 break; 326 case B_RGB15_LITTLE: 327 colour_depth1 = 16; 328 colour_mode = BPP15; 329 break; 330 case B_RGB16_LITTLE: 331 colour_depth1 = 16; 332 colour_mode = BPP16; 333 break; 334 case B_RGB32_LITTLE: 335 colour_depth1 = 32; 336 colour_mode = BPP32; 337 break; 338 default: 339 LOG(8,("SETMODE: Invalid singlehead colour depth 0x%08x\n", target.space)); 340 return B_ERROR; 341 } 342 343 /* set the pixel clock PLL */ 344 if (si->ps.card_type >= G100) 345 //fixme: how about when TVout is enabled??? 346 status = gx00_dac_set_pix_pll(target); 347 else 348 { 349 status = mil2_dac_set_pix_pll((target.timing.pixel_clock)/1000.0, colour_depth1); 350 } 351 if (status==B_ERROR) 352 LOG(8,("CRTC: error setting pixel clock (internal DAC)\n")); 353 354 /* set the colour depth for CRTC1 and the DAC */ 355 gx00_dac_mode(colour_mode,1.0); 356 gx00_crtc_depth(colour_mode); 357 358 /* if we do TVout mode, its non-interlaced (as we are on <= G400MAX for sure) */ 359 si->interlaced_tv_mode = false; 360 361 /* set the display pitch */ 362 gx00_crtc_set_display_pitch(); 363 364 /* tell the card what memory to display */ 365 gx00_crtc_set_display_start(startadd,colour_depth1); 366 367 /* enable primary analog output */ 368 switch (si->ps.card_type) 369 { 370 case G100: 371 case G200: 372 case G400: 373 case G400MAX: 374 if (!si->ps.secondary_head && si->ps.tvout && (target.flags & TV_BITS)) 375 gx00_general_dac_select(DS_CRTC1MAVEN); 376 else 377 gx00_general_dac_select(DS_CRTC1DAC); 378 break; 379 case G450: 380 case G550: 381 gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2); 382 gx50_general_output_select(); 383 break; 384 default: 385 break; 386 } 387 388 /* set the timing */ 389 if (!si->ps.secondary_head && si->ps.tvout && (target.flags & TV_BITS)) 390 { 391 /* calculate MAVEN-CRTC delay: only used during TVout */ 392 si->crtc_delay = 17; 393 if (colour_depth1 == 16) si->crtc_delay += 4; 394 /* setup CRTC1 and it's pixelclock for TVout */ 395 maventv_init(target); 396 } 397 else 398 { 399 gx00_maven_shutoff(); 400 gx00_crtc_set_timing(target); 401 } 402 } 403 404 /* update driver's mode store */ 405 si->dm = target; 406 407 /* set up acceleration for this mode */ 408 gx00_acc_init(); 409 410 /* restore screen(s) output state(s) */ 411 SET_DPMS_MODE(si->dpms_flags); 412 413 /* clear line at bottom of screen if dualhead mode: 414 * MAVEN hardware design fault 'fix'. 415 * Note: 416 * Not applicable for singlehead cards with a MAVEN, since it's only used 417 * for TVout there. */ 418 if ((target.flags & DUALHEAD_BITS) && (si->ps.card_type <= G400MAX)) 419 gx00_maven_clrline(); 420 421 LOG(1,("SETMODE: booted since %f mS\n", system_time()/1000.0)); 422 423 /* enable interrupts using the kernel driver */ 424 interrupt_enable(true); 425 426 /* optimize memory-access if needed */ 427 gx00_crtc_mem_priority(colour_depth1); 428 429 /* Tune RAM CAS-latency if needed. Must be done *here*! */ 430 mga_set_cas_latency(); 431 432 return B_OK; 433 } 434 435 /* 436 Set which pixel of the virtual frame buffer will show up in the 437 top left corner of the display device. Used for page-flipping 438 games and virtual desktops. 439 */ 440 status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) { 441 uint8 colour_depth; 442 uint32 startadd,startadd_right; 443 444 LOG(4,("MOVE_DISPLAY: h %d, v %d\n", h_display_start, v_display_start)); 445 446 /* G400 CRTC1 handles multiples of 8 for 8bit, 4 for 16bit, 2 for 32 bit 447 G400 CRTC2 handles multiples of 32 for 16-bit and 16 for 32-bit - must stoop to this in dualhead 448 */ 449 450 /* reset lower bits, don't return an error! */ 451 if (si->dm.flags & DUALHEAD_BITS) 452 { 453 switch(si->dm.space) 454 { 455 case B_RGB16_LITTLE: 456 colour_depth=16; 457 h_display_start &= ~0x1f; 458 break; 459 case B_RGB32_LITTLE: 460 colour_depth=32; 461 h_display_start &= ~0x0f; 462 break; 463 default: 464 LOG(8,("SET:Invalid DH colour depth 0x%08x, should never happen\n", si->dm.space)); 465 return B_ERROR; 466 } 467 } 468 else 469 { 470 switch(si->dm.space) 471 { 472 case B_CMAP8: 473 colour_depth=8; 474 h_display_start &= ~0x07; 475 break; 476 case B_RGB15_LITTLE: case B_RGB16_LITTLE: 477 colour_depth=16; 478 h_display_start &= ~0x03; 479 break; 480 case B_RGB32_LITTLE: 481 colour_depth=32; 482 h_display_start &= ~0x01; 483 break; 484 default: 485 return B_ERROR; 486 } 487 } 488 489 /* do not run past end of display */ 490 switch (si->dm.flags & DUALHEAD_BITS) 491 { 492 case DUALHEAD_ON: 493 case DUALHEAD_SWITCH: 494 if (((si->dm.timing.h_display * 2) + h_display_start) > si->dm.virtual_width) 495 return B_ERROR; 496 break; 497 default: 498 if ((si->dm.timing.h_display + h_display_start) > si->dm.virtual_width) 499 return B_ERROR; 500 break; 501 } 502 if ((si->dm.timing.v_display + v_display_start) > si->dm.virtual_height) 503 return B_ERROR; 504 505 /* everybody remember where we parked... */ 506 si->dm.h_display_start = h_display_start; 507 si->dm.v_display_start = v_display_start; 508 509 /* actually set the registers */ 510 //fixme: seperate both heads: we need a secondary si->fbc! 511 startadd = v_display_start * si->fbc.bytes_per_row; 512 startadd += h_display_start * (colour_depth >> 3); 513 startadd += (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer; 514 startadd_right = startadd + si->dm.timing.h_display * (colour_depth >> 3); 515 516 /* account for switched CRTC's */ 517 if (si->switched_crtcs) 518 { 519 uint32 temp = startadd; 520 startadd = startadd_right; 521 startadd_right = temp; 522 } 523 524 interrupt_enable(false); 525 526 switch (si->dm.flags&DUALHEAD_BITS) 527 { 528 case DUALHEAD_ON: 529 case DUALHEAD_SWITCH: 530 gx00_crtc_set_display_start(startadd,colour_depth); 531 g400_crtc2_set_display_start(startadd_right,colour_depth); 532 break; 533 case DUALHEAD_OFF: 534 gx00_crtc_set_display_start(startadd,colour_depth); 535 break; 536 case DUALHEAD_CLONE: 537 gx00_crtc_set_display_start(startadd,colour_depth); 538 g400_crtc2_set_display_start(startadd,colour_depth); 539 break; 540 } 541 542 interrupt_enable(true); 543 return B_OK; 544 } 545 546 /* 547 Set the indexed color palette. 548 */ 549 void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags) { 550 int i; 551 uint8 *r,*g,*b; 552 553 /* Protect gamma correction when not in CMAP8 */ 554 if (si->dm.space != B_CMAP8) return; 555 556 r=si->color_data; 557 g=r+256; 558 b=g+256; 559 560 i=first; 561 while (count--) 562 { 563 r[i]=*color_data++; 564 g[i]=*color_data++; 565 b[i]=*color_data++; 566 i++; 567 } 568 gx00_dac_palette(r,g,b); 569 } 570 571 /* Put the display into one of the Display Power Management modes. */ 572 status_t SET_DPMS_MODE(uint32 dpms_flags) 573 { 574 interrupt_enable(false); 575 576 LOG(4,("SET_DPMS_MODE: 0x%08x\n", dpms_flags)); 577 578 /* note current DPMS state for our reference */ 579 si->dpms_flags = dpms_flags; 580 581 if (si->dm.flags & DUALHEAD_BITS) /* dualhead */ 582 { 583 switch(dpms_flags) 584 { 585 case B_DPMS_ON: /* H: on, V: on */ 586 gx00_crtc_dpms(true, true, true); 587 if (si->ps.secondary_head) g400_crtc2_dpms(true, true, true); 588 break; 589 case B_DPMS_STAND_BY: 590 if (si->settings.greensync) 591 { 592 /* blank screen, but keep sync running */ 593 gx00_crtc_dpms(false, true, true); 594 } 595 else 596 { 597 gx00_crtc_dpms(false, false, true); 598 } 599 if (si->ps.secondary_head) 600 { 601 if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) 602 { 603 /* keep display enabled in TVout modes for G450 and G550! */ 604 g400_crtc2_dpms(true, false, true); 605 } 606 else 607 { 608 g400_crtc2_dpms(false, false, true); 609 } 610 } 611 break; 612 case B_DPMS_SUSPEND: 613 if (si->settings.greensync) 614 { 615 /* blank screen, but keep sync running */ 616 gx00_crtc_dpms(false, true, true); 617 } 618 else 619 { 620 gx00_crtc_dpms(false, true, false); 621 } 622 if (si->ps.secondary_head) 623 { 624 if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) 625 { 626 /* keep display enabled in TVout modes for G450 and G550! */ 627 g400_crtc2_dpms(true, true, false); 628 } 629 else 630 { 631 g400_crtc2_dpms(false, true, false); 632 } 633 } 634 break; 635 case B_DPMS_OFF: /* H: off, V: off, display off */ 636 if (si->settings.greensync) 637 { 638 /* blank screen, but keep sync running */ 639 gx00_crtc_dpms(false, true, true); 640 } 641 else 642 { 643 gx00_crtc_dpms(false, false, false); 644 } 645 if (si->ps.secondary_head) 646 { 647 if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) 648 { 649 /* keep display enabled in TVout modes for G450 and G550! */ 650 g400_crtc2_dpms(true, false, false); 651 } 652 else 653 { 654 g400_crtc2_dpms(false, false, false); 655 } 656 } 657 break; 658 default: 659 LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); 660 interrupt_enable(true); 661 return B_ERROR; 662 } 663 } 664 else /* singlehead */ 665 { 666 switch(dpms_flags) 667 { 668 case B_DPMS_ON: /* H: on, V: on */ 669 gx00_crtc_dpms(true, true, true); 670 /* on singlehead cards with TVout program the MAVEN as well */ 671 if (si->dm.flags & TV_BITS) gx00_maven_dpms(true, true, true); 672 break; 673 case B_DPMS_STAND_BY: 674 if (si->settings.greensync) 675 { 676 /* blank screen, but keep sync running */ 677 gx00_crtc_dpms(false, true, true); 678 } 679 else 680 { 681 gx00_crtc_dpms(false, false, true); 682 } 683 /* on singlehead cards with TVout program the MAVEN as well */ 684 if (si->dm.flags & TV_BITS) gx00_maven_dpms(false, false, true); 685 break; 686 case B_DPMS_SUSPEND: 687 if (si->settings.greensync) 688 { 689 /* blank screen, but keep sync running */ 690 gx00_crtc_dpms(false, true, true); 691 } 692 else 693 { 694 gx00_crtc_dpms(false, true, false); 695 } 696 /* on singlehead cards with TVout program the MAVEN as well */ 697 if (si->dm.flags & TV_BITS) gx00_maven_dpms(false, true, false); 698 break; 699 case B_DPMS_OFF: /* H: off, V: off, display off */ 700 if (si->settings.greensync) 701 { 702 /* blank screen, but keep sync running */ 703 gx00_crtc_dpms(false, true, true); 704 } 705 else 706 { 707 gx00_crtc_dpms(false, false, false); 708 } 709 /* on singlehead cards with TVout program the MAVEN as well */ 710 if (si->dm.flags & TV_BITS) gx00_maven_dpms(false, false, false); 711 break; 712 default: 713 LOG(8,("SET: Invalid DPMS settings (SH) 0x%08x\n", dpms_flags)); 714 interrupt_enable(true); 715 return B_ERROR; 716 } 717 } 718 interrupt_enable(true); 719 return B_OK; 720 } 721 722 /* Report device DPMS capabilities. */ 723 uint32 DPMS_CAPABILITIES(void) 724 { 725 if (si->settings.greensync) 726 /* we can blank the screen on CRTC1, G400 CRTC2 does not support intermediate 727 * modes anyway. */ 728 //fixme: G450/G550 support full DPMS on CRTC2... 729 return B_DPMS_ON | B_DPMS_OFF; 730 else 731 /* normally CRTC1 supports full DPMS (and on G450/G550 CRTC2 also).. */ 732 return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; 733 } 734 735 /* Return the current DPMS mode. */ 736 uint32 DPMS_MODE(void) 737 { 738 return si->dpms_flags; 739 } 740