• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  *  ATI Mach64 GX Support
4  */
5 
6 #include <linux/delay.h>
7 #include <linux/fb.h>
8 
9 #include <asm/io.h>
10 
11 #include <video/mach64.h>
12 #include "atyfb.h"
13 
14 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
15 
16 #define REF_FREQ_2595       1432	/*  14.33 MHz  (exact   14.31818) */
17 #define REF_DIV_2595          46	/* really 43 on ICS 2595 !!!  */
18 				  /* ohne Prescaler */
19 #define MAX_FREQ_2595      15938	/* 159.38 MHz  (really 170.486) */
20 #define MIN_FREQ_2595       8000	/*  80.00 MHz  (        85.565) */
21 				  /* mit Prescaler 2, 4, 8 */
22 #define ABS_MIN_FREQ_2595   1000	/*  10.00 MHz  (really  10.697) */
23 #define N_ADJ_2595           257
24 
25 #define STOP_BITS_2595     0x1800
26 
27 
28 #define MIN_N_408		2
29 
30 #define MIN_N_1703		6
31 
32 #define MIN_M		2
33 #define MAX_M		30
34 #define MIN_N		35
35 #define MAX_N		255-8
36 
37 
38     /*
39      *  Support Functions
40      */
41 
aty_dac_waste4(const struct atyfb_par * par)42 static void aty_dac_waste4(const struct atyfb_par *par)
43 {
44 	(void) aty_ld_8(DAC_REGS, par);
45 
46 	(void) aty_ld_8(DAC_REGS + 2, par);
47 	(void) aty_ld_8(DAC_REGS + 2, par);
48 	(void) aty_ld_8(DAC_REGS + 2, par);
49 	(void) aty_ld_8(DAC_REGS + 2, par);
50 }
51 
aty_StrobeClock(const struct atyfb_par * par)52 static void aty_StrobeClock(const struct atyfb_par *par)
53 {
54 	u8 tmp;
55 
56 	udelay(26);
57 
58 	tmp = aty_ld_8(CLOCK_CNTL, par);
59 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, tmp | CLOCK_STROBE, par);
60 	return;
61 }
62 
63 
64     /*
65      *  IBM RGB514 DAC and Clock Chip
66      */
67 
aty_st_514(int offset,u8 val,const struct atyfb_par * par)68 static void aty_st_514(int offset, u8 val, const struct atyfb_par *par)
69 {
70 	aty_st_8(DAC_CNTL, 1, par);
71 	/* right addr byte */
72 	aty_st_8(DAC_W_INDEX, offset & 0xff, par);
73 	/* left addr byte */
74 	aty_st_8(DAC_DATA, (offset >> 8) & 0xff, par);
75 	aty_st_8(DAC_MASK, val, par);
76 	aty_st_8(DAC_CNTL, 0, par);
77 }
78 
aty_set_dac_514(const struct fb_info * info,const union aty_pll * pll,u32 bpp,u32 accel)79 static int aty_set_dac_514(const struct fb_info *info,
80 			   const union aty_pll *pll, u32 bpp, u32 accel)
81 {
82 	struct atyfb_par *par = (struct atyfb_par *) info->par;
83 	static struct {
84 		u8 pixel_dly;
85 		u8 misc2_cntl;
86 		u8 pixel_rep;
87 		u8 pixel_cntl_index;
88 		u8 pixel_cntl_v1;
89 	} tab[3] = {
90 		{
91 		0, 0x41, 0x03, 0x71, 0x45},	/* 8 bpp */
92 		{
93 		0, 0x45, 0x04, 0x0c, 0x01},	/* 555 */
94 		{
95 		0, 0x45, 0x06, 0x0e, 0x00},	/* XRGB */
96 	};
97 	int i;
98 
99 	switch (bpp) {
100 	case 8:
101 	default:
102 		i = 0;
103 		break;
104 	case 16:
105 		i = 1;
106 		break;
107 	case 32:
108 		i = 2;
109 		break;
110 	}
111 	aty_st_514(0x90, 0x00, par);	/* VRAM Mask Low */
112 	aty_st_514(0x04, tab[i].pixel_dly, par);	/* Horizontal Sync Control */
113 	aty_st_514(0x05, 0x00, par);	/* Power Management */
114 	aty_st_514(0x02, 0x01, par);	/* Misc Clock Control */
115 	aty_st_514(0x71, tab[i].misc2_cntl, par);	/* Misc Control 2 */
116 	aty_st_514(0x0a, tab[i].pixel_rep, par);	/* Pixel Format */
117 	aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, par);
118 	/* Misc Control 2 / 16 BPP Control / 32 BPP Control */
119 	return 0;
120 }
121 
aty_var_to_pll_514(const struct fb_info * info,u32 vclk_per,u32 bpp,union aty_pll * pll)122 static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
123 			      u32 bpp, union aty_pll *pll)
124 {
125 	/*
126 	 *  FIXME: use real calculations instead of using fixed values from the old
127 	 *         driver
128 	 */
129 	static struct {
130 		u32 limit;	/* pixlock rounding limit (arbitrary) */
131 		u8 m;		/* (df<<6) | vco_div_count */
132 		u8 n;		/* ref_div_count */
133 	} RGB514_clocks[7] = {
134 		{
135 		8000, (3 << 6) | 20, 9},	/*  7395 ps / 135.2273 MHz */
136 		{
137 		10000, (1 << 6) | 19, 3},	/*  9977 ps / 100.2273 MHz */
138 		{
139 		13000, (1 << 6) | 2, 3},	/* 12509 ps /  79.9432 MHz */
140 		{
141 		14000, (2 << 6) | 8, 7},	/* 13394 ps /  74.6591 MHz */
142 		{
143 		16000, (1 << 6) | 44, 6},	/* 15378 ps /  65.0284 MHz */
144 		{
145 		25000, (1 << 6) | 15, 5},	/* 17460 ps /  57.2727 MHz */
146 		{
147 		50000, (0 << 6) | 53, 7},	/* 33145 ps /  30.1705 MHz */
148 	};
149 	int i;
150 
151 	for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
152 		if (vclk_per <= RGB514_clocks[i].limit) {
153 			pll->ibm514.m = RGB514_clocks[i].m;
154 			pll->ibm514.n = RGB514_clocks[i].n;
155 			return 0;
156 		}
157 	return -EINVAL;
158 }
159 
aty_pll_514_to_var(const struct fb_info * info,const union aty_pll * pll)160 static u32 aty_pll_514_to_var(const struct fb_info *info,
161 			      const union aty_pll *pll)
162 {
163 	struct atyfb_par *par = (struct atyfb_par *) info->par;
164 	u8 df, vco_div_count, ref_div_count;
165 
166 	df = pll->ibm514.m >> 6;
167 	vco_div_count = pll->ibm514.m & 0x3f;
168 	ref_div_count = pll->ibm514.n;
169 
170 	return ((par->ref_clk_per * ref_div_count) << (3 - df))/
171 	    		(vco_div_count + 65);
172 }
173 
aty_set_pll_514(const struct fb_info * info,const union aty_pll * pll)174 static void aty_set_pll_514(const struct fb_info *info,
175 			    const union aty_pll *pll)
176 {
177 	struct atyfb_par *par = (struct atyfb_par *) info->par;
178 
179 	aty_st_514(0x06, 0x02, par);	/* DAC Operation */
180 	aty_st_514(0x10, 0x01, par);	/* PLL Control 1 */
181 	aty_st_514(0x70, 0x01, par);	/* Misc Control 1 */
182 	aty_st_514(0x8f, 0x1f, par);	/* PLL Ref. Divider Input */
183 	aty_st_514(0x03, 0x00, par);	/* Sync Control */
184 	aty_st_514(0x05, 0x00, par);	/* Power Management */
185 	aty_st_514(0x20, pll->ibm514.m, par);	/* F0 / M0 */
186 	aty_st_514(0x21, pll->ibm514.n, par);	/* F1 / N0 */
187 }
188 
189 const struct aty_dac_ops aty_dac_ibm514 = {
190 	.set_dac	= aty_set_dac_514,
191 };
192 
193 const struct aty_pll_ops aty_pll_ibm514 = {
194 	.var_to_pll	= aty_var_to_pll_514,
195 	.pll_to_var	= aty_pll_514_to_var,
196 	.set_pll	= aty_set_pll_514,
197 };
198 
199 
200     /*
201      *  ATI 68860-B DAC
202      */
203 
aty_set_dac_ATI68860_B(const struct fb_info * info,const union aty_pll * pll,u32 bpp,u32 accel)204 static int aty_set_dac_ATI68860_B(const struct fb_info *info,
205 				  const union aty_pll *pll, u32 bpp,
206 				  u32 accel)
207 {
208 	struct atyfb_par *par = (struct atyfb_par *) info->par;
209 	u32 gModeReg, devSetupRegA, temp, mask;
210 
211 	gModeReg = 0;
212 	devSetupRegA = 0;
213 
214 	switch (bpp) {
215 	case 8:
216 		gModeReg = 0x83;
217 		devSetupRegA =
218 		    0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */ ;
219 		break;
220 	case 15:
221 		gModeReg = 0xA0;
222 		devSetupRegA = 0x60;
223 		break;
224 	case 16:
225 		gModeReg = 0xA1;
226 		devSetupRegA = 0x60;
227 		break;
228 	case 24:
229 		gModeReg = 0xC0;
230 		devSetupRegA = 0x60;
231 		break;
232 	case 32:
233 		gModeReg = 0xE3;
234 		devSetupRegA = 0x60;
235 		break;
236 	}
237 
238 	if (!accel) {
239 		gModeReg = 0x80;
240 		devSetupRegA = 0x61;
241 	}
242 
243 	temp = aty_ld_8(DAC_CNTL, par);
244 	aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
245 		 par);
246 
247 	aty_st_8(DAC_REGS + 2, 0x1D, par);
248 	aty_st_8(DAC_REGS + 3, gModeReg, par);
249 	aty_st_8(DAC_REGS, 0x02, par);
250 
251 	temp = aty_ld_8(DAC_CNTL, par);
252 	aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
253 
254 	if (info->fix.smem_len < ONE_MB)
255 		mask = 0x04;
256 	else if (info->fix.smem_len == ONE_MB)
257 		mask = 0x08;
258 	else
259 		mask = 0x0C;
260 
261 	/* The following assumes that the BIOS has correctly set R7 of the
262 	 * Device Setup Register A at boot time.
263 	 */
264 #define A860_DELAY_L	0x80
265 
266 	temp = aty_ld_8(DAC_REGS, par);
267 	aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L),
268 		 par);
269 	temp = aty_ld_8(DAC_CNTL, par);
270 	aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)),
271 		 par);
272 
273 	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
274 	aty_st_le32(DAC_CNTL, 0x47052100, par);
275 	return 0;
276 }
277 
278 const struct aty_dac_ops aty_dac_ati68860b = {
279 	.set_dac	= aty_set_dac_ATI68860_B,
280 };
281 
282 
283     /*
284      *  AT&T 21C498 DAC
285      */
286 
aty_set_dac_ATT21C498(const struct fb_info * info,const union aty_pll * pll,u32 bpp,u32 accel)287 static int aty_set_dac_ATT21C498(const struct fb_info *info,
288 				 const union aty_pll *pll, u32 bpp,
289 				 u32 accel)
290 {
291 	struct atyfb_par *par = (struct atyfb_par *) info->par;
292 	u32 dotClock;
293 	int muxmode = 0;
294 	int DACMask = 0;
295 
296 	dotClock = 100000000 / pll->ics2595.period_in_ps;
297 
298 	switch (bpp) {
299 	case 8:
300 		if (dotClock > 8000) {
301 			DACMask = 0x24;
302 			muxmode = 1;
303 		} else
304 			DACMask = 0x04;
305 		break;
306 	case 15:
307 		DACMask = 0x16;
308 		break;
309 	case 16:
310 		DACMask = 0x36;
311 		break;
312 	case 24:
313 		DACMask = 0xE6;
314 		break;
315 	case 32:
316 		DACMask = 0xE6;
317 		break;
318 	}
319 
320 	if (1 /* info->mach64DAC8Bit */ )
321 		DACMask |= 0x02;
322 
323 	aty_dac_waste4(par);
324 	aty_st_8(DAC_REGS + 2, DACMask, par);
325 
326 	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
327 	aty_st_le32(DAC_CNTL, 0x00072000, par);
328 	return muxmode;
329 }
330 
331 const struct aty_dac_ops aty_dac_att21c498 = {
332 	.set_dac	= aty_set_dac_ATT21C498,
333 };
334 
335 
336     /*
337      *  ATI 18818 / ICS 2595 Clock Chip
338      */
339 
aty_var_to_pll_18818(const struct fb_info * info,u32 vclk_per,u32 bpp,union aty_pll * pll)340 static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
341 				u32 bpp, union aty_pll *pll)
342 {
343 	u32 MHz100;		/* in 0.01 MHz */
344 	u32 program_bits;
345 	u32 post_divider;
346 
347 	/* Calculate the programming word */
348 	MHz100 = 100000000 / vclk_per;
349 
350 	program_bits = -1;
351 	post_divider = 1;
352 
353 	if (MHz100 > MAX_FREQ_2595) {
354 		MHz100 = MAX_FREQ_2595;
355 		return -EINVAL;
356 	} else if (MHz100 < ABS_MIN_FREQ_2595) {
357 		program_bits = 0;	/* MHz100 = 257 */
358 		return -EINVAL;
359 	} else {
360 		while (MHz100 < MIN_FREQ_2595) {
361 			MHz100 *= 2;
362 			post_divider *= 2;
363 		}
364 	}
365 	MHz100 *= 1000;
366 	MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
367 
368 	MHz100 += 500;		/* + 0.5 round */
369 	MHz100 /= 1000;
370 
371 	if (program_bits == -1) {
372 		program_bits = MHz100 - N_ADJ_2595;
373 		switch (post_divider) {
374 		case 1:
375 			program_bits |= 0x0600;
376 			break;
377 		case 2:
378 			program_bits |= 0x0400;
379 			break;
380 		case 4:
381 			program_bits |= 0x0200;
382 			break;
383 		case 8:
384 		default:
385 			break;
386 		}
387 	}
388 
389 	program_bits |= STOP_BITS_2595;
390 
391 	pll->ics2595.program_bits = program_bits;
392 	pll->ics2595.locationAddr = 0;
393 	pll->ics2595.post_divider = post_divider;
394 	pll->ics2595.period_in_ps = vclk_per;
395 
396 	return 0;
397 }
398 
aty_pll_18818_to_var(const struct fb_info * info,const union aty_pll * pll)399 static u32 aty_pll_18818_to_var(const struct fb_info *info,
400 				const union aty_pll *pll)
401 {
402 	return (pll->ics2595.period_in_ps);	/* default for now */
403 }
404 
aty_ICS2595_put1bit(u8 data,const struct atyfb_par * par)405 static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
406 {
407 	u8 tmp;
408 
409 	data &= 0x01;
410 	tmp = aty_ld_8(CLOCK_CNTL, par);
411 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
412 		 (tmp & ~0x04) | (data << 2), par);
413 
414 	tmp = aty_ld_8(CLOCK_CNTL, par);
415 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
416 		 par);
417 
418 	aty_StrobeClock(par);
419 
420 	tmp = aty_ld_8(CLOCK_CNTL, par);
421 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
422 		 par);
423 
424 	aty_StrobeClock(par);
425 	return;
426 }
427 
aty_set_pll18818(const struct fb_info * info,const union aty_pll * pll)428 static void aty_set_pll18818(const struct fb_info *info,
429 			     const union aty_pll *pll)
430 {
431 	struct atyfb_par *par = (struct atyfb_par *) info->par;
432 	u32 program_bits;
433 	u32 locationAddr;
434 
435 	u32 i;
436 
437 	u8 old_clock_cntl;
438 	u8 old_crtc_ext_disp;
439 
440 	old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
441 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
442 
443 	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
444 	aty_st_8(CRTC_GEN_CNTL + 3,
445 		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
446 
447 	mdelay(15);		/* delay for 50 (15) ms */
448 
449 	program_bits = pll->ics2595.program_bits;
450 	locationAddr = pll->ics2595.locationAddr;
451 
452 	/* Program the clock chip */
453 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);	/* Strobe = 0 */
454 	aty_StrobeClock(par);
455 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);	/* Strobe = 0 */
456 	aty_StrobeClock(par);
457 
458 	aty_ICS2595_put1bit(1, par);	/* Send start bits */
459 	aty_ICS2595_put1bit(0, par);	/* Start bit */
460 	aty_ICS2595_put1bit(0, par);	/* Read / ~Write */
461 
462 	for (i = 0; i < 5; i++) {	/* Location 0..4 */
463 		aty_ICS2595_put1bit(locationAddr & 1, par);
464 		locationAddr >>= 1;
465 	}
466 
467 	for (i = 0; i < 8 + 1 + 2 + 2; i++) {
468 		aty_ICS2595_put1bit(program_bits & 1, par);
469 		program_bits >>= 1;
470 	}
471 
472 	mdelay(1);		/* delay for 1 ms */
473 
474 	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
475 	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
476 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
477 		 old_clock_cntl | CLOCK_STROBE, par);
478 
479 	mdelay(50);		/* delay for 50 (15) ms */
480 	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
481 		 ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
482 	return;
483 }
484 
485 const struct aty_pll_ops aty_pll_ati18818_1 = {
486 	.var_to_pll	= aty_var_to_pll_18818,
487 	.pll_to_var	= aty_pll_18818_to_var,
488 	.set_pll	= aty_set_pll18818,
489 };
490 
491 
492     /*
493      *  STG 1703 Clock Chip
494      */
495 
aty_var_to_pll_1703(const struct fb_info * info,u32 vclk_per,u32 bpp,union aty_pll * pll)496 static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
497 			       u32 bpp, union aty_pll *pll)
498 {
499 	u32 mhz100;		/* in 0.01 MHz */
500 	u32 program_bits;
501 	/* u32 post_divider; */
502 	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
503 	u32 temp, tempB;
504 	u16 remainder, preRemainder;
505 	short divider = 0, tempA;
506 
507 	/* Calculate the programming word */
508 	mhz100 = 100000000 / vclk_per;
509 	mach64MinFreq = MIN_FREQ_2595;
510 	mach64MaxFreq = MAX_FREQ_2595;
511 	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
512 
513 	/* Calculate program word */
514 	if (mhz100 == 0)
515 		program_bits = 0xE0;
516 	else {
517 		if (mhz100 < mach64MinFreq)
518 			mhz100 = mach64MinFreq;
519 		if (mhz100 > mach64MaxFreq)
520 			mhz100 = mach64MaxFreq;
521 
522 		divider = 0;
523 		while (mhz100 < (mach64MinFreq << 3)) {
524 			mhz100 <<= 1;
525 			divider += 0x20;
526 		}
527 
528 		temp = (unsigned int) (mhz100);
529 		temp = (unsigned int) (temp * (MIN_N_1703 + 2));
530 		temp -= (short) (mach64RefFreq << 1);
531 
532 		tempA = MIN_N_1703;
533 		preRemainder = 0xffff;
534 
535 		do {
536 			tempB = temp;
537 			remainder = tempB % mach64RefFreq;
538 			tempB = tempB / mach64RefFreq;
539 
540 			if ((tempB & 0xffff) <= 127
541 			    && (remainder <= preRemainder)) {
542 				preRemainder = remainder;
543 				divider &= ~0x1f;
544 				divider |= tempA;
545 				divider =
546 				    (divider & 0x00ff) +
547 				    ((tempB & 0xff) << 8);
548 			}
549 
550 			temp += mhz100;
551 			tempA++;
552 		} while (tempA <= (MIN_N_1703 << 1));
553 
554 		program_bits = divider;
555 	}
556 
557 	pll->ics2595.program_bits = program_bits;
558 	pll->ics2595.locationAddr = 0;
559 	pll->ics2595.post_divider = divider;	/* fuer nix */
560 	pll->ics2595.period_in_ps = vclk_per;
561 
562 	return 0;
563 }
564 
aty_pll_1703_to_var(const struct fb_info * info,const union aty_pll * pll)565 static u32 aty_pll_1703_to_var(const struct fb_info *info,
566 			       const union aty_pll *pll)
567 {
568 	return (pll->ics2595.period_in_ps);	/* default for now */
569 }
570 
aty_set_pll_1703(const struct fb_info * info,const union aty_pll * pll)571 static void aty_set_pll_1703(const struct fb_info *info,
572 			     const union aty_pll *pll)
573 {
574 	struct atyfb_par *par = (struct atyfb_par *) info->par;
575 	u32 program_bits;
576 	u32 locationAddr;
577 
578 	char old_crtc_ext_disp;
579 
580 	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
581 	aty_st_8(CRTC_GEN_CNTL + 3,
582 		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
583 
584 	program_bits = pll->ics2595.program_bits;
585 	locationAddr = pll->ics2595.locationAddr;
586 
587 	/* Program clock */
588 	aty_dac_waste4(par);
589 
590 	(void) aty_ld_8(DAC_REGS + 2, par);
591 	aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
592 	aty_st_8(DAC_REGS + 2, 0, par);
593 	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
594 	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
595 
596 	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
597 	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
598 	return;
599 }
600 
601 const struct aty_pll_ops aty_pll_stg1703 = {
602 	.var_to_pll	= aty_var_to_pll_1703,
603 	.pll_to_var	= aty_pll_1703_to_var,
604 	.set_pll	= aty_set_pll_1703,
605 };
606 
607 
608     /*
609      *  Chrontel 8398 Clock Chip
610      */
611 
aty_var_to_pll_8398(const struct fb_info * info,u32 vclk_per,u32 bpp,union aty_pll * pll)612 static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
613 			       u32 bpp, union aty_pll *pll)
614 {
615 	u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
616 
617 	u32 mhz100;		/* in 0.01 MHz */
618 	u32 program_bits;
619 	/* u32 post_divider; */
620 	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
621 	u16 m, n, k = 0, save_m, save_n, twoToKth;
622 
623 	/* Calculate the programming word */
624 	mhz100 = 100000000 / vclk_per;
625 	mach64MinFreq = MIN_FREQ_2595;
626 	mach64MaxFreq = MAX_FREQ_2595;
627 	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
628 
629 	save_m = 0;
630 	save_n = 0;
631 
632 	/* Calculate program word */
633 	if (mhz100 == 0)
634 		program_bits = 0xE0;
635 	else {
636 		if (mhz100 < mach64MinFreq)
637 			mhz100 = mach64MinFreq;
638 		if (mhz100 > mach64MaxFreq)
639 			mhz100 = mach64MaxFreq;
640 
641 		longMHz100 = mhz100 * 256 / 100;	/* 8 bit scale this */
642 
643 		while (mhz100 < (mach64MinFreq << 3)) {
644 			mhz100 <<= 1;
645 			k++;
646 		}
647 
648 		twoToKth = 1 << k;
649 		diff = 0;
650 		preDiff = 0xFFFFFFFF;
651 
652 		for (m = MIN_M; m <= MAX_M; m++) {
653 			for (n = MIN_N; n <= MAX_N; n++) {
654 				tempA = 938356;		/* 14.31818 * 65536 */
655 				tempA *= (n + 8);	/* 43..256 */
656 				tempB = twoToKth * 256;
657 				tempB *= (m + 2);	/* 4..32 */
658 				fOut = tempA / tempB;	/* 8 bit scale */
659 
660 				if (longMHz100 > fOut)
661 					diff = longMHz100 - fOut;
662 				else
663 					diff = fOut - longMHz100;
664 
665 				if (diff < preDiff) {
666 					save_m = m;
667 					save_n = n;
668 					preDiff = diff;
669 				}
670 			}
671 		}
672 
673 		program_bits = (k << 6) + (save_m) + (save_n << 8);
674 	}
675 
676 	pll->ics2595.program_bits = program_bits;
677 	pll->ics2595.locationAddr = 0;
678 	pll->ics2595.post_divider = 0;
679 	pll->ics2595.period_in_ps = vclk_per;
680 
681 	return 0;
682 }
683 
aty_pll_8398_to_var(const struct fb_info * info,const union aty_pll * pll)684 static u32 aty_pll_8398_to_var(const struct fb_info *info,
685 			       const union aty_pll *pll)
686 {
687 	return (pll->ics2595.period_in_ps);	/* default for now */
688 }
689 
aty_set_pll_8398(const struct fb_info * info,const union aty_pll * pll)690 static void aty_set_pll_8398(const struct fb_info *info,
691 			     const union aty_pll *pll)
692 {
693 	struct atyfb_par *par = (struct atyfb_par *) info->par;
694 	u32 program_bits;
695 	u32 locationAddr;
696 
697 	char old_crtc_ext_disp;
698 	char tmp;
699 
700 	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
701 	aty_st_8(CRTC_GEN_CNTL + 3,
702 		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
703 
704 	program_bits = pll->ics2595.program_bits;
705 	locationAddr = pll->ics2595.locationAddr;
706 
707 	/* Program clock */
708 	tmp = aty_ld_8(DAC_CNTL, par);
709 	aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
710 
711 	aty_st_8(DAC_REGS, locationAddr, par);
712 	aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par);
713 	aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par);
714 
715 	tmp = aty_ld_8(DAC_CNTL, par);
716 	aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3,
717 		 par);
718 
719 	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
720 	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
721 
722 	return;
723 }
724 
725 const struct aty_pll_ops aty_pll_ch8398 = {
726 	.var_to_pll	= aty_var_to_pll_8398,
727 	.pll_to_var	= aty_pll_8398_to_var,
728 	.set_pll	= aty_set_pll_8398,
729 };
730 
731 
732     /*
733      *  AT&T 20C408 Clock Chip
734      */
735 
aty_var_to_pll_408(const struct fb_info * info,u32 vclk_per,u32 bpp,union aty_pll * pll)736 static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
737 			      u32 bpp, union aty_pll *pll)
738 {
739 	u32 mhz100;		/* in 0.01 MHz */
740 	u32 program_bits;
741 	/* u32 post_divider; */
742 	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
743 	u32 temp, tempB;
744 	u16 remainder, preRemainder;
745 	short divider = 0, tempA;
746 
747 	/* Calculate the programming word */
748 	mhz100 = 100000000 / vclk_per;
749 	mach64MinFreq = MIN_FREQ_2595;
750 	mach64MaxFreq = MAX_FREQ_2595;
751 	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
752 
753 	/* Calculate program word */
754 	if (mhz100 == 0)
755 		program_bits = 0xFF;
756 	else {
757 		if (mhz100 < mach64MinFreq)
758 			mhz100 = mach64MinFreq;
759 		if (mhz100 > mach64MaxFreq)
760 			mhz100 = mach64MaxFreq;
761 
762 		while (mhz100 < (mach64MinFreq << 3)) {
763 			mhz100 <<= 1;
764 			divider += 0x40;
765 		}
766 
767 		temp = (unsigned int) mhz100;
768 		temp = (unsigned int) (temp * (MIN_N_408 + 2));
769 		temp -= ((short) (mach64RefFreq << 1));
770 
771 		tempA = MIN_N_408;
772 		preRemainder = 0xFFFF;
773 
774 		do {
775 			tempB = temp;
776 			remainder = tempB % mach64RefFreq;
777 			tempB = tempB / mach64RefFreq;
778 			if (((tempB & 0xFFFF) <= 255)
779 			    && (remainder <= preRemainder)) {
780 				preRemainder = remainder;
781 				divider &= ~0x3f;
782 				divider |= tempA;
783 				divider =
784 				    (divider & 0x00FF) +
785 				    ((tempB & 0xFF) << 8);
786 			}
787 			temp += mhz100;
788 			tempA++;
789 		} while (tempA <= 32);
790 
791 		program_bits = divider;
792 	}
793 
794 	pll->ics2595.program_bits = program_bits;
795 	pll->ics2595.locationAddr = 0;
796 	pll->ics2595.post_divider = divider;	/* fuer nix */
797 	pll->ics2595.period_in_ps = vclk_per;
798 
799 	return 0;
800 }
801 
aty_pll_408_to_var(const struct fb_info * info,const union aty_pll * pll)802 static u32 aty_pll_408_to_var(const struct fb_info *info,
803 			      const union aty_pll *pll)
804 {
805 	return (pll->ics2595.period_in_ps);	/* default for now */
806 }
807 
aty_set_pll_408(const struct fb_info * info,const union aty_pll * pll)808 static void aty_set_pll_408(const struct fb_info *info,
809 			    const union aty_pll *pll)
810 {
811 	struct atyfb_par *par = (struct atyfb_par *) info->par;
812 	u32 program_bits;
813 	u32 locationAddr;
814 
815 	u8 tmpA, tmpB, tmpC;
816 	char old_crtc_ext_disp;
817 
818 	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
819 	aty_st_8(CRTC_GEN_CNTL + 3,
820 		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
821 
822 	program_bits = pll->ics2595.program_bits;
823 	locationAddr = pll->ics2595.locationAddr;
824 
825 	/* Program clock */
826 	aty_dac_waste4(par);
827 	tmpB = aty_ld_8(DAC_REGS + 2, par) | 1;
828 	aty_dac_waste4(par);
829 	aty_st_8(DAC_REGS + 2, tmpB, par);
830 
831 	tmpA = tmpB;
832 	tmpC = tmpA;
833 	tmpA |= 8;
834 	tmpB = 1;
835 
836 	aty_st_8(DAC_REGS, tmpB, par);
837 	aty_st_8(DAC_REGS + 2, tmpA, par);
838 
839 	udelay(400);		/* delay for 400 us */
840 
841 	locationAddr = (locationAddr << 2) + 0x40;
842 	tmpB = locationAddr;
843 	tmpA = program_bits >> 8;
844 
845 	aty_st_8(DAC_REGS, tmpB, par);
846 	aty_st_8(DAC_REGS + 2, tmpA, par);
847 
848 	tmpB = locationAddr + 1;
849 	tmpA = (u8) program_bits;
850 
851 	aty_st_8(DAC_REGS, tmpB, par);
852 	aty_st_8(DAC_REGS + 2, tmpA, par);
853 
854 	tmpB = locationAddr + 2;
855 	tmpA = 0x77;
856 
857 	aty_st_8(DAC_REGS, tmpB, par);
858 	aty_st_8(DAC_REGS + 2, tmpA, par);
859 
860 	udelay(400);		/* delay for 400 us */
861 	tmpA = tmpC & (~(1 | 8));
862 	tmpB = 1;
863 
864 	aty_st_8(DAC_REGS, tmpB, par);
865 	aty_st_8(DAC_REGS + 2, tmpA, par);
866 
867 	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
868 	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
869 	return;
870 }
871 
872 const struct aty_pll_ops aty_pll_att20c408 = {
873 	.var_to_pll	= aty_var_to_pll_408,
874 	.pll_to_var	= aty_pll_408_to_var,
875 	.set_pll	= aty_set_pll_408,
876 };
877 
878 
879     /*
880      *  Unsupported DAC and Clock Chip
881      */
882 
aty_set_dac_unsupported(const struct fb_info * info,const union aty_pll * pll,u32 bpp,u32 accel)883 static int aty_set_dac_unsupported(const struct fb_info *info,
884 				   const union aty_pll *pll, u32 bpp,
885 				   u32 accel)
886 {
887 	struct atyfb_par *par = (struct atyfb_par *) info->par;
888 
889 	aty_st_le32(BUS_CNTL, 0x890e20f1, par);
890 	aty_st_le32(DAC_CNTL, 0x47052100, par);
891 	/* new in 2.2.3p1 from Geert. ???????? */
892 	aty_st_le32(BUS_CNTL, 0x590e10ff, par);
893 	aty_st_le32(DAC_CNTL, 0x47012100, par);
894 	return 0;
895 }
896 
dummy(void)897 static int dummy(void)
898 {
899 	return 0;
900 }
901 
902 const struct aty_dac_ops aty_dac_unsupported = {
903 	.set_dac	= aty_set_dac_unsupported,
904 };
905 
906 const struct aty_pll_ops aty_pll_unsupported = {
907 	.var_to_pll	= (void *) dummy,
908 	.pll_to_var	= (void *) dummy,
909 	.set_pll	= (void *) dummy,
910 };
911