1 /* CTRC functionality */ 2 /* Author: 3 Rudolf Cornelissen 4/2003-4/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: (BIOSmode) 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:(BIOSmode) 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 /* program 'fixed' mode if needed */ 290 if (si->ps.card_type != NM2070) 291 { 292 uint8 width; 293 294 temp = ISAGRPHR(PANELCTRL1); 295 /* we need to wait a bit or the card will mess-up it's register values.. */ 296 snooze(10); 297 298 switch (target.timing.h_display) 299 { 300 case 1280: 301 width = (3 << 5); 302 break; 303 case 1024: 304 width = (2 << 5); 305 break; 306 case 800: 307 width = (1 << 5); 308 break; 309 case 640: 310 default: //fixme: non-std modes should be in between above modes?!? 311 width = (0 << 5); 312 break; 313 } 314 315 switch (si->ps.card_type) 316 { 317 case NM2090: 318 case NM2093: 319 case NM2097: 320 case NM2160: 321 //fixme: checkout b6???? 322 ISAGRPHW(PANELCTRL1, ((temp & ~0x20) | (width & 0x20))); 323 break; 324 default: 325 /* NM2200 and later */ 326 ISAGRPHW(PANELCTRL1, ((temp & ~0x60) | (width & 0x60))); 327 break; 328 } 329 } 330 331 return B_OK; 332 } 333 334 status_t nm_crtc_depth(int mode) 335 { 336 uint8 vid_delay = 0; 337 338 LOG(4,("CRTC: setting colordepth to be displayed\n")); 339 340 /* set VCLK scaling */ 341 switch(mode) 342 { 343 case BPP8: 344 vid_delay = 0x01; 345 break; 346 case BPP15: 347 vid_delay = 0x02; 348 break; 349 case BPP16: 350 vid_delay = 0x03; 351 break; 352 case BPP24: 353 vid_delay = 0x04; 354 break; 355 default: 356 LOG(4,("CRTC: colordepth not supported, aborting!\n")); 357 return B_ERROR; 358 break; 359 } 360 361 switch (si->ps.card_type) 362 { 363 case NM2070: 364 vid_delay |= (ISAGRPHR(COLDEPTH) & 0xf0); 365 break; 366 default: 367 vid_delay |= (ISAGRPHR(COLDEPTH) & 0x70); 368 break; 369 } 370 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 371 snooze(10); 372 ISAGRPHW(COLDEPTH, vid_delay); 373 374 snooze(10); 375 LOG(4,("CRTC: colordepth register readback $%02x\n", (ISAGRPHR(COLDEPTH)))); 376 377 return B_OK; 378 } 379 380 status_t nm_crtc_dpms(bool display, bool h, bool v) 381 { 382 uint8 temp; 383 384 LOG(4,("CRTC: setting DPMS: ")); 385 386 /* start synchronous reset: required before turning screen off! */ 387 ISASEQW(RESET, 0x01); 388 389 /* turn screen off */ 390 temp = ISASEQR(CLKMODE); 391 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 392 snooze(10); 393 394 if (display) 395 { 396 ISASEQW(CLKMODE, (temp & ~0x20)); 397 398 /* end synchronous reset if display should be enabled */ 399 ISASEQW(RESET, 0x03); 400 401 LOG(4,("display on\n")); 402 } 403 else 404 { 405 ISASEQW(CLKMODE, (temp | 0x20)); 406 407 LOG(4,("display off\n")); 408 } 409 410 // LOG(4,("CRTC: setting DPMS (%d,%d,%d)\n", display,h,v)); 411 412 // VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4); 413 414 /* set some required fixed values for proper nm mode initialisation */ 415 // VGAW_I(CRTC,0x17,0xC3); 416 // VGAW_I(CRTC,0x14,0x00); 417 418 return B_OK; 419 } 420 421 status_t nm_crtc_dpms_fetch(bool * display, bool * h, bool * v) 422 { 423 *display = !(ISASEQR(CLKMODE) & 0x20); 424 425 // *display=!((VGAR_I(SEQ,1)&0x20)>>5); 426 // *h=!((VGAR_I(CRTCEXT,1)&0x10)>>4); 427 // *v=!((VGAR_I(CRTCEXT,1)&0x20)>>5); 428 429 *h = *v = true; 430 431 LOG(4,("CTRC: fetched DPMS state:")); 432 if (display) LOG(4,("display on\n")); 433 else LOG(4,("display off\n")); 434 435 return B_OK; 436 } 437 438 status_t nm_crtc_set_display_pitch() 439 { 440 uint32 offset; 441 442 LOG(4,("CRTC: setting card pitch (offset between lines)\n")); 443 444 /* figure out offset value hardware needs: same for all Neomagic cards */ 445 offset = si->fbc.bytes_per_row / 8; 446 447 LOG(2,("CRTC: offset register set to: $%04x\n", offset)); 448 449 /* program the card */ 450 ISACRTCW(PITCHL, (offset & 0xff)); 451 //fixme: test for max supported pitch if possible, 452 //not all bits below will be implemented. 453 //NM2160: confirmed b0 and b1 in register below to exist and work. 454 if (si->ps.card_type != NM2070) 455 ISAGRPHW(CRTC_PITCHE, ((offset & 0xff00) >> 8)); 456 457 return B_OK; 458 } 459 460 status_t nm_crtc_set_display_start(uint32 startadd,uint8 bpp) 461 { 462 uint8 val; 463 uint32 timeout = 0; 464 465 LOG(2,("CRTC: relative startadd: $%06x\n",startadd)); 466 LOG(2,("CRTC: frameRAM: $%08x\n",si->framebuffer)); 467 LOG(2,("CRTC: framebuffer: $%08x\n",si->fbc.frame_buffer)); 468 469 /* make sure we are in retrace, because otherwise distortions might occur 470 * during our reprogramming them (no double buffering) (verified on NM2160) */ 471 472 /* we might have no retraces during setmode! So: 473 * wait 25mS max. for retrace to occur (refresh > 40Hz) */ 474 //fixme? move this function to the kernel driver... is much 'faster'. 475 while ((!(ISARB(INSTAT1) & 0x08)) && (timeout < (25000/4))) 476 { 477 snooze(4); 478 timeout++; 479 } 480 481 /* the neomagic framebuffer startadress is given in 32bit words */ 482 startadd >>= 2; 483 484 /* set standard VGA registers */ 485 ISACRTCW(FBSTADDH, ((startadd & 0x00FF00) >> 8)); 486 ISACRTCW(FBSTADDL, (startadd & 0x0000FF)); 487 488 /* set NM extended register */ 489 //fixme: NM2380 _must_ have one more bit (has >4Mb RAM)!! 490 //this is testable via virtualscreen in 640x480x8 mode... 491 //(b4 is >256Kb adresswrap bit, so that's already occupied) 492 val = ISAGRPHR(FBSTADDE); 493 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 494 snooze(10); 495 if (si->ps.card_type < NM2200) 496 ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x07) | (val & 0xf8))); 497 else 498 ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x0f) | (val & 0xf0))); 499 500 return B_OK; 501 } 502 503 /* setup centering mode for current internal or simultaneous flatpanel mode */ 504 status_t nm_crtc_center(display_mode target) 505 { 506 /* note: 507 * NM2070 apparantly doesn't support horizontal centering this way... */ 508 509 uint8 vcent1, vcent2, vcent3, vcent4, vcent5; 510 uint8 hcent1, hcent2, hcent3, hcent4, hcent5; 511 uint8 ctrl2, ctrl3; 512 513 /* preset no centering */ 514 uint16 hoffset = 0; 515 uint16 voffset = 0; 516 vcent1 = vcent2 = vcent3 = vcent4 = vcent5 = 0x00; 517 hcent1 = hcent2 = hcent3 = hcent4 = hcent5 = 0x00; 518 ctrl2 = ctrl3 = 0x00; 519 520 /* calculate offsets for centering if prudent */ 521 if (target.timing.h_display < si->ps.panel_width) 522 { 523 hoffset = (si->ps.panel_width - target.timing.h_display); 524 /* adjust for register contraints: 525 * horizontal center granularity is 16 pixels */ 526 hoffset = ((hoffset >> 4) - 1); 527 /* turn on horizontal centering? */ 528 ctrl3 = 0x10; 529 } 530 531 if (target.timing.v_display < si->ps.panel_height) 532 { 533 voffset = (si->ps.panel_height - target.timing.v_display); 534 /* adjust for register contraints: 535 * vertical center granularity is 2 pixels */ 536 voffset = ((voffset >> 1) - 2); 537 /* turn on vertical centering? */ 538 ctrl2 = 0x01; 539 } 540 541 switch(target.timing.h_display) 542 { 543 case 640: 544 hcent1 = hoffset; 545 vcent3 = voffset; 546 break; 547 case 800: 548 hcent2 = hoffset; 549 switch(target.timing.v_display) 550 { 551 case 480: 552 //Linux fixme: check this out... 553 vcent3 = voffset; 554 break; 555 case 600: 556 vcent4 = voffset; 557 break; 558 } 559 break; 560 case 1024: 561 hcent5 = hoffset; 562 vcent5 = voffset; 563 break; 564 case 1280: 565 /* this mode equals the largest possible panel on the newest chip: 566 * so no centering needed here. */ 567 break; 568 default: 569 //fixme?: block non-standard modes? for now: not centered. 570 break; 571 } 572 573 /* now program the card's registers */ 574 ISAGRPHW(PANELVCENT1, vcent1); 575 ISAGRPHW(PANELVCENT2, vcent2); 576 ISAGRPHW(PANELVCENT3, vcent3); 577 if (si->ps.card_type > NM2070) 578 { 579 ISAGRPHW(PANELVCENT4, vcent4); 580 ISAGRPHW(PANELHCENT1, hcent1); 581 ISAGRPHW(PANELHCENT2, hcent2); 582 ISAGRPHW(PANELHCENT3, hcent3); 583 } 584 if (si->ps.card_type >= NM2160) 585 { 586 ISAGRPHW(PANELHCENT4, hcent4); 587 } 588 if (si->ps.card_type >= NM2200) 589 { 590 ISAGRPHW(PANELVCENT5, vcent5); 591 ISAGRPHW(PANELHCENT5, hcent5); 592 } 593 594 /* program panel control register 2: don't touch bit 3-5 */ 595 ctrl2 |= (ISAGRPHR(PANELCTRL2) & 0x38); 596 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 597 snooze(10); 598 ISAGRPHW(PANELCTRL2, ctrl2); 599 600 if (si->ps.card_type > NM2070) 601 { 602 /* program panel control register 3: don't touch bit 7-5 and bit 3-0 */ 603 ctrl3 |= (ISAGRPHR(PANELCTRL3) & 0xef); 604 /* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */ 605 snooze(10); 606 ISAGRPHW(PANELCTRL3, ctrl3); 607 } 608 609 return B_OK; 610 } 611 612 status_t nm_crtc_cursor_init() 613 { 614 int i; 615 uint32 * fb; 616 uint32 curadd, curreg; 617 618 /* the cursor is at the end of cardRAM */ 619 curadd = ((si->ps.memory_size * 1024) - si->ps.curmem_size); 620 621 /* set cursor bitmap adress on a 1kb boundary, and move the bits around 622 * so they get placed at the correct registerbits */ 623 curreg = (((curadd >> 10) & 0x000f) << 8); 624 curreg |= (((curadd >> 10) & 0x0ff0) >> 4); 625 /* NM2380 must have an extra bit for > 4Mb: assuming it to be on b12... */ 626 curreg |= ((curadd >> 10) & 0x1000); 627 628 if (si->ps.card_type < NM2200) 629 CR1W(CURADDRESS, curreg); 630 else 631 CR1W(22CURADDRESS, curreg); 632 633 /*set cursor colour*/ 634 if (si->ps.card_type < NM2200) 635 { 636 /* background is black */ 637 CR1W(CURBGCOLOR, 0x00000000); 638 /* foreground is white */ 639 CR1W(CURFGCOLOR, 0x00ffffff); 640 } 641 else 642 { 643 /* background is black */ 644 CR1W(22CURBGCOLOR, 0x00000000); 645 /* foreground is white */ 646 CR1W(22CURFGCOLOR, 0x00ffffff); 647 } 648 649 /* we must set a valid colordepth to get full RAM access on Neomagic cards: 650 * in old pre 8-bit color VGA modes some planemask is in effect apparantly, 651 * allowing access only to every 7th and 8th RAM byte across the entire RAM. */ 652 nm_crtc_depth(BPP8); 653 654 /* clear cursor: so we need full RAM access! */ 655 fb = ((uint32 *)(((uint32)si->framebuffer) + curadd)); 656 for (i = 0; i < (1024/4); i++) 657 { 658 fb[i] = 0; 659 } 660 661 /* activate hardware cursor */ 662 nm_crtc_cursor_show(); 663 664 return B_OK; 665 } 666 667 status_t nm_crtc_cursor_show() 668 { 669 if (si->ps.card_type < NM2200) 670 { 671 CR1W(CURCTRL, 0x00000001); 672 } 673 else 674 { 675 CR1W(22CURCTRL, 0x00000001); 676 } 677 return B_OK; 678 } 679 680 status_t nm_crtc_cursor_hide() 681 { 682 //linux fixme: using this kills PCI(?) access sometimes, so use ISA access as below... 683 /* 684 if (si->ps.card_type < NM2200) 685 { 686 CR1W(CURCTRL, 0x00000000); 687 } 688 else 689 { 690 CR1W(22CURCTRL, 0x00000000); 691 } 692 */ 693 /* disable cursor */ 694 ISAGRPHW(CURCTRL,0x00); 695 696 return B_OK; 697 } 698 699 /*set up cursor shape*/ 700 status_t nm_crtc_cursor_define(uint8* andMask,uint8* xorMask) 701 { 702 uint8 y; 703 uint8 * cursor; 704 705 /* get a pointer to the cursor: it's at the end of cardRAM */ 706 cursor = (uint8*) si->framebuffer; 707 cursor += ((si->ps.memory_size * 1024) - si->ps.curmem_size); 708 709 /*draw the cursor*/ 710 for(y=0;y<16;y++) 711 { 712 cursor[y*16+8]=~*andMask++; 713 cursor[y*16+0]=*xorMask++; 714 cursor[y*16+9]=~*andMask++; 715 cursor[y*16+1]=*xorMask++; 716 } 717 718 //test.. only valid for <NM2200!! 719 /* { 720 float pclk; 721 uint8 n,m,x = 1; 722 n = ISAGRPHR(PLLC_NL); 723 m = ISAGRPHR(PLLC_M); 724 LOG(4,("CRTC: PLLSEL $%02x\n", ISARB(MISCR))); 725 LOG(4,("CRTC: PLLN $%02x\n", n)); 726 LOG(4,("CRTC: PLLM $%02x\n", m)); 727 728 if (n & 0x80) x = 2; 729 n &= 0x7f; 730 pclk = ((si->ps.f_ref * (n + 1)) / ((m + 1) * x)); 731 LOG(2,("CRTC: Pixelclock is %fMHz\n", pclk)); 732 nm_general_output_select(); 733 } 734 */ 735 return B_OK; 736 } 737 738 /*position the cursor*/ 739 status_t nm_crtc_cursor_position(uint16 x ,uint16 y) 740 { 741 //NM2160 is ok without this, still verify the rest..: 742 /* make sure we are not in retrace, because the register(s) might get copied 743 * during our reprogramming them (double buffering feature) */ 744 /* fixme!? 745 while (ACCR(STATUS) & 0x08) 746 { 747 snooze(4); 748 } 749 */ 750 if (si->ps.card_type < NM2200) 751 { 752 CR1W(CURX, (uint32)x); 753 CR1W(CURY, (uint32)y); 754 } 755 else 756 { 757 CR1W(22CURX, (uint32)x); 758 CR1W(22CURY, (uint32)y); 759 } 760 761 return B_OK; 762 } 763