Home | History | Annotate | Line # | Download | only in dev
      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