1 /* CTRC functionality */ 2 /* Authors: 3 Mark Watson 2/2000, 4 Apsed, 5 Rudolf Cornelissen 11/2002-2/2004 6 */ 7 8 #define MODULE_BIT 0x00040000 9 10 #include "mga_std.h" 11 12 /*Adjust passed parameters to a valid mode line*/ 13 status_t gx00_crtc_validate_timing( 14 uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht, 15 uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt 16 ) 17 { 18 /* horizontal */ 19 /* make all parameters multiples of 8 */ 20 *hd_e &= 0x0ff8; /* 2048 is a valid value for this item! */ 21 *hs_s &= 0x0ff8; 22 *hs_e &= 0x0ff8; 23 *ht &= 0x0ff8; 24 25 /* confine to required number of bits, taking logic into account */ 26 if (*hd_e > ((0x00ff + 1) << 3)) *hd_e = ((0x00ff + 1) << 3); 27 if (*hs_s > ((0x01ff - 1) << 3)) *hs_s = ((0x01ff - 1) << 3); 28 if (*hs_e > ( 0x01ff << 3)) *hs_e = ( 0x01ff << 3); 29 if (*ht > ((0x01ff + 5) << 3)) *ht = ((0x01ff + 5) << 3); 30 31 /* NOTE: keep horizontal timing at multiples of 8! */ 32 /* confine to a reasonable width */ 33 if (*hd_e < 640) *hd_e = 640; 34 switch (si->ps.card_type) 35 { 36 case MIL1: 37 case MYST: /* fixme MYST220 has MIL2 range.. */ 38 if (*hd_e > 1600) *hd_e = 1600; 39 break; 40 case MIL2: 41 case G100: 42 case G200: 43 if (*hd_e > 1920) *hd_e = 1920; 44 break; 45 default: /* G400 and up */ 46 if (*hd_e > 2048) *hd_e = 2048; 47 break; 48 } 49 50 /* if hor. total does not leave room for a sensible sync pulse, increase it! */ 51 if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80); 52 53 /* make sure sync pulse is not during display */ 54 if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8); 55 if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8); 56 57 /* correct sync pulse if it is too long: 58 * there are only 5 bits available to save this in the card registers! */ 59 if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8); 60 61 /*vertical*/ 62 /* confine to required number of bits, taking logic into account */ 63 if (*vd_e > 0x7ff ) *vd_e = 0x7ff ; /* linecomp max value = 0x7ff! */ 64 if (*vs_s > (0xfff - 1)) *vs_s = (0xfff - 1); 65 if (*vs_e > 0xfff ) *vs_e = 0xfff ; 66 if (*vt > (0xfff + 2)) *vt = (0xfff + 2); 67 68 /* confine to a reasonable height */ 69 if (*vd_e < 480) *vd_e = 480; 70 switch (si->ps.card_type) 71 { 72 case MIL1: 73 case MYST: /* fixme MYST220 has MIL2 range.. */ 74 if (*vd_e > 1200) *vd_e = 1200; 75 break; 76 case MIL2: 77 case G100: 78 case G200: 79 if (*vd_e > 1440) *vd_e = 1440; 80 break; 81 default: /* G400 and up */ 82 if (*vd_e > 1536) *vd_e = 1536; 83 break; 84 } 85 86 /*if vertical total does not leave room for a sync pulse, increase it!*/ 87 if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3); 88 89 /* make sure sync pulse is not during display */ 90 if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1); 91 if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1); 92 93 /* correct sync pulse if it is too long: 94 * there are only 4 bits available to save this in the card registers! */ 95 if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f); 96 97 return B_OK; 98 } 99 100 /* set a mode line - inputs are in pixels */ 101 status_t gx00_crtc_set_timing(display_mode target) 102 { 103 uint8 temp; 104 105 uint32 htotal; /*total horizontal total VCLKs*/ 106 uint32 hdisp_e; /*end of horizontal display (begins at 0)*/ 107 uint32 hsync_s; /*begin of horizontal sync pulse*/ 108 uint32 hsync_e; /*end of horizontal sync pulse*/ 109 uint32 hblnk_s; /*begin horizontal blanking*/ 110 uint32 hblnk_e; /*end horizontal blanking*/ 111 112 uint32 vtotal; /*total vertical total scanlines*/ 113 uint32 vdisp_e; /*end of vertical display*/ 114 uint32 vsync_s; /*begin of vertical sync pulse*/ 115 uint32 vsync_e; /*end of vertical sync pulse*/ 116 uint32 vblnk_s; /*begin vertical blanking*/ 117 uint32 vblnk_e; /*end vertical blanking*/ 118 119 uint32 linecomp; /*split screen and vdisp_e interrupt*/ 120 121 LOG(4,("CRTC: setting timing\n")); 122 123 /* Modify parameters as required by standard VGA */ 124 htotal = ((target.timing.h_total >> 3) - 5); 125 hdisp_e = ((target.timing.h_display >> 3) - 1); 126 hblnk_s = hdisp_e; 127 hblnk_e = (htotal + 4); 128 hsync_s = (target.timing.h_sync_start >> 3); 129 hsync_e = (target.timing.h_sync_end >> 3); 130 131 vtotal = target.timing.v_total - 2; 132 vdisp_e = target.timing.v_display - 1; 133 vblnk_s = vdisp_e; 134 vblnk_e = (vtotal + 1); 135 vsync_s = target.timing.v_sync_start - 1; /* Matrox */ 136 vsync_e = target.timing.v_sync_end - 1; /* Matrox */ 137 138 /* We use the Matrox linecomp INT function to detect the 139 * vertical retrace at the earliest possible moment.. */ 140 linecomp = target.timing.v_display; 141 142 /*log the mode I am setting*/ 143 LOG(2,("CRTC:\n\tHTOT:%x\n\tHDISPEND:%x\n\tHBLNKS:%x\n\tHBLNKE:%x\n\tHSYNCS:%x\n\tHSYNCE:%x\n\t",htotal,hdisp_e,hblnk_s,hblnk_e,hsync_s,hsync_e)); 144 LOG(2,("VTOT:%x\n\tVDISPEND:%x\n\tVBLNKS:%x\n\tVBLNKE:%x\n\tVSYNCS:%x\n\tVSYNCE:%x\n",vtotal,vdisp_e,vblnk_s,vblnk_e,vsync_s,vsync_e)); 145 146 /*actually program the card! Note linecomp is programmed to vblnk_s for VBI*/ 147 /*horizontal - VGA regs*/ 148 149 VGAW_I(CRTC, 0x00, (htotal & 0x0ff)); 150 VGAW_I(CRTC, 0x01, (hdisp_e & 0x0ff)); 151 VGAW_I(CRTC, 0x02, (hblnk_s & 0x0ff)); 152 /* b7 should be set for compatibility reasons */ 153 VGAW_I(CRTC, 0x03, ((hblnk_e & 0x01f) | 0x80)); 154 VGAW_I(CRTC, 0x04, (hsync_s & 0x0ff)); 155 VGAW_I(CRTC, 0x05, (hsync_e & 0x01f) | ((hblnk_e & 0x020) << 2)); 156 157 /*vertical - VGA regs*/ 158 VGAW_I(CRTC, 0x06, (vtotal & 0x0ff)); 159 VGAW_I(CRTC, 0x07, 160 ( 161 ((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) | 162 ((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) | 163 ((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) | 164 ((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4)) 165 )); 166 VGAW_I(CRTC, 0x08, 0x00); 167 VGAW_I(CRTC, 0x09, ((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6))); 168 VGAW_I(CRTC, 0x10, (vsync_s & 0x0ff)); 169 VGAW_I(CRTC, 0x11, (((VGAR_I(CRTC, 0x11)) & 0xf0) | (vsync_e & 0x00f))); 170 VGAW_I(CRTC, 0x12, (vdisp_e & 0x0ff)); 171 VGAW_I(CRTC, 0x15, (vblnk_s & 0x0ff)); 172 VGAW_I(CRTC, 0x16, (vblnk_e & 0x0ff)); 173 VGAW_I(CRTC, 0x18, (linecomp & 0x0ff)); 174 175 /* horizontal - extended regs */ 176 /* do not touch external sync reset inputs: used for TVout */ 177 VGAW_I(CRTCEXT, 1, 178 ( 179 ((htotal & 0x100) >> (8 - 0)) | 180 ((hblnk_s & 0x100) >> (8 - 1)) | 181 ((hsync_s & 0x100) >> (8 - 2)) | 182 ((hblnk_e & 0x040) >> (6 - 6)) | 183 (VGAR_I(CRTCEXT, 1) & 0xb8) 184 )); 185 186 /*vertical - extended regs*/ 187 VGAW_I(CRTCEXT, 2, 188 ( 189 ((vtotal & 0xc00) >> (10 - 0)) | 190 ((vdisp_e & 0x400) >> (10 - 2)) | 191 ((vblnk_s & 0xc00) >> (10 - 3)) | 192 ((vsync_s & 0xc00) >> (10 - 5)) | 193 ((linecomp & 0x400) >> (10 - 7)) 194 )); 195 196 /* setup HSYNC & VSYNC polarity */ 197 LOG(2,("CRTC: sync polarity: ")); 198 temp = VGAR(MISCR); 199 if (target.timing.flags & B_POSITIVE_HSYNC) 200 { 201 LOG(2,("H:pos ")); 202 temp &= ~0x40; 203 } 204 else 205 { 206 LOG(2,("H:neg ")); 207 temp |= 0x40; 208 } 209 if (target.timing.flags & B_POSITIVE_VSYNC) 210 { 211 LOG(2,("V:pos ")); 212 temp &= ~0x80; 213 } 214 else 215 { 216 LOG(2,("V:neg ")); 217 temp |= 0x80; 218 } 219 VGAW(MISCW, temp); 220 221 LOG(2,(", MISC reg readback: $%02x\n", VGAR(MISCR))); 222 223 return B_OK; 224 } 225 226 status_t gx00_crtc_depth(int mode) 227 { 228 uint8 viddelay = 0; // in CRTCEXT3, reserved if >= G100 229 230 if (si->ps.card_type < G100) do { // apsed TODO in caller 231 if (si->ps.memory_size <= 2) { viddelay = 1<<3; break;} 232 if (si->ps.memory_size <= 4) { viddelay = 0<<3; break;} 233 viddelay = 2<<3; // for 8 to 16Mb of memory 234 } while (0); 235 236 /* setup green_sync if requested */ 237 if (si->settings.greensync) 238 { 239 /* enable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */ 240 if (si->ps.card_type <= MIL2) 241 DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20)); 242 else 243 DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20)); 244 /* select horizontal _and_ vertical sync */ 245 viddelay |= 0x40; 246 247 LOG(4,("CRTC: sync_on_green enabled\n")); 248 } 249 else 250 { 251 /* disable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */ 252 if (si->ps.card_type <= MIL2) 253 DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20)); 254 else 255 DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20)); 256 257 LOG(4,("CRTC: sync_on_green disabled\n")); 258 } 259 260 /*set VCLK scaling*/ 261 switch(mode) 262 { 263 case BPP8: 264 VGAW_I(CRTCEXT,3,viddelay|0x80); 265 break; 266 case BPP15:case BPP16: 267 VGAW_I(CRTCEXT,3,viddelay|0x81); 268 break; 269 case BPP24: 270 VGAW_I(CRTCEXT,3,viddelay|0x82); 271 break; 272 case BPP32:case BPP32DIR: 273 VGAW_I(CRTCEXT,3,viddelay|0x83); 274 break; 275 } 276 return B_OK; 277 } 278 279 status_t gx00_crtc_dpms(bool display, bool h, bool v) // MIL2 280 { 281 LOG(4,("CRTC: setting DPMS: ")); 282 283 if (display) 284 { 285 VGAW_I(SEQ,1, 0x00); 286 LOG(4,("display on, ")); 287 } 288 else 289 { 290 VGAW_I(SEQ,1, 0x20); 291 LOG(4,("display off, ")); 292 } 293 if (h) 294 { 295 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xef)); 296 LOG(4,("hsync enabled, ")); 297 } 298 else 299 { 300 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x10)); 301 LOG(4,("hsync disabled, ")); 302 } 303 if (v) 304 { 305 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xdf)); 306 LOG(4,("vsync enabled\n")); 307 } 308 else 309 { 310 VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x20)); 311 LOG(4,("vsync disabled\n")); 312 } 313 314 /* set some required fixed values for proper MGA mode initialisation */ 315 VGAW_I(CRTC,0x17,0xC3); 316 VGAW_I(CRTC,0x14,0x00); 317 318 /* make sure CRTC1 sync is patched through on connector on G450/G550! */ 319 if (si->ps.card_type >= G450) 320 { 321 if (si->crossed_conns) 322 { 323 /* patch through HD15 hsync and vsync unmodified */ 324 DXIW(SYNCCTRL, (DXIR(SYNCCTRL) & 0x0f)); 325 } 326 else 327 { 328 /* patch through DVI-A hsync and vsync unmodified */ 329 DXIW(SYNCCTRL, (DXIR(SYNCCTRL) & 0xf0)); 330 } 331 } 332 333 return B_OK; 334 } 335 336 status_t gx00_crtc_dpms_fetch(bool *display, bool *h, bool *v) // MIL2 337 { 338 *display=!(VGAR_I(SEQ, 1) & 0x20); 339 *h=!(VGAR_I(CRTCEXT, 1) & 0x10); 340 *v=!(VGAR_I(CRTCEXT, 1) & 0x20); 341 342 LOG(4,("CTRC: fetched DPMS state: ")); 343 if (*display) LOG(4,("display on, ")); 344 else LOG(4,("display off, ")); 345 if (*h) LOG(4,("hsync enabled, ")); 346 else LOG(4,("hsync disabled, ")); 347 if (*v) LOG(4,("vsync enabled\n")); 348 else LOG(4,("vsync disabled\n")); 349 350 return B_OK; 351 } 352 353 status_t gx00_crtc_set_display_pitch() 354 { 355 uint32 offset; 356 357 LOG(4,("CRTC: setting card pitch (offset between lines)\n")); 358 359 /* figure out offset value hardware needs: 360 * same for MIL1-G550 cards assuming MIL1/2 uses the TVP3026 64-bits DAC etc. */ 361 offset = si->fbc.bytes_per_row / 16; 362 363 LOG(2,("CRTC: offset register: 0x%04x\n",offset)); 364 365 /*program the card!*/ 366 VGAW_I(CRTC,0x13,(offset&0xFF)); 367 VGAW_I(CRTCEXT,0,(VGAR_I(CRTCEXT,0)&0xCF)|((offset&0x300)>>4)); 368 return B_OK; 369 } 370 371 status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp) 372 { 373 uint32 ext0; 374 375 LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp)); 376 377 /* Matrox docs are false/incomplete, always program qword adress. */ 378 startadd >>= 3; 379 380 LOG(2,("CRTC: startadd: %x\n",startadd)); 381 LOG(2,("CRTC: frameRAM: %x\n",si->framebuffer)); 382 LOG(2,("CRTC: framebuffer: %x\n",si->fbc.frame_buffer)); 383 384 /* make sure we are in retrace on MIL cards (if possible), because otherwise 385 * distortions might occur during our reprogramming them (no double buffering) */ 386 if (si->ps.card_type < G100) 387 { 388 /* we might have no retraces during setmode! */ 389 uint32 timeout = 0; 390 /* wait 25mS max. for retrace to occur (refresh > 40Hz) */ 391 while ((!(ACCR(STATUS) & 0x08)) && (timeout < (25000/4))) 392 { 393 snooze(4); 394 timeout++; 395 } 396 } 397 398 /*set standard registers*/ 399 VGAW_I(CRTC,0xD,startadd&0xFF); 400 VGAW_I(CRTC,0xC,(startadd&0xFF00)>>8); 401 402 //calculate extra bits that are standard over Gx00 series 403 ext0 = VGAR_I(CRTCEXT,0)&0xB0; 404 ext0|= (startadd&0xF0000)>>16; 405 406 //if card is a G200 or G400 then do first extension bit 407 if (si->ps.card_type>=G200) 408 ext0|=(startadd&0x100000)>>14; 409 410 //if card is a G400 then do write to its extension register 411 if (si->ps.card_type>=G400) 412 VGAW_I(CRTCEXT,8,((startadd&0x200000)>>21)); 413 414 //write the extension bits 415 VGAW_I(CRTCEXT,0,ext0); 416 417 return B_OK; 418 } 419 420 status_t gx00_crtc_mem_priority(uint8 colordepth) 421 { 422 float tpixclk, tmclk, refresh, temp; 423 uint8 mp, vc, hiprilvl, maxhipri, prioctl; 424 425 /* we can only do this if card pins is read OK *and* card is coldstarted! */ 426 if (si->settings.usebios || (si->ps.pins_status != B_OK)) 427 { 428 LOG(4,("CRTC: Card not coldstarted, skipping memory priority level setup\n")); 429 return B_OK; 430 } 431 432 /* only on G200 the mem_priority register should be programmed with this formula */ 433 if (si->ps.card_type != G200) 434 { 435 LOG(4,("CRTC: Memory priority level setup not needed, skipping\n")); 436 return B_OK; 437 } 438 439 /* make sure the G200 is running at peak performance, so for instance high-res 440 * overlay distortions due to bandwidth limitations are minimal. 441 * Note please that later cards have plenty of bandwidth to cope by default. 442 * Note also that the formula needed is entirely cardtype-dependant! */ 443 LOG(4,("CRTC: Setting G200 memory priority level\n")); 444 445 /* set memory controller pipe depth, assuming no codec or Vin operating */ 446 switch ((si->ps.memrdbk_reg & 0x00c00000) >> 22) 447 { 448 case 0: 449 mp = 52; 450 break; 451 case 1: 452 mp = 41; 453 break; 454 case 2: 455 mp = 32; 456 break; 457 default: 458 mp = 52; 459 LOG(8,("CRTC: Streamer flowcontrol violation in PINS, defaulting to %%00\n")); 460 break; 461 } 462 463 /* calculate number of videoclocks needed per 8 pixels */ 464 vc = (8 * colordepth) / 64; 465 466 /* calculate pixelclock period (nS) */ 467 tpixclk = 1000000 / si->dm.timing.pixel_clock; 468 469 /* calculate memoryclock period (nS) */ 470 if (si->ps.v3_option2_reg & 0x08) 471 { 472 tmclk = 1000.0 / si->ps.std_engine_clock; 473 } 474 else 475 { 476 if (si->ps.v3_clk_div & 0x02) 477 tmclk = 3000.0 / si->ps.std_engine_clock; 478 else 479 tmclk = 2000.0 / si->ps.std_engine_clock; 480 } 481 482 /* calculate refreshrate of current displaymode */ 483 refresh = ((si->dm.timing.pixel_clock * 1000) / 484 ((uint32)si->dm.timing.h_total * (uint32)si->dm.timing.v_total)); 485 486 /* calculate high priority request level, but stay on the 'crtc-safe' side: 487 * hence 'formula + 1.0' instead of 'formula + 0.5' */ 488 temp = (((((mp * tmclk) + (11 * vc * tpixclk)) / tpixclk) - (vc - 1)) / (8 * vc)) + 1.0; 489 if (temp > 7.0) temp = 7.0; 490 if (temp < 0.0) temp = 0.0; 491 hiprilvl = 7 - ((uint8) temp); 492 /* limit non-crtc priority so crtc always stays 'just' OK */ 493 if (hiprilvl > 4) hiprilvl = 4; 494 if ((si->dm.timing.v_display > 768) && (hiprilvl > 3)) hiprilvl = 3; 495 if ((si->dm.timing.v_display > 864) && (hiprilvl > 2) && (refresh >= 76.0)) hiprilvl = 2; 496 if ((si->dm.timing.v_display > 1024) && (hiprilvl > 2)) hiprilvl = 2; 497 498 /* calculate maximum high priority requests */ 499 temp = (vc * (tmclk / tpixclk)) + 0.5; 500 if (temp > (float)hiprilvl) temp = (float)hiprilvl; 501 if (temp < 0.0) temp = 0.0; 502 maxhipri = ((uint8) temp); 503 504 /* program the card */ 505 prioctl = ((hiprilvl & 0x07) | ((maxhipri & 0x07) << 4)); 506 VGAW_I(CRTCEXT, 6, prioctl); 507 508 /* log results */ 509 LOG(4,("CRTC: Vclks/char is %d, pixClk period %02.2fnS, memClk period %02.2fnS\n", 510 vc, tpixclk, tmclk)); 511 LOG(4,("CRTC: memory priority control register is set to $%02x\n", prioctl)); 512 513 return B_OK; 514 } 515 516 status_t gx00_crtc_cursor_init() 517 { 518 int i; 519 520 if (si->ps.card_type >= G100) 521 { 522 uint32 * fb; 523 /* cursor bitmap will be stored at the start of the framebuffer on >= G100 */ 524 const uint32 curadd = 0; 525 526 /* set cursor bitmap adress ... */ 527 DXIW(CURADDL,curadd >> 10); 528 DXIW(CURADDH,curadd >> 18); 529 /* ... and repeat that: G100 requires other programming order than later cards!?! */ 530 DXIW(CURADDL,curadd >> 10); 531 DXIW(CURADDH,curadd >> 18); 532 533 /*set cursor colour*/ 534 DXIW(CURCOL0RED,0XFF); 535 DXIW(CURCOL0GREEN,0xFF); 536 DXIW(CURCOL0BLUE,0xFF); 537 DXIW(CURCOL1RED,0); 538 DXIW(CURCOL1GREEN,0); 539 DXIW(CURCOL1BLUE,0); 540 DXIW(CURCOL2RED,0); 541 DXIW(CURCOL2GREEN,0); 542 DXIW(CURCOL2BLUE,0); 543 544 /*clear cursor*/ 545 fb = (uint32 *) si->framebuffer + curadd; 546 for (i=0;i<(1024/4);i++) 547 { 548 fb[i]=0; 549 } 550 } 551 else 552 /* <= G100 cards have serial cursor color registers, 553 * and dedicated cursor bitmap RAM (in TVP3026 DAC) 554 */ 555 { 556 /* select first colorRAM adress */ 557 DACW(TVP_CUROVRWTADD,0x00); 558 /* overscan/border color is black, order of colors set is R,G,B */ 559 DACW(TVP_CUROVRDATA,0xff); 560 DACW(TVP_CUROVRDATA,0xff); 561 DACW(TVP_CUROVRDATA,0xff); 562 /* set sursor color 0 */ 563 DACW(TVP_CUROVRDATA,0xff); 564 DACW(TVP_CUROVRDATA,0xff); 565 DACW(TVP_CUROVRDATA,0xff); 566 /* set sursor color 1 */ 567 DACW(TVP_CUROVRDATA,0x00); 568 DACW(TVP_CUROVRDATA,0x00); 569 DACW(TVP_CUROVRDATA,0x00); 570 /* set sursor color 2 */ 571 DACW(TVP_CUROVRDATA,0x00); 572 DACW(TVP_CUROVRDATA,0x00); 573 DACW(TVP_CUROVRDATA,0x00); 574 575 /* select first cursor pattern DAC-internal RAM adress, and 576 * make sure indirect cursor control register is selected as active register */ 577 DXIW(CURCTRL,(DXIR(CURCTRL) & 0x73)); 578 DACW(PALWTADD,0x00); 579 /* now clear it, auto-incrementing the adress */ 580 for(i=0;i<1024;i++) 581 { 582 DACW(TVP_CURRAMDATA,0x00); 583 } 584 } 585 586 /* activate hardware cursor */ 587 DXIW(CURCTRL,1); 588 589 return B_OK; 590 } 591 592 status_t gx00_crtc_cursor_show() 593 { 594 if ((si->ps.card_type < G100) && (si->dm.timing.h_total > 2048)) 595 { 596 /* MIL1/2 DAC needs to be told if h_total for the active mode gets above 2048 */ 597 DXIW(CURCTRL, 0x11); 598 } 599 else 600 { 601 DXIW(CURCTRL, 0x01); 602 } 603 604 return B_OK; 605 } 606 607 status_t gx00_crtc_cursor_hide() 608 { 609 DXIW(CURCTRL,0); 610 return B_OK; 611 } 612 613 /*set up cursor shape*/ 614 status_t gx00_crtc_cursor_define(uint8* andMask,uint8* xorMask) 615 { 616 int y; 617 618 if(si->ps.card_type >= G100) 619 { 620 uint8 * cursor; 621 622 /*get a pointer to the cursor*/ 623 cursor = (uint8*) si->framebuffer; 624 625 /*draw the cursor*/ 626 for(y=0;y<16;y++) 627 { 628 cursor[y*16+7]=~*andMask++; 629 cursor[y*16+15]=*xorMask++; 630 cursor[y*16+6]=~*andMask++; 631 cursor[y*16+14]=*xorMask++; 632 } 633 } 634 else 635 /* <= G100 cards have dedicated cursor bitmap RAM (in TVP3026 DAC) */ 636 { 637 uint8 curctrl; 638 639 /* disable the cursor to prevent distortions in screen output */ 640 curctrl = (DXIR(CURCTRL)); 641 DXIW(CURCTRL, (curctrl & 0xfc)); 642 /* select first cursor pattern DAC-internal RAM adress for plane 0 */ 643 DXIW(CURCTRL, (DXIR(CURCTRL) & ~0x0c)); 644 DACW(PALWTADD, 0x00); 645 /* now fill it, partly auto-incrementing the adress */ 646 for(y = 0; y < 16; y++) 647 { 648 DACW(PALWTADD, (y * 8)); 649 DACW(TVP_CURRAMDATA, ~*andMask++); 650 DACW(TVP_CURRAMDATA, ~*andMask++); 651 } 652 /* select first cursor pattern DAC-internal RAM adress for plane 1 */ 653 DXIW(CURCTRL, (DXIR(CURCTRL) | 0x08)); 654 DACW(PALWTADD, 0x00); 655 /* now fill it, partly auto-incrementing the adress */ 656 for(y = 0; y < 16; y++) 657 { 658 DACW(PALWTADD, y*8); 659 DACW(TVP_CURRAMDATA, *xorMask++); 660 DACW(TVP_CURRAMDATA, *xorMask++); 661 } 662 /* delay restoring the cursor to prevent distortions in screen output */ 663 snooze(5); 664 /* restore the cursor */ 665 DXIW(CURCTRL, curctrl); 666 } 667 668 return B_OK; 669 } 670 671 /*position the cursor*/ 672 status_t gx00_crtc_cursor_position(uint16 x ,uint16 y) 673 { 674 int i=64; 675 676 x+=i; 677 y+=i; 678 679 /* make sure we are not in retrace, because the register(s) might get copied 680 * during our reprogramming them (double buffering feature) */ 681 while (ACCR(STATUS) & 0x08) 682 { 683 snooze(4); 684 } 685 686 DACW(CURSPOSXL,x&0xFF); 687 DACW(CURSPOSXH,x>>8); 688 DACW(CURSPOSYL,y&0xFF); 689 DACW(CURSPOSYH,y>>8); 690 691 return B_OK; 692 } 693