fb.c revision 1.11
1/* $NetBSD: fb.c,v 1.11 2002/05/31 21:40:49 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/param.h> 30#include <sys/device.h> 31#include <sys/ioctl.h> 32#include <sys/malloc.h> 33#include <sys/systm.h> 34 35#include <uvm/uvm_extern.h> 36 37#include <machine/adrsmap.h> 38#include <machine/autoconf.h> 39 40#include <dev/wscons/wsconsio.h> 41#include <dev/wscons/wsdisplayvar.h> 42#include <dev/rasops/rasops.h> 43 44struct fb_devconfig { 45 u_char *dc_fbbase; /* VRAM base address */ 46 struct rasops_info dc_ri; 47}; 48 49struct fb_softc { 50 struct device sc_dev; 51 struct fb_devconfig *sc_dc; 52 int sc_nscreens; 53}; 54 55int fb_match(struct device *, struct cfdata *, void *); 56void fb_attach(struct device *, struct device *, void *); 57 58int fb_common_init(struct fb_devconfig *); 59int fb_is_console(void); 60 61int fb_ioctl(void *, u_long, caddr_t, int, struct proc *); 62paddr_t fb_mmap(void *, off_t, int); 63int fb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *, 64 int *, long *); 65void fb_free_screen(void *, void *); 66int fb_show_screen(void *, void *, int, void (*)(void *, int, int), void *); 67 68void fb_cnattach(void); 69 70static void fb253_init(void); 71 72struct cfattach fb_ca = { 73 sizeof(struct fb_softc), fb_match, fb_attach, 74}; 75 76struct fb_devconfig fb_console_dc; 77 78struct wsdisplay_accessops fb_accessops = { 79 fb_ioctl, 80 fb_mmap, 81 fb_alloc_screen, 82 fb_free_screen, 83 fb_show_screen, 84 NULL /* load_font */ 85}; 86 87struct wsscreen_descr fb_stdscreen = { 88 "std", 89 0, 0, 90 0, 91 0, 0, 92 WSSCREEN_REVERSE 93}; 94 95const struct wsscreen_descr *fb_scrlist[] = { 96 &fb_stdscreen 97}; 98 99struct wsscreen_list fb_screenlist = { 100 sizeof(fb_scrlist) / sizeof(fb_scrlist[0]), fb_scrlist 101}; 102 103#define NWB253_VRAM ((u_char *) 0x88000000) 104#define NWB253_CTLREG ((u_short *)0xb8ff0000) 105#define NWB253_CRTREG ((u_short *)0xb8fe0000) 106 107static char *devname[8] = { "NWB-512", "NWB-518", "NWE-501" }; /* XXX ? */ 108 109int 110fb_match(parent, match, aux) 111 struct device *parent; 112 struct cfdata *match; 113 void *aux; 114{ 115 struct confargs *ca = aux; 116 117 if (strcmp(ca->ca_name, "fb") != 0) 118 return 0; 119 120 if (badaddr(NWB253_CTLREG, 2) || badaddr(NWB253_CRTREG, 2)) 121 return 0; 122 if ((*(volatile u_short *)NWB253_CTLREG & 7) != 4) 123 return 0; 124 125 return 1; 126} 127 128void 129fb_attach(parent, self, aux) 130 struct device *parent, *self; 131 void *aux; 132{ 133 struct fb_softc *sc = (void *)self; 134 struct wsemuldisplaydev_attach_args waa; 135 struct fb_devconfig *dc; 136 struct rasops_info *ri; 137 int console; 138 volatile u_short *ctlreg = NWB253_CTLREG; 139 int id; 140 141 console = fb_is_console(); 142 143 if (console) { 144 dc = &fb_console_dc; 145 ri = &dc->dc_ri; 146 sc->sc_nscreens = 1; 147 } else { 148 dc = malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK); 149 bzero(dc, sizeof(struct fb_devconfig)); 150 151 dc->dc_fbbase = NWB253_VRAM; 152 fb_common_init(dc); 153 ri = &dc->dc_ri; 154 155 /* clear screen */ 156 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0); 157 158 fb253_init(); 159 } 160 sc->sc_dc = dc; 161 162 id = (*ctlreg >> 8) & 0xf; 163 printf(": %s, %d x %d, %dbpp\n", devname[id], 164 ri->ri_width, ri->ri_height, ri->ri_depth); 165 166 waa.console = console; 167 waa.scrdata = &fb_screenlist; 168 waa.accessops = &fb_accessops; 169 waa.accesscookie = sc; 170 171 config_found(self, &waa, wsemuldisplaydevprint); 172} 173 174int 175fb_common_init(dc) 176 struct fb_devconfig *dc; 177{ 178 struct rasops_info *ri = &dc->dc_ri; 179 volatile u_short *ctlreg = NWB253_CTLREG; 180 int id; 181 int width, height, xoff, yoff, cols, rows; 182 183 id = (*ctlreg >> 8) & 0xf; 184 185 /* initialize rasops */ 186 switch (id) { 187 case 0: 188 width = 816; 189 height = 1024; 190 break; 191 case 1: 192 case 2: 193 width = 1024; 194 height = 768; 195 break; 196 } 197 198 ri->ri_width = width; 199 ri->ri_height = height; 200 ri->ri_depth = 1; 201 ri->ri_stride = 2048 / 8; 202 ri->ri_bits = dc->dc_fbbase; 203 ri->ri_flg = RI_FULLCLEAR; 204 205 rasops_init(ri, 24, 80); 206 rows = (height - 2) / ri->ri_font->fontheight; 207 cols = ((width - 2) / ri->ri_font->fontwidth) & ~7; 208 xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3; 209 yoff = (height - rows * ri->ri_font->fontheight) / 2; 210 rasops_reconfig(ri, rows, cols); 211 212 ri->ri_xorigin = xoff; 213 ri->ri_yorigin = yoff; 214 ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff; 215 216 fb_stdscreen.nrows = ri->ri_rows; 217 fb_stdscreen.ncols = ri->ri_cols; 218 fb_stdscreen.textops = &ri->ri_ops; 219 fb_stdscreen.capabilities = ri->ri_caps; 220 221 return 0; 222} 223 224int 225fb_is_console() 226{ 227 volatile u_int *dipsw = (void *)DIP_SWITCH; 228 229 if (*dipsw & 7) /* XXX right? */ 230 return 1; 231 232 return 0; 233} 234 235int 236fb_ioctl(v, cmd, data, flag, p) 237 void *v; 238 u_long cmd; 239 caddr_t data; 240 int flag; 241 struct proc *p; 242{ 243 struct fb_softc *sc = v; 244 struct fb_devconfig *dc = sc->sc_dc; 245 struct wsdisplay_fbinfo *wdf; 246 247 switch (cmd) { 248 case WSDISPLAYIO_GTYPE: 249 *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ 250 return 0; 251 252 case WSDISPLAYIO_GINFO: 253 wdf = (void *)data; 254 wdf->height = dc->dc_ri.ri_height; 255 wdf->width = dc->dc_ri.ri_width; 256 wdf->depth = dc->dc_ri.ri_depth; 257 wdf->cmsize = 2; 258 return 0; 259 260 case WSDISPLAYIO_SVIDEO: 261 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF) { 262 volatile u_short *ctlreg = NWB253_CTLREG; 263 *ctlreg = 0; /* stop crtc */ 264 } else 265 fb253_init(); 266 return 0; 267 268 case WSDISPLAYIO_GETCMAP: 269 case WSDISPLAYIO_PUTCMAP: 270 break; 271 } 272 return EPASSTHROUGH; 273} 274 275paddr_t 276fb_mmap(v, offset, prot) 277 void *v; 278 off_t offset; 279 int prot; 280{ 281 struct fb_softc *sc = v; 282 struct fb_devconfig *dc = sc->sc_dc; 283 284 if (offset >= 2048 * 2048 / 8 || offset < 0) 285 return -1; 286 287 return mips_btop((int)dc->dc_fbbase + offset); 288} 289 290int 291fb_alloc_screen(v, scrdesc, cookiep, ccolp, crowp, attrp) 292 void *v; 293 const struct wsscreen_descr *scrdesc; 294 void **cookiep; 295 int *ccolp, *crowp; 296 long *attrp; 297{ 298 struct fb_softc *sc = v; 299 struct rasops_info *ri = &sc->sc_dc->dc_ri; 300 long defattr; 301 302 if (sc->sc_nscreens > 0) 303 return ENOMEM; 304 305 *cookiep = ri; 306 *ccolp = *crowp = 0; 307 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 308 *attrp = defattr; 309 sc->sc_nscreens++; 310 311 return 0; 312} 313 314void 315fb_free_screen(v, cookie) 316 void *v; 317 void *cookie; 318{ 319 struct fb_softc *sc = v; 320 321 if (sc->sc_dc == &fb_console_dc) 322 panic("fb_free_screen: console"); 323 324 sc->sc_nscreens--; 325} 326 327int 328fb_show_screen(v, cookie, waitok, cb, cbarg) 329 void *v; 330 void *cookie; 331 int waitok; 332 void (*cb)(void *, int, int); 333 void *cbarg; 334{ 335 return 0; 336} 337 338void 339fb_cnattach() 340{ 341 struct fb_devconfig *dc = &fb_console_dc; 342 struct rasops_info *ri = &dc->dc_ri; 343 long defattr; 344 345 if (!fb_is_console()) 346 return; 347 348 dc->dc_fbbase = NWB253_VRAM; 349 fb_common_init(dc); 350 351 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 352 wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr); 353} 354 355static u_char 356nwp512_data1[] = { 357 0x00, 0x44, 358 0x01, 0x33, 359 0x02, 0x3c, 360 0x03, 0x38, 361 0x04, 0x84, 362 0x05, 0x03, 363 0x06, 0x80, 364 0x07, 0x80, 365 0x08, 0x10, 366 0x09, 0x07, 367 0x0a, 0x20, 368 0x0c, 0x00, 369 0x0d, 0x00, 370 0x1b, 0x03 371}; 372 373static u_char 374nwp512_data2[] = { 375 0x1e, 0x08, 376 0x20, 0x08, 377 0x21, 0x0d 378}; 379 380static u_char 381nwp518_data1[] = { 382 0x00, 0x52, 383 0x01, 0x40, 384 0x02, 0x4a, 385 0x03, 0x49, 386 0x04, 0x63, 387 0x05, 0x02, 388 0x06, 0x60, 389 0x07, 0x60, 390 0x08, 0x10, 391 0x09, 0x07, 392 0x0a, 0x20, 393 0x0c, 0x00, 394 0x0d, 0x00, 395 0x1b, 0x04 396}; 397 398static u_char 399nwp518_data2[] = { 400 0x1e, 0x08, 401 0x20, 0x00, 402 0x21, 0x00 403}; 404 405static u_char 406nwe501_data1[] = { 407 0x00, 0x4b, 408 0x01, 0x40, 409 0x02, 0x4a, 410 0x03, 0x43, 411 0x04, 0x64, 412 0x05, 0x02, 413 0x06, 0x60, 414 0x07, 0x60, 415 0x08, 0x10, 416 0x09, 0x07, 417 0x0a, 0x20, 418 0x0c, 0x00, 419 0x0d, 0x00, 420 0x1b, 0x04 421}; 422 423static u_char 424nwe501_data2[] = { 425 0x1e, 0x08, 426 0x20, 0x00, 427 0x21, 0x00 428}; 429 430static u_char 431*crtc_data[3][2] = { 432 { nwp512_data1, nwp512_data2 }, 433 { nwp518_data1, nwp518_data2 }, 434 { nwe501_data1, nwe501_data2 } 435}; 436 437static void 438fb253_init(void) 439{ 440 volatile u_short *ctlreg = NWB253_CTLREG; 441 volatile u_short *crtreg = NWB253_CRTREG; 442 int id = (*ctlreg >> 8) & 0xf; 443 u_char *p; 444 int i; 445 446 *ctlreg = 0; /* stop crtc */ 447 delay(10); 448 449 /* initialize crtc without R3{0,1,2} */ 450 p = crtc_data[id][0]; 451 for (i = 0; i < 28; i++) { 452 *crtreg++ = *p++; 453 delay(10); 454 } 455 456 *ctlreg = 0x02; /* start crtc */ 457 delay(10); 458 459 /* set crtc control reg */ 460 p = crtc_data[id][1]; 461 for (i = 0; i < 6; i++) { 462 *crtreg++ = *p++; 463 delay(10); 464 } 465} 466 467#if 0 468static struct wsdisplay_font newsrom8x16; 469static struct wsdisplay_font newsrom12x24; 470static char fontarea16[96][32]; 471static char fontarea24[96][96]; 472 473void 474initfont(ri) 475 struct rasops_info *ri; 476{ 477 int c, x; 478 479 for (c = 0; c < 96; c++) { 480 x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7; 481 bcopy((char *)0xb8e00000 + x + 96, fontarea16 + c, 32); 482 bcopy((char *)0xb8e00000 + x, fontarea24 + c, 96); 483 } 484 485 newsrom8x16.name = "rom8x16"; 486 newsrom8x16.firstchar = 32; 487 newsrom8x16.numchars = 96; 488 newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO; 489 newsrom8x16.fontwidth = 8; 490 newsrom8x16.fontheight = 16; 491 newsrom8x16.stride = 2; 492 newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R; 493 newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R; 494 newsrom8x16.data = fontarea16; 495 496 newsrom12x24.name = "rom12x24"; 497 newsrom12x24.firstchar = 32; 498 newsrom12x24.numchars = 96; 499 newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO; 500 newsrom12x24.fontwidth = 12; 501 newsrom12x24.fontheight = 24; 502 newsrom12x24.stride = 4; 503 newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R; 504 newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R; 505 newsrom12x24.data = fontarea24; 506 507 ri->ri_font = &newsrom8x16; 508 ri->ri_font = &newsrom12x24; 509 ri->ri_wsfcookie = -1; /* not using wsfont */ 510} 511#endif 512