Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
88
OUTREG8(Radeon*radeon, ulong offset, uchar val)
89
{
90
	((uchar *)(radeon->mmio + offset))[0] = val;
91
}
92
 
93
static void
94
OUTREG(Radeon*radeon, ulong offset, ulong val)
95
{
96
	((ulong *)(radeon->mmio + offset))[0] = val;
97
}
98
 
99
static ulong
100
INREG(Radeon*radeon, ulong offset)
101
{
102
	return ((ulong *)(radeon->mmio + offset))[0];
103
}
104
 
105
static void
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
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
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
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
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
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 *
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
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
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
279
options(Vga*, Ctlr*ctlr)
280
{
281
	ctlr->flag |= Hlinear | Foptions;
282
}
283
 
284
static int
285
radeondiv(int n, int d)
286
{
287
	return (n + d/2) / d;
288
}
289
 
290
static void
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
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
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
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
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
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
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
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
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
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
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
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
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
};