/*
* ICS534x GENDAC.
* For now assumed to be hooked to either a Tseng Labs ET4000-W32p
* (Hercules Dynamite Power, the Hercules generates RS2 using CLK3)
* or an ARK2000pv (Diamond Stealth64 Graphics 2001).
*/
static uchar
setrs2(Vga* vga, Ctlr* ctlr)
{
uchar rs2;
static void
clock(Vga* vga, Ctlr* ctlr)
{
ulong f, m, n, r;
double fmin, fmax, t, tok;
/*
* The PLL frequency is defined by:
* (M+2)
* Fout = ------------ x Fref
* (N+2) x 2**R
* where M, N and R have the following contraints:
* 1) 2MHz < Fref < 32MHz
* 2) Fref
* 600KHz < ----- <= 8Mhz
* (N+2)
* 3) (M+2) x Fref
* 60MHz <= ------------ <= 270MHz
* (N+2)
* 4) Fout < 135MHz
* 5) 1 <= M <= 127, 1 <= N <= 31, 0 <= R <= 3
*
* First determine R by finding the highest value
* for which
* 2**R x Fout <= 270Mhz
* The datasheet says that if the multiplexed 16-bit
* pseudo-colour mode is used then N2 (vga->r) must
* be 2.
*/
if(ctlr->flag & Upclk2x8)
vga->r[0] = 2;
else{
vga->r[0] = 4;
for(r = 0; r <= 3; r++){
f = vga->f[0]*(1<<r);
if(60000000 < f && f <= 270000000)
vga->r[0] = r;
}
if(vga->r[0] > 3)
error("%s: pclk %lud out of range\n",
ctlr->name, vga->f[0]);
}
/*
* Now find the closest match for M and N.
* Lower values of M and N give better noise rejection.
*/
fmin = vga->f[0]*0.995;
fmax = vga->f[0]*1.005;
tok = 0.0;
for(n = 31; n >= 1; n--){
t = RefFreq/(n+2);
if(600000 >= t || t > 8000000)
continue;
t = vga->f[0]*(n+2)*(1<<vga->r[0]);
t /= RefFreq;
m = (t+0.5) - 2;
if(m > 127)
continue;
t = (m+2)*RefFreq;
t /= (n+2)*(1<<vga->r[0]);
if(fmin <= t && t < fmax){
vga->m[0] = m;
vga->n[0] = n;
tok = t;
}
}
if(tok == 0.0)
error("%s: pclk %lud out of range\n", ctlr->name, vga->f[0]);
}
/*
* Part comes in -135, -110 and -80MHz speed-grades.
*/
pclk = 80000000;
if(p = strrchr(ctlr->name, '-'))
pclk = strtoul(p+1, 0, 0) * 1000000;
/*
* If we don't already have a desired pclk,
* take it from the mode.
* Check it's within range.
*/
if(vga->f[0] == 0)
vga->f[0] = vga->mode->frequency;
if(vga->f[0] > pclk)
error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
/*
* Determine whether to use 2x8-bit mode or not.
* If yes and the clock has already been initialised,
* initialise it again.
*/
if(vga->ctlr && (vga->ctlr->flag & Hpclk2x8) && vga->mode->z == 8 && vga->f[0] >= pclk/2){
vga->f[0] /= 2;
resyncinit(vga, ctlr, Upclk2x8, 0);
}
/*
* Clock bits. If the desired video clock is
* one of the two standard VGA clocks it can just be
* set using bits <3:2> of vga->misc, otherwise we
* need to programme the DCLK PLL.
*/
vga->misc &= ~0x0C;
if(vga->f[0] == VgaFreq0)
vga->i[0] = 0;
else if(vga->f[0] == VgaFreq1){
vga->misc |= 0x04;
vga->i[0] = 1;
}
else{
/*
* Initialise the PLL parameters.
* Use CLK0 f7 internal clock (there are only 3
* clock-select bits).
*/
clock(vga, ctlr);
vga->i[0] = 0x07;
}