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