igsfb_subr.c revision 1.1
1/*	$NetBSD: igsfb_subr.c,v 1.1 2002/09/24 18:17:25 uwe Exp $ */
2
3/*
4 * Copyright (c) 2002 Valeriy E. Ushakov
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * Integraphics Systems IGA 168x and CyberPro series.
32 */
33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: igsfb_subr.c,v 1.1 2002/09/24 18:17:25 uwe Exp $");
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/device.h>
40
41#include <machine/bus.h>
42
43#include <dev/wscons/wsconsio.h>
44
45#include <dev/ic/igsfbreg.h>
46#include <dev/ic/igsfbvar.h>
47
48
49static void	igsfb_init_seq(struct igsfb_softc *);
50static void	igsfb_init_crtc(struct igsfb_softc *);
51static void	igsfb_init_grfx(struct igsfb_softc *);
52static void	igsfb_init_attr(struct igsfb_softc *);
53static void	igsfb_init_ext(struct igsfb_softc *);
54static void	igsfb_init_dac(struct igsfb_softc *);
55
56static void	igsfb_freq_latch(struct igsfb_softc *);
57static void	igsfb_video_on(struct igsfb_softc *);
58
59
60
61/*
62 * Enable chip.
63 */
64int
65igsfb_enable(iot)
66	bus_space_tag_t iot;
67{
68	bus_space_handle_t vdoh;
69	bus_space_handle_t vseh;
70	bus_space_handle_t regh;
71	int ret;
72
73	ret = bus_space_map(iot, IGS_VDO, 1, 0, &vdoh);
74	if (ret != 0) {
75		printf("unable to map VDO register\n");
76		goto out0;
77	}
78
79	ret = bus_space_map(iot, IGS_VSE, 1, 0, &vseh);
80	if (ret != 0) {
81		printf("unable to map VSE register\n");
82		goto out1;
83	}
84
85	ret = bus_space_map(iot, IGS_REG_BASE, IGS_REG_SIZE, 0, &regh);
86	if (ret != 0) {
87		printf("unable to map I/O registers\n");
88		goto out2;
89	}
90
91	/*
92	 * Start decoding i/o space accesses.
93	 */
94	bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE | IGS_VDO_SETUP);
95	bus_space_write_1(iot, vseh, 0, IGS_VSE_ENABLE);
96	bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE);
97
98	/*
99	 * Start decoding memory space accesses (XXX: move out of here?
100	 * we program this register in igsfb_init_ext).
101	 * While here, enable coprocessor and select IGS_COP_BASE_B.
102	 */
103	igs_ext_write(iot, regh, IGS_EXT_BIU_MISC_CTL,
104		      (IGS_EXT_BIU_LINEAREN
105		       | IGS_EXT_BIU_COPREN | IGS_EXT_BIU_COPASELB));
106
107	bus_space_unmap(iot, regh, IGS_REG_SIZE);
108  out2:	bus_space_unmap(iot, vseh, 1);
109  out1:	bus_space_unmap(iot, vdoh, 1);
110  out0: return (ret);
111}
112
113
114/*
115 * Init sequencer.
116 * This is common for all video modes.
117 */
118static void
119igsfb_init_seq(sc)
120	struct igsfb_softc *sc;
121{
122	bus_space_tag_t iot = sc->sc_iot;
123	bus_space_handle_t ioh = sc->sc_ioh;
124
125	/* start messing with sequencer */
126	igs_seq_write(iot, ioh, IGS_SEQ_RESET, 0);
127
128	igs_seq_write(iot, ioh, 1, 0x01); /* 8 dot clock */
129	igs_seq_write(iot, ioh, 2, 0x0f); /* enable all maps */
130	igs_seq_write(iot, ioh, 3, 0x00); /* character generator */
131	igs_seq_write(iot, ioh, 4, 0x0e); /* memory mode */
132
133	/* this selects color mode among other things */
134	bus_space_write_1(iot, ioh, IGS_MISC_OUTPUT_W, 0xef);
135
136	/* normal sequencer operation */
137	igs_seq_write(iot, ioh, IGS_SEQ_RESET,
138		      IGS_SEQ_RESET_SYNC | IGS_SEQ_RESET_ASYNC);
139}
140
141/*
142 * Init CRTC to 640x480 8bpp at 60Hz
143 */
144static void
145igsfb_init_crtc(sc)
146	struct igsfb_softc *sc;
147{
148	bus_space_tag_t iot = sc->sc_iot;
149	bus_space_handle_t ioh = sc->sc_ioh;
150
151	igs_crtc_write(iot, ioh, 0x00, 0x5f);
152	igs_crtc_write(iot, ioh, 0x01, 0x4f);
153	igs_crtc_write(iot, ioh, 0x02, 0x50);
154	igs_crtc_write(iot, ioh, 0x03, 0x80);
155	igs_crtc_write(iot, ioh, 0x04, 0x52);
156	igs_crtc_write(iot, ioh, 0x05, 0x9d);
157	igs_crtc_write(iot, ioh, 0x06, 0x0b);
158	igs_crtc_write(iot, ioh, 0x07, 0x3e);
159
160	/* next block is almost constant, only bit 6 in reg 9 differs */
161	igs_crtc_write(iot, ioh, 0x08, 0x00);
162	igs_crtc_write(iot, ioh, 0x09, 0x40); /* <- either 0x40 or 0x60 */
163	igs_crtc_write(iot, ioh, 0x0a, 0x00);
164	igs_crtc_write(iot, ioh, 0x0b, 0x00);
165	igs_crtc_write(iot, ioh, 0x0c, 0x00);
166	igs_crtc_write(iot, ioh, 0x0d, 0x00);
167	igs_crtc_write(iot, ioh, 0x0e, 0x00);
168	igs_crtc_write(iot, ioh, 0x0f, 0x00);
169
170	igs_crtc_write(iot, ioh, 0x10, 0xe9);
171	igs_crtc_write(iot, ioh, 0x11, 0x8b);
172	igs_crtc_write(iot, ioh, 0x12, 0xdf);
173	igs_crtc_write(iot, ioh, 0x13, 0x50);
174	igs_crtc_write(iot, ioh, 0x14, 0x00);
175	igs_crtc_write(iot, ioh, 0x15, 0xe6);
176	igs_crtc_write(iot, ioh, 0x16, 0x04);
177	igs_crtc_write(iot, ioh, 0x17, 0xc3);
178
179	igs_crtc_write(iot, ioh, 0x18, 0xff);
180}
181
182
183/*
184 * Init graphics controller.
185 * This is common for all video modes.
186 */
187static void
188igsfb_init_grfx(sc)
189	struct igsfb_softc *sc;
190{
191	bus_space_tag_t iot = sc->sc_iot;
192	bus_space_handle_t ioh = sc->sc_ioh;
193
194	igs_grfx_write(iot, ioh, 0, 0x00);
195	igs_grfx_write(iot, ioh, 1, 0x00);
196	igs_grfx_write(iot, ioh, 2, 0x00);
197	igs_grfx_write(iot, ioh, 3, 0x00);
198	igs_grfx_write(iot, ioh, 4, 0x00);
199	igs_grfx_write(iot, ioh, 5, 0x60); /* SRMODE, MODE256 */
200	igs_grfx_write(iot, ioh, 6, 0x05); /* 64k @ a0000, GRAPHICS */
201	igs_grfx_write(iot, ioh, 7, 0x0f); /* color compare all */
202	igs_grfx_write(iot, ioh, 8, 0xff); /* bitmask = all bits mutable */
203}
204
205
206/*
207 * Init attribute controller.
208 * This is common for all video modes.
209 */
210static void
211igsfb_init_attr(sc)
212	struct igsfb_softc *sc;
213{
214	bus_space_tag_t iot = sc->sc_iot;
215	bus_space_handle_t ioh = sc->sc_ioh;
216	int i;
217
218	igs_attr_flip_flop(iot, ioh);	/* reset attr flip-flop to address */
219
220	for (i = 0; i < 16; ++i)	/* crt palette */
221		igs_attr_write(iot, ioh, i, i);
222
223	igs_attr_write(iot, ioh, 0x10, 0x01); /* select graphic mode */
224	igs_attr_write(iot, ioh, 0x11, 0x00); /* crt overscan color */
225	igs_attr_write(iot, ioh, 0x12, 0x0f); /* color plane enable */
226	igs_attr_write(iot, ioh, 0x13, 0x00);
227	igs_attr_write(iot, ioh, 0x14, 0x00);
228}
229
230
231/*
232 * When done with ATTR controller, call this to unblank the screen.
233 */
234static void
235igsfb_video_on(sc)
236	struct igsfb_softc *sc;
237{
238	bus_space_tag_t iot = sc->sc_iot;
239	bus_space_handle_t ioh = sc->sc_ioh;
240
241	igs_attr_flip_flop(iot, ioh);
242	bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20);
243	bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20);
244}
245
246
247/*
248 * Latch VCLK (b0/b1) and MCLK (b2/b3) values.
249 */
250static void
251igsfb_freq_latch(sc)
252	struct igsfb_softc *sc;
253{
254	bus_space_tag_t iot = sc->sc_iot;
255	bus_space_handle_t ioh = sc->sc_ioh;
256
257	bus_space_write_1(iot, ioh, IGS_EXT_IDX, 0xb9);
258	bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x80);
259	bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x00);
260}
261
262
263static void
264igsfb_init_ext(sc)
265	struct igsfb_softc *sc;
266{
267	bus_space_tag_t iot = sc->sc_iot;
268	bus_space_handle_t ioh = sc->sc_ioh;
269
270	igs_ext_write(iot, ioh, 0x10, 0x10); /* IGS_EXT_START_ADDR enable */
271	igs_ext_write(iot, ioh, 0x12, 0x00); /* IGS_EXT_IRQ_CTL disable  */
272	igs_ext_write(iot, ioh, 0x13, 0x00); /* MBZ for normal operation */
273
274	igs_ext_write(iot, ioh, 0x31, 0x00); /* segment write ptr */
275	igs_ext_write(iot, ioh, 0x32, 0x00); /* segment read ptr */
276
277	/* IGS_EXT_BIU_MISC_CTL: linear, segon */
278	igs_ext_write(iot, ioh, 0x33, 0x11);
279
280	/* sprite location */
281	igs_ext_write(iot, ioh, 0x50, 0x00);
282	igs_ext_write(iot, ioh, 0x51, 0x00);
283	igs_ext_write(iot, ioh, 0x52, 0x00);
284	igs_ext_write(iot, ioh, 0x53, 0x00);
285	igs_ext_write(iot, ioh, 0x54, 0x00);
286	igs_ext_write(iot, ioh, 0x55, 0x00);
287	igs_ext_write(iot, ioh, 0x56, 0x00); /* sprite control */
288
289	/* IGS_EXT_GRFX_MODE */
290	igs_ext_write(iot, ioh, 0x57, 0x01); /* raster fb */
291
292	/* overscan R/G/B */
293	igs_ext_write(iot, ioh, 0x58, 0x00);
294	igs_ext_write(iot, ioh, 0x59, 0x00);
295	igs_ext_write(iot, ioh, 0x5A, 0x00);
296
297	/*
298	 * Video memory size &c.  We rely on firmware to program
299	 * BUS_CTL(30), MEM_CTL1(71), MEM_CTL2(72) appropriately.
300	 */
301
302	/* ext memory ctl0 */
303	igs_ext_write(iot, ioh, 0x70, 0x0B); /* enable fifo, seq */
304
305	/* ext hidden ctl1 */
306	igs_ext_write(iot, ioh, 0x73, 0x30); /* XXX: krups: 0x20 */
307
308	/* ext fifo control */
309	igs_ext_write(iot, ioh, 0x74, 0x10); /* XXX: krups: 0x1b */
310	igs_ext_write(iot, ioh, 0x75, 0x10); /* XXX: krups: 0x1e */
311
312	igs_ext_write(iot, ioh, 0x76, 0x00); /* ext seq. */
313	igs_ext_write(iot, ioh, 0x7A, 0xC8); /* ext. hidden ctl */
314
315	/* ext graphics ctl: GCEXTPATH.  krups 1, nettrom 1, docs 3 */
316	igs_ext_write(iot, ioh, 0x90, 0x01);
317
318	if (sc->sc_is2k)	/* select normal vclk/mclk registers */
319	    igs_ext_write(iot, ioh, 0xBF, 0x00);
320
321	igs_ext_write(iot, ioh, 0xB0, 0xD2); /* VCLK = 25.175MHz */
322	igs_ext_write(iot, ioh, 0xB1, 0xD3);
323	igs_ext_write(iot, ioh, 0xB2, 0xDB); /* MCLK = 75MHz*/
324	igs_ext_write(iot, ioh, 0xB3, 0x54);
325	igsfb_freq_latch(sc);
326
327	if (sc->sc_is2k)
328	    igs_ext_write(iot, ioh, 0xF8, 0x04); /* XXX: ??? */
329
330	/* 640x480 8bpp at 60Hz */
331	igs_ext_write(iot, ioh, 0x11, 0x00);
332	igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */
333	igs_ext_write(iot, ioh, 0x14, 0x51);
334	igs_ext_write(iot, ioh, 0x15, 0x00);
335}
336
337
338static void
339igsfb_init_dac(sc)
340	struct igsfb_softc *sc;
341{
342	bus_space_tag_t iot = sc->sc_iot;
343	bus_space_handle_t ioh = sc->sc_ioh;
344	u_int8_t reg;
345
346	/* RAMDAC address 2 select */
347	reg = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL);
348	igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
349		      reg | IGS_EXT_SPRITE_DAC_PEL);
350
351	/* VREFEN, DAC8 */
352	bus_space_write_1(iot, ioh, IGS_DAC_CMD, 0x06);
353
354	/* restore */
355	igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, reg);
356
357	bus_space_write_1(iot, ioh, IGS_PEL_MASK, 0xff);
358}
359
360
361void
362igsfb_1024x768_8bpp_60Hz(sc)
363	struct igsfb_softc *sc;
364{
365	bus_space_tag_t iot = sc->sc_iot;
366	bus_space_handle_t ioh = sc->sc_ioh;
367
368	igs_crtc_write(iot, ioh, 0x11, 0x00); /* write enable CRTC 0..7 */
369
370	igs_crtc_write(iot, ioh, 0x00, 0xa3);
371	igs_crtc_write(iot, ioh, 0x01, 0x7f);
372	igs_crtc_write(iot, ioh, 0x02, 0x7f); /* krups: 80 */
373	igs_crtc_write(iot, ioh, 0x03, 0x85); /* krups: 84 */
374	igs_crtc_write(iot, ioh, 0x04, 0x84); /* krups: 88 */
375	igs_crtc_write(iot, ioh, 0x05, 0x95); /* krups: 99 */
376	igs_crtc_write(iot, ioh, 0x06, 0x24);
377	igs_crtc_write(iot, ioh, 0x07, 0xfd);
378
379	/* next block is almost constant, only bit 6 in reg 9 differs */
380	igs_crtc_write(iot, ioh, 0x08, 0x00);
381	igs_crtc_write(iot, ioh, 0x09, 0x60); /* <- either 0x40 or 0x60 */
382	igs_crtc_write(iot, ioh, 0x0a, 0x00);
383	igs_crtc_write(iot, ioh, 0x0b, 0x00);
384	igs_crtc_write(iot, ioh, 0x0c, 0x00);
385	igs_crtc_write(iot, ioh, 0x0d, 0x00);
386	igs_crtc_write(iot, ioh, 0x0e, 0x00);
387	igs_crtc_write(iot, ioh, 0x0f, 0x00);
388
389	igs_crtc_write(iot, ioh, 0x10, 0x06);
390	igs_crtc_write(iot, ioh, 0x11, 0x8c);
391	igs_crtc_write(iot, ioh, 0x12, 0xff);
392	igs_crtc_write(iot, ioh, 0x13, 0x80); /* depends on BPP */
393	igs_crtc_write(iot, ioh, 0x14, 0x0f);
394	igs_crtc_write(iot, ioh, 0x15, 0x02);
395	igs_crtc_write(iot, ioh, 0x16, 0x21);
396	igs_crtc_write(iot, ioh, 0x17, 0xe3);
397	igs_crtc_write(iot, ioh, 0x18, 0xff);
398
399	igs_ext_write(iot, ioh, 0xB0, 0xE2); /* VCLK */
400	igs_ext_write(iot, ioh, 0xB1, 0x58);
401#if 1
402	/* XXX: hmm, krups does this */
403	igs_ext_write(iot, ioh, 0xB2, 0xE2); /* MCLK */
404	igs_ext_write(iot, ioh, 0xB3, 0x58);
405#endif
406	igsfb_freq_latch(sc);
407
408	igs_ext_write(iot, ioh, 0x11, 0x00);
409	igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */
410	igs_ext_write(iot, ioh, 0x14, 0x81);
411	igs_ext_write(iot, ioh, 0x15, 0x00);
412}
413
414
415static void igsfb_xxx_snoop(struct igsfb_softc *); /* XXX: debugging */
416
417static void
418igsfb_xxx_snoop(sc)
419	struct igsfb_softc *sc;
420{
421	bus_space_tag_t iot = sc->sc_iot;
422	bus_space_handle_t ioh = sc->sc_ioh;
423	u_int8_t reg;
424
425	/* Memory size */
426	reg = igs_ext_read(iot, ioh, IGS_EXT_BUS_CTL);
427	printf(">>> EXT.30 = 0x%02x\n", reg);
428
429	/*
430	 * Memory type &c.
431	 * netwinder = 0x63 -> serial DRAM   1Mx16 chips
432	 *     krups = 0x03 -> serial DRAM 256Kx?? chips
433	 */
434	reg = igs_ext_read(iot, ioh, IGS_EXT_MEM_CTL1);
435	printf(">>> EXT.71 = 0x%02x\n", reg);
436
437	/*
438	 * netwinder = 0x02 -> 4Mb, 32bit bus
439	 *     krups = 0x05 -> 2Mb, 64bit bus
440	 */
441	reg = igs_ext_read(iot, ioh, IGS_EXT_MEM_CTL2);
442	printf(">>> EXT.72 = 0x%02x\n", reg);
443}
444
445
446/*
447 * igs-video-init from krups prom
448 */
449void
450igsfb_hw_setup(sc)
451	struct igsfb_softc *sc;
452{
453	igsfb_xxx_snoop(sc);	/* misc debugging printfs */
454
455	igsfb_init_seq(sc);
456	igsfb_init_crtc(sc);
457	igsfb_init_attr(sc);
458	igsfb_init_grfx(sc);
459	igsfb_init_ext(sc);
460	igsfb_init_dac(sc);
461
462	igsfb_1024x768_8bpp_60Hz(sc);
463	igsfb_video_on(sc);
464}
465