xref: /netbsd/sys/dev/ic/igsfb_subr.c (revision c4a72b64)
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 
49 static void	igsfb_init_seq(struct igsfb_softc *);
50 static void	igsfb_init_crtc(struct igsfb_softc *);
51 static void	igsfb_init_grfx(struct igsfb_softc *);
52 static void	igsfb_init_attr(struct igsfb_softc *);
53 static void	igsfb_init_ext(struct igsfb_softc *);
54 static void	igsfb_init_dac(struct igsfb_softc *);
55 
56 static void	igsfb_freq_latch(struct igsfb_softc *);
57 static void	igsfb_video_on(struct igsfb_softc *);
58 
59 
60 
61 /*
62  * Enable chip.
63  */
64 int
65 igsfb_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  */
118 static void
119 igsfb_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  */
144 static void
145 igsfb_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  */
187 static void
188 igsfb_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  */
210 static void
211 igsfb_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  */
234 static void
235 igsfb_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  */
250 static void
251 igsfb_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 
263 static void
264 igsfb_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 
338 static void
339 igsfb_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 
361 void
362 igsfb_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 
415 static void igsfb_xxx_snoop(struct igsfb_softc *); /* XXX: debugging */
416 
417 static void
418 igsfb_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  */
449 void
450 igsfb_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