xref: /plan9/sys/src/cmd/aux/vga/radeon.c (revision 8cf6001e50e647a07ccf484b8e2f9940411befb9)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 #include "radeon.h"
8 
9 static int	debug = 0;
10 
11 #define DBGPRINT	if (debug) print
12 
13 enum {
14 	Kilo	 = 1024,
15 	Mega	 = Kilo *Kilo,
16 };
17 
18 enum {
19 	DISPLAY_CRT,
20 	DISPLAY_FP,
21 	DISPLAY_LCD,
22 };
23 
24 typedef struct Radeon Radeon;
25 struct Radeon {
26 	uintptr	mmio;
27 	Pcidev	*pci;
28 	uchar	*bios;
29 
30 	ulong	fbsize;
31 	int	display_type;
32 
33 	ulong	ovr_clr;
34 	ulong	ovr_wid_top_bottom;
35 	ulong	ovr_wid_left_right;
36 	ulong	ov0_scale_cntl;
37 	ulong	subpic_cntl;
38 	ulong	viph_control;
39 	ulong	i2c_cntl_1;
40 	ulong	rbbm_soft_reset;
41 	ulong	cap0_trig_cntl;
42 	ulong	cap1_trig_cntl;
43 	ulong	gen_int_cntl;
44 	ulong	bus_cntl;
45 
46 	ulong	crtc_gen_cntl;
47 	ulong	crtc_ext_cntl;
48 	ulong	dac_cntl;
49 
50 	ulong	crtc_h_total_disp;
51 	ulong	crtc_h_sync_strt_wid;
52 	ulong	crtc_v_total_disp;
53 	ulong	crtc_v_sync_strt_wid;
54 
55 	ulong	crtc_pitch;
56 
57 	ulong	crtc_offset;
58 	ulong	crtc_offset_cntl;
59 
60 	ulong	htotal_cntl;
61 
62 	ulong	surface_cntl;
63 
64 	int	r300_workaround;
65 
66 	/* inited from rom */
67 	ushort	reference_freq;
68 	ushort	reference_div;
69 	ushort	xclk;
70 	ulong	max_pll_freq;
71 	ulong	min_pll_freq;
72 
73 	ulong	pll_output_freq;
74 	ulong	feedback_div;
75 	ulong	dot_clock_freq;
76 
77 	ulong	post_div;
78 	ulong	ppll_ref_div;
79 	ulong	ppll_div_3;
80 };
81 
82 /* from io.c */
83 extern char *readbios(long len, long offset);
84 
85 static void radeon300_workaround(Radeon*radeon);
86 
87 static void
OUTREG8(Radeon * radeon,ulong offset,uchar val)88 OUTREG8(Radeon*radeon, ulong offset, uchar val)
89 {
90 	((uchar *)(radeon->mmio + offset))[0] = val;
91 }
92 
93 static void
OUTREG(Radeon * radeon,ulong offset,ulong val)94 OUTREG(Radeon*radeon, ulong offset, ulong val)
95 {
96 	((ulong *)(radeon->mmio + offset))[0] = val;
97 }
98 
99 static ulong
INREG(Radeon * radeon,ulong offset)100 INREG(Radeon*radeon, ulong offset)
101 {
102 	return ((ulong *)(radeon->mmio + offset))[0];
103 }
104 
105 static void
OUTREGP(Radeon * radeon,ulong offset,ulong val,ulong mask)106 OUTREGP(Radeon*radeon, ulong offset, ulong val, ulong mask)
107 {
108 	OUTREG(radeon, offset, (INREG(radeon, offset) & mask) | val);
109 }
110 
111 static void
OUTPLL(Radeon * radeon,ulong offset,ulong val)112 OUTPLL(Radeon*radeon, ulong offset, ulong val)
113 {
114 	OUTREG8(radeon, CLOCK_CNTL_INDEX,
115 		(offset & 0x3f) | PLL_WR_EN);
116 	OUTREG(radeon, CLOCK_CNTL_DATA, val);
117 }
118 
119 static ulong
INPLL(Radeon * radeon,ulong offset)120 INPLL(Radeon*radeon, ulong offset)
121 {
122 	ulong data;
123 
124 	OUTREG8(radeon, CLOCK_CNTL_INDEX, offset & 0x3f);
125 	data = INREG(radeon, CLOCK_CNTL_DATA);
126 	if (radeon->r300_workaround)
127 		radeon300_workaround(radeon);
128 	return data;
129 }
130 
131 static void
OUTPLLP(Radeon * radeon,ulong offset,ulong val,ulong mask)132 OUTPLLP(Radeon*radeon, ulong offset, ulong val, ulong mask)
133 {
134 	OUTPLL(radeon, offset, (INPLL(radeon, offset) & mask) | val);
135 }
136 
137 static void
radeon300_workaround(Radeon * radeon)138 radeon300_workaround(Radeon*radeon)
139 {
140 	ulong save, tmp;
141 
142 	save = INREG(radeon, CLOCK_CNTL_INDEX);
143 	tmp = save & ~(0x3f | PLL_WR_EN);
144 	OUTREG(radeon, CLOCK_CNTL_INDEX, tmp);
145 	tmp = INREG(radeon, CLOCK_CNTL_DATA);
146 	OUTREG(radeon, CLOCK_CNTL_INDEX, save);
147 	USED(tmp);
148 }
149 
150 static void
radeon_getbiosparams(Radeon * radeon)151 radeon_getbiosparams(Radeon*radeon)
152 {
153 	ulong addr;
154 	ushort offset, pib;
155 	uchar *bios;
156 
157 	radeon->bios = nil;
158 	addr = 0xC0000;
159 	bios = (uchar *)readbios(0x10000, addr);
160 	if (bios[0] != 0x55 || bios[1] != 0xAA) {
161 		addr = 0xE0000;
162 		bios = (uchar *)readbios(0x10000, addr);
163 		if (bios[0] != 0x55 || bios[1] != 0xAA) {
164 			print("radeon: bios not found\n");
165 			return;
166 		}
167 	}
168 
169 	radeon->bios = bios;
170 	offset = BIOS16(radeon, BIOS_START);
171 
172 	pib = BIOS16(radeon, offset + 0x30);
173 
174 	radeon->reference_freq	 = BIOS16(radeon, pib + 0x0e);
175 	radeon->reference_div	 = BIOS16(radeon, pib + 0x10);
176 	radeon->min_pll_freq	 = BIOS32(radeon, pib + 0x12);
177 	radeon->max_pll_freq	 = BIOS32(radeon, pib + 0x16);
178 	radeon->xclk		 = BIOS16(radeon, pib + 0x08);
179 
180 	DBGPRINT("radeon: bios=0x%08ulx offset=0x%ux\n", addr, offset);
181 	DBGPRINT("radeon: pll_info_block: 0x%ux\n", pib);
182 	DBGPRINT("radeon: reference_freq: %ud\n", radeon->reference_freq);
183 	DBGPRINT("radeon: reference_div:  %ud\n", radeon->reference_div);
184 	DBGPRINT("radeon: min_pll_freq:   %uld\n", radeon->min_pll_freq);
185 	DBGPRINT("radeon: max_pll_freq:   %uld\n", radeon->max_pll_freq);
186 	DBGPRINT("radeon: xclk:           %ud\n", radeon->xclk);
187 }
188 
189 static Pcidev *
radeonpci(int * isr300)190 radeonpci(int *isr300)
191 {
192 	static Pcidev * p = nil;
193 	struct pciids *ids;
194 
195 	DBGPRINT("radeon: ATI Technologies Inc. Radeon [789]xxx drivers (v0.1)\n");
196 	while ((p = pcimatch(p, ATI_PCIVID, 0)) != nil)
197 		for (ids = radeon_pciids; ids->did; ids++)
198 			if (ids->did == p->did) {
199 				DBGPRINT("radeon: Found %s\n", ids->name);
200 				DBGPRINT("radeon: did:%04ux rid:%02ux\n",
201 					p->did, p->rid);
202 				if (isr300)
203 					*isr300 = ids->type == ATI_R300;
204 				return p;
205 			}
206 	DBGPRINT("radeon: not found!\n");
207 	return nil;
208 }
209 
210 static void
vga_disable(Vga * vga)211 vga_disable(Vga*vga)
212 {
213 	Ctlr *c;
214 
215 	for (c = vga->link; c; c = c->link)
216 		if (strncmp(c->name, "vga", 3) == 0)
217 			c->load = nil;
218 }
219 
220 static void
snarf(Vga * vga,Ctlr * ctlr)221 snarf(Vga *vga, Ctlr *ctlr)
222 {
223 	int isr300;
224 	ulong tmp;
225 	uintptr mmio;
226 	Pcidev *p;
227 	Radeon *radeon;
228 
229 	if (vga->private == nil) {
230 		vga_disable(vga);
231 
232 		vga->private = alloc(sizeof(Radeon));
233 		radeon = vga->private;
234 
235 		p = radeonpci(&isr300);
236 		if (p == nil)
237 			error("%s: not found\n", ctlr->name);
238 
239 		vgactlw("type", ctlr->name);
240 
241 		mmio = (uintptr)segattach(0, "radeonmmio", (void *)0,
242 			p->mem[2].size);
243 		if (mmio == ~0)
244 			error("%s: can't attach mmio segment\n", ctlr->name);
245 
246 		DBGPRINT("radeon: mmio address: %08#p [size=%#x]\n",
247 			(void *)mmio, p->mem[2].size);
248 
249 		radeon->pci = p;
250 		radeon->r300_workaround = isr300;
251 		radeon->mmio = mmio;
252 	}
253 
254 	radeon = vga->private;
255 	radeon->fbsize = INREG(radeon, CONFIG_MEMSIZE);
256 	vga->vmz = radeon->fbsize;
257 	DBGPRINT("radeon: frame buffer size=%uld [%uldMB]\n",
258 		radeon->fbsize, radeon->fbsize / Mega);
259 
260 	tmp = INREG(radeon, FP_GEN_CNTL);
261 	if (tmp & FP_EN_TMDS)
262 		radeon->display_type = DISPLAY_FP;
263 	else
264 		radeon->display_type = DISPLAY_CRT;
265 
266 	DBGPRINT("radeon: display type: %s\n",
267 		radeon->display_type == DISPLAY_CRT? "CRT": "FLAT PANEL");
268 
269 	if (radeon->display_type != DISPLAY_CRT)
270 		error("unsupported NON CRT Display\n");
271 
272 	radeon_getbiosparams(radeon);
273 	radeon->bus_cntl = INREG(radeon, BUS_CNTL);
274 	DBGPRINT("radeon: PPLL_CNTL=0x%08ulx\n", INPLL(radeon, PPLL_CNTL));
275 	ctlr->flag |= Fsnarf;
276 }
277 
278 static void
options(Vga *,Ctlr * ctlr)279 options(Vga*, Ctlr*ctlr)
280 {
281 	ctlr->flag |= Hlinear | Foptions;
282 }
283 
284 static int
radeondiv(int n,int d)285 radeondiv(int n, int d)
286 {
287 	return (n + d/2) / d;
288 }
289 
290 static void
radeon_init_common_registers(Radeon * radeon)291 radeon_init_common_registers(Radeon*radeon)
292 {
293 	radeon->ovr_clr		= 0;
294 	radeon->ovr_wid_left_right	= 0;
295 	radeon->ovr_wid_top_bottom	= 0;
296 	radeon->ov0_scale_cntl	= 0;
297 	radeon->subpic_cntl	= 0;
298 	radeon->viph_control	= 0;
299 	radeon->i2c_cntl_1	= 0;
300 	radeon->rbbm_soft_reset	= 0;
301 	radeon->cap0_trig_cntl	= 0;
302 	radeon->cap1_trig_cntl	= 0;
303 	if (radeon->bus_cntl & BUS_READ_BURST)
304 		radeon->bus_cntl |= BUS_RD_DISCARD_EN;
305 }
306 
307 static void
radeon_init_crtc_registers(Radeon * radeon,Mode * mode)308 radeon_init_crtc_registers(Radeon*radeon, Mode*mode)
309 {
310 	int format, dac6bit, hsync_wid, vsync_wid, hsync_start, hsync_fudge;
311 	int bpp;
312 	static int hsync_fudge_default[] = {
313 		0x00, 0x12, 0x09, 0x09, 0x06, 0x05,
314 	};
315 
316 	format = 0;
317 	bpp = 0;
318 	dac6bit = 0;
319 	switch (mode->z) {
320 	case 6:
321 		format = 2;
322 		dac6bit = 1;
323 		bpp =  8;
324 		break;
325 	case 8:
326 		format = 2;
327 		dac6bit = 0;
328 		bpp =  8;
329 		break;
330 	case 15:
331 		format = 3;
332 		dac6bit = 0;
333 		bpp = 16;
334 		break;
335 	case 16:
336 		format = 4;
337 		dac6bit = 0;
338 		bpp = 16;
339 		break;
340 	case 24:
341 		format = 5;
342 		dac6bit = 0;
343 		bpp = 24;
344 		break;
345 	case 32:
346 		format = 6;
347 		dac6bit = 0;
348 		bpp = 32;
349 		break;
350 	default:
351 		error("radeon: unsupported mode depth %d\n", mode->z);
352 	}
353 	hsync_fudge = hsync_fudge_default[format-1];
354 
355 	DBGPRINT("mode->z = %d (format = %d, bpp = %d, dac6bit = %s)\n",
356 		mode->z, format, bpp, dac6bit? "true": "false");
357 
358 	radeon->crtc_gen_cntl = CRTC_EN | CRTC_EXT_DISP_EN | format << 8 |
359 		(mode->interlace? CRTC_INTERLACE_EN: 0);
360 	radeon->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON;
361 	radeon->dac_cntl = DAC_MASK_ALL | DAC_VGA_ADR_EN |
362 		(dac6bit? 0: DAC_8BIT_EN);
363 
364 	radeon->crtc_h_total_disp = ((mode->ht/8 - 1) & 0x3ff) |
365 		((mode->x/8 - 1) & 0x1ff) << 16;
366 
367 	hsync_wid = (mode->ehb - mode->shb) / 8;
368 	if (hsync_wid == 0)
369 		hsync_wid = 1;
370 
371 	hsync_start = mode->shb - 8 + hsync_fudge;
372 
373 	DBGPRINT("hsync_start=%d hsync_wid=%d hsync_fudge=%d\n",
374 		hsync_start, hsync_wid, hsync_fudge);
375 
376 	radeon->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
377 		(hsync_wid & 0x3f) << 16 | (mode->hsync? CRTC_H_SYNC_POL: 0));
378 	radeon->crtc_v_total_disp = ((mode->vt - 1) & 0xffff) |
379 		(mode->y - 1) << 16;
380 
381 	vsync_wid = mode->vre - mode->vrs;
382 	if (!vsync_wid)
383 		vsync_wid = 1;
384 
385 	radeon->crtc_v_sync_strt_wid = (((mode->vrs - 1) & 0xfff) |
386 		(vsync_wid & 0x1f) << 16 | (mode->vsync? CRTC_V_SYNC_POL: 0));
387 	radeon->crtc_offset = 0;
388 	radeon->crtc_offset_cntl = INREG(radeon, CRTC_OFFSET_CNTL);
389 	radeon->crtc_pitch = (mode->x * bpp + bpp * 8 - 1) / (bpp * 8);
390 	radeon->crtc_pitch |= radeon->crtc_pitch << 16;
391 }
392 
393 struct divider {
394 	int	divider;
395 	int	bitvalue;
396 };
397 
398 static void
radeon_init_pll_registers(Radeon * radeon,ulong freq)399 radeon_init_pll_registers(Radeon*radeon, ulong freq)
400 {
401 	struct divider *post_div;
402 	static struct divider post_divs[] = {
403 		{ 1, 0 },
404 		{ 2, 1 },
405 		{ 4, 2 },
406 		{ 8, 3 },
407 		{ 3, 4 },
408 		{ 16, 5 },
409 		{ 6, 6 },
410 		{ 12, 7 },
411 		{ 0, 0 }
412 	};
413 
414 	DBGPRINT("radeon: initpll: freq=%uld\n", freq);
415 
416 	if (freq > radeon->max_pll_freq)
417 		freq = radeon->max_pll_freq;
418 	if (freq * 12 < radeon->min_pll_freq)
419 		freq = radeon->min_pll_freq / 12;
420 
421 	for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
422 		radeon->pll_output_freq = post_div->divider * freq;
423 		if (radeon->pll_output_freq >= radeon->min_pll_freq &&
424 		    radeon->pll_output_freq <= radeon->max_pll_freq)
425 			break;
426 	}
427 
428 	radeon->dot_clock_freq = freq;
429 	radeon->feedback_div = radeondiv(radeon->reference_div *
430 		radeon->pll_output_freq, radeon->reference_freq);
431 	radeon->post_div = post_div->divider;
432 
433 	DBGPRINT("dc=%uld, of=%uld, fd=%uld, pd=%uld\n", radeon->dot_clock_freq,
434 		radeon->pll_output_freq, radeon->feedback_div, radeon->post_div);
435 
436 	radeon->ppll_ref_div = radeon->reference_div;
437 	radeon->ppll_div_3 = radeon->feedback_div | post_div->bitvalue << 16;
438 	radeon->htotal_cntl = 0;
439 	radeon->surface_cntl = 0;
440 }
441 
442 static void
init(Vga * vga,Ctlr * ctlr)443 init(Vga*vga, Ctlr*ctlr)
444 {
445 	Radeon *radeon;
446 	Mode *mode;
447 
448 	radeon	 = vga->private;
449 	mode	 = vga->mode;
450 
451 	DBGPRINT("radeon: monitor type = '%s'\n", mode->type);
452 	DBGPRINT("radeon: size = '%s'\n", mode->size);
453 	DBGPRINT("radeon: chan = '%s'\n", mode->chan);
454 	DBGPRINT("radeon: freq=%d deffreq=%d x=%d y=%d z=%d\n",
455 		mode->frequency, mode->deffrequency, mode->x, mode->y, mode->z);
456 	DBGPRINT("radeon: ht=%d shb=%d ehb=%d shs=%d ehs=%d hsync='%c'\n",
457 		mode->ht, mode->shb, mode->ehb, mode->shs, mode->ehs,
458 		mode->hsync? mode->hsync: ' ');
459 	DBGPRINT("radeon: vt=%d vrs=%d vre=%d vsync='%c'\n",
460 		mode->vt, mode->vrs, mode->vre, mode->vsync? mode->vsync: ' ');
461 
462 	radeon_init_common_registers(radeon);
463 	radeon_init_crtc_registers(radeon, mode);
464 	radeon_init_pll_registers(radeon, mode->frequency / 10000);
465 	ctlr->flag |= Finit | Ulinear;
466 }
467 
468 static void
radeon_blank(Radeon * radeon)469 radeon_blank(Radeon*radeon)
470 {
471 	OUTREGP(radeon, CRTC_EXT_CNTL,
472 		  CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS,
473 		~(CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS));
474 }
475 
476 static void
radeon_unblank(Radeon * radeon)477 radeon_unblank(Radeon*radeon)
478 {
479 	OUTREGP(radeon, CRTC_EXT_CNTL, CRTC_CRT_ON,
480 		~(CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS));
481 }
482 
483 static void
radeon_load_common_registers(Radeon * radeon)484 radeon_load_common_registers(Radeon*radeon)
485 {
486 	OUTREG(radeon, OVR_CLR, 		radeon->ovr_clr);
487 	OUTREG(radeon, OVR_WID_LEFT_RIGHT, 	radeon->ovr_wid_left_right);
488 	OUTREG(radeon, OVR_WID_TOP_BOTTOM, 	radeon->ovr_wid_top_bottom);
489 	OUTREG(radeon, OV0_SCALE_CNTL, 		radeon->ov0_scale_cntl);
490 	OUTREG(radeon, SUBPIC_CNTL, 		radeon->subpic_cntl);
491 	OUTREG(radeon, VIPH_CONTROL, 		radeon->viph_control);
492 	OUTREG(radeon, I2C_CNTL_1, 		radeon->i2c_cntl_1);
493 	OUTREG(radeon, GEN_INT_CNTL, 		radeon->gen_int_cntl);
494 	OUTREG(radeon, CAP0_TRIG_CNTL, 		radeon->cap0_trig_cntl);
495 	OUTREG(radeon, CAP1_TRIG_CNTL, 		radeon->cap1_trig_cntl);
496 	OUTREG(radeon, BUS_CNTL, 		radeon->bus_cntl);
497 	OUTREG(radeon, SURFACE_CNTL, 		radeon->surface_cntl);
498 }
499 
500 static void
radeon_load_crtc_registers(Radeon * radeon)501 radeon_load_crtc_registers(Radeon*radeon)
502 {
503 	OUTREG(radeon, CRTC_GEN_CNTL, radeon->crtc_gen_cntl);
504 	OUTREGP(radeon, CRTC_EXT_CNTL, radeon->crtc_ext_cntl,
505 		CRTC_VSYNC_DIS | CRTC_HSYNC_DIS | CRTC_DISPLAY_DIS);
506 	OUTREGP(radeon, DAC_CNTL, radeon->dac_cntl,
507 		DAC_RANGE_CNTL | DAC_BLANKING);
508 	OUTREG(radeon, CRTC_H_TOTAL_DISP, 	radeon->crtc_h_total_disp);
509 	OUTREG(radeon, CRTC_H_SYNC_STRT_WID, 	radeon->crtc_h_sync_strt_wid);
510 	OUTREG(radeon, CRTC_V_TOTAL_DISP, 	radeon->crtc_v_total_disp);
511 	OUTREG(radeon, CRTC_V_SYNC_STRT_WID, 	radeon->crtc_v_sync_strt_wid);
512 	OUTREG(radeon, CRTC_OFFSET, 		radeon->crtc_offset);
513 	OUTREG(radeon, CRTC_OFFSET_CNTL, 	radeon->crtc_offset_cntl);
514 	OUTREG(radeon, CRTC_PITCH, 		radeon->crtc_pitch);
515 }
516 
517 static void
radeon_pllwaitupd(Radeon * radeon)518 radeon_pllwaitupd(Radeon*radeon)
519 {
520 	int i;
521 
522 	for (i = 0; i < 10000; i++)
523 		if (!(INPLL(radeon, PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R))
524 			break;
525 }
526 
527 static void
radeon_pllwriteupd(Radeon * radeon)528 radeon_pllwriteupd(Radeon*radeon)
529 {
530 	while (INPLL(radeon, PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
531 		;
532 	OUTPLLP(radeon, PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
533 }
534 
535 static void
radeon_load_pll_registers(Radeon * radeon)536 radeon_load_pll_registers(Radeon*radeon)
537 {
538 	OUTPLLP(radeon, VCLK_ECP_CNTL,
539 		VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
540 	OUTPLLP(radeon, PPLL_CNTL,
541 	      PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
542 	    ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
543 	OUTREGP(radeon, CLOCK_CNTL_INDEX, PLL_DIV_SEL, ~PLL_DIV_SEL);
544 	if (radeon->r300_workaround) {
545 		DBGPRINT("r300_workaround\n");
546 		if (radeon->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK)
547 			/*
548 			 * When restoring console mode, use saved PPLL_REF_DIV
549 			 * setting.
550 			 */
551 			OUTPLLP(radeon, PPLL_REF_DIV, radeon->ppll_ref_div, 0);
552 		else
553 			/* R300 uses ref_div_acc field as real ref divider */
554 			OUTPLLP(radeon, PPLL_REF_DIV,
555 			    radeon->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT,
556 				~R300_PPLL_REF_DIV_ACC_MASK);
557 	} else
558 		OUTPLLP(radeon, PPLL_REF_DIV, radeon->ppll_ref_div,
559 			~PPLL_REF_DIV_MASK);
560 
561 	OUTPLLP(radeon, PPLL_DIV_3, radeon->ppll_div_3, ~PPLL_FB3_DIV_MASK);
562 	OUTPLLP(radeon, PPLL_DIV_3, radeon->ppll_div_3, ~PPLL_POST3_DIV_MASK);
563 
564 	radeon_pllwriteupd(radeon);
565 	radeon_pllwaitupd(radeon);
566 
567 	OUTPLL(radeon, HTOTAL_CNTL, radeon->htotal_cntl);
568 	OUTPLLP(radeon, PPLL_CNTL, 0,
569 		~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN |
570 		  PPLL_VGA_ATOMIC_UPDATE_EN));
571 
572 	if (debug) {
573 		Bprint(&stdout, "Wrote: 0x%08ulx 0x%08ulx 0x%08ulx (0x%08ulx)\n",
574 			radeon->ppll_ref_div, radeon->ppll_div_3,
575 			radeon->htotal_cntl, INPLL(radeon, PPLL_CNTL));
576 		Bprint(&stdout, "Wrote: rd=%uld, fd=%uld, pd=%uld\n",
577 			radeon->ppll_ref_div & PPLL_REF_DIV_MASK,
578 			radeon->ppll_div_3 & PPLL_FB3_DIV_MASK,
579 			(radeon->ppll_div_3 & PPLL_POST3_DIV_MASK) >> 16);
580 	}
581 
582 	/* Let the clock to lock */
583 	sleep(5);
584 
585 	OUTPLLP(radeon, VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
586 }
587 
588 static void
load(Vga * vga,Ctlr * ctlr)589 load(Vga*vga, Ctlr*ctlr)
590 {
591 	Radeon *radeon;
592 
593 	radeon = (Radeon *) vga->private;
594 	radeon_blank(radeon);
595 	radeon_load_common_registers(radeon);
596 	radeon_load_crtc_registers(radeon);
597 	radeon_load_pll_registers(radeon);
598 	radeon_unblank(radeon);
599 
600 	/* init palette [gamma] */
601 	if (vga->mode->z > 8) {
602 		int i;
603 
604 		OUTREG(radeon, PALETTE_INDEX, 0);
605 		for (i = 0; i < 256; i++)
606 			OUTREG(radeon, PALETTE_DATA, i << 16 | i << 8 | i);
607 	}
608 
609 	ctlr->flag |= Fload;
610 }
611 
612 static void
dump(Vga * vga,Ctlr * ctlr)613 dump(Vga*vga, Ctlr*ctlr)
614 {
615 	Radeon *radeon;
616 
617 	USED(ctlr);
618 	radeon = (Radeon *)vga->private;
619 	USED(radeon);
620 }
621 
622 Ctlr radeon = {
623 	"radeon",
624 	snarf,
625 	options,
626 	init,
627 	load,
628 	dump,
629 };
630 Ctlr radeonhwgc = {
631 	"radeonhwgc",
632 	0, 					/* snarf */
633 	0, 					/* options */
634 	0, 					/* init */
635 	0, 					/* load */
636 	0, 					/* dump */
637 };
638