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