1 /* program the DAC */ 2 /* Author: 3 Rudolf Cornelissen 12/2003 4 */ 5 6 #define MODULE_BIT 0x00010000 7 8 #include "nv_std.h" 9 10 static status_t nv4_nv10_nv20_dac_pix_pll_find( 11 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test); 12 static status_t g100_g400max_dac_sys_pll_find( 13 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result); 14 15 /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ 16 status_t nv_dac_mode(int mode,float brightness) 17 { 18 uint8 *r,*g,*b; 19 int i, ri; 20 21 /*set colour arrays to point to space reserved in shared info*/ 22 r = si->color_data; 23 g = r + 256; 24 b = g + 256; 25 26 LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness)); 27 /* init the palette for brightness specified */ 28 /* (Nvidia cards always use MSbits from screenbuffer as index for PAL) */ 29 for (i = 0; i < 256; i++) 30 { 31 ri = i * brightness; 32 if (ri > 255) ri = 255; 33 b[i] = g[i] = r[i] = ri; 34 } 35 36 if (nv_dac_palette(r,g,b) != B_OK) return B_ERROR; 37 38 /*set the mode - also sets VCLK dividor*/ 39 // DXIW(MULCTRL, mode); 40 // LOG(2,("DAC: mulctrl 0x%02x\n", DXIR(MULCTRL))); 41 42 /* disable palette RAM adressing mask */ 43 NV_REG8(NV8_PALMASK) = 0xff; 44 LOG(2,("DAC: PAL pixrdmsk readback $%02x\n", NV_REG8(NV8_PALMASK))); 45 46 return B_OK; 47 } 48 49 /*program the DAC palette using the given r,g,b values*/ 50 status_t nv_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256]) 51 { 52 int i; 53 54 LOG(4,("DAC: setting palette\n")); 55 56 /* select first PAL adress before starting programming */ 57 NV_REG8(NV8_PALINDW) = 0x00; 58 59 /* loop through all 256 to program DAC */ 60 for (i = 0; i < 256; i++) 61 { 62 /* the 6 implemented bits are on b0-b5 of the bus */ 63 NV_REG8(NV8_PALDATA) = r[i]; 64 NV_REG8(NV8_PALDATA) = g[i]; 65 NV_REG8(NV8_PALDATA) = b[i]; 66 } 67 if (NV_REG8(NV8_PALINDW) != 0x00) 68 { 69 LOG(8,("DAC: PAL write index incorrect after programming\n")); 70 return B_ERROR; 71 } 72 if (1) 73 {//reread LUT 74 uint8 R, G, B; 75 76 /* select first PAL adress to read (modulo 3 counter) */ 77 NV_REG8(NV8_PALINDR) = 0x00; 78 for (i = 0; i < 256; i++) 79 { 80 R = NV_REG8(NV8_PALDATA); 81 G = NV_REG8(NV8_PALDATA); 82 B = NV_REG8(NV8_PALDATA); 83 if ((r[i] != R) || (g[i] != G) || (b[i] != B)) 84 LOG(1,("DAC palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed 85 } 86 } 87 88 return B_OK; 89 } 90 91 /*program the pixpll - frequency in kHz*/ 92 /*important notes: 93 * PIXPLLC is used - others should be kept as is 94 * BESCLK,CRTC2 are not touched 95 */ 96 status_t nv_dac_set_pix_pll(display_mode target) 97 { 98 uint8 m=0,n=0,p=0; 99 // uint time = 0; 100 101 float pix_setting, req_pclk; 102 status_t result; 103 104 req_pclk = (target.timing.pixel_clock)/1000.0; 105 LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk)); 106 107 /* signal that we actually want to set the mode */ 108 result = nv_dac_pix_pll_find(target,&pix_setting,&m,&n,&p, 1); 109 if (result != B_OK) 110 { 111 return result; 112 } 113 114 /*reprogram (disable,select,wait for stability,enable)*/ 115 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/ 116 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/ 117 118 /* select pixelPLL registerset C */ 119 DACW(PLLSEL, 0x10000700); 120 121 /* program new frequency */ 122 DACW(PIXPLLC, ((p << 16) | (n << 8) | m)); 123 124 /* Wait for the PIXPLL frequency to lock until timeout occurs */ 125 //fixme: do NV cards have a LOCK indication bit?? 126 /* while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000)) 127 { 128 time++; 129 snooze(1); 130 } 131 132 if (time > 2000) 133 LOG(2,("DAC: PIX PLL frequency not locked!\n")); 134 else 135 LOG(2,("DAC: PIX PLL frequency locked\n")); 136 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); //enable the PIXPLL 137 */ 138 139 //for now: 140 /* Give the PIXPLL frequency some time to lock... */ 141 snooze(1000); 142 LOG(2,("DAC: PIX PLL frequency should be locked now...\n")); 143 144 return B_OK; 145 } 146 147 /* find nearest valid pix pll */ 148 status_t nv_dac_pix_pll_find 149 (display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 150 { 151 switch (si->ps.card_type) { 152 default: return nv4_nv10_nv20_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test); 153 } 154 return B_ERROR; 155 } 156 157 /* find nearest valid pixel PLL setting */ 158 static status_t nv4_nv10_nv20_dac_pix_pll_find( 159 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 160 { 161 int m = 0, n = 0, p = 0/*, m_max*/; 162 float error, error_best = 999999999; 163 int best[3]; 164 float f_vco, max_pclk; 165 float req_pclk = target.timing.pixel_clock/1000.0; 166 167 /* determine the max. reference-frequency postscaler setting for the 168 * current card (see G100, G200 and G400 specs). */ 169 /* switch(si->ps.card_type) 170 { 171 case G100: 172 LOG(4,("DAC: G100 restrictions apply\n")); 173 m_max = 7; 174 break; 175 case G200: 176 LOG(4,("DAC: G200 restrictions apply\n")); 177 m_max = 7; 178 break; 179 default: 180 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 181 m_max = 32; 182 break; 183 } 184 */ 185 LOG(4,("DAC: NV4/NV10/NV20 restrictions apply\n")); 186 187 /* determine the max. pixelclock for the current videomode */ 188 switch (target.space) 189 { 190 case B_CMAP8: 191 max_pclk = si->ps.max_dac1_clock_8; 192 break; 193 case B_RGB15_LITTLE: 194 case B_RGB16_LITTLE: 195 max_pclk = si->ps.max_dac1_clock_16; 196 break; 197 case B_RGB24_LITTLE: 198 max_pclk = si->ps.max_dac1_clock_24; 199 break; 200 case B_RGB32_LITTLE: 201 max_pclk = si->ps.max_dac1_clock_32; 202 break; 203 default: 204 /* use fail-safe value */ 205 max_pclk = si->ps.max_dac1_clock_32; 206 break; 207 } 208 /* if some dualhead mode is active, an extra restriction might apply */ 209 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 210 max_pclk = si->ps.max_dac1_clock_32dh; 211 212 /* Make sure the requested pixelclock is within the PLL's operational limits */ 213 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 214 if (req_pclk < (si->ps.min_pixel_vco / 16.0)) 215 { 216 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 217 req_pclk, (float)(si->ps.min_pixel_vco / 16.0))); 218 req_pclk = (si->ps.min_pixel_vco / 16.0); 219 } 220 /* upper limit is given by pins in combination with current active mode */ 221 if (req_pclk > max_pclk) 222 { 223 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 224 req_pclk, (float)max_pclk)); 225 req_pclk = max_pclk; 226 } 227 228 /* iterate through all valid PLL postscaler settings */ 229 for (p=0x01; p < 0x20; p = p<<1) 230 { 231 /* calculate the needed VCO frequency for this postscaler setting */ 232 f_vco = req_pclk * p; 233 234 /* check if this is within range of the VCO specs */ 235 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco)) 236 { 237 /* NV31 (FX5600) tweak (missing register for 2nd VCO postscaler) */ 238 f_vco /= si->pixpll_vco_div2; 239 240 /* iterate trough all valid reference-frequency postscaler settings */ 241 for (m = 7; m <= 14; m++) 242 { 243 /* check if phase-discriminator will be within operational limits */ 244 if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue; 245 246 /* calculate VCO postscaler setting for current setup.. */ 247 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 248 /* ..and check for validity */ 249 if ((n < 1) || (n > 255)) continue; 250 251 /* find error in frequency this setting gives */ 252 /* si->pixpll_vco_div2 below is NV31 (FX5600) tweak (missing register) */ 253 error = 254 fabs((req_pclk / si->pixpll_vco_div2) - (((si->ps.f_ref / m) * n) / p)); 255 256 /* note the setting if best yet */ 257 if (error < error_best) 258 { 259 error_best = error; 260 best[0]=m; 261 best[1]=n; 262 best[2]=p; 263 } 264 } 265 } 266 } 267 268 /* setup the scalers programming values for found optimum setting */ 269 m = best[0]; 270 n = best[1]; 271 p = best[2]; 272 273 /* log the VCO frequency found */ 274 f_vco = ((si->ps.f_ref / m) * n); 275 /* NV31 (FX5600) tweak (missing register for 2nd VCO postscaler) */ 276 f_vco *= si->pixpll_vco_div2; 277 278 LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco)); 279 280 /* return the results */ 281 *calc_pclk = (f_vco / p); 282 *m_result = m; 283 *n_result = n; 284 switch(p) 285 { 286 case 1: 287 p = 0x00; 288 break; 289 case 2: 290 p = 0x01; 291 break; 292 case 4: 293 p = 0x02; 294 break; 295 case 8: 296 p = 0x03; 297 break; 298 case 16: 299 p = 0x04; 300 break; 301 } 302 *p_result = p; 303 304 /* display the found pixelclock values */ 305 LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 306 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 307 308 return B_OK; 309 } 310 311 /* find nearest valid system PLL setting */ 312 static status_t g100_g400max_dac_sys_pll_find( 313 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result) 314 { 315 int m = 0, n = 0, p = 0, m_max; 316 float error, error_best = 999999999; 317 int best[3]; 318 float f_vco; 319 320 /* determine the max. reference-frequency postscaler setting for the 321 * current card (see G100, G200 and G400 specs). */ 322 switch(si->ps.card_type) 323 { 324 /* case G100: 325 LOG(4,("DAC: G100 restrictions apply\n")); 326 m_max = 7; 327 break; 328 case G200: 329 LOG(4,("DAC: G200 restrictions apply\n")); 330 m_max = 7; 331 break; 332 */ default: 333 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 334 m_max = 32; 335 break; 336 } 337 338 /* Make sure the requested systemclock is within the PLL's operational limits */ 339 /* lower limit is min_system_vco divided by highest postscaler-factor */ 340 if (req_sclk < (si->ps.min_system_vco / 8.0)) 341 { 342 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 343 req_sclk, (float)(si->ps.min_system_vco / 8.0))); 344 req_sclk = (si->ps.min_system_vco / 8.0); 345 } 346 /* upper limit is max_system_vco */ 347 if (req_sclk > si->ps.max_system_vco) 348 { 349 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 350 req_sclk, (float)si->ps.max_system_vco)); 351 req_sclk = si->ps.max_system_vco; 352 } 353 354 /* iterate through all valid PLL postscaler settings */ 355 for (p=0x01; p < 0x10; p = p<<1) 356 { 357 /* calculate the needed VCO frequency for this postscaler setting */ 358 f_vco = req_sclk * p; 359 360 /* check if this is within range of the VCO specs */ 361 if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco)) 362 { 363 /* iterate trough all valid reference-frequency postscaler settings */ 364 for (m = 2; m <= m_max; m++) 365 { 366 /* calculate VCO postscaler setting for current setup.. */ 367 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 368 /* ..and check for validity */ 369 if ((n < 8) || (n > 128)) continue; 370 371 /* find error in frequency this setting gives */ 372 error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p)); 373 374 /* note the setting if best yet */ 375 if (error < error_best) 376 { 377 error_best = error; 378 best[0]=m; 379 best[1]=n; 380 best[2]=p; 381 } 382 } 383 } 384 } 385 386 /* setup the scalers programming values for found optimum setting */ 387 m=best[0] - 1; 388 n=best[1] - 1; 389 p=best[2] - 1; 390 391 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed, 392 * for the current card (see G100, G200 and G400 specs). */ 393 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); 394 LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco)); 395 396 switch(si->ps.card_type) 397 { 398 default: 399 for(;;) 400 { 401 if (f_vco >= 240) {p |= (0x03 << 3); break;}; 402 if (f_vco >= 170) {p |= (0x02 << 3); break;}; 403 if (f_vco >= 110) {p |= (0x01 << 3); break;}; 404 break; 405 } 406 break; 407 } 408 409 /* return the results */ 410 *calc_sclk = f_vco / ((p & 0x07) + 1); 411 *m_result = m; 412 *n_result = n; 413 *p_result = p; 414 415 /* display the found pixelclock values */ 416 LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 417 req_sclk, *calc_sclk, *m_result, *n_result, *p_result)); 418 419 return B_OK; 420 } 421 422 /*set up system pll - NB mclk is memory clock */ 423 status_t g400_dac_set_sys_pll() 424 { 425 /* values for DAC sys pll registers */ 426 uint8 m, n, p; 427 // uint time = 0; 428 float calc_sclk; 429 430 LOG(1,("DAC: Setting up G400/G400MAX system clock\n")); 431 g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p); 432 433 /* reprogram the clock - set PCI/AGP, program, set to programmed */ 434 /* clear, so don't o/clock addons */ 435 // CFGW(OPTION2, 0); 436 /* disable the SYSPLL */ 437 // CFGW(OPTION, CFGR(OPTION) | 0x04); 438 /* select the PCI/AGP clock */ 439 // CFGW(OPTION3, 0); 440 /* enable the SYSPLL */ 441 // CFGW(OPTION, CFGR(OPTION) & 0xfffffffb); 442 443 /* program the new clock */ 444 // DXIW(SYSPLLM, m); 445 // DXIW(SYSPLLN, n); 446 // DXIW(SYSPLLP, p); 447 448 /* Wait for the SYSPLL frequency to lock until timeout occurs */ 449 /* while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000)) 450 { 451 time++; 452 snooze(1); 453 } 454 455 if (time > 2000) 456 LOG(2,("DAC: sys PLL frequency not locked!\n")); 457 else 458 LOG(2,("DAC: sys PLL frequency locked\n")); 459 */ 460 /* disable the SYSPLL */ 461 // CFGW(OPTION, CFGR(OPTION) | 0x04); 462 /* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */ 463 // CFGW(OPTION3, si->ps.option3_reg); 464 /* make sure the PLLs are not swapped (set default config) */ 465 // CFGW(OPTION, CFGR(OPTION) & 0xffffffbf); 466 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */ 467 // CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20); 468 469 return B_OK; 470 } 471