1 /* $NetBSD: igsfb_subr.c,v 1.3 2003/05/30 22:41:52 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.3 2003/05/30 22:41:52 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/wsdisplayvar.h> 44 #include <dev/wscons/wsconsio.h> 45 #include <dev/rasops/rasops.h> 46 47 #include <dev/ic/igsfbreg.h> 48 #include <dev/ic/igsfbvar.h> 49 50 51 static void igsfb_init_seq(struct igsfb_devconfig *); 52 static void igsfb_init_crtc(struct igsfb_devconfig *); 53 static void igsfb_init_grfx(struct igsfb_devconfig *); 54 static void igsfb_init_attr(struct igsfb_devconfig *); 55 static void igsfb_init_ext(struct igsfb_devconfig *); 56 static void igsfb_init_dac(struct igsfb_devconfig *); 57 58 static void igsfb_freq_latch(struct igsfb_devconfig *); 59 static void igsfb_video_on(struct igsfb_devconfig *); 60 61 62 63 /* 64 * Enable chip. 65 */ 66 int 67 igsfb_enable(iot, iobase, ioflags) 68 bus_space_tag_t iot; 69 bus_addr_t iobase; 70 int ioflags; 71 { 72 bus_space_handle_t vdoh; 73 bus_space_handle_t vseh; 74 bus_space_handle_t regh; 75 int ret; 76 77 ret = bus_space_map(iot, iobase + IGS_VDO, 1, ioflags, &vdoh); 78 if (ret != 0) { 79 printf("unable to map VDO register\n"); 80 goto out0; 81 } 82 83 ret = bus_space_map(iot, iobase + IGS_VSE, 1, ioflags, &vseh); 84 if (ret != 0) { 85 printf("unable to map VSE register\n"); 86 goto out1; 87 } 88 89 ret = bus_space_map(iot, iobase + IGS_REG_BASE, IGS_REG_SIZE, ioflags, 90 ®h); 91 if (ret != 0) { 92 printf("unable to map I/O registers\n"); 93 goto out2; 94 } 95 96 /* 97 * Start decoding i/o space accesses. 98 */ 99 bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE | IGS_VDO_SETUP); 100 bus_space_write_1(iot, vseh, 0, IGS_VSE_ENABLE); 101 bus_space_write_1(iot, vdoh, 0, IGS_VDO_ENABLE); 102 103 /* 104 * Start decoding memory space accesses (XXX: move out of here? 105 * we program this register in igsfb_init_ext). 106 * While here, enable coprocessor and select IGS_COP_BASE_B. 107 */ 108 igs_ext_write(iot, regh, IGS_EXT_BIU_MISC_CTL, 109 (IGS_EXT_BIU_LINEAREN 110 | IGS_EXT_BIU_COPREN | IGS_EXT_BIU_COPASELB)); 111 112 bus_space_unmap(iot, regh, IGS_REG_SIZE); 113 out2: bus_space_unmap(iot, vseh, 1); 114 out1: bus_space_unmap(iot, vdoh, 1); 115 out0: return (ret); 116 } 117 118 119 /* 120 * Init sequencer. 121 * This is common for all video modes. 122 */ 123 static void 124 igsfb_init_seq(dc) 125 struct igsfb_devconfig *dc; 126 { 127 bus_space_tag_t iot = dc->dc_iot; 128 bus_space_handle_t ioh = dc->dc_ioh; 129 130 /* start messing with sequencer */ 131 igs_seq_write(iot, ioh, IGS_SEQ_RESET, 0); 132 133 igs_seq_write(iot, ioh, 1, 0x01); /* 8 dot clock */ 134 igs_seq_write(iot, ioh, 2, 0x0f); /* enable all maps */ 135 igs_seq_write(iot, ioh, 3, 0x00); /* character generator */ 136 igs_seq_write(iot, ioh, 4, 0x0e); /* memory mode */ 137 138 /* this selects color mode among other things */ 139 bus_space_write_1(iot, ioh, IGS_MISC_OUTPUT_W, 0xef); 140 141 /* normal sequencer operation */ 142 igs_seq_write(iot, ioh, IGS_SEQ_RESET, 143 IGS_SEQ_RESET_SYNC | IGS_SEQ_RESET_ASYNC); 144 } 145 146 /* 147 * Init CRTC to 640x480 8bpp at 60Hz 148 */ 149 static void 150 igsfb_init_crtc(dc) 151 struct igsfb_devconfig *dc; 152 { 153 bus_space_tag_t iot = dc->dc_iot; 154 bus_space_handle_t ioh = dc->dc_ioh; 155 156 igs_crtc_write(iot, ioh, 0x00, 0x5f); 157 igs_crtc_write(iot, ioh, 0x01, 0x4f); 158 igs_crtc_write(iot, ioh, 0x02, 0x50); 159 igs_crtc_write(iot, ioh, 0x03, 0x80); 160 igs_crtc_write(iot, ioh, 0x04, 0x52); 161 igs_crtc_write(iot, ioh, 0x05, 0x9d); 162 igs_crtc_write(iot, ioh, 0x06, 0x0b); 163 igs_crtc_write(iot, ioh, 0x07, 0x3e); 164 165 /* next block is almost constant, only bit 6 in reg 9 differs */ 166 igs_crtc_write(iot, ioh, 0x08, 0x00); 167 igs_crtc_write(iot, ioh, 0x09, 0x40); /* <- either 0x40 or 0x60 */ 168 igs_crtc_write(iot, ioh, 0x0a, 0x00); 169 igs_crtc_write(iot, ioh, 0x0b, 0x00); 170 igs_crtc_write(iot, ioh, 0x0c, 0x00); 171 igs_crtc_write(iot, ioh, 0x0d, 0x00); 172 igs_crtc_write(iot, ioh, 0x0e, 0x00); 173 igs_crtc_write(iot, ioh, 0x0f, 0x00); 174 175 igs_crtc_write(iot, ioh, 0x10, 0xe9); 176 igs_crtc_write(iot, ioh, 0x11, 0x8b); 177 igs_crtc_write(iot, ioh, 0x12, 0xdf); 178 igs_crtc_write(iot, ioh, 0x13, 0x50); 179 igs_crtc_write(iot, ioh, 0x14, 0x00); 180 igs_crtc_write(iot, ioh, 0x15, 0xe6); 181 igs_crtc_write(iot, ioh, 0x16, 0x04); 182 igs_crtc_write(iot, ioh, 0x17, 0xc3); 183 184 igs_crtc_write(iot, ioh, 0x18, 0xff); 185 } 186 187 188 /* 189 * Init graphics controller. 190 * This is common for all video modes. 191 */ 192 static void 193 igsfb_init_grfx(dc) 194 struct igsfb_devconfig *dc; 195 { 196 bus_space_tag_t iot = dc->dc_iot; 197 bus_space_handle_t ioh = dc->dc_ioh; 198 199 igs_grfx_write(iot, ioh, 0, 0x00); 200 igs_grfx_write(iot, ioh, 1, 0x00); 201 igs_grfx_write(iot, ioh, 2, 0x00); 202 igs_grfx_write(iot, ioh, 3, 0x00); 203 igs_grfx_write(iot, ioh, 4, 0x00); 204 igs_grfx_write(iot, ioh, 5, 0x60); /* SRMODE, MODE256 */ 205 igs_grfx_write(iot, ioh, 6, 0x05); /* 64k @ a0000, GRAPHICS */ 206 igs_grfx_write(iot, ioh, 7, 0x0f); /* color compare all */ 207 igs_grfx_write(iot, ioh, 8, 0xff); /* bitmask = all bits mutable */ 208 } 209 210 211 /* 212 * Init attribute controller. 213 * This is common for all video modes. 214 */ 215 static void 216 igsfb_init_attr(dc) 217 struct igsfb_devconfig *dc; 218 { 219 bus_space_tag_t iot = dc->dc_iot; 220 bus_space_handle_t ioh = dc->dc_ioh; 221 int i; 222 223 igs_attr_flip_flop(iot, ioh); /* reset attr flip-flop to address */ 224 225 for (i = 0; i < 16; ++i) /* crt palette */ 226 igs_attr_write(iot, ioh, i, i); 227 228 igs_attr_write(iot, ioh, 0x10, 0x01); /* select graphic mode */ 229 igs_attr_write(iot, ioh, 0x11, 0x00); /* crt overscan color */ 230 igs_attr_write(iot, ioh, 0x12, 0x0f); /* color plane enable */ 231 igs_attr_write(iot, ioh, 0x13, 0x00); 232 igs_attr_write(iot, ioh, 0x14, 0x00); 233 } 234 235 236 /* 237 * When done with ATTR controller, call this to unblank the screen. 238 */ 239 static void 240 igsfb_video_on(dc) 241 struct igsfb_devconfig *dc; 242 { 243 bus_space_tag_t iot = dc->dc_iot; 244 bus_space_handle_t ioh = dc->dc_ioh; 245 246 igs_attr_flip_flop(iot, ioh); 247 bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20); 248 bus_space_write_1(iot, ioh, IGS_ATTR_IDX, 0x20); 249 } 250 251 252 /* 253 * Latch VCLK (b0/b1) and MCLK (b2/b3) values. 254 */ 255 static void 256 igsfb_freq_latch(dc) 257 struct igsfb_devconfig *dc; 258 { 259 bus_space_tag_t iot = dc->dc_iot; 260 bus_space_handle_t ioh = dc->dc_ioh; 261 262 bus_space_write_1(iot, ioh, IGS_EXT_IDX, 0xb9); 263 bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x80); 264 bus_space_write_1(iot, ioh, IGS_EXT_PORT, 0x00); 265 } 266 267 268 static void 269 igsfb_init_ext(dc) 270 struct igsfb_devconfig *dc; 271 { 272 bus_space_tag_t iot = dc->dc_iot; 273 bus_space_handle_t ioh = dc->dc_ioh; 274 int is_cyberpro = (dc->dc_id >= 0x2000); 275 276 igs_ext_write(iot, ioh, 0x10, 0x10); /* IGS_EXT_START_ADDR enable */ 277 igs_ext_write(iot, ioh, 0x12, 0x00); /* IGS_EXT_IRQ_CTL disable */ 278 igs_ext_write(iot, ioh, 0x13, 0x00); /* MBZ for normal operation */ 279 280 igs_ext_write(iot, ioh, 0x31, 0x00); /* segment write ptr */ 281 igs_ext_write(iot, ioh, 0x32, 0x00); /* segment read ptr */ 282 283 /* IGS_EXT_BIU_MISC_CTL: linearen, copren, copaselb, segon */ 284 igs_ext_write(iot, ioh, 0x33, 0x1d); 285 286 /* sprite location */ 287 igs_ext_write(iot, ioh, 0x50, 0x00); 288 igs_ext_write(iot, ioh, 0x51, 0x00); 289 igs_ext_write(iot, ioh, 0x52, 0x00); 290 igs_ext_write(iot, ioh, 0x53, 0x00); 291 igs_ext_write(iot, ioh, 0x54, 0x00); 292 igs_ext_write(iot, ioh, 0x55, 0x00); 293 igs_ext_write(iot, ioh, 0x56, 0x00); /* sprite control */ 294 295 /* IGS_EXT_GRFX_MODE */ 296 igs_ext_write(iot, ioh, 0x57, 0x01); /* raster fb */ 297 298 /* overscan R/G/B */ 299 igs_ext_write(iot, ioh, 0x58, 0x00); 300 igs_ext_write(iot, ioh, 0x59, 0x00); 301 igs_ext_write(iot, ioh, 0x5A, 0x00); 302 303 /* 304 * Video memory size &c. We rely on firmware to program 305 * BUS_CTL(30), MEM_CTL1(71), MEM_CTL2(72) appropriately. 306 */ 307 308 /* ext memory ctl0 */ 309 igs_ext_write(iot, ioh, 0x70, 0x0B); /* enable fifo, seq */ 310 311 /* ext hidden ctl1 */ 312 igs_ext_write(iot, ioh, 0x73, 0x30); /* XXX: krups: 0x20 */ 313 314 /* ext fifo control */ 315 igs_ext_write(iot, ioh, 0x74, 0x10); /* XXX: krups: 0x1b */ 316 igs_ext_write(iot, ioh, 0x75, 0x10); /* XXX: krups: 0x1e */ 317 318 igs_ext_write(iot, ioh, 0x76, 0x00); /* ext seq. */ 319 igs_ext_write(iot, ioh, 0x7A, 0xC8); /* ext. hidden ctl */ 320 321 /* ext graphics ctl: GCEXTPATH. krups 1, nettrom 1, docs 3 */ 322 igs_ext_write(iot, ioh, 0x90, 0x01); 323 324 if (is_cyberpro) /* select normal vclk/mclk registers */ 325 igs_ext_write(iot, ioh, 0xBF, 0x00); 326 327 igs_ext_write(iot, ioh, 0xB0, 0xD2); /* VCLK = 25.175MHz */ 328 igs_ext_write(iot, ioh, 0xB1, 0xD3); 329 igs_ext_write(iot, ioh, 0xB2, 0xDB); /* MCLK = 75MHz*/ 330 igs_ext_write(iot, ioh, 0xB3, 0x54); 331 igsfb_freq_latch(dc); 332 333 if (is_cyberpro) 334 igs_ext_write(iot, ioh, 0xF8, 0x04); /* XXX: ??? */ 335 336 /* 640x480 8bpp at 60Hz */ 337 igs_ext_write(iot, ioh, 0x11, 0x00); 338 igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */ 339 igs_ext_write(iot, ioh, 0x14, 0x51); 340 igs_ext_write(iot, ioh, 0x15, 0x00); 341 } 342 343 344 static void 345 igsfb_init_dac(dc) 346 struct igsfb_devconfig *dc; 347 { 348 bus_space_tag_t iot = dc->dc_iot; 349 bus_space_handle_t ioh = dc->dc_ioh; 350 u_int8_t reg; 351 352 /* RAMDAC address 2 select */ 353 reg = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL); 354 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 355 reg | IGS_EXT_SPRITE_DAC_PEL); 356 357 /* VREFEN, DAC8 */ 358 bus_space_write_1(iot, ioh, IGS_DAC_CMD, 0x06); 359 360 /* restore */ 361 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, reg); 362 363 bus_space_write_1(iot, ioh, IGS_PEL_MASK, 0xff); 364 } 365 366 367 void 368 igsfb_1024x768_8bpp_60Hz(dc) 369 struct igsfb_devconfig *dc; 370 { 371 bus_space_tag_t iot = dc->dc_iot; 372 bus_space_handle_t ioh = dc->dc_ioh; 373 374 igs_crtc_write(iot, ioh, 0x11, 0x00); /* write enable CRTC 0..7 */ 375 376 igs_crtc_write(iot, ioh, 0x00, 0xa3); 377 igs_crtc_write(iot, ioh, 0x01, 0x7f); 378 igs_crtc_write(iot, ioh, 0x02, 0x7f); /* krups: 80 */ 379 igs_crtc_write(iot, ioh, 0x03, 0x85); /* krups: 84 */ 380 igs_crtc_write(iot, ioh, 0x04, 0x84); /* krups: 88 */ 381 igs_crtc_write(iot, ioh, 0x05, 0x95); /* krups: 99 */ 382 igs_crtc_write(iot, ioh, 0x06, 0x24); 383 igs_crtc_write(iot, ioh, 0x07, 0xfd); 384 385 /* next block is almost constant, only bit 6 in reg 9 differs */ 386 igs_crtc_write(iot, ioh, 0x08, 0x00); 387 igs_crtc_write(iot, ioh, 0x09, 0x60); /* <- either 0x40 or 0x60 */ 388 igs_crtc_write(iot, ioh, 0x0a, 0x00); 389 igs_crtc_write(iot, ioh, 0x0b, 0x00); 390 igs_crtc_write(iot, ioh, 0x0c, 0x00); 391 igs_crtc_write(iot, ioh, 0x0d, 0x00); 392 igs_crtc_write(iot, ioh, 0x0e, 0x00); 393 igs_crtc_write(iot, ioh, 0x0f, 0x00); 394 395 igs_crtc_write(iot, ioh, 0x10, 0x06); 396 igs_crtc_write(iot, ioh, 0x11, 0x8c); 397 igs_crtc_write(iot, ioh, 0x12, 0xff); 398 igs_crtc_write(iot, ioh, 0x13, 0x80); /* depends on BPP */ 399 igs_crtc_write(iot, ioh, 0x14, 0x0f); 400 igs_crtc_write(iot, ioh, 0x15, 0x02); 401 igs_crtc_write(iot, ioh, 0x16, 0x21); 402 igs_crtc_write(iot, ioh, 0x17, 0xe3); 403 igs_crtc_write(iot, ioh, 0x18, 0xff); 404 405 igs_ext_write(iot, ioh, 0xB0, 0xE2); /* VCLK */ 406 igs_ext_write(iot, ioh, 0xB1, 0x58); 407 #if 1 408 /* XXX: hmm, krups does this */ 409 igs_ext_write(iot, ioh, 0xB2, 0xE2); /* MCLK */ 410 igs_ext_write(iot, ioh, 0xB3, 0x58); 411 #endif 412 igsfb_freq_latch(dc); 413 414 igs_ext_write(iot, ioh, 0x11, 0x00); 415 igs_ext_write(iot, ioh, 0x77, 0x01); /* 8bpp, indexed */ 416 igs_ext_write(iot, ioh, 0x14, 0x81); 417 igs_ext_write(iot, ioh, 0x15, 0x00); 418 } 419 420 421 /* 422 * igs-video-init from krups prom 423 */ 424 void 425 igsfb_hw_setup(dc) 426 struct igsfb_devconfig *dc; 427 { 428 429 igsfb_init_seq(dc); 430 igsfb_init_crtc(dc); 431 igsfb_init_attr(dc); 432 igsfb_init_grfx(dc); 433 igsfb_init_ext(dc); 434 igsfb_init_dac(dc); 435 436 igsfb_1024x768_8bpp_60Hz(dc); 437 igsfb_video_on(dc); 438 } 439