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