1/* 2 * Copyright (c) 1993-1999 NVIDIA, Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "riva_local.h" 29#include "compiler.h" 30#include "riva_include.h" 31#include "riva_hw.h" 32#include "riva_tbl.h" 33 34/* 35 * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT 36 * operate identically (except TNT has more memory and better 3D quality. 37 */ 38static int nv3Busy 39( 40 RIVA_HW_INST *chip 41) 42{ 43 return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01)); 44} 45static void vgaLockUnlock 46( 47 RIVA_HW_INST *chip, 48 Bool Lock 49) 50{ 51 CARD8 cr11; 52 VGA_WR08(chip->PCIO, 0x3D4, 0x11); 53 cr11 = VGA_RD08(chip->PCIO, 0x3D5); 54 if(Lock) cr11 |= 0x80; 55 else cr11 &= ~0x80; 56 VGA_WR08(chip->PCIO, 0x3D5, cr11); 57} 58 59static void nv3LockUnlock 60( 61 RIVA_HW_INST *chip, 62 Bool Lock 63) 64{ 65 VGA_WR08(chip->PVIO, 0x3C4, 0x06); 66 VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57); 67 vgaLockUnlock(chip, Lock); 68} 69static int ShowHideCursor 70( 71 RIVA_HW_INST *chip, 72 int ShowHide 73) 74{ 75 int current; 76 current = chip->CurrentState->cursor1; 77 chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) | 78 (ShowHide & 0x01); 79 VGA_WR08(chip->PCIO, 0x3D4, 0x31); 80 VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1); 81 return (current & 0x01); 82} 83 84/****************************************************************************\ 85* * 86* The video arbitration routines calculate some "magic" numbers. Fixes * 87* the snow seen when accessing the framebuffer without it. * 88* It just works (I hope). * 89* * 90\****************************************************************************/ 91 92#define DEFAULT_GR_LWM 100 93#define DEFAULT_VID_LWM 100 94#define DEFAULT_GR_BURST_SIZE 256 95#define DEFAULT_VID_BURST_SIZE 128 96#define VIDEO 0 97#define GRAPHICS 1 98#define MPORT 2 99#define ENGINE 3 100#define GFIFO_SIZE 320 101#define GFIFO_SIZE_128 256 102#define MFIFO_SIZE 120 103#define VFIFO_SIZE 256 104#define ABS(a) ((a) > 0 ? (a) : -(a)) 105typedef struct { 106 int gdrain_rate; 107 int vdrain_rate; 108 int mdrain_rate; 109 int gburst_size; 110 int vburst_size; 111 char vid_en; 112 char gr_en; 113 int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm; 114 int by_gfacc; 115 char vid_only_once; 116 char gr_only_once; 117 char first_vacc; 118 char first_gacc; 119 char first_macc; 120 int vocc; 121 int gocc; 122 int mocc; 123 char cur; 124 char engine_en; 125 char converged; 126 int priority; 127} nv3_arb_info; 128typedef struct { 129 int graphics_lwm; 130 int video_lwm; 131 int graphics_burst_size; 132 int video_burst_size; 133 int graphics_hi_priority; 134 int media_hi_priority; 135 int rtl_values; 136 int valid; 137} nv3_fifo_info; 138typedef struct { 139 char pix_bpp; 140 char enable_video; 141 char gr_during_vid; 142 char enable_mp; 143 int memory_width; 144 int video_scale; 145 int pclk_khz; 146 int mclk_khz; 147 int mem_page_miss; 148 int mem_latency; 149 char mem_aligned; 150} nv3_sim_state; 151static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) 152{ 153 int iter = 0; 154 int tmp; 155 int vfsize, mfsize, gfsize; 156 int mburst_size = 32; 157 int mmisses, gmisses, vmisses; 158 int misses; 159 int vlwm, glwm; 160 int last, next, cur; 161 int max_gfsize ; 162 long ns; 163 164 vlwm = 0; 165 glwm = 0; 166 vfsize = 0; 167 gfsize = 0; 168 cur = ainfo->cur; 169 mmisses = 2; 170 gmisses = 2; 171 vmisses = 2; 172 if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128; 173 else max_gfsize = GFIFO_SIZE; 174 max_gfsize = GFIFO_SIZE; 175 while (1) 176 { 177 if (ainfo->vid_en) 178 { 179 if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc; 180 if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ; 181 ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; 182 vfsize = ns * ainfo->vdrain_rate / 1000000; 183 vfsize = ainfo->wcvlwm - ainfo->vburst_size + vfsize; 184 } 185 if (state->enable_mp) 186 { 187 if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc; 188 } 189 if (ainfo->gr_en) 190 { 191 if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ; 192 if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc; 193 ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; 194 gfsize = (ns * (long) ainfo->gdrain_rate)/1000000; 195 gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize; 196 } 197 mfsize = 0; 198 if (!state->gr_during_vid && ainfo->vid_en) 199 if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once) 200 next = VIDEO; 201 else if (ainfo->mocc < 0) 202 next = MPORT; 203 else if (ainfo->gocc< ainfo->by_gfacc) 204 next = GRAPHICS; 205 else return (0); 206 else switch (ainfo->priority) 207 { 208 case VIDEO: 209 if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) 210 next = VIDEO; 211 else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) 212 next = GRAPHICS; 213 else if (ainfo->mocc<0) 214 next = MPORT; 215 else return (0); 216 break; 217 case GRAPHICS: 218 if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) 219 next = GRAPHICS; 220 else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) 221 next = VIDEO; 222 else if (ainfo->mocc<0) 223 next = MPORT; 224 else return (0); 225 break; 226 default: 227 if (ainfo->mocc<0) 228 next = MPORT; 229 else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) 230 next = GRAPHICS; 231 else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) 232 next = VIDEO; 233 else return (0); 234 break; 235 } 236 last = cur; 237 cur = next; 238 iter++; 239 switch (cur) 240 { 241 case VIDEO: 242 if (last==cur) misses = 0; 243 else if (ainfo->first_vacc) misses = vmisses; 244 else misses = 1; 245 ainfo->first_vacc = 0; 246 if (last!=cur) 247 { 248 ns = 1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 249 vlwm = ns * ainfo->vdrain_rate/ 1000000; 250 vlwm = ainfo->vocc - vlwm; 251 } 252 ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz; 253 ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000; 254 ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000; 255 ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000; 256 break; 257 case GRAPHICS: 258 if (last==cur) misses = 0; 259 else if (ainfo->first_gacc) misses = gmisses; 260 else misses = 1; 261 ainfo->first_gacc = 0; 262 if (last!=cur) 263 { 264 ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ; 265 glwm = ns * ainfo->gdrain_rate/1000000; 266 glwm = ainfo->gocc - glwm; 267 } 268 ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; 269 ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; 270 ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000; 271 ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000; 272 break; 273 default: 274 if (last==cur) misses = 0; 275 else if (ainfo->first_macc) misses = mmisses; 276 else misses = 1; 277 ainfo->first_macc = 0; 278 ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz; 279 ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; 280 ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000; 281 ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000; 282 break; 283 } 284 if (iter>100) 285 { 286 ainfo->converged = 0; 287 return (1); 288 } 289 ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz; 290 tmp = ns * ainfo->gdrain_rate/1000000; 291 if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize) 292 { 293 ainfo->converged = 0; 294 return (1); 295 } 296 ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; 297 tmp = ns * ainfo->vdrain_rate/1000000; 298 if (ABS(ainfo->vburst_size) + (ABS(ainfo->wcvlwm + 32) & ~0xf) - tmp> VFIFO_SIZE) 299 { 300 ainfo->converged = 0; 301 return (1); 302 } 303 if (ABS(ainfo->gocc) > max_gfsize) 304 { 305 ainfo->converged = 0; 306 return (1); 307 } 308 if (ABS(ainfo->vocc) > VFIFO_SIZE) 309 { 310 ainfo->converged = 0; 311 return (1); 312 } 313 if (ABS(ainfo->mocc) > MFIFO_SIZE) 314 { 315 ainfo->converged = 0; 316 return (1); 317 } 318 if (ABS(vfsize) > VFIFO_SIZE) 319 { 320 ainfo->converged = 0; 321 return (1); 322 } 323 if (ABS(gfsize) > max_gfsize) 324 { 325 ainfo->converged = 0; 326 return (1); 327 } 328 if (ABS(mfsize) > MFIFO_SIZE) 329 { 330 ainfo->converged = 0; 331 return (1); 332 } 333 } 334} 335static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state, nv3_arb_info *ainfo) 336{ 337 long ens, vns, mns, gns; 338 int mmisses, gmisses, vmisses, eburst_size, mburst_size; 339 int refresh_cycle; 340 341 refresh_cycle = 0; 342 refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5; 343 mmisses = 2; 344 if (state->mem_aligned) gmisses = 2; 345 else gmisses = 3; 346 vmisses = 2; 347 eburst_size = state->memory_width * 1; 348 mburst_size = 32; 349 gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 350 ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000; 351 ainfo->wcmocc = 0; 352 ainfo->wcgocc = 0; 353 ainfo->wcvocc = 0; 354 ainfo->wcvlwm = 0; 355 ainfo->wcglwm = 0; 356 ainfo->engine_en = 1; 357 ainfo->converged = 1; 358 if (ainfo->engine_en) 359 { 360 ens = 1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz; 361 ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0; 362 ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0; 363 ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0; 364 ainfo->cur = ENGINE; 365 ainfo->first_vacc = 1; 366 ainfo->first_gacc = 1; 367 ainfo->first_macc = 1; 368 nv3_iterate(res_info, state,ainfo); 369 } 370 if (state->enable_mp) 371 { 372 mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; 373 ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000; 374 ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000; 375 ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000; 376 ainfo->cur = MPORT; 377 ainfo->first_vacc = 1; 378 ainfo->first_gacc = 1; 379 ainfo->first_macc = 0; 380 nv3_iterate(res_info, state,ainfo); 381 } 382 if (ainfo->gr_en) 383 { 384 ainfo->first_vacc = 1; 385 ainfo->first_gacc = 0; 386 ainfo->first_macc = 1; 387 gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; 388 ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000; 389 ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0; 390 ainfo->mocc = state->enable_mp ? 0-gns*ainfo->mdrain_rate/1000000: 0; 391 ainfo->cur = GRAPHICS; 392 nv3_iterate(res_info, state,ainfo); 393 } 394 if (ainfo->vid_en) 395 { 396 ainfo->first_vacc = 0; 397 ainfo->first_gacc = 1; 398 ainfo->first_macc = 1; 399 vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; 400 ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000; 401 ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0; 402 ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ; 403 ainfo->cur = VIDEO; 404 nv3_iterate(res_info, state, ainfo); 405 } 406 if (ainfo->converged) 407 { 408 res_info->graphics_lwm = (int)ABS(ainfo->wcglwm) + 16; 409 res_info->video_lwm = (int)ABS(ainfo->wcvlwm) + 32; 410 res_info->graphics_burst_size = ainfo->gburst_size; 411 res_info->video_burst_size = ainfo->vburst_size; 412 res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS); 413 res_info->media_hi_priority = (ainfo->priority == MPORT); 414 if (res_info->video_lwm > 160) 415 { 416 res_info->graphics_lwm = 256; 417 res_info->video_lwm = 128; 418 res_info->graphics_burst_size = 64; 419 res_info->video_burst_size = 64; 420 res_info->graphics_hi_priority = 0; 421 res_info->media_hi_priority = 0; 422 ainfo->converged = 0; 423 return (0); 424 } 425 if (res_info->video_lwm > 128) 426 { 427 res_info->video_lwm = 128; 428 } 429 return (1); 430 } 431 else 432 { 433 res_info->graphics_lwm = 256; 434 res_info->video_lwm = 128; 435 res_info->graphics_burst_size = 64; 436 res_info->video_burst_size = 64; 437 res_info->graphics_hi_priority = 0; 438 res_info->media_hi_priority = 0; 439 return (0); 440 } 441} 442static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) 443{ 444 int done, g,v, p; 445 446 done = 0; 447 for (p=0; p < 2; p++) 448 { 449 for (g=128 ; g > 32; g= g>> 1) 450 { 451 for (v=128; v >=32; v = v>> 1) 452 { 453 ainfo->priority = p; 454 ainfo->gburst_size = g; 455 ainfo->vburst_size = v; 456 done = nv3_arb(res_info, state,ainfo); 457 if (done && (g==128)) 458 if ((res_info->graphics_lwm + g) > 256) 459 done = 0; 460 if (done) 461 goto Done; 462 } 463 } 464 } 465 466 Done: 467 return done; 468} 469static void nv3CalcArbitration 470( 471 nv3_fifo_info * res_info, 472 nv3_sim_state * state 473) 474{ 475 nv3_fifo_info save_info; 476 nv3_arb_info ainfo; 477 char res_gr, res_vid; 478 479 ainfo.gr_en = 1; 480 ainfo.vid_en = state->enable_video; 481 ainfo.vid_only_once = 0; 482 ainfo.gr_only_once = 0; 483 ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); 484 ainfo.vdrain_rate = (int) state->pclk_khz * 2; 485 if (state->video_scale != 0) 486 ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale; 487 ainfo.mdrain_rate = 33000; 488 res_info->rtl_values = 0; 489 if (!state->gr_during_vid && state->enable_video) 490 { 491 ainfo.gr_only_once = 1; 492 ainfo.gr_en = 1; 493 ainfo.gdrain_rate = 0; 494 res_vid = nv3_get_param(res_info, state, &ainfo); 495 res_vid = ainfo.converged; 496 save_info.video_lwm = res_info->video_lwm; 497 save_info.video_burst_size = res_info->video_burst_size; 498 ainfo.vid_en = 1; 499 ainfo.vid_only_once = 1; 500 ainfo.gr_en = 1; 501 ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); 502 ainfo.vdrain_rate = 0; 503 res_gr = nv3_get_param(res_info, state, &ainfo); 504 res_gr = ainfo.converged; 505 res_info->video_lwm = save_info.video_lwm; 506 res_info->video_burst_size = save_info.video_burst_size; 507 res_info->valid = res_gr & res_vid; 508 } 509 else 510 { 511 if (!ainfo.gr_en) ainfo.gdrain_rate = 0; 512 if (!ainfo.vid_en) ainfo.vdrain_rate = 0; 513 res_gr = nv3_get_param(res_info, state, &ainfo); 514 res_info->valid = ainfo.converged; 515 } 516} 517static void nv3UpdateArbitrationSettings 518( 519 unsigned VClk, 520 unsigned pixelDepth, 521 unsigned *burst, 522 unsigned *lwm, 523 RIVA_HW_INST *chip 524) 525{ 526 nv3_fifo_info fifo_data; 527 nv3_sim_state sim_data; 528 unsigned int M, N, P, pll, MClk; 529 530 pll = chip->PRAMDAC[0x00000504/4]; 531 M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; 532 MClk = (N * chip->CrystalFreqKHz / M) >> P; 533 sim_data.pix_bpp = (char)pixelDepth; 534 sim_data.enable_video = 0; 535 sim_data.enable_mp = 0; 536 sim_data.video_scale = 1; 537 sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; 538 sim_data.memory_width = 128; 539 540 sim_data.mem_latency = 9; 541 sim_data.mem_aligned = 1; 542 sim_data.mem_page_miss = 11; 543 sim_data.gr_during_vid = 0; 544 sim_data.pclk_khz = VClk; 545 sim_data.mclk_khz = MClk; 546 nv3CalcArbitration(&fifo_data, &sim_data); 547 if (fifo_data.valid) 548 { 549 int b = fifo_data.graphics_burst_size >> 4; 550 *burst = 0; 551 while (b >>= 1) (*burst)++; 552 *lwm = fifo_data.graphics_lwm >> 3; 553 } 554 else 555 { 556 *lwm = 0x24; 557 *burst = 0x2; 558 } 559} 560 561/****************************************************************************\ 562* * 563* RIVA Mode State Routines * 564* * 565\****************************************************************************/ 566 567/* 568 * Calculate the Video Clock parameters for the PLL. 569 */ 570static int CalcVClock 571( 572 int clockIn, 573 int *clockOut, 574 int *mOut, 575 int *nOut, 576 int *pOut, 577 RIVA_HW_INST *chip 578) 579{ 580 unsigned lowM, highM, highP; 581 unsigned DeltaNew, DeltaOld; 582 unsigned VClk, Freq; 583 unsigned M, N, P; 584 585 DeltaOld = 0xFFFFFFFF; 586 587 VClk = (unsigned)clockIn; 588 589 if (chip->CrystalFreqKHz == 13500) 590 { 591 lowM = 7; 592 highM = 12; 593 } 594 else 595 { 596 lowM = 8; 597 highM = 13; 598 } 599 600 highP = 3; 601 for (P = 0; P <= highP; P ++) 602 { 603 Freq = VClk << P; 604 if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz)) 605 { 606 for (M = lowM; M <= highM; M++) 607 { 608 N = (VClk << P) * M / chip->CrystalFreqKHz; 609 if(N <= 255) { 610 Freq = (chip->CrystalFreqKHz * N / M) >> P; 611 if (Freq > VClk) 612 DeltaNew = Freq - VClk; 613 else 614 DeltaNew = VClk - Freq; 615 if (DeltaNew < DeltaOld) 616 { 617 *mOut = M; 618 *nOut = N; 619 *pOut = P; 620 *clockOut = Freq; 621 DeltaOld = DeltaNew; 622 } 623 } 624 } 625 } 626 } 627 return (DeltaOld != 0xFFFFFFFF); 628} 629/* 630 * Calculate extended mode parameters (SVGA) and save in a 631 * mode state structure. 632 */ 633static void CalcStateExt 634( 635 RIVA_HW_INST *chip, 636 RIVA_HW_STATE *state, 637 int bpp, 638 int width, 639 int hDisplaySize, 640 int height, 641 int dotClock, 642 int flags 643) 644{ 645 int pixelDepth, VClk = 0, m = 0, n = 0, p = 0; 646 /* 647 * Save mode parameters. 648 */ 649 state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */ 650 state->width = width; 651 state->height = height; 652 /* 653 * Extended RIVA registers. 654 */ 655 pixelDepth = (bpp + 1)/8; 656 CalcVClock(dotClock, &VClk, &m, &n, &p, chip); 657 658 nv3UpdateArbitrationSettings(VClk, 659 pixelDepth * 8, 660 &(state->arbitration0), 661 &(state->arbitration1), 662 chip); 663 state->cursor0 = 0x00; 664 state->cursor1 = 0x78; 665 if (flags & V_DBLSCAN) 666 state->cursor1 |= 2; 667 state->cursor2 = 0x00000000; 668 state->pllsel = 0x10010100; 669 state->config = ((width + 31)/32) 670 | (((pixelDepth > 2) ? 3 : pixelDepth) << 8) 671 | 0x1000; 672 state->general = 0x00100100; 673 state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02; 674 675 676 state->vpll = (p << 16) | (n << 8) | m; 677 state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3; 678 state->pixel = pixelDepth > 2 ? 3 : pixelDepth; 679 state->offset = 0; 680 state->pitch = pixelDepth * width; 681} 682/* 683 * Load fixed function state and pre-calculated/stored state. 684 */ 685#define LOAD_FIXED_STATE(tbl,dev) \ 686 for (i = 0; i < sizeof(tbl##Table##dev)/8; i++) \ 687 chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1] 688#define LOAD_FIXED_STATE_8BPP(tbl,dev) \ 689 for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++) \ 690 chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1] 691#define LOAD_FIXED_STATE_15BPP(tbl,dev) \ 692 for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++) \ 693 chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1] 694#define LOAD_FIXED_STATE_16BPP(tbl,dev) \ 695 for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++) \ 696 chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1] 697#define LOAD_FIXED_STATE_32BPP(tbl,dev) \ 698 for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++) \ 699 chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1] 700static void UpdateFifoState 701( 702 RIVA_HW_INST *chip 703) 704{ 705} 706static void LoadStateExt 707( 708 RIVA_HW_INST *chip, 709 RIVA_HW_STATE *state 710) 711{ 712 int i; 713 714 /* 715 * Load HW fixed function state. 716 */ 717 LOAD_FIXED_STATE(Riva,PMC); 718 LOAD_FIXED_STATE(Riva,PTIMER); 719 /* 720 * Make sure frame buffer config gets set before loading PRAMIN. 721 */ 722 chip->PFB[0x00000200/4] = state->config; 723 LOAD_FIXED_STATE(nv3,PFIFO); 724 LOAD_FIXED_STATE(nv3,PRAMIN); 725 LOAD_FIXED_STATE(nv3,PGRAPH); 726 switch (state->bpp) 727 { 728 case 15: 729 case 16: 730 LOAD_FIXED_STATE_15BPP(nv3,PRAMIN); 731 LOAD_FIXED_STATE_15BPP(nv3,PGRAPH); 732 break; 733 case 24: 734 case 32: 735 LOAD_FIXED_STATE_32BPP(nv3,PRAMIN); 736 LOAD_FIXED_STATE_32BPP(nv3,PGRAPH); 737 break; 738 case 8: 739 default: 740 LOAD_FIXED_STATE_8BPP(nv3,PRAMIN); 741 LOAD_FIXED_STATE_8BPP(nv3,PGRAPH); 742 break; 743 } 744 for (i = 0x00000; i < 0x00800; i++) 745 chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03; 746 chip->PGRAPH[0x00000630/4] = state->offset; 747 chip->PGRAPH[0x00000634/4] = state->offset; 748 chip->PGRAPH[0x00000638/4] = state->offset; 749 chip->PGRAPH[0x0000063C/4] = state->offset; 750 chip->PGRAPH[0x00000650/4] = state->pitch; 751 chip->PGRAPH[0x00000654/4] = state->pitch; 752 chip->PGRAPH[0x00000658/4] = state->pitch; 753 chip->PGRAPH[0x0000065C/4] = state->pitch; 754 755 LOAD_FIXED_STATE(Riva,FIFO); 756 UpdateFifoState(chip); 757 758 /* 759 * Load HW mode state. 760 */ 761 VGA_WR08(chip->PCIO, 0x03D4, 0x19); 762 VGA_WR08(chip->PCIO, 0x03D5, state->repaint0); 763 VGA_WR08(chip->PCIO, 0x03D4, 0x1A); 764 VGA_WR08(chip->PCIO, 0x03D5, state->repaint1); 765 VGA_WR08(chip->PCIO, 0x03D4, 0x25); 766 VGA_WR08(chip->PCIO, 0x03D5, state->screen); 767 VGA_WR08(chip->PCIO, 0x03D4, 0x28); 768 VGA_WR08(chip->PCIO, 0x03D5, state->pixel); 769 VGA_WR08(chip->PCIO, 0x03D4, 0x2D); 770 VGA_WR08(chip->PCIO, 0x03D5, state->horiz); 771 VGA_WR08(chip->PCIO, 0x03D4, 0x1B); 772 VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0); 773 VGA_WR08(chip->PCIO, 0x03D4, 0x20); 774 VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1); 775 VGA_WR08(chip->PCIO, 0x03D4, 0x30); 776 VGA_WR08(chip->PCIO, 0x03D5, state->cursor0); 777 VGA_WR08(chip->PCIO, 0x03D4, 0x31); 778 VGA_WR08(chip->PCIO, 0x03D5, state->cursor1); 779 VGA_WR08(chip->PCIO, 0x03D4, 0x2F); 780 VGA_WR08(chip->PCIO, 0x03D5, state->cursor2); 781 VGA_WR08(chip->PCIO, 0x03D4, 0x39); 782 VGA_WR08(chip->PCIO, 0x03D5, state->interlace); 783 784 chip->PRAMDAC[0x00000508/4] = state->vpll; 785 chip->PRAMDAC[0x0000050C/4] = state->pllsel; 786 chip->PRAMDAC[0x00000600/4] = state->general; 787 788 /* 789 * Turn off VBlank enable and reset. 790 */ 791 chip->PCRTC[0x00000140/4] = 0; 792 chip->PCRTC[0x00000100/4] = chip->VBlankBit; 793 /* 794 * Set interrupt enable. 795 */ 796 chip->PMC[0x00000140/4] = chip->EnableIRQ & 0x01; 797 /* 798 * Set current state pointer. 799 */ 800 chip->CurrentState = state; 801 /* 802 * Reset FIFO free and empty counts. 803 */ 804 chip->FifoFreeCount = 0; 805 /* Free count from first subchannel */ 806 chip->FifoEmptyCount = chip->Rop->FifoFree; 807} 808 809static void UnloadStateExt 810( 811 RIVA_HW_INST *chip, 812 RIVA_HW_STATE *state 813) 814{ 815 /* 816 * Save current HW state. 817 */ 818 VGA_WR08(chip->PCIO, 0x03D4, 0x19); 819 state->repaint0 = VGA_RD08(chip->PCIO, 0x03D5); 820 VGA_WR08(chip->PCIO, 0x03D4, 0x1A); 821 state->repaint1 = VGA_RD08(chip->PCIO, 0x03D5); 822 VGA_WR08(chip->PCIO, 0x03D4, 0x25); 823 state->screen = VGA_RD08(chip->PCIO, 0x03D5); 824 VGA_WR08(chip->PCIO, 0x03D4, 0x28); 825 state->pixel = VGA_RD08(chip->PCIO, 0x03D5); 826 VGA_WR08(chip->PCIO, 0x03D4, 0x2D); 827 state->horiz = VGA_RD08(chip->PCIO, 0x03D5); 828 VGA_WR08(chip->PCIO, 0x03D4, 0x1B); 829 state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5); 830 VGA_WR08(chip->PCIO, 0x03D4, 0x20); 831 state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5); 832 VGA_WR08(chip->PCIO, 0x03D4, 0x30); 833 state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5); 834 VGA_WR08(chip->PCIO, 0x03D4, 0x31); 835 state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5); 836 VGA_WR08(chip->PCIO, 0x03D4, 0x2F); 837 state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5); 838 VGA_WR08(chip->PCIO, 0x03D4, 0x39); 839 state->interlace = VGA_RD08(chip->PCIO, 0x03D5); 840 state->vpll = chip->PRAMDAC[0x00000508/4]; 841 state->pllsel = chip->PRAMDAC[0x0000050C/4]; 842 state->general = chip->PRAMDAC[0x00000600/4]; 843 state->config = chip->PFB[0x00000200/4]; 844 state->offset = chip->PGRAPH[0x00000630/4]; 845 state->pitch = chip->PGRAPH[0x00000650/4]; 846} 847 848static void SetStartAddress 849( 850 RIVA_HW_INST *chip, 851 unsigned start 852) 853{ 854 int offset = start >> 2; 855 int pan = (start & 3) << 1; 856 unsigned char tmp; 857 858 /* 859 * Unlock extended registers. 860 */ 861 chip->LockUnlock(chip, 0); 862 /* 863 * Set start address. 864 */ 865 VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset); 866 offset >>= 8; 867 VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset); 868 offset >>= 8; 869 VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5); 870 VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F)); 871 VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5); 872 VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60)); 873 /* 874 * 4 pixel pan register. 875 */ 876 offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A); 877 VGA_WR08(chip->PCIO, 0x3C0, 0x13); 878 VGA_WR08(chip->PCIO, 0x3C0, pan); 879} 880/****************************************************************************\ 881* * 882* Probe RIVA Chip Configuration * 883* * 884\****************************************************************************/ 885 886static void nv3GetConfig 887( 888 RIVA_HW_INST *chip 889) 890{ 891 /* 892 * Fill in chip configuration. 893 */ 894 if (chip->PFB[0x00000000/4] & 0x00000020) 895 { 896 if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) 897 && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) 898 { 899 /* 900 * SDRAM 128 ZX. 901 */ 902 chip->RamBandwidthKBytesPerSec = 800000; 903 switch (chip->PFB[0x00000000/4] & 0x03) 904 { 905 case 2: 906 chip->RamAmountKBytes = 1024 * 4; 907 break; 908 case 1: 909 chip->RamAmountKBytes = 1024 * 2; 910 break; 911 default: 912 chip->RamAmountKBytes = 1024 * 8; 913 break; 914 } 915 } 916 else 917 { 918 chip->RamBandwidthKBytesPerSec = 1000000; 919 chip->RamAmountKBytes = 1024 * 8; 920 } 921 } 922 else 923 { 924 /* 925 * SGRAM 128. 926 */ 927 chip->RamBandwidthKBytesPerSec = 1000000; 928 switch (chip->PFB[0x00000000/4] & 0x00000003) 929 { 930 case 0: 931 chip->RamAmountKBytes = 1024 * 8; 932 break; 933 case 2: 934 chip->RamAmountKBytes = 1024 * 4; 935 break; 936 default: 937 chip->RamAmountKBytes = 1024 * 2; 938 break; 939 } 940 } 941 chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; 942 chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]); 943 chip->VBlankBit = 0x00000100; 944 chip->MaxVClockFreqKHz = 256000; 945 /* 946 * Set chip functions. 947 */ 948 chip->Busy = nv3Busy; 949 chip->ShowHideCursor = ShowHideCursor; 950 chip->CalcStateExt = CalcStateExt; 951 chip->LoadStateExt = LoadStateExt; 952 chip->UnloadStateExt = UnloadStateExt; 953 chip->SetStartAddress = SetStartAddress; 954 chip->LockUnlock = nv3LockUnlock; 955} 956int RivaGetConfig 957( 958 RivaPtr pRiva 959) 960{ 961 RIVA_HW_INST *chip = &pRiva->riva; 962 963 nv3GetConfig(chip); 964 /* 965 * Fill in FIFO pointers. 966 */ 967 chip->Rop = (RivaRop *)&(chip->FIFO[0x00000000/4]); 968 chip->Clip = (RivaClip *)&(chip->FIFO[0x00002000/4]); 969 chip->Patt = (RivaPattern *)&(chip->FIFO[0x00004000/4]); 970 chip->Pixmap = (RivaPixmap *)&(chip->FIFO[0x00006000/4]); 971 chip->Blt = (RivaScreenBlt *)&(chip->FIFO[0x00008000/4]); 972 chip->Bitmap = (RivaBitmap *)&(chip->FIFO[0x0000A000/4]); 973 chip->Line = (RivaLine *)&(chip->FIFO[0x0000C000/4]); 974 return (0); 975} 976