igsfb_subr.c revision 1.1.2.2 1 /* $NetBSD: igsfb_subr.c,v 1.1.2.2 2002/10/10 18:39:01 jdolecek 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.2.2 2002/10/10 18:39:01 jdolecek 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, ®h);
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