added system PLL specific calc routine

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9177 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2004-10-04 11:30:45 +00:00
parent f8eb549d45
commit 52e0509d97
3 changed files with 74 additions and 113 deletions
+67 -89
View File
@@ -1,6 +1,6 @@
/* program the DAC */
/* Author:
Rudolf Cornelissen 12/2003-9/2004
Rudolf Cornelissen 12/2003-10/2004
*/
#define MODULE_BIT 0x00010000
@@ -9,8 +9,6 @@
static status_t nv4_nv10_nv20_dac_pix_pll_find(
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
static status_t g100_g400max_dac_sys_pll_find(
float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
/* see if an analog VGA monitor is connected to connector #1 */
bool nv_dac_crt_connected(void)
@@ -386,19 +384,19 @@ static status_t nv4_nv10_nv20_dac_pix_pll_find(
}
/* find nearest valid system PLL setting */
static status_t g100_g400max_dac_sys_pll_find(
float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
status_t nv_dac_sys_pll_find(
float req_sclk, float* calc_sclk, uint8* m_result, uint8* n_result, uint8* p_result, uint8 test)
{
int m = 0, n = 0, p = 0, m_max;
int m = 0, n = 0, p = 0/*, m_max*/;
float error, error_best = 999999999;
int best[3];
float f_vco;
/* determine the max. reference-frequency postscaler setting for the
* current card (see G100, G200 and G400 specs). */
switch(si->ps.card_type)
/* switch(si->ps.card_type)
{
/* case G100:
case G100:
LOG(4,("DAC: G100 restrictions apply\n"));
m_max = 7;
break;
@@ -406,30 +404,32 @@ static status_t g100_g400max_dac_sys_pll_find(
LOG(4,("DAC: G200 restrictions apply\n"));
m_max = 7;
break;
*/ default:
default:
LOG(4,("DAC: G400/G400MAX restrictions apply\n"));
m_max = 32;
break;
}
*/
LOG(4,("DAC: NV4/NV10/NV20 restrictions apply\n"));
/* Make sure the requested systemclock is within the PLL's operational limits */
/* Make sure the requested clock is within the PLL's operational limits */
/* lower limit is min_system_vco divided by highest postscaler-factor */
if (req_sclk < (si->ps.min_system_vco / 8.0))
if (req_sclk < (si->ps.min_system_vco / 16.0))
{
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
req_sclk, (float)(si->ps.min_system_vco / 8.0)));
req_sclk = (si->ps.min_system_vco / 8.0);
req_sclk, (float)(si->ps.min_system_vco / 16.0)));
req_sclk = (si->ps.min_system_vco / 16.0);
}
/* upper limit is max_system_vco */
/* upper limit is given by pins */
if (req_sclk > si->ps.max_system_vco)
{
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
req_sclk, (float)si->ps.max_system_vco));
req_sclk, (float)si->ps.max_system_vco));
req_sclk = si->ps.max_system_vco;
}
/* iterate through all valid PLL postscaler settings */
for (p=0x01; p < 0x10; p = p<<1)
for (p=0x01; p < 0x20; p = p<<1)
{
/* calculate the needed VCO frequency for this postscaler setting */
f_vco = req_sclk * p;
@@ -437,16 +437,37 @@ static status_t g100_g400max_dac_sys_pll_find(
/* check if this is within range of the VCO specs */
if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
{
/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
if (si->ps.ext_pll) f_vco /= 4;
/* iterate trough all valid reference-frequency postscaler settings */
for (m = 2; m <= m_max; m++)
for (m = 7; m <= 14; m++)
{
/* check if phase-discriminator will be within operational limits */
//fixme: PLL calcs will be resetup/splitup/updated...
if (si->ps.card_type == NV36)
{
if (((si->ps.f_ref / m) < 3.2) || ((si->ps.f_ref / m) > 6.4)) continue;
}
else
{
if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
}
/* calculate VCO postscaler setting for current setup.. */
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
/* ..and check for validity */
if ((n < 8) || (n > 128)) continue;
if ((n < 1) || (n > 255)) continue;
/* find error in frequency this setting gives */
error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p));
if (si->ps.ext_pll)
{
/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
error = fabs((req_sclk / 4) - (((si->ps.f_ref / m) * n) / p));
}
else
error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p));
/* note the setting if best yet */
if (error < error_best)
@@ -461,32 +482,39 @@ static status_t g100_g400max_dac_sys_pll_find(
}
/* setup the scalers programming values for found optimum setting */
m=best[0] - 1;
n=best[1] - 1;
p=best[2] - 1;
m = best[0];
n = best[1];
p = best[2];
/* log the VCO frequency found */
f_vco = ((si->ps.f_ref / m) * n);
/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
if (si->ps.ext_pll) f_vco *= 4;
/* calc the needed PLL loopbackfilter setting belonging to current VCO speed,
* for the current card (see G100, G200 and G400 specs). */
f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
switch(si->ps.card_type)
{
default:
for(;;)
{
if (f_vco >= 240) {p |= (0x03 << 3); break;};
if (f_vco >= 170) {p |= (0x02 << 3); break;};
if (f_vco >= 110) {p |= (0x01 << 3); break;};
break;
}
break;
}
/* return the results */
*calc_sclk = f_vco / ((p & 0x07) + 1);
*calc_sclk = (f_vco / p);
*m_result = m;
*n_result = n;
switch(p)
{
case 1:
p = 0x00;
break;
case 2:
p = 0x01;
break;
case 4:
p = 0x02;
break;
case 8:
p = 0x03;
break;
case 16:
p = 0x04;
break;
}
*p_result = p;
/* display the found pixelclock values */
@@ -495,53 +523,3 @@ static status_t g100_g400max_dac_sys_pll_find(
return B_OK;
}
/*set up system pll - NB mclk is memory clock */
status_t g400_dac_set_sys_pll()
{
/* values for DAC sys pll registers */
uint8 m, n, p;
// uint time = 0;
float calc_sclk;
LOG(1,("DAC: Setting up G400/G400MAX system clock\n"));
g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
/* reprogram the clock - set PCI/AGP, program, set to programmed */
/* clear, so don't o/clock addons */
// CFGW(OPTION2, 0);
/* disable the SYSPLL */
// CFGW(OPTION, CFGR(OPTION) | 0x04);
/* select the PCI/AGP clock */
// CFGW(OPTION3, 0);
/* enable the SYSPLL */
// CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
/* program the new clock */
// DXIW(SYSPLLM, m);
// DXIW(SYSPLLN, n);
// DXIW(SYSPLLP, p);
/* Wait for the SYSPLL frequency to lock until timeout occurs */
/* while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
{
time++;
snooze(1);
}
if (time > 2000)
LOG(2,("DAC: sys PLL frequency not locked!\n"));
else
LOG(2,("DAC: sys PLL frequency locked\n"));
*/
/* disable the SYSPLL */
// CFGW(OPTION, CFGR(OPTION) | 0x04);
/* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
// CFGW(OPTION3, si->ps.option3_reg);
/* make sure the PLLs are not swapped (set default config) */
// CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
// CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
return B_OK;
}
@@ -182,9 +182,9 @@ static status_t pins3_5_read(uint8 *rom, uint32 offset)
LOG(8,("INFO: PLL VCO range is %dkHz - %dkHz\n", fvco_min, fvco_max));
/* modify presets to reflect card capability */
si->ps.min_system_vco = fvco_min / 1000;
si->ps.max_system_vco = fvco_max / 1000;
//fixme: enable and modify PLL code...
//si->ps.min_system_vco = fvco_min / 1000;
//si->ps.max_system_vco = fvco_max / 1000;
//si->ps.min_pixel_vco = fvco_min / 1000;
//si->ps.max_pixel_vco = fvco_max / 1000;
//si->ps.min_video_vco = fvco_min / 1000;
@@ -412,13 +412,9 @@ static status_t exec_type1_script(uint8* rom, uint16 adress, int16* size, uint16
reg, ((float)data2)));
if (exec)
{
//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...
display_mode target;
float calced_clk;
uint8 m, n, p;
target.space = B_CMAP8;
target.timing.pixel_clock = (data2 * 1000);
nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);
nv_dac_sys_pll_find(((float)data2), &calced_clk, &m, &n, &p, 0);
NV_REG32(reg) = ((p << 16) | (n << 8) | m);
}
log_pll(reg);
@@ -718,13 +714,9 @@ static status_t exec_type1_script(uint8* rom, uint16 adress, int16* size, uint16
LOG(8,("cmd 'calculate and set PLL 32bit reg $%08x for %.3fMHz'\n", reg, (data / 100.0)));
if (exec)
{
//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...
display_mode target;
float calced_clk;
uint8 m, n, p;
target.space = B_CMAP8;
target.timing.pixel_clock = (data * 10);
nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);
nv_dac_sys_pll_find((data / 100.0), &calced_clk, &m, &n, &p, 0);
NV_REG32(reg) = ((p << 16) | (n << 8) | m);
}
log_pll(reg);
@@ -1035,13 +1027,9 @@ static status_t exec_type2_script_mode(uint8* rom, uint16* adress, int16* size,
reg2, (data2 / 100.0)));
if (*exec && reg2)
{
//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...
display_mode target;
float calced_clk;
uint8 m, n, p;
target.space = B_CMAP8;
target.timing.pixel_clock = (data2 * 10);
nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);
nv_dac_sys_pll_find((data2 / 100.0), &calced_clk, &m, &n, &p, 0);
NV_REG32(reg2) = ((p << 16) | (n << 8) | m);
//fixme?
/* program 2nd set N and M scalers if they exist (b31=1 enables them) */
@@ -1542,7 +1530,6 @@ static status_t exec_type2_script_mode(uint8* rom, uint16* adress, int16* size,
}
/* execute */
//fixme: setup new PLL routines that adhere to pins speeds for VCO, etc...
*adress += 1;
reg = *((uint32*)(&(rom[*adress])));
*adress += 4;
@@ -1551,13 +1538,9 @@ static status_t exec_type2_script_mode(uint8* rom, uint16* adress, int16* size,
LOG(8,("cmd 'calculate and set PLL 32bit reg $%08x for %.3fMHz'\n", reg, (data / 100.0)));
if (*exec)
{
//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...
display_mode target;
float calced_clk;
uint8 m, n, p;
target.space = B_CMAP8;
target.timing.pixel_clock = (data * 10);
nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);
nv_dac_sys_pll_find((data / 100.0), &calced_clk, &m, &n, &p, 0);
NV_REG32(reg) = ((p << 16) | (n << 8) | m);
//fixme?
/* program 2nd set N and M scalers if they exist (b31=1 enables them) */
@@ -44,7 +44,7 @@ status_t nv_dac_mode(int,float);
status_t nv_dac_palette(uint8*,uint8*,uint8*);
status_t nv_dac_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8);
status_t nv_dac_set_pix_pll(display_mode target);
status_t g400_dac_set_sys_pll(void);
status_t nv_dac_sys_pll_find(float, float*, uint8*, uint8*, uint8*, uint8);
/* DAC2 functions */
bool nv_dac2_crt_connected(void);