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
43static 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
53static 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
69static 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
80static 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
123static 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
161static 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
175static 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
190const struct aty_dac_ops aty_dac_ibm514 = {
191	.set_dac	= aty_set_dac_514,
192};
193
194const 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
205static 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
279const 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
288static 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
332const 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
341static 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		MHz100 = MAX_FREQ_2595;
356		return -EINVAL;
357	} else if (MHz100 < ABS_MIN_FREQ_2595) {
358		program_bits = 0;	/* MHz100 = 257 */
359		return -EINVAL;
360	} else {
361		while (MHz100 < MIN_FREQ_2595) {
362			MHz100 *= 2;
363			post_divider *= 2;
364		}
365	}
366	MHz100 *= 1000;
367	MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
368
369	MHz100 += 500;		/* + 0.5 round */
370	MHz100 /= 1000;
371
372	if (program_bits == -1) {
373		program_bits = MHz100 - N_ADJ_2595;
374		switch (post_divider) {
375		case 1:
376			program_bits |= 0x0600;
377			break;
378		case 2:
379			program_bits |= 0x0400;
380			break;
381		case 4:
382			program_bits |= 0x0200;
383			break;
384		case 8:
385		default:
386			break;
387		}
388	}
389
390	program_bits |= STOP_BITS_2595;
391
392	pll->ics2595.program_bits = program_bits;
393	pll->ics2595.locationAddr = 0;
394	pll->ics2595.post_divider = post_divider;
395	pll->ics2595.period_in_ps = vclk_per;
396
397	return 0;
398}
399
400static u32 aty_pll_18818_to_var(const struct fb_info *info,
401				const union aty_pll *pll)
402{
403	return (pll->ics2595.period_in_ps);	/* default for now */
404}
405
406static void aty_ICS2595_put1bit(u8 data, const struct atyfb_par *par)
407{
408	u8 tmp;
409
410	data &= 0x01;
411	tmp = aty_ld_8(CLOCK_CNTL, par);
412	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
413		 (tmp & ~0x04) | (data << 2), par);
414
415	tmp = aty_ld_8(CLOCK_CNTL, par);
416	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (0 << 3),
417		 par);
418
419	aty_StrobeClock(par);
420
421	tmp = aty_ld_8(CLOCK_CNTL, par);
422	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, (tmp & ~0x08) | (1 << 3),
423		 par);
424
425	aty_StrobeClock(par);
426	return;
427}
428
429static void aty_set_pll18818(const struct fb_info *info,
430			     const union aty_pll *pll)
431{
432	struct atyfb_par *par = (struct atyfb_par *) info->par;
433	u32 program_bits;
434	u32 locationAddr;
435
436	u32 i;
437
438	u8 old_clock_cntl;
439	u8 old_crtc_ext_disp;
440
441	old_clock_cntl = aty_ld_8(CLOCK_CNTL, par);
442	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
443
444	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
445	aty_st_8(CRTC_GEN_CNTL + 3,
446		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
447
448	mdelay(15);		/* delay for 50 (15) ms */
449
450	program_bits = pll->ics2595.program_bits;
451	locationAddr = pll->ics2595.locationAddr;
452
453	/* Program the clock chip */
454	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);	/* Strobe = 0 */
455	aty_StrobeClock(par);
456	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 1, par);	/* Strobe = 0 */
457	aty_StrobeClock(par);
458
459	aty_ICS2595_put1bit(1, par);	/* Send start bits */
460	aty_ICS2595_put1bit(0, par);	/* Start bit */
461	aty_ICS2595_put1bit(0, par);	/* Read / ~Write */
462
463	for (i = 0; i < 5; i++) {	/* Location 0..4 */
464		aty_ICS2595_put1bit(locationAddr & 1, par);
465		locationAddr >>= 1;
466	}
467
468	for (i = 0; i < 8 + 1 + 2 + 2; i++) {
469		aty_ICS2595_put1bit(program_bits & 1, par);
470		program_bits >>= 1;
471	}
472
473	mdelay(1);		/* delay for 1 ms */
474
475	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
476	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
477	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
478		 old_clock_cntl | CLOCK_STROBE, par);
479
480	mdelay(50);		/* delay for 50 (15) ms */
481	aty_st_8(CLOCK_CNTL + par->clk_wr_offset,
482		 ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par);
483	return;
484}
485
486const struct aty_pll_ops aty_pll_ati18818_1 = {
487	.var_to_pll	= aty_var_to_pll_18818,
488	.pll_to_var	= aty_pll_18818_to_var,
489	.set_pll	= aty_set_pll18818,
490};
491
492
493    /*
494     *  STG 1703 Clock Chip
495     */
496
497static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
498			       u32 bpp, union aty_pll *pll)
499{
500	u32 mhz100;		/* in 0.01 MHz */
501	u32 program_bits;
502	/* u32 post_divider; */
503	u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
504	u32 temp, tempB;
505	u16 remainder, preRemainder;
506	short divider = 0, tempA;
507
508	/* Calculate the programming word */
509	mhz100 = 100000000 / vclk_per;
510	mach64MinFreq = MIN_FREQ_2595;
511	mach64MaxFreq = MAX_FREQ_2595;
512	mach64RefFreq = REF_FREQ_2595;	/* 14.32 MHz */
513
514	/* Calculate program word */
515	if (mhz100 == 0)
516		program_bits = 0xE0;
517	else {
518		if (mhz100 < mach64MinFreq)
519			mhz100 = mach64MinFreq;
520		if (mhz100 > mach64MaxFreq)
521			mhz100 = mach64MaxFreq;
522
523		divider = 0;
524		while (mhz100 < (mach64MinFreq << 3)) {
525			mhz100 <<= 1;
526			divider += 0x20;
527		}
528
529		temp = (unsigned int) (mhz100);
530		temp = (unsigned int) (temp * (MIN_N_1703 + 2));
531		temp -= (short) (mach64RefFreq << 1);
532
533		tempA = MIN_N_1703;
534		preRemainder = 0xffff;
535
536		do {
537			tempB = temp;
538			remainder = tempB % mach64RefFreq;
539			tempB = tempB / mach64RefFreq;
540
541			if ((tempB & 0xffff) <= 127
542			    && (remainder <= preRemainder)) {
543				preRemainder = remainder;
544				divider &= ~0x1f;
545				divider |= tempA;
546				divider =
547				    (divider & 0x00ff) +
548				    ((tempB & 0xff) << 8);
549			}
550
551			temp += mhz100;
552			tempA++;
553		} while (tempA <= (MIN_N_1703 << 1));
554
555		program_bits = divider;
556	}
557
558	pll->ics2595.program_bits = program_bits;
559	pll->ics2595.locationAddr = 0;
560	pll->ics2595.post_divider = divider;	/* fuer nix */
561	pll->ics2595.period_in_ps = vclk_per;
562
563	return 0;
564}
565
566static u32 aty_pll_1703_to_var(const struct fb_info *info,
567			       const union aty_pll *pll)
568{
569	return (pll->ics2595.period_in_ps);	/* default for now */
570}
571
572static void aty_set_pll_1703(const struct fb_info *info,
573			     const union aty_pll *pll)
574{
575	struct atyfb_par *par = (struct atyfb_par *) info->par;
576	u32 program_bits;
577	u32 locationAddr;
578
579	char old_crtc_ext_disp;
580
581	old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
582	aty_st_8(CRTC_GEN_CNTL + 3,
583		 old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par);
584
585	program_bits = pll->ics2595.program_bits;
586	locationAddr = pll->ics2595.locationAddr;
587
588	/* Program clock */
589	aty_dac_waste4(par);
590
591	(void) aty_ld_8(DAC_REGS + 2, par);
592	aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par);
593	aty_st_8(DAC_REGS + 2, 0, par);
594	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par);
595	aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par);
596
597	(void) aty_ld_8(DAC_REGS, par);	/* Clear DAC Counter */
598	aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par);
599	return;
600}
601
602const struct aty_pll_ops aty_pll_stg1703 = {
603	.var_to_pll	= aty_var_to_pll_1703,
604	.pll_to_var	= aty_pll_1703_to_var,
605	.set_pll	= aty_set_pll_1703,
606};
607
608
609    /*
610     *  Chrontel 8398 Clock Chip
611     */
612
613static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
614			       u32 bpp, union aty_pll *pll)
615{
616	u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
617
618	u32 mhz100;		/* in 0.01 MHz */
619	u32 program_bits;
620	/* u32 post_divider; */
621	u32 mach64MinFreq, mach64MaxFreq;
622	u16 m, n, k = 0, save_m, save_n, twoToKth;
623
624	/* Calculate the programming word */
625	mhz100 = 100000000 / vclk_per;
626	mach64MinFreq = MIN_FREQ_2595;
627	mach64MaxFreq = MAX_FREQ_2595;
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
684static 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
690static 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
725const 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
736static 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
802static 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
808static 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
872const 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
883static 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
897static int dummy(void)
898{
899	return 0;
900}
901
902const struct aty_dac_ops aty_dac_unsupported = {
903	.set_dac	= aty_set_dac_unsupported,
904};
905
906const 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