1 /* CTRC functionality */ 2 /* Author: 3 Rudolf Cornelissen 11/2002-9/2009 4 */ 5 6 #define MODULE_BIT 0x00040000 7 8 #include "nv_std.h" 9 10 /* 11 Enable/Disable interrupts. Just a wrapper around the 12 ioctl() to the kernel driver. 13 */ 14 status_t nv_crtc_interrupt_enable(bool flag) 15 { 16 status_t result = B_OK; 17 nv_set_vblank_int svi; 18 19 if (si->ps.int_assigned) 20 { 21 /* set the magic number so the driver knows we're for real */ 22 svi.magic = NV_PRIVATE_DATA_MAGIC; 23 svi.crtc = 0; 24 svi.do_it = flag; 25 /* contact driver and get a pointer to the registers and shared data */ 26 result = ioctl(fd, NV_RUN_INTERRUPTS, &svi, sizeof(svi)); 27 } 28 29 return result; 30 } 31 32 /* doing general fail-safe default setup here */ 33 //fixme: this is a _very_ basic setup, and it's preliminary... 34 status_t nv_crtc_update_fifo() 35 { 36 uint8 bytes_per_pixel = 1; 37 uint32 drain; 38 39 /* we are only using this on >>coldstarted<< cards which really need this */ 40 //fixme: re-enable or remove after general user confirmation of behaviour... 41 if (/*(si->settings.usebios) ||*/ (si->ps.card_type != NV05M64)) return B_OK; 42 43 /* enable access to primary head */ 44 set_crtc_owner(0); 45 46 /* set CRTC FIFO low watermark according to memory drain */ 47 switch(si->dm.space) 48 { 49 case B_CMAP8: 50 bytes_per_pixel = 1; 51 break; 52 case B_RGB15_LITTLE: 53 case B_RGB16_LITTLE: 54 bytes_per_pixel = 2; 55 break; 56 case B_RGB24_LITTLE: 57 bytes_per_pixel = 3; 58 break; 59 case B_RGB32_LITTLE: 60 bytes_per_pixel = 4; 61 break; 62 } 63 /* fixme: 64 * - I should probably include the refreshrate as well; 65 * - and the memory clocking speed, core clocking speed, RAM buswidth.. */ 66 drain = si->dm.timing.h_display * si->dm.timing.v_display * bytes_per_pixel; 67 68 /* Doesn't work for other than 32bit space (yet?) */ 69 if (si->dm.space != B_RGB32_LITTLE) 70 { 71 /* BIOS defaults */ 72 CRTCW(FIFO, 0x03); 73 CRTCW(FIFO_LWM, 0x20); 74 LOG(4,("CRTC: FIFO low-watermark set to $20, burst size 256 (BIOS defaults)\n")); 75 return B_OK; 76 } 77 78 if (drain > (((uint32)1280) * 1024 * 4)) 79 { 80 /* set CRTC FIFO burst size for 'smaller' bursts */ 81 CRTCW(FIFO, 0x01); 82 /* Instruct CRTC to fetch new data 'earlier' */ 83 CRTCW(FIFO_LWM, 0x40); 84 LOG(4,("CRTC: FIFO low-watermark set to $40, burst size 64\n")); 85 } 86 else 87 { 88 if (drain > (((uint32)1024) * 768 * 4)) 89 { 90 /* BIOS default */ 91 CRTCW(FIFO, 0x02); 92 /* Instruct CRTC to fetch new data 'earlier' */ 93 CRTCW(FIFO_LWM, 0x40); 94 LOG(4,("CRTC: FIFO low-watermark set to $40, burst size 128\n")); 95 } 96 else 97 { 98 /* BIOS defaults */ 99 CRTCW(FIFO, 0x03); 100 CRTCW(FIFO_LWM, 0x20); 101 LOG(4,("CRTC: FIFO low-watermark set to $20, burst size 256 (BIOS defaults)\n")); 102 } 103 } 104 105 return B_OK; 106 } 107 108 /* Adjust passed parameters to a valid mode line */ 109 status_t nv_crtc_validate_timing( 110 uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht, 111 uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt 112 ) 113 { 114 /* horizontal */ 115 /* make all parameters multiples of 8 */ 116 *hd_e &= 0xfff8; 117 *hs_s &= 0xfff8; 118 *hs_e &= 0xfff8; 119 *ht &= 0xfff8; 120 121 /* confine to required number of bits, taking logic into account */ 122 if (*hd_e > ((0x01ff - 2) << 3)) *hd_e = ((0x01ff - 2) << 3); 123 if (*hs_s > ((0x01ff - 1) << 3)) *hs_s = ((0x01ff - 1) << 3); 124 if (*hs_e > ( 0x01ff << 3)) *hs_e = ( 0x01ff << 3); 125 if (*ht > ((0x01ff + 5) << 3)) *ht = ((0x01ff + 5) << 3); 126 127 /* NOTE: keep horizontal timing at multiples of 8! */ 128 /* confine to a reasonable width */ 129 if (*hd_e < 640) *hd_e = 640; 130 if (si->ps.card_type > NV04) 131 { 132 if (*hd_e > 2048) *hd_e = 2048; 133 } 134 else 135 { 136 if (*hd_e > 1920) *hd_e = 1920; 137 } 138 139 /* if hor. total does not leave room for a sensible sync pulse, increase it! */ 140 if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80); 141 142 /* if hor. total does not adhere to max. blanking pulse width, decrease it! */ 143 if (*ht > (*hd_e + 0x3f8)) *ht = (*hd_e + 0x3f8); 144 145 /* make sure sync pulse is not during display */ 146 if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8); 147 if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8); 148 149 /* correct sync pulse if it is too long: 150 * there are only 5 bits available to save this in the card registers! */ 151 if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8); 152 153 /*vertical*/ 154 /* confine to required number of bits, taking logic into account */ 155 //fixme if needed: on GeForce cards there are 12 instead of 11 bits... 156 if (*vd_e > (0x7ff - 2)) *vd_e = (0x7ff - 2); 157 if (*vs_s > (0x7ff - 1)) *vs_s = (0x7ff - 1); 158 if (*vs_e > 0x7ff ) *vs_e = 0x7ff ; 159 if (*vt > (0x7ff + 2)) *vt = (0x7ff + 2); 160 161 /* confine to a reasonable height */ 162 if (*vd_e < 480) *vd_e = 480; 163 if (si->ps.card_type > NV04) 164 { 165 if (*vd_e > 1536) *vd_e = 1536; 166 } 167 else 168 { 169 if (*vd_e > 1440) *vd_e = 1440; 170 } 171 172 /*if vertical total does not leave room for a sync pulse, increase it!*/ 173 if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3); 174 175 /* if vert. total does not adhere to max. blanking pulse width, decrease it! */ 176 if (*vt > (*vd_e + 0xff)) *vt = (*vd_e + 0xff); 177 178 /* make sure sync pulse is not during display */ 179 if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1); 180 if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1); 181 182 /* correct sync pulse if it is too long: 183 * there are only 4 bits available to save this in the card registers! */ 184 if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f); 185 186 return B_OK; 187 } 188 189 /*set a mode line - inputs are in pixels*/ 190 status_t nv_crtc_set_timing(display_mode target) 191 { 192 uint8 temp; 193 194 uint32 htotal; /*total horizontal total VCLKs*/ 195 uint32 hdisp_e; /*end of horizontal display (begins at 0)*/ 196 uint32 hsync_s; /*begin of horizontal sync pulse*/ 197 uint32 hsync_e; /*end of horizontal sync pulse*/ 198 uint32 hblnk_s; /*begin horizontal blanking*/ 199 uint32 hblnk_e; /*end horizontal blanking*/ 200 201 uint32 vtotal; /*total vertical total scanlines*/ 202 uint32 vdisp_e; /*end of vertical display*/ 203 uint32 vsync_s; /*begin of vertical sync pulse*/ 204 uint32 vsync_e; /*end of vertical sync pulse*/ 205 uint32 vblnk_s; /*begin vertical blanking*/ 206 uint32 vblnk_e; /*end vertical blanking*/ 207 208 uint32 linecomp; /*split screen and vdisp_e interrupt*/ 209 210 LOG(4,("CRTC: setting timing\n")); 211 212 /* setup tuned internal modeline for flatpanel if connected and active */ 213 /* notes: 214 * - the CRTC modeline must end earlier than the panel modeline to keep correct 215 * sync going; 216 * - if the CRTC modeline ends too soon, pixelnoise will occur in 8 (or so) pixel 217 * wide horizontal stripes. This can be observed earliest on fullscreen overlay, 218 * and if it gets worse, also normal desktop output will suffer. The stripes 219 * are mainly visible at the left of the screen, over the entire screen height. */ 220 if (si->ps.monitors & CRTC1_TMDS) 221 { 222 LOG(2,("CRTC: DFP active: tuning modeline\n")); 223 224 /* horizontal timing */ 225 target.timing.h_sync_start = 226 ((uint16)((si->ps.p1_timing.h_sync_start / ((float)si->ps.p1_timing.h_display)) * 227 target.timing.h_display)) & 0xfff8; 228 229 target.timing.h_sync_end = 230 ((uint16)((si->ps.p1_timing.h_sync_end / ((float)si->ps.p1_timing.h_display)) * 231 target.timing.h_display)) & 0xfff8; 232 233 target.timing.h_total = 234 (((uint16)((si->ps.p1_timing.h_total / ((float)si->ps.p1_timing.h_display)) * 235 target.timing.h_display)) & 0xfff8) - 8; 236 237 /* in native mode the CRTC needs some extra time to keep synced correctly; 238 * OTOH the overlay unit distorts if we reserve too much time! */ 239 if (target.timing.h_display == si->ps.p1_timing.h_display) 240 { 241 /* NV11 timing has different constraints than later cards */ 242 if (si->ps.card_type == NV11) 243 target.timing.h_total -= 56; 244 else 245 /* confirmed NV34 with 1680x1050 panel */ 246 target.timing.h_total -= 32; 247 } 248 249 /* assure sync pulse is at the correct timing position */ 250 if (target.timing.h_sync_start == target.timing.h_display) 251 target.timing.h_sync_start += 8; 252 if (target.timing.h_sync_end == target.timing.h_total) 253 target.timing.h_sync_end -= 8; 254 /* assure we (still) have a sync pulse */ 255 if (target.timing.h_sync_start == target.timing.h_sync_end) { 256 if (target.timing.h_sync_end < (target.timing.h_total - 8)) { 257 target.timing.h_sync_end += 8; 258 } else { 259 if (target.timing.h_sync_start > (target.timing.h_display + 8)) { 260 target.timing.h_sync_start -= 8; 261 } else { 262 LOG(2,("CRTC: tuning modeline, not enough room for Hsync pulse, forcing it anyway..\n")); 263 target.timing.h_sync_start -= 8; 264 } 265 } 266 } 267 268 /* vertical timing */ 269 target.timing.v_sync_start = 270 ((uint16)((si->ps.p1_timing.v_sync_start / ((float)si->ps.p1_timing.v_display)) * 271 target.timing.v_display)); 272 273 target.timing.v_sync_end = 274 ((uint16)((si->ps.p1_timing.v_sync_end / ((float)si->ps.p1_timing.v_display)) * 275 target.timing.v_display)); 276 277 target.timing.v_total = 278 ((uint16)((si->ps.p1_timing.v_total / ((float)si->ps.p1_timing.v_display)) * 279 target.timing.v_display)) - 1; 280 281 /* assure sync pulse is at the correct timing position */ 282 if (target.timing.v_sync_start == target.timing.v_display) 283 target.timing.v_sync_start += 1; 284 if (target.timing.v_sync_end == target.timing.v_total) 285 target.timing.v_sync_end -= 1; 286 /* assure we (still) have a sync pulse */ 287 if (target.timing.v_sync_start == target.timing.v_sync_end) { 288 if (target.timing.v_sync_end < (target.timing.v_total - 1)) { 289 target.timing.v_sync_end += 1; 290 } else { 291 if (target.timing.v_sync_start > (target.timing.v_display + 1)) { 292 target.timing.v_sync_start -= 1; 293 } else { 294 LOG(2,("CRTC: tuning modeline, not enough room for Vsync pulse, forcing it anyway..\n")); 295 target.timing.v_sync_start -= 1; 296 } 297 } 298 } 299 300 /* disable GPU scaling testmode so automatic scaling will be done */ 301 DACW(FP_DEBUG1, 0); 302 } 303 304 /* Modify parameters as required by standard VGA */ 305 htotal = ((target.timing.h_total >> 3) - 5); 306 hdisp_e = ((target.timing.h_display >> 3) - 1); 307 hblnk_s = hdisp_e; 308 hblnk_e = (htotal + 4); 309 hsync_s = (target.timing.h_sync_start >> 3); 310 hsync_e = (target.timing.h_sync_end >> 3); 311 312 vtotal = target.timing.v_total - 2; 313 vdisp_e = target.timing.v_display - 1; 314 vblnk_s = vdisp_e; 315 vblnk_e = (vtotal + 1); 316 vsync_s = target.timing.v_sync_start; 317 vsync_e = target.timing.v_sync_end; 318 319 /* prevent memory adress counter from being reset (linecomp may not occur) */ 320 linecomp = target.timing.v_display; 321 322 /* enable access to primary head */ 323 set_crtc_owner(0); 324 325 /* Note for laptop and DVI flatpanels: 326 * CRTC timing has a seperate set of registers from flatpanel timing. 327 * The flatpanel timing registers have scaling registers that are used to match 328 * these two modelines. */ 329 { 330 LOG(4,("CRTC: Setting full timing...\n")); 331 332 /* log the mode that will be set */ 333 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)); 334 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)); 335 336 /* actually program the card! */ 337 /* unlock CRTC registers at index 0-7 */ 338 CRTCW(VSYNCE, (CRTCR(VSYNCE) & 0x7f)); 339 /* horizontal standard VGA regs */ 340 CRTCW(HTOTAL, (htotal & 0xff)); 341 CRTCW(HDISPE, (hdisp_e & 0xff)); 342 CRTCW(HBLANKS, (hblnk_s & 0xff)); 343 /* also unlock vertical retrace registers in advance */ 344 CRTCW(HBLANKE, ((hblnk_e & 0x1f) | 0x80)); 345 CRTCW(HSYNCS, (hsync_s & 0xff)); 346 CRTCW(HSYNCE, ((hsync_e & 0x1f) | ((hblnk_e & 0x20) << 2))); 347 348 /* vertical standard VGA regs */ 349 CRTCW(VTOTAL, (vtotal & 0xff)); 350 CRTCW(OVERFLOW, 351 ( 352 ((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) | 353 ((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) | 354 ((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) | 355 ((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4)) 356 )); 357 CRTCW(PRROWSCN, 0x00); /* not used */ 358 CRTCW(MAXSCLIN, (((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6)))); 359 CRTCW(VSYNCS, (vsync_s & 0xff)); 360 CRTCW(VSYNCE, ((CRTCR(VSYNCE) & 0xf0) | (vsync_e & 0x0f))); 361 CRTCW(VDISPE, (vdisp_e & 0xff)); 362 CRTCW(VBLANKS, (vblnk_s & 0xff)); 363 CRTCW(VBLANKE, (vblnk_e & 0xff)); 364 CRTCW(LINECOMP, (linecomp & 0xff)); 365 366 /* horizontal extended regs */ 367 //fixme: we reset bit4. is this correct?? 368 CRTCW(HEB, (CRTCR(HEB) & 0xe0) | 369 ( 370 ((htotal & 0x100) >> (8 - 0)) | 371 ((hdisp_e & 0x100) >> (8 - 1)) | 372 ((hblnk_s & 0x100) >> (8 - 2)) | 373 ((hsync_s & 0x100) >> (8 - 3)) 374 )); 375 376 /* (mostly) vertical extended regs */ 377 CRTCW(LSR, 378 ( 379 ((vtotal & 0x400) >> (10 - 0)) | 380 ((vdisp_e & 0x400) >> (10 - 1)) | 381 ((vsync_s & 0x400) >> (10 - 2)) | 382 ((vblnk_s & 0x400) >> (10 - 3)) | 383 ((hblnk_e & 0x040) >> (6 - 4)) 384 //fixme: we still miss one linecomp bit!?! is this it?? 385 //| ((linecomp & 0x400) >> 3) 386 )); 387 388 /* more vertical extended regs (on GeForce cards only) */ 389 if (si->ps.card_arch >= NV10A) 390 { 391 CRTCW(EXTRA, 392 ( 393 ((vtotal & 0x800) >> (11 - 0)) | 394 ((vdisp_e & 0x800) >> (11 - 2)) | 395 ((vsync_s & 0x800) >> (11 - 4)) | 396 ((vblnk_s & 0x800) >> (11 - 6)) 397 //fixme: do we miss another linecomp bit!?! 398 )); 399 } 400 401 /* setup 'large screen' mode */ 402 if (target.timing.h_display >= 1280) 403 CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0xfb)); 404 else 405 CRTCW(REPAINT1, (CRTCR(REPAINT1) | 0x04)); 406 407 /* setup HSYNC & VSYNC polarity */ 408 LOG(2,("CRTC: sync polarity: ")); 409 temp = NV_REG8(NV8_MISCR); 410 if (target.timing.flags & B_POSITIVE_HSYNC) 411 { 412 LOG(2,("H:pos ")); 413 temp &= ~0x40; 414 } 415 else 416 { 417 LOG(2,("H:neg ")); 418 temp |= 0x40; 419 } 420 if (target.timing.flags & B_POSITIVE_VSYNC) 421 { 422 LOG(2,("V:pos ")); 423 temp &= ~0x80; 424 } 425 else 426 { 427 LOG(2,("V:neg ")); 428 temp |= 0x80; 429 } 430 NV_REG8(NV8_MISCW) = temp; 431 432 LOG(2,(", MISC reg readback: $%02x\n", NV_REG8(NV8_MISCR))); 433 } 434 435 /* always disable interlaced operation */ 436 /* (interlace is supported on upto and including NV10, NV15, and NV30 and up) */ 437 CRTCW(INTERLACE, 0xff); 438 439 /* disable CRTC slaved mode unless a panel is in use */ 440 // fixme: this kills TVout when it was in use... 441 if (!(si->ps.monitors & CRTC1_TMDS)) CRTCW(PIXEL, (CRTCR(PIXEL) & 0x7f)); 442 443 /* setup flatpanel if connected and active */ 444 if (si->ps.monitors & CRTC1_TMDS) 445 { 446 uint32 iscale_x, iscale_y; 447 448 /* calculate inverse scaling factors used by hardware in 20.12 format */ 449 iscale_x = (((1 << 12) * target.timing.h_display) / si->ps.p1_timing.h_display); 450 iscale_y = (((1 << 12) * target.timing.v_display) / si->ps.p1_timing.v_display); 451 452 /* unblock flatpanel timing programming (or something like that..) */ 453 CRTCW(FP_HTIMING, 0); 454 CRTCW(FP_VTIMING, 0); 455 LOG(2,("CRTC: FP_HTIMING reg readback: $%02x\n", CRTCR(FP_HTIMING))); 456 LOG(2,("CRTC: FP_VTIMING reg readback: $%02x\n", CRTCR(FP_VTIMING))); 457 458 /* enable full width visibility on flatpanel */ 459 DACW(FP_HVALID_S, 0); 460 DACW(FP_HVALID_E, (si->ps.p1_timing.h_display - 1)); 461 /* enable full height visibility on flatpanel */ 462 DACW(FP_VVALID_S, 0); 463 DACW(FP_VVALID_E, (si->ps.p1_timing.v_display - 1)); 464 465 /* nVidia cards support upscaling except on ??? */ 466 /* NV11 cards can upscale after all! */ 467 if (0)//si->ps.card_type == NV11) 468 { 469 /* disable last fetched line limiting */ 470 DACW(FP_DEBUG2, 0x00000000); 471 /* inform panel to scale if needed */ 472 if ((iscale_x != (1 << 12)) || (iscale_y != (1 << 12))) 473 { 474 LOG(2,("CRTC: DFP needs to do scaling\n")); 475 DACW(FP_TG_CTRL, (DACR(FP_TG_CTRL) | 0x00000100)); 476 } 477 else 478 { 479 LOG(2,("CRTC: no scaling for DFP needed\n")); 480 DACW(FP_TG_CTRL, (DACR(FP_TG_CTRL) & 0xfffffeff)); 481 } 482 } 483 else 484 { 485 float dm_aspect; 486 487 LOG(2,("CRTC: GPU scales for DFP if needed\n")); 488 489 /* calculate display mode aspect */ 490 dm_aspect = (target.timing.h_display / ((float)target.timing.v_display)); 491 492 /* limit last fetched line if vertical scaling is done */ 493 if (iscale_y != (1 << 12)) 494 DACW(FP_DEBUG2, ((1 << 28) | ((target.timing.v_display - 1) << 16))); 495 else 496 DACW(FP_DEBUG2, 0x00000000); 497 498 /* inform panel not to scale */ 499 DACW(FP_TG_CTRL, (DACR(FP_TG_CTRL) & 0xfffffeff)); 500 501 /* GPU scaling is automatically setup by hardware, so only modify this 502 * scalingfactor for non 4:3 (1.33) aspect panels; 503 * let's consider 1280x1024 1:33 aspect (it's 1.25 aspect actually!) */ 504 505 /* correct for widescreen panels relative to mode... 506 * (so if panel is more widescreen than mode being set) */ 507 /* BTW: known widescreen panels: 508 * 1280 x 800 (1.60), 509 * 1440 x 900 (1.60), 510 * 1680 x 1050 (1.60), 511 * 1920 x 1200 (1.60). */ 512 /* known 4:3 aspect non-standard resolution panels: 513 * 1400 x 1050 (1.33). */ 514 /* NOTE: 515 * allow 0.10 difference so 1280x1024 panels will be used fullscreen! */ 516 if ((iscale_x != (1 << 12)) && (si->ps.crtc1_screen.aspect > (dm_aspect + 0.10))) 517 { 518 uint16 diff; 519 520 LOG(2,("CRTC: (relative) widescreen panel: tuning horizontal scaling\n")); 521 522 /* X-scaling should be the same as Y-scaling */ 523 iscale_x = iscale_y; 524 /* enable testmode (b12) and program modified X-scaling factor */ 525 DACW(FP_DEBUG1, (((iscale_x >> 1) & 0x00000fff) | (1 << 12))); 526 /* center/cut-off left and right side of screen */ 527 diff = ((si->ps.p1_timing.h_display - 528 ((target.timing.h_display * (1 << 12)) / iscale_x)) 529 / 2); 530 DACW(FP_HVALID_S, diff); 531 DACW(FP_HVALID_E, ((si->ps.p1_timing.h_display - diff) - 1)); 532 } 533 /* correct for portrait panels... */ 534 /* NOTE: 535 * allow 0.10 difference so 1280x1024 panels will be used fullscreen! */ 536 if ((iscale_y != (1 << 12)) && (si->ps.crtc1_screen.aspect < (dm_aspect - 0.10))) 537 { 538 LOG(2,("CRTC: (relative) portrait panel: should tune vertical scaling\n")); 539 /* fixme: implement if this kind of portrait panels exist on nVidia... */ 540 } 541 } 542 543 /* do some logging.. */ 544 LOG(2,("CRTC: FP_HVALID_S reg readback: $%08x\n", DACR(FP_HVALID_S))); 545 LOG(2,("CRTC: FP_HVALID_E reg readback: $%08x\n", DACR(FP_HVALID_E))); 546 LOG(2,("CRTC: FP_VVALID_S reg readback: $%08x\n", DACR(FP_VVALID_S))); 547 LOG(2,("CRTC: FP_VVALID_E reg readback: $%08x\n", DACR(FP_VVALID_E))); 548 LOG(2,("CRTC: FP_DEBUG0 reg readback: $%08x\n", DACR(FP_DEBUG0))); 549 LOG(2,("CRTC: FP_DEBUG1 reg readback: $%08x\n", DACR(FP_DEBUG1))); 550 LOG(2,("CRTC: FP_DEBUG2 reg readback: $%08x\n", DACR(FP_DEBUG2))); 551 LOG(2,("CRTC: FP_DEBUG3 reg readback: $%08x\n", DACR(FP_DEBUG3))); 552 LOG(2,("CRTC: FP_TG_CTRL reg readback: $%08x\n", DACR(FP_TG_CTRL))); 553 } 554 555 return B_OK; 556 } 557 558 status_t nv_crtc_depth(int mode) 559 { 560 uint8 viddelay = 0; 561 uint32 genctrl = 0; 562 563 /* set VCLK scaling */ 564 switch(mode) 565 { 566 case BPP8: 567 viddelay = 0x01; 568 /* genctrl b4 & b5 reset: 'direct mode' */ 569 genctrl = 0x00101100; 570 break; 571 case BPP15: 572 viddelay = 0x02; 573 /* genctrl b4 & b5 set: 'indirect mode' (via colorpalette) */ 574 genctrl = 0x00100130; 575 break; 576 case BPP16: 577 viddelay = 0x02; 578 /* genctrl b4 & b5 set: 'indirect mode' (via colorpalette) */ 579 genctrl = 0x00101130; 580 break; 581 case BPP24: 582 viddelay = 0x03; 583 /* genctrl b4 & b5 set: 'indirect mode' (via colorpalette) */ 584 genctrl = 0x00100130; 585 break; 586 case BPP32: 587 viddelay = 0x03; 588 /* genctrl b4 & b5 set: 'indirect mode' (via colorpalette) */ 589 genctrl = 0x00101130; 590 break; 591 } 592 /* enable access to primary head */ 593 set_crtc_owner(0); 594 595 CRTCW(PIXEL, ((CRTCR(PIXEL) & 0xfc) | viddelay)); 596 DACW(GENCTRL, genctrl); 597 598 return B_OK; 599 } 600 601 status_t nv_crtc_dpms(bool display, bool h, bool v, bool do_panel) 602 { 603 uint8 temp; 604 char msg[100]; 605 606 strlcpy(msg, "CRTC: setting DPMS: ", sizeof(msg)); 607 608 /* enable access to primary head */ 609 set_crtc_owner(0); 610 611 /* start synchronous reset: required before turning screen off! */ 612 SEQW(RESET, 0x01); 613 614 temp = SEQR(CLKMODE); 615 if (display) 616 { 617 /* turn screen on */ 618 SEQW(CLKMODE, (temp & ~0x20)); 619 620 /* end synchronous reset because display should be enabled */ 621 SEQW(RESET, 0x03); 622 623 if (do_panel && (si->ps.monitors & CRTC1_TMDS)) 624 { 625 if (!si->ps.laptop) 626 { 627 /* restore original panelsync and panel-enable */ 628 uint32 panelsync = 0x00000000; 629 if(si->ps.p1_timing.flags & B_POSITIVE_VSYNC) panelsync |= 0x00000001; 630 if(si->ps.p1_timing.flags & B_POSITIVE_HSYNC) panelsync |= 0x00000010; 631 /* display enable polarity (not an official flag) */ 632 if(si->ps.p1_timing.flags & B_BLANK_PEDESTAL) panelsync |= 0x10000000; 633 DACW(FP_TG_CTRL, ((DACR(FP_TG_CTRL) & 0xcfffffcc) | panelsync)); 634 635 //fixme?: looks like we don't need this after all: 636 /* powerup both LVDS (laptop panellink) and TMDS (DVI panellink) 637 * internal transmitters... */ 638 /* note: 639 * the powerbits in this register are hardwired to the DVI connectors, 640 * instead of to the DACs! (confirmed NV34) */ 641 //fixme... 642 //DACW(FP_DEBUG0, (DACR(FP_DEBUG0) & 0xcfffffff)); 643 /* ... and powerup external TMDS transmitter if it exists */ 644 /* (confirmed OK on NV28 and NV34) */ 645 //CRTCW(0x59, (CRTCR(0x59) | 0x01)); 646 647 strlcat(msg, "(panel-)", sizeof(msg)); 648 } 649 else 650 { 651 //fixme? linux only does this on dualhead cards... 652 //fixme: see if LVDS head can be determined with two panels there... 653 if (!(si->ps.monitors & CRTC2_TMDS) && (si->ps.card_type != NV11)) 654 { 655 /* b2 = 0 = enable laptop panel backlight */ 656 /* note: this seems to be a write-only register. */ 657 NV_REG32(NV32_LVDS_PWR) = 0x00000003; 658 659 strlcat(msg, "(panel-)", sizeof(msg)); 660 } 661 } 662 } 663 664 strlcat(msg, "display on, ", sizeof(msg)); 665 } 666 else 667 { 668 /* turn screen off */ 669 SEQW(CLKMODE, (temp | 0x20)); 670 671 if (do_panel && (si->ps.monitors & CRTC1_TMDS)) 672 { 673 if (!si->ps.laptop) 674 { 675 /* shutoff panelsync and disable panel */ 676 DACW(FP_TG_CTRL, ((DACR(FP_TG_CTRL) & 0xcfffffcc) | 0x20000022)); 677 678 //fixme?: looks like we don't need this after all: 679 /* powerdown both LVDS (laptop panellink) and TMDS (DVI panellink) 680 * internal transmitters... */ 681 /* note: 682 * the powerbits in this register are hardwired to the DVI connectors, 683 * instead of to the DACs! (confirmed NV34) */ 684 //fixme... 685 //DACW(FP_DEBUG0, (DACR(FP_DEBUG0) | 0x30000000)); 686 /* ... and powerdown external TMDS transmitter if it exists */ 687 /* (confirmed OK on NV28 and NV34) */ 688 //CRTCW(0x59, (CRTCR(0x59) & 0xfe)); 689 690 strlcat(msg, "(panel-)", sizeof(msg)); 691 } 692 else 693 { 694 //fixme? linux only does this on dualhead cards... 695 //fixme: see if LVDS head can be determined with two panels there... 696 if (!(si->ps.monitors & CRTC2_TMDS) && (si->ps.card_type != NV11)) 697 { 698 /* b2 = 1 = disable laptop panel backlight */ 699 /* note: this seems to be a write-only register. */ 700 NV_REG32(NV32_LVDS_PWR) = 0x00000007; 701 702 strlcat(msg, "(panel-)", sizeof(msg)); 703 } 704 } 705 } 706 707 strlcat(msg, "display off, ", sizeof(msg)); 708 } 709 710 if (h) 711 { 712 CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0x7f)); 713 strlcat(msg, "hsync enabled, ", sizeof(msg)); 714 } 715 else 716 { 717 CRTCW(REPAINT1, (CRTCR(REPAINT1) | 0x80)); 718 strlcat(msg, "hsync disabled, ", sizeof(msg)); 719 } 720 if (v) 721 { 722 CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0xbf)); 723 strlcat(msg, "vsync enabled\n", sizeof(msg)); 724 } 725 else 726 { 727 CRTCW(REPAINT1, (CRTCR(REPAINT1) | 0x40)); 728 strlcat(msg, "vsync disabled\n", sizeof(msg)); 729 } 730 731 LOG(4, (msg)); 732 733 return B_OK; 734 } 735 736 status_t nv_crtc_set_display_pitch() 737 { 738 uint32 offset; 739 740 LOG(4,("CRTC: setting card pitch (offset between lines)\n")); 741 742 /* figure out offset value hardware needs */ 743 offset = si->fbc.bytes_per_row / 8; 744 745 LOG(2,("CRTC: offset register set to: $%04x\n", offset)); 746 747 /* enable access to primary head */ 748 set_crtc_owner(0); 749 750 /* program the card */ 751 CRTCW(PITCHL, (offset & 0x00ff)); 752 CRTCW(REPAINT0, ((CRTCR(REPAINT0) & 0x1f) | ((offset & 0x0700) >> 3))); 753 754 return B_OK; 755 } 756 757 status_t nv_crtc_set_display_start(uint32 startadd,uint8 bpp) 758 { 759 uint8 temp; 760 uint32 timeout = 0; 761 762 LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp)); 763 764 LOG(2,("CRTC: startadd: $%08x\n", startadd)); 765 LOG(2,("CRTC: frameRAM: $%08x\n", si->framebuffer)); 766 LOG(2,("CRTC: framebuffer: $%08x\n", si->fbc.frame_buffer)); 767 768 /* we might have no retraces during setmode! */ 769 /* wait 25mS max. for retrace to occur (refresh > 40Hz) */ 770 while (((NV_REG32(NV32_RASTER) & 0x000007ff) < si->dm.timing.v_display) && 771 (timeout < (25000/10))) 772 { 773 /* don't snooze much longer or retrace might get missed! */ 774 snooze(10); 775 timeout++; 776 } 777 778 /* enable access to primary head */ 779 set_crtc_owner(0); 780 781 if (si->ps.card_arch == NV04A) 782 { 783 /* upto 32Mb RAM adressing: must be used this way on pre-NV10! */ 784 785 /* set standard registers */ 786 /* (NVidia: startadress in 32bit words (b2 - b17) */ 787 CRTCW(FBSTADDL, ((startadd & 0x000003fc) >> 2)); 788 CRTCW(FBSTADDH, ((startadd & 0x0003fc00) >> 10)); 789 790 /* set extended registers */ 791 /* NV4 extended bits: (b18-22) */ 792 temp = (CRTCR(REPAINT0) & 0xe0); 793 CRTCW(REPAINT0, (temp | ((startadd & 0x007c0000) >> 18))); 794 /* NV4 extended bits: (b23-24) */ 795 temp = (CRTCR(HEB) & 0x9f); 796 CRTCW(HEB, (temp | ((startadd & 0x01800000) >> 18))); 797 } 798 else 799 { 800 /* upto 4Gb RAM adressing: must be used on NV10 and later! */ 801 /* NOTE: 802 * While this register also exists on pre-NV10 cards, it will 803 * wrap-around at 16Mb boundaries!! */ 804 805 /* 30bit adress in 32bit words */ 806 NV_REG32(NV32_NV10FBSTADD32) = (startadd & 0xfffffffc); 807 } 808 809 /* set NV4/NV10 byte adress: (b0 - 1) */ 810 ATBW(HORPIXPAN, ((startadd & 0x00000003) << 1)); 811 812 return B_OK; 813 } 814 815 status_t nv_crtc_cursor_init() 816 { 817 int i; 818 vuint32 * fb; 819 /* cursor bitmap will be stored at the start of the framebuffer */ 820 const uint32 curadd = 0; 821 822 /* enable access to primary head */ 823 set_crtc_owner(0); 824 825 /* set cursor bitmap adress ... */ 826 if ((si->ps.card_arch == NV04A) || (si->ps.laptop)) 827 { 828 /* must be used this way on pre-NV10 and on all 'Go' cards! */ 829 830 /* cursorbitmap must start on 2Kbyte boundary: */ 831 /* set adress bit11-16, and set 'no doublescan' (registerbit 1 = 0) */ 832 CRTCW(CURCTL0, ((curadd & 0x0001f800) >> 9)); 833 /* set adress bit17-23, and set graphics mode cursor(?) (registerbit 7 = 1) */ 834 CRTCW(CURCTL1, (((curadd & 0x00fe0000) >> 17) | 0x80)); 835 /* set adress bit24-31 */ 836 CRTCW(CURCTL2, ((curadd & 0xff000000) >> 24)); 837 } 838 else 839 { 840 /* upto 4Gb RAM adressing: 841 * can be used on NV10 and later (except for 'Go' cards)! */ 842 /* NOTE: 843 * This register does not exist on pre-NV10 and 'Go' cards. */ 844 845 /* cursorbitmap must still start on 2Kbyte boundary: */ 846 NV_REG32(NV32_NV10CURADD32) = (curadd & 0xfffff800); 847 } 848 849 /* set cursor colour: not needed because of direct nature of cursor bitmap. */ 850 851 /*clear cursor*/ 852 fb = (vuint32 *) si->framebuffer + curadd; 853 for (i=0;i<(2048/4);i++) 854 { 855 fb[i]=0; 856 } 857 858 /* select 32x32 pixel, 16bit color cursorbitmap, no doublescan */ 859 NV_REG32(NV32_CURCONF) = 0x02000100; 860 861 /* activate hardware-sync between cursor updates and vertical retrace where 862 * available */ 863 if (si->ps.card_arch >= NV10A) 864 DACW(NV10_CURSYNC, (DACR(NV10_CURSYNC) | 0x02000000)); 865 866 /* activate hardware cursor */ 867 nv_crtc_cursor_show(); 868 869 return B_OK; 870 } 871 872 status_t nv_crtc_cursor_show() 873 { 874 LOG(4,("CRTC: enabling cursor\n")); 875 876 /* enable access to CRTC1 on dualhead cards */ 877 set_crtc_owner(0); 878 879 /* b0 = 1 enables cursor */ 880 CRTCW(CURCTL0, (CRTCR(CURCTL0) | 0x01)); 881 882 /* workaround for hardware bug confirmed existing on NV43: 883 * Cursor visibility is not updated without a position update if its hardware 884 * retrace sync is enabled. */ 885 if (si->ps.card_arch == NV40A) DACW(CURPOS, (DACR(CURPOS))); 886 887 return B_OK; 888 } 889 890 status_t nv_crtc_cursor_hide() 891 { 892 LOG(4,("CRTC: disabling cursor\n")); 893 894 /* enable access to primary head */ 895 set_crtc_owner(0); 896 897 /* b0 = 0 disables cursor */ 898 CRTCW(CURCTL0, (CRTCR(CURCTL0) & 0xfe)); 899 900 /* workaround for hardware bug confirmed existing on NV43: 901 * Cursor visibility is not updated without a position update if its hardware 902 * retrace sync is enabled. */ 903 if (si->ps.card_arch == NV40A) DACW(CURPOS, (DACR(CURPOS))); 904 905 return B_OK; 906 } 907 908 /*set up cursor shape*/ 909 status_t nv_crtc_cursor_define(uint8* andMask,uint8* xorMask) 910 { 911 int x, y; 912 uint8 b; 913 vuint16 *cursor; 914 uint16 pixel; 915 916 /* get a pointer to the cursor */ 917 cursor = (vuint16*) si->framebuffer; 918 919 /* draw the cursor */ 920 /* (Nvidia cards have a RGB15 direct color cursor bitmap, bit #16 is transparancy) */ 921 for (y = 0; y < 16; y++) 922 { 923 b = 0x80; 924 for (x = 0; x < 8; x++) 925 { 926 /* preset transparant */ 927 pixel = 0x0000; 928 /* set white if requested */ 929 if ((!(*andMask & b)) && (!(*xorMask & b))) pixel = 0xffff; 930 /* set black if requested */ 931 if ((!(*andMask & b)) && (*xorMask & b)) pixel = 0x8000; 932 /* set invert if requested */ 933 if ( (*andMask & b) && (*xorMask & b)) pixel = 0x7fff; 934 /* place the pixel in the bitmap */ 935 cursor[x + (y * 32)] = pixel; 936 b >>= 1; 937 } 938 xorMask++; 939 andMask++; 940 b = 0x80; 941 for (; x < 16; x++) 942 { 943 /* preset transparant */ 944 pixel = 0x0000; 945 /* set white if requested */ 946 if ((!(*andMask & b)) && (!(*xorMask & b))) pixel = 0xffff; 947 /* set black if requested */ 948 if ((!(*andMask & b)) && (*xorMask & b)) pixel = 0x8000; 949 /* set invert if requested */ 950 if ( (*andMask & b) && (*xorMask & b)) pixel = 0x7fff; 951 /* place the pixel in the bitmap */ 952 cursor[x + (y * 32)] = pixel; 953 b >>= 1; 954 } 955 xorMask++; 956 andMask++; 957 } 958 959 return B_OK; 960 } 961 962 /* position the cursor */ 963 status_t nv_crtc_cursor_position(uint16 x, uint16 y) 964 { 965 /* the cursor position is updated during retrace by card hardware except for 966 * pre-GeForce cards */ 967 if (si->ps.card_arch < NV10A) 968 { 969 uint16 yhigh; 970 uint32 timeout = 0; 971 972 /* make sure we are beyond the first line of the cursorbitmap being drawn during 973 * updating the position to prevent distortions: no double buffering feature */ 974 /* Note: 975 * we need to return as quick as possible or some apps will exhibit lagging.. */ 976 977 /* read the old cursor Y position */ 978 yhigh = ((DACR(CURPOS) & 0x0fff0000) >> 16); 979 /* make sure we will wait until we are below both the old and new Y position: 980 * visible cursorbitmap drawing needs to be done at least... */ 981 if (y > yhigh) yhigh = y; 982 983 if (yhigh < (si->dm.timing.v_display - 16)) 984 { 985 /* we have vertical lines below old and new cursorposition to spare. So we 986 * update the cursor postion 'mid-screen', but below that area. */ 987 /* wait 25mS max. (refresh > 40Hz) */ 988 while ((((uint16)(NV_REG32(NV32_RASTER) & 0x000007ff)) < (yhigh + 16)) && 989 (timeout < (25000/10))) 990 { 991 snooze(10); 992 timeout++; 993 } 994 } 995 else 996 { 997 timeout = 0; 998 /* no room to spare, just wait for retrace (is relatively slow) */ 999 /* wait 25mS max. (refresh > 40Hz) */ 1000 while (((NV_REG32(NV32_RASTER) & 0x000007ff) < si->dm.timing.v_display) && 1001 (timeout < (25000/10))) 1002 { 1003 /* don't snooze much longer or retrace might get missed! */ 1004 snooze(10); 1005 timeout++; 1006 } 1007 } 1008 } 1009 1010 /* update cursorposition */ 1011 DACW(CURPOS, ((x & 0x0fff) | ((y & 0x0fff) << 16))); 1012 1013 return B_OK; 1014 } 1015 1016 status_t nv_crtc_stop_tvout(void) 1017 { 1018 uint16 cnt; 1019 1020 LOG(4,("CRTC: stopping TV output\n")); 1021 1022 /* enable access to primary head */ 1023 set_crtc_owner(0); 1024 1025 /* just to be sure Vsync is _really_ enabled */ 1026 CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0xbf)); 1027 1028 /* wait for one image to be generated to make sure VGA has kicked in and is 1029 * running OK before continuing... 1030 * (Kicking in will fail often if we do not wait here) */ 1031 /* Note: 1032 * The used CRTC's Vsync is required to be enabled here. The DPMS state 1033 * programming in the driver makes sure this is the case. 1034 * (except for driver startup: see nv_general.c.) */ 1035 1036 /* make sure we are 'in' active VGA picture: wait with timeout! */ 1037 cnt = 1; 1038 while ((NV_REG8(NV8_INSTAT1) & 0x08) && cnt) 1039 { 1040 snooze(1); 1041 cnt++; 1042 } 1043 /* wait for next vertical retrace start on VGA: wait with timeout! */ 1044 cnt = 1; 1045 while ((!(NV_REG8(NV8_INSTAT1) & 0x08)) && cnt) 1046 { 1047 snooze(1); 1048 cnt++; 1049 } 1050 /* now wait until we are 'in' active VGA picture again: wait with timeout! */ 1051 cnt = 1; 1052 while ((NV_REG8(NV8_INSTAT1) & 0x08) && cnt) 1053 { 1054 snooze(1); 1055 cnt++; 1056 } 1057 1058 /* set CRTC to master mode (b7 = 0) if it wasn't slaved for a panel before */ 1059 if (!(si->ps.slaved_tmds1)) CRTCW(PIXEL, (CRTCR(PIXEL) & 0x03)); 1060 1061 /* CAUTION: 1062 * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but 1063 * write actions do succeed ... 1064 * This is confirmed for both ISA and PCI access, on NV04 and NV11. */ 1065 1066 /* setup TVencoder connection */ 1067 /* b1-0 = %00: encoder type is SLAVE; 1068 * b24 = 1: VIP datapos is b0-7 */ 1069 //fixme if needed: setup completely instead of relying on pre-init by BIOS.. 1070 //(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work) 1071 DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000003) | 0x01000000)); 1072 1073 /* tell GPU to use pixelclock from internal source instead of using TVencoder */ 1074 if (si->ps.secondary_head) 1075 DACW(PLLSEL, 0x30000f00); 1076 else 1077 DACW(PLLSEL, 0x10000700); 1078 1079 /* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of 1080 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */ 1081 CRTCW(TREG, 0x00); 1082 1083 /* select panel encoder, not TV encoder if needed (b0 = 1). 1084 * Note: 1085 * Both are devices (often) using the CRTC in slaved mode. */ 1086 if (si->ps.slaved_tmds1) CRTCW(LCD, (CRTCR(LCD) | 0x01)); 1087 1088 return B_OK; 1089 } 1090 1091 status_t nv_crtc_start_tvout(void) 1092 { 1093 LOG(4,("CRTC: starting TV output\n")); 1094 1095 if (si->ps.secondary_head) 1096 { 1097 /* switch TV encoder to CRTC1 */ 1098 NV_REG32(NV32_2FUNCSEL) &= ~0x00000100; 1099 NV_REG32(NV32_FUNCSEL) |= 0x00000100; 1100 } 1101 1102 /* enable access to primary head */ 1103 set_crtc_owner(0); 1104 1105 /* CAUTION: 1106 * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but 1107 * write actions do succeed ... 1108 * This is confirmed for both ISA and PCI access, on NV04 and NV11. */ 1109 1110 /* setup TVencoder connection */ 1111 /* b1-0 = %01: encoder type is MASTER; 1112 * b24 = 1: VIP datapos is b0-7 */ 1113 //fixme if needed: setup completely instead of relying on pre-init by BIOS.. 1114 //(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work) 1115 DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000002) | 0x01000001)); 1116 1117 /* tell GPU to use pixelclock from TVencoder instead of using internal source */ 1118 /* (nessecary or display will 'shiver' on both TV and VGA.) */ 1119 if (si->ps.secondary_head) 1120 DACW(PLLSEL, 0x20030f00); 1121 else 1122 DACW(PLLSEL, 0x00030700); 1123 1124 /* Set overscan color to 'black' */ 1125 /* note: 1126 * Change this instruction for a visible overscan color if you're trying to 1127 * center the output on TV. Use it as a guide-'line' then ;-) */ 1128 ATBW(OSCANCOLOR, 0x00); 1129 1130 /* set CRTC to slaved mode (b7 = 1) and clear TVadjust (b3-5 = %000) */ 1131 CRTCW(PIXEL, ((CRTCR(PIXEL) & 0xc7) | 0x80)); 1132 /* select TV encoder, not panel encoder (b0 = 0). 1133 * Note: 1134 * Both are devices (often) using the CRTC in slaved mode. */ 1135 CRTCW(LCD, (CRTCR(LCD) & 0xfe)); 1136 1137 /* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of 1138 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */ 1139 CRTCW(TREG, 0x80); 1140 1141 return B_OK; 1142 } 1143