1 1.34 tsutsui /* $NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $ */ 2 1.5 tsubai 3 1.5 tsubai /*- 4 1.5 tsubai * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 5 1.1 tsubai * 6 1.1 tsubai * Redistribution and use in source and binary forms, with or without 7 1.1 tsubai * modification, are permitted provided that the following conditions 8 1.1 tsubai * are met: 9 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 10 1.1 tsubai * notice, this list of conditions and the following disclaimer. 11 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 13 1.1 tsubai * documentation and/or other materials provided with the distribution. 14 1.5 tsubai * 3. The name of the author may not be used to endorse or promote products 15 1.5 tsubai * derived from this software without specific prior written permission. 16 1.1 tsubai * 17 1.5 tsubai * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.5 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.5 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.5 tsubai * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.5 tsubai * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.5 tsubai * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.5 tsubai * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.5 tsubai * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.5 tsubai * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 1.5 tsubai * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 tsubai */ 28 1.34 tsutsui /*- 29 1.34 tsutsui * Copyright (c) 2023 Izumi Tsutsui. All rights reserved. 30 1.34 tsutsui * 31 1.34 tsutsui * Redistribution and use in source and binary forms, with or without 32 1.34 tsutsui * modification, are permitted provided that the following conditions 33 1.34 tsutsui * are met: 34 1.34 tsutsui * 1. Redistributions of source code must retain the above copyright 35 1.34 tsutsui * notice, this list of conditions and the following disclaimer. 36 1.34 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 37 1.34 tsutsui * notice, this list of conditions and the following disclaimer in the 38 1.34 tsutsui * documentation and/or other materials provided with the distribution. 39 1.34 tsutsui * 40 1.34 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 41 1.34 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 42 1.34 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 43 1.34 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 44 1.34 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 1.34 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 46 1.34 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 47 1.34 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 48 1.34 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 49 1.34 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 1.34 tsutsui */ 51 1.17 lukem 52 1.17 lukem #include <sys/cdefs.h> 53 1.34 tsutsui __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $"); 54 1.1 tsubai 55 1.1 tsubai #include <sys/param.h> 56 1.1 tsubai #include <sys/device.h> 57 1.5 tsubai #include <sys/ioctl.h> 58 1.27 thorpej #include <sys/kmem.h> 59 1.1 tsubai #include <sys/systm.h> 60 1.1 tsubai 61 1.5 tsubai #include <uvm/uvm_extern.h> 62 1.5 tsubai 63 1.5 tsubai #include <machine/adrsmap.h> 64 1.16 tsutsui 65 1.16 tsutsui #include <newsmips/dev/hbvar.h> 66 1.1 tsubai 67 1.5 tsubai #include <dev/wscons/wsconsio.h> 68 1.5 tsubai #include <dev/wscons/wsdisplayvar.h> 69 1.5 tsubai #include <dev/rasops/rasops.h> 70 1.5 tsubai 71 1.5 tsubai struct fb_devconfig { 72 1.31 tsutsui uint8_t *dc_fbbase; /* VRAM base address */ 73 1.5 tsubai struct rasops_info dc_ri; 74 1.34 tsutsui int dc_model; 75 1.34 tsutsui #define NWB253 0 76 1.34 tsutsui #define LCDM 1 77 1.34 tsutsui int dc_displayid; 78 1.34 tsutsui #define NWP512 0 79 1.34 tsutsui #define NWP518 1 80 1.34 tsutsui #define NWE501 2 81 1.34 tsutsui int dc_size; 82 1.5 tsubai }; 83 1.1 tsubai 84 1.1 tsubai struct fb_softc { 85 1.24 tsutsui device_t sc_dev; 86 1.5 tsubai struct fb_devconfig *sc_dc; 87 1.5 tsubai int sc_nscreens; 88 1.1 tsubai }; 89 1.1 tsubai 90 1.30 tsutsui static int fb_match(device_t, cfdata_t, void *); 91 1.30 tsutsui static void fb_attach(device_t, device_t, void *); 92 1.5 tsubai 93 1.30 tsutsui static int fb_common_init(struct fb_devconfig *); 94 1.30 tsutsui static int fb_is_console(void); 95 1.5 tsubai 96 1.30 tsutsui static int fb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 97 1.30 tsutsui static paddr_t fb_mmap(void *, void *, off_t, int); 98 1.30 tsutsui static int fb_alloc_screen(void *, const struct wsscreen_descr *, void **, 99 1.30 tsutsui int *, int *, long *); 100 1.30 tsutsui static void fb_free_screen(void *, void *); 101 1.30 tsutsui static int fb_show_screen(void *, void *, int, void (*)(void *, int, int), 102 1.30 tsutsui void *); 103 1.5 tsubai 104 1.5 tsubai void fb_cnattach(void); 105 1.5 tsubai 106 1.34 tsutsui static int fb_set_state(struct fb_softc *, int); 107 1.34 tsutsui 108 1.34 tsutsui static bool fb253_probe(void); 109 1.34 tsutsui static bool fblcdm_probe(void); 110 1.34 tsutsui static bool fb_probe_model(struct fb_devconfig *); 111 1.34 tsutsui static void fb_init(struct fb_devconfig *); 112 1.9 matt static void fb253_init(void); 113 1.34 tsutsui static void fblcdm_init(void); 114 1.1 tsubai 115 1.24 tsutsui CFATTACH_DECL_NEW(fb, sizeof(struct fb_softc), 116 1.14 thorpej fb_match, fb_attach, NULL, NULL); 117 1.5 tsubai 118 1.30 tsutsui static struct fb_devconfig fb_console_dc; 119 1.5 tsubai 120 1.30 tsutsui static struct wsdisplay_accessops fb_accessops = { 121 1.32 tsutsui .ioctl = fb_ioctl, 122 1.32 tsutsui .mmap = fb_mmap, 123 1.32 tsutsui .alloc_screen = fb_alloc_screen, 124 1.32 tsutsui .free_screen = fb_free_screen, 125 1.32 tsutsui .show_screen = fb_show_screen, 126 1.32 tsutsui .load_font = NULL 127 1.5 tsubai }; 128 1.5 tsubai 129 1.30 tsutsui static struct wsscreen_descr fb_stdscreen = { 130 1.32 tsutsui .name = "std", 131 1.32 tsutsui .ncols = 0, 132 1.32 tsutsui .nrows = 0, 133 1.32 tsutsui .textops = NULL, 134 1.32 tsutsui .fontwidth = 0, 135 1.32 tsutsui .fontheight = 0, 136 1.32 tsutsui .capabilities = WSSCREEN_REVERSE 137 1.1 tsubai }; 138 1.1 tsubai 139 1.30 tsutsui static const struct wsscreen_descr *fb_scrlist[] = { 140 1.5 tsubai &fb_stdscreen 141 1.5 tsubai }; 142 1.5 tsubai 143 1.30 tsutsui static struct wsscreen_list fb_screenlist = { 144 1.32 tsutsui .nscreens = __arraycount(fb_scrlist), 145 1.32 tsutsui .screens = fb_scrlist 146 1.5 tsubai }; 147 1.1 tsubai 148 1.34 tsutsui #define NWB253_VRAM 0x88000000 149 1.24 tsutsui #define NWB253_CTLREG ((uint16_t *)0xb8ff0000) 150 1.24 tsutsui #define NWB253_CRTREG ((uint16_t *)0xb8fe0000) 151 1.1 tsubai 152 1.34 tsutsui static const char *nwb253dispname[8] = { 153 1.34 tsutsui [NWP512] = "NWB-512", 154 1.34 tsutsui [NWP518] = "NWB-518", 155 1.34 tsutsui [NWE501] = "NWE-501" 156 1.34 tsutsui }; /* XXX ? */ 157 1.34 tsutsui 158 1.34 tsutsui #define LCDM_VRAM 0x90200000 159 1.34 tsutsui #define LCDM_PORT ((uint32_t *)0xb0000000) 160 1.34 tsutsui #define LCDM_DIMMER ((uint32_t *)0xb0100000) 161 1.34 tsutsui #define LCDM_DIMMER_ON 0xf0 162 1.34 tsutsui #define LCDM_DIMMER_OFF 0xf1 163 1.34 tsutsui #define LCDM_CTRL ((uint8_t *)0xbff50000) /* XXX no macro in 4.4BSD */ 164 1.34 tsutsui #define LCDM_CRTC ((uint8_t *)0xbff60000) 165 1.5 tsubai 166 1.30 tsutsui static int 167 1.24 tsutsui fb_match(device_t parent, cfdata_t cf, void *aux) 168 1.1 tsubai { 169 1.16 tsutsui struct hb_attach_args *ha = aux; 170 1.1 tsubai 171 1.16 tsutsui if (strcmp(ha->ha_name, "fb") != 0) 172 1.1 tsubai return 0; 173 1.1 tsubai 174 1.34 tsutsui if (fb253_probe() && ha->ha_addr == NWB253_VRAM) 175 1.34 tsutsui return 1; 176 1.34 tsutsui if (fblcdm_probe() && ha->ha_addr == LCDM_VRAM) 177 1.34 tsutsui return 1; 178 1.1 tsubai 179 1.34 tsutsui return 0; 180 1.1 tsubai } 181 1.1 tsubai 182 1.30 tsutsui static void 183 1.24 tsutsui fb_attach(device_t parent, device_t self, void *aux) 184 1.1 tsubai { 185 1.24 tsutsui struct fb_softc *sc = device_private(self); 186 1.5 tsubai struct wsemuldisplaydev_attach_args waa; 187 1.5 tsubai struct fb_devconfig *dc; 188 1.5 tsubai struct rasops_info *ri; 189 1.5 tsubai int console; 190 1.34 tsutsui const char *devname; 191 1.5 tsubai 192 1.24 tsutsui sc->sc_dev = self; 193 1.24 tsutsui 194 1.5 tsubai console = fb_is_console(); 195 1.5 tsubai 196 1.5 tsubai if (console) { 197 1.5 tsubai dc = &fb_console_dc; 198 1.5 tsubai ri = &dc->dc_ri; 199 1.25 tsutsui ri->ri_flg &= ~RI_NO_AUTO; 200 1.5 tsubai sc->sc_nscreens = 1; 201 1.5 tsubai } else { 202 1.27 thorpej dc = kmem_zalloc(sizeof(struct fb_devconfig), KM_SLEEP); 203 1.5 tsubai 204 1.34 tsutsui fb_probe_model(dc); 205 1.5 tsubai fb_common_init(dc); 206 1.5 tsubai ri = &dc->dc_ri; 207 1.5 tsubai 208 1.5 tsubai /* clear screen */ 209 1.5 tsubai (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0); 210 1.5 tsubai 211 1.34 tsutsui fb_init(dc); 212 1.5 tsubai } 213 1.5 tsubai sc->sc_dc = dc; 214 1.5 tsubai 215 1.34 tsutsui switch (dc->dc_model) { 216 1.34 tsutsui case NWB253: 217 1.34 tsutsui devname = nwb253dispname[dc->dc_displayid]; 218 1.34 tsutsui break; 219 1.34 tsutsui case LCDM: 220 1.34 tsutsui devname = "LCD-MONO"; 221 1.34 tsutsui break; 222 1.34 tsutsui default: 223 1.34 tsutsui /* should not be here */ 224 1.34 tsutsui devname = "unknown"; 225 1.34 tsutsui break; 226 1.34 tsutsui } 227 1.34 tsutsui aprint_normal(": %s, %d x %d, %dbpp\n", devname, 228 1.5 tsubai ri->ri_width, ri->ri_height, ri->ri_depth); 229 1.5 tsubai 230 1.5 tsubai waa.console = console; 231 1.5 tsubai waa.scrdata = &fb_screenlist; 232 1.5 tsubai waa.accessops = &fb_accessops; 233 1.5 tsubai waa.accesscookie = sc; 234 1.1 tsubai 235 1.29 thorpej config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE); 236 1.1 tsubai } 237 1.1 tsubai 238 1.34 tsutsui static bool 239 1.34 tsutsui fb253_probe(void) 240 1.34 tsutsui { 241 1.34 tsutsui 242 1.34 tsutsui if (hb_badaddr(NWB253_CTLREG, 2) || hb_badaddr(NWB253_CRTREG, 2)) 243 1.34 tsutsui return false; 244 1.34 tsutsui if ((*(volatile uint16_t *)NWB253_CTLREG & 7) != 4) 245 1.34 tsutsui return false; 246 1.34 tsutsui 247 1.34 tsutsui return true; 248 1.34 tsutsui } 249 1.34 tsutsui 250 1.34 tsutsui static bool 251 1.34 tsutsui fblcdm_probe(void) 252 1.34 tsutsui { 253 1.34 tsutsui 254 1.34 tsutsui if (hb_badaddr(LCDM_CTRL, 1)) 255 1.34 tsutsui return false; 256 1.34 tsutsui if (*(volatile uint8_t *)LCDM_CTRL != 0xff) 257 1.34 tsutsui return false; 258 1.34 tsutsui 259 1.34 tsutsui return true; 260 1.34 tsutsui } 261 1.34 tsutsui 262 1.34 tsutsui static bool 263 1.34 tsutsui fb_probe_model(struct fb_devconfig *dc) 264 1.34 tsutsui { 265 1.34 tsutsui 266 1.34 tsutsui if (fb253_probe()) { 267 1.34 tsutsui volatile uint16_t *ctlreg = NWB253_CTLREG; 268 1.34 tsutsui 269 1.34 tsutsui dc->dc_model = NWB253; 270 1.34 tsutsui dc->dc_displayid = (*ctlreg >> 8) & 0xf; 271 1.34 tsutsui return true; 272 1.34 tsutsui } 273 1.34 tsutsui if (fblcdm_probe()) { 274 1.34 tsutsui dc->dc_model = LCDM; 275 1.34 tsutsui dc->dc_displayid = 0; /* no variant */ 276 1.34 tsutsui return true; 277 1.34 tsutsui } 278 1.34 tsutsui 279 1.34 tsutsui return false; 280 1.34 tsutsui } 281 1.34 tsutsui 282 1.30 tsutsui static int 283 1.19 tsutsui fb_common_init(struct fb_devconfig *dc) 284 1.1 tsubai { 285 1.5 tsubai struct rasops_info *ri = &dc->dc_ri; 286 1.34 tsutsui int width, height, stride, xoff, yoff, cols, rows; 287 1.5 tsubai 288 1.34 tsutsui switch (dc->dc_model) { 289 1.34 tsutsui case NWB253: 290 1.34 tsutsui dc->dc_fbbase = (uint8_t *)NWB253_VRAM; 291 1.34 tsutsui 292 1.34 tsutsui switch (dc->dc_displayid) { 293 1.34 tsutsui case NWP512: 294 1.34 tsutsui width = 816; 295 1.34 tsutsui height = 1024; 296 1.34 tsutsui break; 297 1.34 tsutsui case NWP518: 298 1.34 tsutsui case NWE501: 299 1.34 tsutsui default: 300 1.34 tsutsui width = 1024; 301 1.34 tsutsui height = 768; 302 1.34 tsutsui break; 303 1.34 tsutsui } 304 1.34 tsutsui stride = 2048 / 8; 305 1.34 tsutsui dc->dc_size = stride * 2048; 306 1.34 tsutsui break; 307 1.5 tsubai 308 1.34 tsutsui case LCDM: 309 1.34 tsutsui dc->dc_fbbase = (uint8_t *)LCDM_VRAM; 310 1.34 tsutsui width = 1120; 311 1.34 tsutsui height = 780; 312 1.34 tsutsui stride = width / 8; 313 1.34 tsutsui dc->dc_size = stride * height; 314 1.5 tsubai break; 315 1.34 tsutsui 316 1.18 dsl default: 317 1.34 tsutsui panic("fb: no valid framebuffer"); 318 1.1 tsubai } 319 1.1 tsubai 320 1.34 tsutsui /* initialize rasops */ 321 1.34 tsutsui 322 1.5 tsubai ri->ri_width = width; 323 1.5 tsubai ri->ri_height = height; 324 1.5 tsubai ri->ri_depth = 1; 325 1.34 tsutsui ri->ri_stride = stride; 326 1.5 tsubai ri->ri_bits = dc->dc_fbbase; 327 1.5 tsubai ri->ri_flg = RI_FULLCLEAR; 328 1.25 tsutsui if (dc == &fb_console_dc) 329 1.25 tsutsui ri->ri_flg |= RI_NO_AUTO; 330 1.5 tsubai 331 1.5 tsubai rasops_init(ri, 24, 80); 332 1.5 tsubai rows = (height - 2) / ri->ri_font->fontheight; 333 1.5 tsubai cols = ((width - 2) / ri->ri_font->fontwidth) & ~7; 334 1.5 tsubai xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3; 335 1.5 tsubai yoff = (height - rows * ri->ri_font->fontheight) / 2; 336 1.5 tsubai rasops_reconfig(ri, rows, cols); 337 1.15 tsutsui 338 1.5 tsubai ri->ri_xorigin = xoff; 339 1.5 tsubai ri->ri_yorigin = yoff; 340 1.5 tsubai ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff; 341 1.15 tsutsui 342 1.5 tsubai fb_stdscreen.nrows = ri->ri_rows; 343 1.33 tsutsui fb_stdscreen.ncols = ri->ri_cols; 344 1.5 tsubai fb_stdscreen.textops = &ri->ri_ops; 345 1.5 tsubai fb_stdscreen.capabilities = ri->ri_caps; 346 1.1 tsubai 347 1.1 tsubai return 0; 348 1.1 tsubai } 349 1.1 tsubai 350 1.30 tsutsui static int 351 1.19 tsutsui fb_is_console(void) 352 1.1 tsubai { 353 1.5 tsubai volatile u_int *dipsw = (void *)DIP_SWITCH; 354 1.1 tsubai 355 1.5 tsubai if (*dipsw & 7) /* XXX right? */ 356 1.5 tsubai return 1; 357 1.1 tsubai 358 1.1 tsubai return 0; 359 1.1 tsubai } 360 1.1 tsubai 361 1.30 tsutsui static int 362 1.23 christos fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 363 1.1 tsubai { 364 1.5 tsubai struct fb_softc *sc = v; 365 1.5 tsubai struct fb_devconfig *dc = sc->sc_dc; 366 1.5 tsubai struct wsdisplay_fbinfo *wdf; 367 1.1 tsubai 368 1.5 tsubai switch (cmd) { 369 1.5 tsubai case WSDISPLAYIO_GTYPE: 370 1.5 tsubai *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ 371 1.5 tsubai return 0; 372 1.1 tsubai 373 1.5 tsubai case WSDISPLAYIO_GINFO: 374 1.5 tsubai wdf = (void *)data; 375 1.5 tsubai wdf->height = dc->dc_ri.ri_height; 376 1.5 tsubai wdf->width = dc->dc_ri.ri_width; 377 1.5 tsubai wdf->depth = dc->dc_ri.ri_depth; 378 1.34 tsutsui wdf->cmsize = 0; 379 1.5 tsubai return 0; 380 1.1 tsubai 381 1.26 tsutsui case WSDISPLAYIO_LINEBYTES: 382 1.26 tsutsui *(u_int *)data = dc->dc_ri.ri_stride; 383 1.26 tsutsui return 0; 384 1.26 tsutsui 385 1.5 tsubai case WSDISPLAYIO_SVIDEO: 386 1.34 tsutsui return fb_set_state(sc, *(int *)data); 387 1.1 tsubai 388 1.5 tsubai case WSDISPLAYIO_GETCMAP: 389 1.5 tsubai case WSDISPLAYIO_PUTCMAP: 390 1.11 thorpej break; 391 1.1 tsubai } 392 1.10 atatat return EPASSTHROUGH; 393 1.1 tsubai } 394 1.1 tsubai 395 1.34 tsutsui static int 396 1.34 tsutsui fb_set_state(struct fb_softc *sc, int state) 397 1.34 tsutsui { 398 1.34 tsutsui struct fb_devconfig *dc = sc->sc_dc; 399 1.34 tsutsui volatile uint16_t *ctlreg; 400 1.34 tsutsui volatile uint32_t *dimmerreg; 401 1.34 tsutsui 402 1.34 tsutsui if (state != WSDISPLAYIO_VIDEO_OFF && state != WSDISPLAYIO_VIDEO_ON) 403 1.34 tsutsui return EINVAL; 404 1.34 tsutsui 405 1.34 tsutsui switch (dc->dc_model) { 406 1.34 tsutsui case NWB253: 407 1.34 tsutsui if (state == WSDISPLAYIO_VIDEO_OFF) { 408 1.34 tsutsui ctlreg = NWB253_CTLREG; 409 1.34 tsutsui *ctlreg = 0; /* stop crtc */ 410 1.34 tsutsui } else { 411 1.34 tsutsui fb253_init(); 412 1.34 tsutsui } 413 1.34 tsutsui break; 414 1.34 tsutsui case LCDM: 415 1.34 tsutsui dimmerreg = LCDM_DIMMER; 416 1.34 tsutsui if (state == WSDISPLAYIO_VIDEO_OFF) { 417 1.34 tsutsui *dimmerreg = LCDM_DIMMER_OFF; 418 1.34 tsutsui } else { 419 1.34 tsutsui *dimmerreg = LCDM_DIMMER_ON; 420 1.34 tsutsui } 421 1.34 tsutsui break; 422 1.34 tsutsui default: 423 1.34 tsutsui /* should not be here */ 424 1.34 tsutsui break; 425 1.34 tsutsui } 426 1.34 tsutsui return 0; 427 1.34 tsutsui } 428 1.34 tsutsui 429 1.30 tsutsui static paddr_t 430 1.22 jmmv fb_mmap(void *v, void *vs, off_t offset, int prot) 431 1.1 tsubai { 432 1.5 tsubai struct fb_softc *sc = v; 433 1.5 tsubai struct fb_devconfig *dc = sc->sc_dc; 434 1.1 tsubai 435 1.34 tsutsui if (offset >= dc->dc_size || offset < 0) 436 1.1 tsubai return -1; 437 1.1 tsubai 438 1.5 tsubai return mips_btop((int)dc->dc_fbbase + offset); 439 1.5 tsubai } 440 1.1 tsubai 441 1.30 tsutsui static int 442 1.19 tsutsui fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep, 443 1.19 tsutsui int *ccolp, int *crowp, long *attrp) 444 1.5 tsubai { 445 1.5 tsubai struct fb_softc *sc = v; 446 1.5 tsubai struct rasops_info *ri = &sc->sc_dc->dc_ri; 447 1.5 tsubai long defattr; 448 1.5 tsubai 449 1.5 tsubai if (sc->sc_nscreens > 0) 450 1.5 tsubai return ENOMEM; 451 1.5 tsubai 452 1.5 tsubai *cookiep = ri; 453 1.5 tsubai *ccolp = *crowp = 0; 454 1.12 junyoung (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 455 1.5 tsubai *attrp = defattr; 456 1.5 tsubai sc->sc_nscreens++; 457 1.1 tsubai 458 1.5 tsubai return 0; 459 1.1 tsubai } 460 1.1 tsubai 461 1.30 tsutsui static void 462 1.19 tsutsui fb_free_screen(void *v, void *cookie) 463 1.1 tsubai { 464 1.5 tsubai struct fb_softc *sc = v; 465 1.5 tsubai 466 1.5 tsubai if (sc->sc_dc == &fb_console_dc) 467 1.24 tsutsui panic("%s: console", __func__); 468 1.5 tsubai 469 1.5 tsubai sc->sc_nscreens--; 470 1.1 tsubai } 471 1.1 tsubai 472 1.30 tsutsui static int 473 1.19 tsutsui fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), 474 1.19 tsutsui void *cbarg) 475 1.1 tsubai { 476 1.19 tsutsui 477 1.5 tsubai return 0; 478 1.1 tsubai } 479 1.1 tsubai 480 1.5 tsubai void 481 1.19 tsutsui fb_cnattach(void) 482 1.1 tsubai { 483 1.5 tsubai struct fb_devconfig *dc = &fb_console_dc; 484 1.5 tsubai struct rasops_info *ri = &dc->dc_ri; 485 1.5 tsubai long defattr; 486 1.5 tsubai 487 1.5 tsubai if (!fb_is_console()) 488 1.5 tsubai return; 489 1.5 tsubai 490 1.34 tsutsui if (!fb_probe_model(dc)) 491 1.34 tsutsui return; 492 1.34 tsutsui 493 1.5 tsubai fb_common_init(dc); 494 1.34 tsutsui fb_init(dc); 495 1.34 tsutsui 496 1.34 tsutsui /* 497 1.34 tsutsui * Wait CRTC output or LCD backlight become settled 498 1.34 tsutsui * before starting to print kernel greeting messages. 499 1.34 tsutsui */ 500 1.34 tsutsui delay(500 * 1000); 501 1.5 tsubai 502 1.12 junyoung (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 503 1.5 tsubai wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr); 504 1.5 tsubai } 505 1.5 tsubai 506 1.34 tsutsui static void 507 1.34 tsutsui fb_init(struct fb_devconfig *dc) 508 1.34 tsutsui { 509 1.34 tsutsui 510 1.34 tsutsui switch (dc->dc_model) { 511 1.34 tsutsui case NWB253: 512 1.34 tsutsui fb253_init(); 513 1.34 tsutsui break; 514 1.34 tsutsui case LCDM: 515 1.34 tsutsui fblcdm_init(); 516 1.34 tsutsui break; 517 1.34 tsutsui default: 518 1.34 tsutsui /* should not be here */ 519 1.34 tsutsui break; 520 1.34 tsutsui } 521 1.34 tsutsui } 522 1.34 tsutsui 523 1.19 tsutsui static const uint8_t 524 1.5 tsubai nwp512_data1[] = { 525 1.5 tsubai 0x00, 0x44, 526 1.5 tsubai 0x01, 0x33, 527 1.5 tsubai 0x02, 0x3c, 528 1.5 tsubai 0x03, 0x38, 529 1.5 tsubai 0x04, 0x84, 530 1.5 tsubai 0x05, 0x03, 531 1.5 tsubai 0x06, 0x80, 532 1.5 tsubai 0x07, 0x80, 533 1.5 tsubai 0x08, 0x10, 534 1.5 tsubai 0x09, 0x07, 535 1.5 tsubai 0x0a, 0x20, 536 1.5 tsubai 0x0c, 0x00, 537 1.5 tsubai 0x0d, 0x00, 538 1.5 tsubai 0x1b, 0x03 539 1.5 tsubai }; 540 1.1 tsubai 541 1.19 tsutsui static const uint8_t 542 1.5 tsubai nwp512_data2[] = { 543 1.5 tsubai 0x1e, 0x08, 544 1.5 tsubai 0x20, 0x08, 545 1.5 tsubai 0x21, 0x0d 546 1.5 tsubai }; 547 1.1 tsubai 548 1.19 tsutsui static const uint8_t 549 1.5 tsubai nwp518_data1[] = { 550 1.5 tsubai 0x00, 0x52, 551 1.5 tsubai 0x01, 0x40, 552 1.5 tsubai 0x02, 0x4a, 553 1.5 tsubai 0x03, 0x49, 554 1.5 tsubai 0x04, 0x63, 555 1.5 tsubai 0x05, 0x02, 556 1.5 tsubai 0x06, 0x60, 557 1.5 tsubai 0x07, 0x60, 558 1.5 tsubai 0x08, 0x10, 559 1.5 tsubai 0x09, 0x07, 560 1.5 tsubai 0x0a, 0x20, 561 1.5 tsubai 0x0c, 0x00, 562 1.5 tsubai 0x0d, 0x00, 563 1.5 tsubai 0x1b, 0x04 564 1.5 tsubai }; 565 1.1 tsubai 566 1.19 tsutsui static const uint8_t 567 1.5 tsubai nwp518_data2[] = { 568 1.5 tsubai 0x1e, 0x08, 569 1.5 tsubai 0x20, 0x00, 570 1.5 tsubai 0x21, 0x00 571 1.5 tsubai }; 572 1.1 tsubai 573 1.19 tsutsui static const uint8_t 574 1.5 tsubai nwe501_data1[] = { 575 1.5 tsubai 0x00, 0x4b, 576 1.5 tsubai 0x01, 0x40, 577 1.5 tsubai 0x02, 0x4a, 578 1.5 tsubai 0x03, 0x43, 579 1.5 tsubai 0x04, 0x64, 580 1.5 tsubai 0x05, 0x02, 581 1.5 tsubai 0x06, 0x60, 582 1.5 tsubai 0x07, 0x60, 583 1.5 tsubai 0x08, 0x10, 584 1.5 tsubai 0x09, 0x07, 585 1.5 tsubai 0x0a, 0x20, 586 1.5 tsubai 0x0c, 0x00, 587 1.5 tsubai 0x0d, 0x00, 588 1.5 tsubai 0x1b, 0x04 589 1.5 tsubai }; 590 1.1 tsubai 591 1.19 tsutsui static const uint8_t 592 1.5 tsubai nwe501_data2[] = { 593 1.5 tsubai 0x1e, 0x08, 594 1.5 tsubai 0x20, 0x00, 595 1.5 tsubai 0x21, 0x00 596 1.5 tsubai }; 597 1.1 tsubai 598 1.19 tsutsui static const uint8_t 599 1.5 tsubai *crtc_data[3][2] = { 600 1.5 tsubai { nwp512_data1, nwp512_data2 }, 601 1.5 tsubai { nwp518_data1, nwp518_data2 }, 602 1.5 tsubai { nwe501_data1, nwe501_data2 } 603 1.5 tsubai }; 604 1.1 tsubai 605 1.1 tsubai static void 606 1.9 matt fb253_init(void) 607 1.1 tsubai { 608 1.24 tsutsui volatile uint16_t *ctlreg = NWB253_CTLREG; 609 1.24 tsutsui volatile uint16_t *crtreg = NWB253_CRTREG; 610 1.8 tsubai int id = (*ctlreg >> 8) & 0xf; 611 1.19 tsutsui const uint8_t *p; 612 1.5 tsubai int i; 613 1.5 tsubai 614 1.5 tsubai *ctlreg = 0; /* stop crtc */ 615 1.5 tsubai delay(10); 616 1.5 tsubai 617 1.5 tsubai /* initialize crtc without R3{0,1,2} */ 618 1.5 tsubai p = crtc_data[id][0]; 619 1.5 tsubai for (i = 0; i < 28; i++) { 620 1.5 tsubai *crtreg++ = *p++; 621 1.5 tsubai delay(10); 622 1.5 tsubai } 623 1.5 tsubai 624 1.5 tsubai *ctlreg = 0x02; /* start crtc */ 625 1.5 tsubai delay(10); 626 1.5 tsubai 627 1.5 tsubai /* set crtc control reg */ 628 1.5 tsubai p = crtc_data[id][1]; 629 1.5 tsubai for (i = 0; i < 6; i++) { 630 1.5 tsubai *crtreg++ = *p++; 631 1.5 tsubai delay(10); 632 1.5 tsubai } 633 1.5 tsubai } 634 1.5 tsubai 635 1.34 tsutsui static const uint8_t lcdcrtc_data[] = { 636 1.34 tsutsui 0, 47, 637 1.34 tsutsui 1, 35, 638 1.34 tsutsui 9, 0, 639 1.34 tsutsui 10, 0, 640 1.34 tsutsui 11, 0, 641 1.34 tsutsui 12, 0, 642 1.34 tsutsui 13, 0, 643 1.34 tsutsui 14, 0, 644 1.34 tsutsui 15, 0, 645 1.34 tsutsui 18, 35, 646 1.34 tsutsui 19, 0x01, 647 1.34 tsutsui 20, 0x85, 648 1.34 tsutsui 21, 0, 649 1.34 tsutsui 22, 0x10 650 1.34 tsutsui }; 651 1.34 tsutsui 652 1.34 tsutsui static void 653 1.34 tsutsui fblcdm_init(void) 654 1.34 tsutsui { 655 1.34 tsutsui volatile uint8_t *crtcreg = LCDM_CRTC; 656 1.34 tsutsui volatile uint32_t *portreg = LCDM_PORT; 657 1.34 tsutsui volatile uint32_t *dimmerreg = LCDM_DIMMER; 658 1.34 tsutsui int i; 659 1.34 tsutsui 660 1.34 tsutsui /* initialize crtc */ 661 1.34 tsutsui for (i = 0; i < 28; i++) { 662 1.34 tsutsui *crtcreg++ = lcdcrtc_data[i]; 663 1.34 tsutsui delay(10); 664 1.34 tsutsui } 665 1.34 tsutsui 666 1.34 tsutsui delay(1000); 667 1.34 tsutsui *portreg = 1; 668 1.34 tsutsui *dimmerreg = LCDM_DIMMER_ON; 669 1.34 tsutsui } 670 1.34 tsutsui 671 1.5 tsubai #if 0 672 1.5 tsubai static struct wsdisplay_font newsrom8x16; 673 1.5 tsubai static struct wsdisplay_font newsrom12x24; 674 1.31 tsutsui static uint8_t fontarea16[96][32]; 675 1.31 tsutsui static uint8_t fontarea24[96][96]; 676 1.5 tsubai 677 1.5 tsubai void 678 1.19 tsutsui initfont(struct rasops_info *ri) 679 1.5 tsubai { 680 1.5 tsubai int c, x; 681 1.5 tsubai 682 1.5 tsubai for (c = 0; c < 96; c++) { 683 1.5 tsubai x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7; 684 1.31 tsutsui memcpy(fontarea16 + c, (uint8_t *)0xb8e00000 + x + 96, 32); 685 1.31 tsutsui memcpy(fontarea24 + c, (uint8_t *)0xb8e00000 + x, 96); 686 1.33 tsutsui } 687 1.5 tsubai 688 1.5 tsubai newsrom8x16.name = "rom8x16"; 689 1.5 tsubai newsrom8x16.firstchar = 32; 690 1.5 tsubai newsrom8x16.numchars = 96; 691 1.5 tsubai newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO; 692 1.5 tsubai newsrom8x16.fontwidth = 8; 693 1.5 tsubai newsrom8x16.fontheight = 16; 694 1.5 tsubai newsrom8x16.stride = 2; 695 1.5 tsubai newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R; 696 1.5 tsubai newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R; 697 1.5 tsubai newsrom8x16.data = fontarea16; 698 1.5 tsubai 699 1.5 tsubai newsrom12x24.name = "rom12x24"; 700 1.5 tsubai newsrom12x24.firstchar = 32; 701 1.5 tsubai newsrom12x24.numchars = 96; 702 1.5 tsubai newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO; 703 1.5 tsubai newsrom12x24.fontwidth = 12; 704 1.5 tsubai newsrom12x24.fontheight = 24; 705 1.5 tsubai newsrom12x24.stride = 4; 706 1.5 tsubai newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R; 707 1.5 tsubai newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R; 708 1.5 tsubai newsrom12x24.data = fontarea24; 709 1.5 tsubai 710 1.5 tsubai ri->ri_font = &newsrom8x16; 711 1.5 tsubai ri->ri_font = &newsrom12x24; 712 1.5 tsubai ri->ri_wsfcookie = -1; /* not using wsfont */ 713 1.1 tsubai } 714 1.5 tsubai #endif 715