#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "cir.h"
#define CLOCK_FACTOR 28636
#define MIN_VCO CLOCK_FACTOR
#define MAX_VCO 111000
#define VCOVAL(n, d) \
((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) )
#define CLOCKVAL(n, d) \
(VCOVAL(n, d) >> ((d) & 1))
typedef struct {
unsigned char numer;
unsigned char denom;
} cirrusClockRec;
static cirrusClockRec cirrusClockTab[] = {
{ 0x2C, 0x33 },
{ 0x4A, 0x2B },
{ 0x5B, 0x2F },
{ 0x45, 0x30 },
{ 0x7E, 0x33 },
{ 0x42, 0x1F },
{ 0x51, 0x3A },
{ 0x55, 0x36 },
{ 0x65, 0x3A },
{ 0x76, 0x34 },
{ 0x7E, 0x32 },
{ 0x6E, 0x2A },
{ 0x5F, 0x22 },
{ 0x7D, 0x2A },
{ 0x58, 0x1C },
{ 0x49, 0x16 },
{ 0x46, 0x14 },
{ 0x53, 0x16 },
{ 0x5C, 0x18 },
{ 0x6D, 0x1A },
{ 0x58, 0x14 },
{ 0x6D, 0x18 },
{ 0x42, 0x0E },
{ 0x69, 0x14 },
{ 0x5E, 0x10 },
{ 0x5C, 0x0E },
{ 0x67, 0x0E },
{ 0x60, 0x0C },
};
#define NU_FIXED_CLOCKS (sizeof(cirrusClockTab)/sizeof(cirrusClockTab[0]))
Bool
CirrusFindClock(int *rfreq, int max_clock, int *num_out, int *den_out)
{
int n, i;
int num = 0, den = 0;
int freq, ffreq = 0, mindiff = 0;
freq = *rfreq;
for (i = 0; i < NU_FIXED_CLOCKS; i++) {
int diff;
diff = abs(CLOCKVAL(cirrusClockTab[i].numer,
cirrusClockTab[i].denom) - freq);
if (diff < freq / 1000) {
num = cirrusClockTab[i].numer;
den = cirrusClockTab[i].denom;
ffreq = CLOCKVAL(num, den);
goto foundclock;
}
}
if (MAX_VCO > max_clock)
max_clock = MAX_VCO;
mindiff = freq;
for (n = 0x10; n < 0x7f; n++) {
int d;
for (d = 0x14; d < 0x3f; d++) {
int c, diff;
if ((VCOVAL(n, d) < MIN_VCO) || (VCOVAL(n, d) > max_clock))
continue;
c = CLOCKVAL(n, d);
diff = abs(c - freq);
if (diff < mindiff) {
mindiff = diff;
num = n;
den = d;
ffreq = c;
}
}
}
if (0 == num || 0 == den)
return FALSE;
foundclock:
*num_out = num;
*den_out = den;
*rfreq = ffreq;
return TRUE;
}