20 static inline unsigned int g450_vco2f(
unsigned char p,
unsigned int fvco) {
21 return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1);
24 static inline unsigned int g450_f2vco(
unsigned char p,
unsigned int fin) {
25 return (p & 0x40) ? fin : fin << ((p & 3) + 1);
28 static unsigned int g450_mnp2vco(
const struct matrox_fb_info *minfo,
33 m = ((mnp >> 16) & 0x0FF) + 1;
34 n = ((mnp >> 7) & 0x1FE) + 4;
35 return (minfo->
features.pll.ref_freq * n + (m >> 1)) / m;
40 return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp));
43 static inline unsigned int pll_freq_delta(
unsigned int f1,
unsigned int f2) {
52 #define NO_MORE_MNP 0x01FFFFFF
53 #define G450_MNP_FREQBITS (0xFFFFFF43)
55 static unsigned int g450_nextpll(
const struct matrox_fb_info *minfo,
57 unsigned int *fvco,
unsigned int mnp)
60 unsigned int tvco = *fvco;
62 m = (mnp >> 16) & 0xFF;
66 if (m == 0 || m == 0xFF) {
77 if (tvco < pi->vcomin) {
86 }
else if (tvco < 700000) {
88 }
else if (tvco < 1000000) {
90 }
else if (tvco < 1150000) {
99 n = ((tvco * (m+1) + minfo->
features.pll.ref_freq) / (minfo->
features.pll.ref_freq * 2)) - 2;
100 }
while (n < 0x03 || n > 0x7A);
101 return (m << 16) | (n << 8) | p;
104 static unsigned int g450_firstpll(
const struct matrox_fb_info *minfo,
106 unsigned int *vco,
unsigned int fout)
112 if (fout > (vcomax / 2)) {
123 tvco = g450_f2vco(p, fout);
124 while (p && (tvco > vcomax)) {
128 if (tvco < pi->vcomin) {
133 return g450_nextpll(minfo, pi, vco, 0xFF0000 | p);
136 static inline unsigned int g450_setpll(
const struct matrox_fb_info *minfo,
137 unsigned int mnp,
unsigned int pll)
173 static inline unsigned int g450_cmppll(
const struct matrox_fb_info *minfo,
174 unsigned int mnp,
unsigned int pll)
176 unsigned char m = mnp >> 16;
177 unsigned char n = mnp >> 8;
178 unsigned char p = mnp;
209 static inline int g450_isplllocked(
const struct matrox_fb_info *minfo,
214 for (j = 0; j < 1000; j++) {
219 for (i = 0; i < 100; i++) {
222 return r >= (90 * 0x40);
229 static int g450_testpll(
const struct matrox_fb_info *minfo,
unsigned int mnp,
232 return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll));
235 static void updatehwstate_clk(
struct matrox_hw_state*
hw,
unsigned int mnp,
unsigned int pll) {
238 hw->
DACclk[3] = mnp >> 16;
248 if (g450_cmppll(minfo, mnp, pll)) {
249 g450_setpll(minfo, mnp, pll);
253 static inline unsigned int g450_findworkingpll(
struct matrox_fb_info *minfo,
255 unsigned int *mnparray,
256 unsigned int mnpcount)
258 unsigned int found = 0;
260 unsigned int mnpfound = mnparray[0];
262 for (idx = 0; idx < mnpcount; idx++) {
263 unsigned int sarray[3];
273 if ((mnp & 0x38) != 0x38) {
278 while (sptr >= sarray) {
279 unsigned int mnp = *sptr--;
281 if (g450_testpll(minfo, mnp - 0x0300, pll) &&
282 g450_testpll(minfo, mnp + 0x0300, pll) &&
283 g450_testpll(minfo, mnp - 0x0200, pll) &&
284 g450_testpll(minfo, mnp + 0x0200, pll) &&
285 g450_testpll(minfo, mnp - 0x0100, pll) &&
286 g450_testpll(minfo, mnp + 0x0100, pll)) {
287 if (g450_testpll(minfo, mnp, pll)) {
290 }
else if (!found && g450_testpll(minfo, mnp, pll)) {
296 g450_setpll(minfo, mnpfound, pll);
300 static void g450_addcache(
struct matrox_pll_cache* ci,
unsigned int mnp_key,
unsigned int mnp_value) {
306 ci->
data[0].mnp_value = mnp_value;
315 for (i = 0; i < ci->
valid; i++) {
316 if (ci->
data[i].mnp_key == mnp_key) {
319 mnp = ci->
data[
i].mnp_value;
322 ci->
data[0].mnp_key = mnp_key;
323 ci->
data[0].mnp_value = mnp;
331 static int __g450_setclk(
struct matrox_fb_info *minfo,
unsigned int fout,
332 unsigned int pll,
unsigned int *mnparray,
333 unsigned int *deltaarray)
335 unsigned int mnpcount;
336 unsigned int pixel_vco;
394 pi = &minfo->
limits.pixel;
395 ci = &minfo->
cache.pixel;
406 pi = &minfo->
limits.system;
407 ci = &minfo->
cache.system;
423 pixel_vco = g450_mnp2vco(minfo, mnp);
426 pi = &minfo->
limits.video;
427 ci = &minfo->
cache.video;
438 for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp !=
NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) {
443 vco = g450_mnp2vco(minfo, mnp);
446 unsigned int big, small;
448 if (vco < pixel_vco) {
455 while (big > small) {
463 delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
464 for (idx = mnpcount; idx > 0; idx--) {
469 if (delta <= deltaarray[idx-1]) {
474 if (delta == deltaarray[idx-1]
475 && vco != g450_mnp2vco(minfo, mnparray[idx-1])
476 && vco < (pi->
vcomin * 17 / 16)) {
479 mnparray[
idx] = mnparray[idx-1];
480 deltaarray[
idx] = deltaarray[idx-1];
499 mnp = g450_checkcache(minfo, ci, mnparray[0]);
503 mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount);
504 g450_addcache(ci, mnparray[0], mnp);
506 updatehwstate_clk(&minfo->
hw, mnp, pll);
514 #define MNP_TABLE_SIZE 64
525 r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE);