1 /* CTRC functionality */ 2 /* Author: 3 Rudolf Cornelissen 4/2003-1/2004 4 */ 5 6 #define MODULE_BIT 0x00040000 7 8 #include "nm_std.h" 9 10 /* Adjust passed parameters to a valid mode line */ 11 //fixme: the order of the sync edges should also be checked, 12 //just like the sync signal's min. pulse length... 13 status_t nm_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 &= 0xfff8; 21 *hs_s &= 0xfff8; 22 *hs_e &= 0xfff8; 23 *ht &= 0xfff8; 24 25 /* confine to required number of bits, taking logic into account */ 26 if (*hd_e > ((0xff - 2) << 3)) *hd_e = ((0xff - 2) << 3); 27 if (*hs_s > ((0xff - 1) << 3)) *hs_s = ((0xff - 1) << 3); 28 if (*hs_e > ( 0xff << 3)) *hs_e = ( 0xff << 3); 29 if (*ht > ((0xff + 5) << 3)) *ht = ((0xff + 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 if (*hd_e > si->ps.max_crtc_width) *hd_e = si->ps.max_crtc_width; 35 36 /* if hor. total does not leave room for a sensible sync pulse, increase it! */ 37 if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80); 38 39 /* make sure sync pulse is not during display */ 40 if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8); 41 if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8); 42 43 /* correct sync pulse if it is too long: 44 * there are only 5 bits available to save this in the card registers! */ 45 if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8); 46 47 /*vertical*/ 48 /* confine to required number of bits, taking logic into account */ 49 if (si->ps.card_type < NM2200) 50 { 51 if (*vd_e > (0x3ff - 2)) *vd_e = (0x3ff - 2); 52 if (*vs_s > (0x3ff - 1)) *vs_s = (0x3ff - 1); 53 if (*vs_e > 0x3ff ) *vs_e = 0x3ff ; 54 if (*vt > (0x3ff + 2)) *vt = (0x3ff + 2); 55 } 56 else 57 { 58 if (*vd_e > (0x7ff - 2)) *vd_e = (0x7ff - 2); 59 if (*vs_s > (0x7ff - 1)) *vs_s = (0x7ff - 1); 60 if (*vs_e > 0x7ff ) *vs_e = 0x7ff ; 61 if (*vt > (0x7ff + 2)) *vt = (0x7ff + 2); 62 } 63 64 /* confine to a reasonable height */ 65 if (*vd_e < 480) *vd_e = 480; 66 if (*vd_e > si->ps.max_crtc_height) *vd_e = si->ps.max_crtc_height; 67 68 /*if vertical total does not leave room for a sync pulse, increase it!*/ 69 if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3); 70 71 /* make sure sync pulse is not during display */ 72 if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1); 73 if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1); 74 75 /* correct sync pulse if it is too long: 76 * there are only 4 bits available to save this in the card registers! */ 77 if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f); 78 79 return B_OK; 80 } 81 82 /* set a mode line */ 83 status_t nm_crtc_set_timing(display_mode target, bool crt_only) 84 { 85 uint8 temp; 86 87 uint32 htotal; /*total horizontal total VCLKs*/ 88 uint32 hdisp_e; /*end of horizontal display (begins at 0)*/ 89 uint32 hsync_s; /*begin of horizontal sync pulse*/ 90 uint32 hsync_e; /*end of horizontal sync pulse*/ 91 uint32 hblnk_s; /*begin horizontal blanking*/ 92 uint32 hblnk_e; /*end horizontal blanking*/ 93 94 uint32 vtotal; /*total vertical total scanlines*/ 95 uint32 vdisp_e; /*end of vertical display*/ 96 uint32 vsync_s; /*begin of vertical sync pulse*/ 97 uint32 vsync_e; /*end of vertical sync pulse*/ 98 uint32 vblnk_s; /*begin vertical blanking*/ 99 uint32 vblnk_e; /*end vertical blanking*/ 100 101 uint32 linecomp; /*split screen and vdisp_e interrupt*/ 102 103 LOG(4,("CRTC: setting timing\n")); 104 105 /* modify visible sceensize if needed */ 106 /* (note that MOVE_CURSOR checks for a panning/scrolling mode itself, 107 * the display_mode as placed in si->dm may _not_ be modified!) */ 108 if (!(crt_only)) 109 { 110 if (target.timing.h_display > si->ps.panel_width) 111 { 112 target.timing.h_display = si->ps.panel_width; 113 LOG(4, ("CRTC: req. width > panel width: setting panning mode\n")); 114 } 115 if (target.timing.v_display > si->ps.panel_height) 116 { 117 target.timing.v_display = si->ps.panel_height; 118 LOG(4, ("CRTC: req. height > panel height: setting scrolling mode\n")); 119 } 120 } 121 122 /* Modify parameters as required by standard VGA */ 123 htotal = ((target.timing.h_total >> 3) - 5); 124 hdisp_e = ((target.timing.h_display >> 3) - 1); 125 hblnk_s = hdisp_e; 126 hblnk_e = (htotal + 0); /* this register differs from standard VGA! (says + 4) */ 127 hsync_s = (target.timing.h_sync_start >> 3); 128 hsync_e = (target.timing.h_sync_end >> 3); 129 130 vtotal = target.timing.v_total - 2; 131 vdisp_e = target.timing.v_display - 1; 132 vblnk_s = vdisp_e; 133 vblnk_e = (vtotal + 1); 134 vsync_s = target.timing.v_sync_start;//-1; 135 vsync_e = target.timing.v_sync_end;//-1; 136 137 /* prevent memory adress counter from being reset (linecomp may not occur) */ 138 linecomp = target.timing.v_display; 139 140 if (crt_only) 141 { 142 LOG(4,("CRTC: CRT only mode, setting full timing...\n")); 143 144 /* log the mode that will be set */ 145 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)); 146 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)); 147 148 /* actually program the card! */ 149 /* unlock CRTC registers at index 0-7 */ 150 temp = (ISACRTCR(VSYNCE) & 0x7f); 151 /* we need to wait a bit or the card will mess-up it's register values.. */ 152 snooze(10); 153 ISACRTCW(VSYNCE, temp); 154 /* horizontal standard VGA regs */ 155 ISACRTCW(HTOTAL, (htotal & 0xff)); 156 ISACRTCW(HDISPE, (hdisp_e & 0xff)); 157 ISACRTCW(HBLANKS, (hblnk_s & 0xff)); 158 /* also unlock vertical retrace registers in advance */ 159 ISACRTCW(HBLANKE, ((hblnk_e & 0x1f) | 0x80)); 160 ISACRTCW(HSYNCS, (hsync_s & 0xff)); 161 ISACRTCW(HSYNCE, ((hsync_e & 0x1f) | ((hblnk_e & 0x20) << 2))); 162 163 /* vertical standard VGA regs */ 164 ISACRTCW(VTOTAL, (vtotal & 0xff)); 165 ISACRTCW(OVERFLOW, 166 ( 167 ((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) | 168 ((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) | 169 ((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) | 170 ((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4)) 171 )); 172 ISACRTCW(PRROWSCN, 0x00); /* not used */ 173 ISACRTCW(MAXSCLIN, (((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6)))); 174 ISACRTCW(VSYNCS, (vsync_s & 0xff)); 175 temp = (ISACRTCR(VSYNCE) & 0xf0); 176 /* we need to wait a bit or the card will mess-up it's register values.. */ 177 snooze(10); 178 ISACRTCW(VSYNCE, (temp | (vsync_e & 0x0f))); 179 ISACRTCW(VDISPE, (vdisp_e & 0xff)); 180 ISACRTCW(VBLANKS, (vblnk_s & 0xff)); 181 ISACRTCW(VBLANKE, (vblnk_e & 0xff)); 182 //linux: 183 // regp->CRTC[23] = 0xC3; 184 ISACRTCW(LINECOMP, (linecomp & 0xff)); 185 186 /* horizontal - no extended regs available or needed on NeoMagic chips */ 187 188 /* vertical - extended regs */ 189 //fixme: checkout if b2 or 3 should be switched! (linux contains error here) 190 //fixme: linecomp should also have an extra bit... testable by setting linecomp 191 //to 100 for example and then try out writing an '1' to b2, b3(!) and the rest 192 //for screenorig reset visible on upper half of the screen or not at all.. 193 if (si->ps.card_type >= NM2200) 194 ISACRTCW(VEXT, 195 ( 196 ((vtotal & 0x400) >> (10 - 0)) | 197 ((vdisp_e & 0x400) >> (10 - 1)) | 198 ((vblnk_s & 0x400) >> (10 - 2)) | 199 ((vsync_s & 0x400) >> (10 - 3))/*| 200 ((linecomp&0x400)>>3)*/ 201 )); 202 203 /* setup HSYNC & VSYNC polarity */ 204 LOG(2,("CRTC: sync polarity: ")); 205 temp = ISARB(MISCR); 206 if (target.timing.flags & B_POSITIVE_HSYNC) 207 { 208 LOG(2,("H:pos ")); 209 temp &= ~0x40; 210 } 211 else 212 { 213 LOG(2,("H:neg ")); 214 temp |= 0x40; 215 } 216 if (target.timing.flags & B_POSITIVE_VSYNC) 217 { 218 LOG(2,("V:pos ")); 219 temp &= ~0x80; 220 } 221 else 222 { 223 LOG(2,("V:neg ")); 224 temp |= 0x80; 225 } 226 /* we need to wait a bit or the card will mess-up it's register values.. */ 227 snooze(10); 228 ISAWB(MISCW, temp); 229 230 LOG(2,(", MISC reg readback: $%02x\n", ISARB(MISCR))); 231 } 232 else 233 { 234 LOG(4,("CRTC: internal flatpanel active, setting display region only\n")); 235 236 /* actually program the card! */ 237 /* unlock CRTC registers at index 0-7 */ 238 temp = (ISACRTCR(VSYNCE) & 0x7f); 239 /* we need to wait a bit or the card will mess-up it's register values.. */ 240 snooze(10); 241 ISACRTCW(VSYNCE, temp); 242 /* horizontal standard VGA regs */ 243 ISACRTCW(HDISPE, (hdisp_e & 0xff)); 244 245 /* vertical standard VGA regs */ 246 temp = (ISACRTCR(OVERFLOW) & ~0x52); 247 /* we need to wait a bit or the card will mess-up it's register values.. */ 248 snooze(10); 249 ISACRTCW(OVERFLOW, 250 ( 251 temp | 252 ((vdisp_e & 0x100) >> (8 - 1)) | 253 ((vdisp_e & 0x200) >> (9 - 6)) | 254 ((linecomp & 0x100) >> (8 - 4)) 255 )); 256 257 ISACRTCW(PRROWSCN, 0x00); /* not used */ 258 259 temp = (ISACRTCR(MAXSCLIN) & ~0x40); 260 /* we need to wait a bit or the card will mess-up it's register values.. */ 261 snooze(10); 262 ISACRTCW(MAXSCLIN, (temp | ((linecomp & 0x200) >> (9 - 6)))); 263 264 ISACRTCW(VDISPE, (vdisp_e & 0xff)); 265 //linux: 266 // regp->CRTC[23] = 0xC3; 267 ISACRTCW(LINECOMP, (linecomp & 0xff)); 268 269 /* horizontal - no extended regs available or needed on NeoMagic chips */ 270 271 /* vertical - extended regs */ 272 //fixme: linecomp should have an extra bit... testable by setting linecomp 273 //to 100 for example and then try out writing an '1' to b2, b3(!) and the rest 274 //for screenorig reset visible on upper half of the screen or not at all.. 275 if (si->ps.card_type >= NM2200) 276 { 277 temp = (ISACRTCR(VEXT) & ~0x02); 278 /* we need to wait a bit or the card will mess-up it's register values.. */ 279 snooze(10); 280 ISACRTCW(VEXT, 281 ( 282 temp | 283 ((vdisp_e & 0x400) >> (10 - 1))/*| 284 ((linecomp&0x400)>>3)*/ 285 )); 286 } 287 } 288 289 return B_OK; 290 } 291 292 status_t nm_crtc_depth(int mode) 293 { 294 uint8 vid_delay = 0; 295 296 LOG(4,("CRTC: setting colordepth to be displayed\n")); 297 298 /* set VCLK scaling */ 299 switch(mode) 300 { 301 case BPP8: 302 vid_delay = 0x01; 303 break; 304 case BPP15: 305 vid_delay = 0x02; 306 break; 307 case BPP16: 308 vid_delay = 0x03; 309 break; 310 case BPP24: 311 vid_delay = 0x04; 312 break; 313 default: 314 LOG(4,("CRTC: colordepth not supported, aborting!\n")); 315 return B_ERROR; 316 break; 317 } 318 319 switch (si->ps.card_type) 320 { 321 case NM2070: 322 vid_delay |= (ISAGRPHR(COLDEPTH) & 0xf0); 323 break; 324 default: 325 vid_delay |= (ISAGRPHR(COLDEPTH) & 0x70); 326 break; 327 } 328 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 329 snooze(10); 330 ISAGRPHW(COLDEPTH, vid_delay); 331 332 snooze(10); 333 LOG(4,("CRTC: colordepth register readback $%02x\n", (ISAGRPHR(COLDEPTH)))); 334 335 return B_OK; 336 } 337 338 status_t nm_crtc_dpms(bool display, bool h, bool v) 339 { 340 uint8 temp; 341 342 LOG(4,("CRTC: setting DPMS: ")); 343 344 /* start synchronous reset: required before turning screen off! */ 345 ISASEQW(RESET, 0x01); 346 347 /* turn screen off */ 348 temp = ISASEQR(CLKMODE); 349 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 350 snooze(10); 351 352 if (display) 353 { 354 ISASEQW(CLKMODE, (temp & ~0x20)); 355 356 /* end synchronous reset if display should be enabled */ 357 ISASEQW(RESET, 0x03); 358 359 LOG(4,("display on\n")); 360 } 361 else 362 { 363 ISASEQW(CLKMODE, (temp | 0x20)); 364 365 LOG(4,("display off\n")); 366 } 367 368 // LOG(4,("CRTC: setting DPMS (%d,%d,%d)\n", display,h,v)); 369 370 // VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4); 371 372 /* set some required fixed values for proper nm mode initialisation */ 373 // VGAW_I(CRTC,0x17,0xC3); 374 // VGAW_I(CRTC,0x14,0x00); 375 376 return B_OK; 377 } 378 379 status_t nm_crtc_dpms_fetch(bool * display, bool * h, bool * v) 380 { 381 *display = !(ISASEQR(CLKMODE) & 0x20); 382 383 // *display=!((VGAR_I(SEQ,1)&0x20)>>5); 384 // *h=!((VGAR_I(CRTCEXT,1)&0x10)>>4); 385 // *v=!((VGAR_I(CRTCEXT,1)&0x20)>>5); 386 387 *h = *v = true; 388 389 LOG(4,("CTRC: fetched DPMS state:")); 390 if (display) LOG(4,("display on\n")); 391 else LOG(4,("display off\n")); 392 393 return B_OK; 394 } 395 396 status_t nm_crtc_set_display_pitch() 397 { 398 uint32 offset; 399 400 LOG(4,("CRTC: setting card pitch (offset between lines)\n")); 401 402 /* figure out offset value hardware needs: same for all Neomagic cards */ 403 offset = si->fbc.bytes_per_row / 8; 404 405 LOG(2,("CRTC: offset register set to: $%04x\n", offset)); 406 407 /* program the card */ 408 ISACRTCW(PITCHL, (offset & 0xff)); 409 //fixme: test for max supported pitch if possible, 410 //not all bits below will be implemented. 411 //NM2160: confirmed b0 and b1 in register below to exist and work. 412 ISAGRPHW(CRTC_PITCHE, ((offset & 0xff00) >> 8)); 413 414 return B_OK; 415 } 416 417 status_t nm_crtc_set_display_start(uint32 startadd,uint8 bpp) 418 { 419 uint8 val; 420 uint32 timeout = 0; 421 422 LOG(2,("CRTC: relative startadd: $%06x\n",startadd)); 423 LOG(2,("CRTC: frameRAM: $%08x\n",si->framebuffer)); 424 LOG(2,("CRTC: framebuffer: $%08x\n",si->fbc.frame_buffer)); 425 426 /* make sure we are in retrace, because otherwise distortions might occur 427 * during our reprogramming them (no double buffering) (verified on NM2160) */ 428 429 /* we might have no retraces during setmode! So: 430 * wait 25mS max. for retrace to occur (refresh > 40Hz) */ 431 //fixme? move this function to the kernel driver... is much 'faster'. 432 while ((!(ISARB(INSTAT1) & 0x08)) && (timeout < (25000/4))) 433 { 434 snooze(4); 435 timeout++; 436 } 437 438 /* the neomagic framebuffer startadress is given in 32bit words */ 439 startadd >>= 2; 440 441 /* set standard VGA registers */ 442 ISACRTCW(FBSTADDH, ((startadd & 0x00FF00) >> 8)); 443 ISACRTCW(FBSTADDL, (startadd & 0x0000FF)); 444 445 /* set NM extended register */ 446 //fixme: NM2380 _must_ have one more bit (has >4Mb RAM)!! 447 //this is testable via virtualscreen in 640x480x8 mode... 448 //(b4 is >256Kb adresswrap bit, so that's already occupied) 449 val = ISAGRPHR(FBSTADDE); 450 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 451 snooze(10); 452 if (si->ps.card_type < NM2200) 453 ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x07) | (val & 0xf8))); 454 else 455 ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x0f) | (val & 0xf0))); 456 457 return B_OK; 458 } 459 460 /* setup centering mode for current internal or simultaneous flatpanel mode */ 461 status_t nm_crtc_center(display_mode target) 462 { 463 uint8 vcent1, vcent2, vcent3, vcent4, vcent5; 464 uint8 hcent1, hcent2, hcent3, hcent4, hcent5; 465 uint8 ctrl2, ctrl3; 466 467 /* preset no centering */ 468 uint16 hoffset = 0; 469 uint16 voffset = 0; 470 vcent1 = vcent2 = vcent3 = vcent4 = vcent5 = 0x00; 471 hcent1 = hcent2 = hcent3 = hcent4 = hcent5 = 0x00; 472 ctrl2 = ctrl3 = 0x00; 473 474 /* calculate offsets for centering if prudent */ 475 if (target.timing.h_display < si->ps.panel_width) 476 { 477 hoffset = (si->ps.panel_width - target.timing.h_display); 478 /* adjust for register contraints: 479 * horizontal center granularity is 16 pixels */ 480 hoffset = ((hoffset >> 4) - 1); 481 //fixme: what does this do? 482 /* turn on horizontal centering? */ 483 ctrl3 = 0x10; 484 } 485 486 if (target.timing.v_display < si->ps.panel_height) 487 { 488 voffset = (si->ps.panel_height - target.timing.v_display); 489 /* adjust for register contraints: 490 * vertical center granularity is 2 pixels */ 491 voffset = ((voffset >> 1) - 2); 492 //fixme: what does this do? 493 /* turn on vertical centering? */ 494 ctrl2 = 0x01; 495 } 496 497 switch(target.timing.h_display) 498 { 499 case 640: 500 hcent1 = hoffset; 501 vcent3 = voffset; 502 break; 503 case 800: 504 hcent2 = hoffset; 505 switch(target.timing.v_display) 506 { 507 case 480: 508 //Linux fixme: check this out... 509 vcent3 = voffset; 510 break; 511 case 600: 512 vcent4 = voffset; 513 break; 514 } 515 break; 516 case 1024: 517 hcent5 = hoffset; 518 vcent5 = voffset; 519 break; 520 case 1280: 521 /* this mode equals the largest possible panel on the newest chip: 522 * so no centering needed here. */ 523 break; 524 default: 525 //fixme?: block non-standard modes? for now: not centered. 526 break; 527 } 528 529 /* now program the card's registers */ 530 ISAGRPHW(PANELVCENT1, vcent1); 531 ISAGRPHW(PANELVCENT2, vcent2); 532 ISAGRPHW(PANELVCENT3, vcent3); 533 if (si->ps.card_type > NM2070) 534 { 535 ISAGRPHW(PANELVCENT4, vcent4); 536 ISAGRPHW(PANELHCENT1, hcent1); 537 ISAGRPHW(PANELHCENT2, hcent2); 538 ISAGRPHW(PANELHCENT3, hcent3); 539 } 540 if (si->ps.card_type >= NM2160) 541 { 542 ISAGRPHW(PANELHCENT4, hcent4); 543 } 544 if (si->ps.card_type >= NM2200) 545 { 546 ISAGRPHW(PANELVCENT5, vcent5); 547 ISAGRPHW(PANELHCENT5, hcent5); 548 } 549 550 /* program panel control register 2: don't touch bit 3-5 */ 551 ctrl2 |= (ISAGRPHR(PANELCTRL2) & 0x38); 552 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 553 snooze(10); 554 ISAGRPHW(PANELCTRL2, ctrl2); 555 556 if (si->ps.card_type > NM2070) 557 { 558 /* program panel control register 3: don't touch bit 7-5 and bit 3-0 */ 559 ctrl3 |= (ISAGRPHR(PANELCTRL3) & 0xef); 560 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 561 snooze(10); 562 ISAGRPHW(PANELCTRL3, ctrl3); 563 } 564 565 return B_OK; 566 } 567 568 status_t nm_crtc_cursor_init() 569 { 570 int i; 571 uint32 * fb; 572 /* cursor bitmap will be stored at the start of the framebuffer */ 573 uint32 curadd = 0, curreg; 574 575 /* set cursor bitmap adress on a 1kb boundary, and move the bits around 576 * so they get placed at the correct registerbits */ 577 //fixme: NM2380 must have an extra bit for > 4Mb??? 578 curreg = (((curadd >> 10) & 0x000f) << 8); 579 curreg |= (((curadd >> 10) & 0x0ff0) >> 4); 580 581 if (si->ps.card_type < NM2200) 582 CR1W(CURADDRESS, curreg); 583 else 584 CR1W(22CURADDRESS, curreg); 585 586 /*set cursor colour*/ 587 if (si->ps.card_type < NM2200) 588 { 589 /* background is black */ 590 CR1W(CURBGCOLOR, 0x00000000); 591 /* foreground is white */ 592 CR1W(CURFGCOLOR, 0x00ffffff); 593 } 594 else 595 { 596 /* background is black */ 597 CR1W(22CURBGCOLOR, 0x00000000); 598 /* foreground is white */ 599 CR1W(22CURFGCOLOR, 0x00ffffff); 600 } 601 602 /*clear cursor*/ 603 fb = (uint32 *) si->framebuffer + curadd; 604 for (i=0;i<(1024/4);i++) 605 { 606 fb[i]=0; 607 } 608 609 /* activate hardware cursor */ 610 nm_crtc_cursor_show(); 611 612 return B_OK; 613 } 614 615 status_t nm_crtc_cursor_show() 616 { 617 if (si->ps.card_type < NM2200) 618 { 619 CR1W(CURCTRL, 0x00000001); 620 } 621 else 622 { 623 CR1W(22CURCTRL, 0x00000001); 624 } 625 return B_OK; 626 } 627 628 status_t nm_crtc_cursor_hide() 629 { 630 //linux fixme: using this kills PCI(?) access sometimes, so use ISA access as below... 631 /* 632 if (si->ps.card_type < NM2200) 633 { 634 CR1W(CURCTRL, 0x00000000); 635 } 636 else 637 { 638 CR1W(22CURCTRL, 0x00000000); 639 } 640 */ 641 /* disable cursor */ 642 ISAGRPHW(CURCTRL,0x00); 643 644 return B_OK; 645 } 646 647 /*set up cursor shape*/ 648 status_t nm_crtc_cursor_define(uint8* andMask,uint8* xorMask) 649 { 650 uint8 y; 651 uint8 * cursor; 652 653 /*get a pointer to the cursor*/ 654 cursor = (uint8*) si->framebuffer; 655 656 /*draw the cursor*/ 657 for(y=0;y<16;y++) 658 { 659 cursor[y*16+8]=~*andMask++; 660 cursor[y*16+0]=*xorMask++; 661 cursor[y*16+9]=~*andMask++; 662 cursor[y*16+1]=*xorMask++; 663 } 664 665 //test.. only valid for <NM2200!! 666 /* { 667 float pclk; 668 uint8 n,m,x = 1; 669 n = ISAGRPHR(PLLC_NL); 670 m = ISAGRPHR(PLLC_M); 671 LOG(4,("CRTC: PLLSEL $%02x\n", ISARB(MISCR))); 672 LOG(4,("CRTC: PLLN $%02x\n", n)); 673 LOG(4,("CRTC: PLLM $%02x\n", m)); 674 675 if (n & 0x80) x = 2; 676 n &= 0x7f; 677 pclk = ((si->ps.f_ref * (n + 1)) / ((m + 1) * x)); 678 LOG(2,("CRTC: Pixelclock is %fMHz\n", pclk)); 679 nm_general_output_select(); 680 } 681 */ 682 return B_OK; 683 } 684 685 /*position the cursor*/ 686 status_t nm_crtc_cursor_position(uint16 x ,uint16 y) 687 { 688 //NM2160 is ok without this, still verify the rest..: 689 /* make sure we are not in retrace, because the register(s) might get copied 690 * during our reprogramming them (double buffering feature) */ 691 /* fixme!? 692 while (ACCR(STATUS) & 0x08) 693 { 694 snooze(4); 695 } 696 */ 697 if (si->ps.card_type < NM2200) 698 { 699 CR1W(CURX, (uint32)x); 700 CR1W(CURY, (uint32)y); 701 } 702 else 703 { 704 CR1W(22CURX, (uint32)x); 705 CR1W(22CURY, (uint32)y); 706 } 707 708 return B_OK; 709 } 710