Home | History | Annotate | Line # | Download | only in windermere
      1  1.3   thorpej /*      $NetBSD: wmlcd.c,v 1.3 2021/08/07 16:18:48 thorpej Exp $      */
      2  1.1  kiyohara /*
      3  1.1  kiyohara  * Copyright (c) 2013 KIYOHARA Takashi
      4  1.1  kiyohara  * All rights reserved.
      5  1.1  kiyohara  *
      6  1.1  kiyohara  * Redistribution and use in source and binary forms, with or without
      7  1.1  kiyohara  * modification, are permitted provided that the following conditions
      8  1.1  kiyohara  * are met:
      9  1.1  kiyohara  * 1. Redistributions of source code must retain the above copyright
     10  1.1  kiyohara  *    notice, this list of conditions and the following disclaimer.
     11  1.1  kiyohara  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  kiyohara  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  kiyohara  *    documentation and/or other materials provided with the distribution.
     14  1.1  kiyohara  *
     15  1.1  kiyohara  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  1.1  kiyohara  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.1  kiyohara  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.1  kiyohara  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  1.1  kiyohara  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  1.1  kiyohara  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.1  kiyohara  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1  kiyohara  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  1.1  kiyohara  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  1.1  kiyohara  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  1.1  kiyohara  * POSSIBILITY OF SUCH DAMAGE.
     26  1.1  kiyohara  */
     27  1.1  kiyohara #include <sys/cdefs.h>
     28  1.3   thorpej __KERNEL_RCSID(0, "$NetBSD: wmlcd.c,v 1.3 2021/08/07 16:18:48 thorpej Exp $");
     29  1.1  kiyohara 
     30  1.1  kiyohara #include "rnd.h"
     31  1.1  kiyohara 
     32  1.1  kiyohara #include <sys/param.h>
     33  1.1  kiyohara #include <sys/bus.h>
     34  1.1  kiyohara #include <sys/device.h>
     35  1.1  kiyohara #include <sys/errno.h>
     36  1.1  kiyohara 
     37  1.1  kiyohara #include <uvm/uvm_extern.h>
     38  1.1  kiyohara 
     39  1.1  kiyohara #include <epoc32/windermere/windermerereg.h>
     40  1.1  kiyohara #include <epoc32/windermere/windermerevar.h>
     41  1.1  kiyohara 
     42  1.1  kiyohara #include <dev/cons.h>
     43  1.1  kiyohara #include <dev/wscons/wsconsio.h>
     44  1.1  kiyohara #include <dev/wscons/wsdisplayvar.h>
     45  1.1  kiyohara #include <dev/rasops/rasops.h>
     46  1.1  kiyohara 
     47  1.1  kiyohara #include "locators.h"
     48  1.1  kiyohara 
     49  1.1  kiyohara #define LCD_SIZE	0x100
     50  1.1  kiyohara 
     51  1.1  kiyohara static int is_console;
     52  1.1  kiyohara struct wmlcd_softc {
     53  1.1  kiyohara 	device_t sc_dev;
     54  1.1  kiyohara 
     55  1.1  kiyohara 	bus_space_tag_t sc_iot;
     56  1.1  kiyohara 	bus_space_handle_t sc_ioh;
     57  1.1  kiyohara 
     58  1.1  kiyohara 	vaddr_t sc_buffer;
     59  1.1  kiyohara 
     60  1.1  kiyohara 	struct rasops_info sc_ri;
     61  1.1  kiyohara };
     62  1.1  kiyohara 
     63  1.1  kiyohara static int wmlcd_match(device_t, cfdata_t, void *);
     64  1.1  kiyohara static void wmlcd_attach(device_t, device_t, void *);
     65  1.1  kiyohara 
     66  1.1  kiyohara /* wsdisplay functions */
     67  1.1  kiyohara static int wmlcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
     68  1.1  kiyohara static paddr_t wmlcd_mmap(void *, void *, off_t, int);
     69  1.1  kiyohara static int wmlcd_alloc_screen(void *, const struct wsscreen_descr *, void **,
     70  1.1  kiyohara 			      int *, int *, long *);
     71  1.1  kiyohara static void wmlcd_free_screen(void *, void *);
     72  1.1  kiyohara static int wmlcd_show_screen(void *, void *, int,
     73  1.1  kiyohara 			     void (*)(void *, int, int), void *);
     74  1.1  kiyohara 
     75  1.1  kiyohara CFATTACH_DECL_NEW(wmlcd, sizeof(struct wmlcd_softc),
     76  1.1  kiyohara     wmlcd_match, wmlcd_attach, NULL, NULL);
     77  1.1  kiyohara 
     78  1.1  kiyohara 
     79  1.1  kiyohara #define WMLCD_DEFAULT_DEPTH	4
     80  1.1  kiyohara /* Linux like palette data */
     81  1.1  kiyohara const static char palette_2bpp[] = {
     82  1.1  kiyohara 	0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00,
     83  1.1  kiyohara 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     84  1.1  kiyohara 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     85  1.1  kiyohara 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     86  1.1  kiyohara };
     87  1.1  kiyohara const static char palette_4bpp[] = {
     88  1.1  kiyohara 	0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x07, 0x00,
     89  1.1  kiyohara 	0x03, 0x00, 0x04, 0x00, 0x06, 0x00, 0x0a, 0x00,
     90  1.1  kiyohara 	0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x0c, 0x00,
     91  1.1  kiyohara 	0x08, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x0f, 0x00,
     92  1.1  kiyohara };
     93  1.1  kiyohara 
     94  1.1  kiyohara static struct wsscreen_descr wmlcd_descr = {
     95  1.1  kiyohara 	.name = "wmlcd",
     96  1.1  kiyohara 	.fontwidth = 8,
     97  1.1  kiyohara 	.fontheight = 16,
     98  1.1  kiyohara 	.capabilities = WSSCREEN_WSCOLORS,
     99  1.1  kiyohara };
    100  1.1  kiyohara static const struct wsscreen_descr *wmlcd_descrs[] = {
    101  1.1  kiyohara 	&wmlcd_descr
    102  1.1  kiyohara };
    103  1.1  kiyohara 
    104  1.1  kiyohara static const struct wsscreen_list wmlcd_screen_list = {
    105  1.1  kiyohara 	.nscreens = __arraycount(wmlcd_descrs),
    106  1.1  kiyohara 	.screens = wmlcd_descrs,
    107  1.1  kiyohara };
    108  1.1  kiyohara 
    109  1.1  kiyohara struct wsdisplay_accessops wmlcd_accessops = {
    110  1.1  kiyohara 	wmlcd_ioctl,
    111  1.1  kiyohara 	wmlcd_mmap,
    112  1.1  kiyohara 	wmlcd_alloc_screen,
    113  1.1  kiyohara 	wmlcd_free_screen,
    114  1.1  kiyohara 	wmlcd_show_screen,
    115  1.1  kiyohara 	NULL,
    116  1.1  kiyohara 	NULL,
    117  1.1  kiyohara 	NULL,
    118  1.1  kiyohara };
    119  1.1  kiyohara 
    120  1.1  kiyohara /* ARGSUSED */
    121  1.1  kiyohara static int
    122  1.1  kiyohara wmlcd_match(device_t parent, cfdata_t match, void *aux)
    123  1.1  kiyohara {
    124  1.1  kiyohara 	struct windermere_attach_args *aa = aux;
    125  1.1  kiyohara 
    126  1.1  kiyohara 	/* Wildcard not accept */
    127  1.1  kiyohara 	if (aa->aa_offset == WINDERMERECF_OFFSET_DEFAULT)
    128  1.1  kiyohara 		return 0;
    129  1.1  kiyohara 
    130  1.1  kiyohara 	aa->aa_size = LCD_SIZE;
    131  1.1  kiyohara 	return 1;
    132  1.1  kiyohara }
    133  1.1  kiyohara 
    134  1.1  kiyohara /* ARGSUSED */
    135  1.1  kiyohara static void
    136  1.1  kiyohara wmlcd_attach(device_t parent, device_t self, void *aux)
    137  1.1  kiyohara {
    138  1.1  kiyohara 	struct wmlcd_softc *sc = device_private(self);
    139  1.1  kiyohara 	struct windermere_attach_args *aa = aux;
    140  1.1  kiyohara 	struct wsemuldisplaydev_attach_args waa;
    141  1.1  kiyohara 	prop_dictionary_t dict = device_properties(self);
    142  1.1  kiyohara 	paddr_t paddr;
    143  1.1  kiyohara 	struct rasops_info *ri;
    144  1.1  kiyohara 	uint32_t lcdctl, width, height, addr, depth;
    145  1.1  kiyohara 	int c, i;
    146  1.1  kiyohara 	const char *palette;
    147  1.1  kiyohara 
    148  1.1  kiyohara 	aprint_naive("\n");
    149  1.1  kiyohara 	aprint_normal("\n");
    150  1.1  kiyohara 
    151  1.1  kiyohara 	sc->sc_dev = self;
    152  1.1  kiyohara 	if (windermere_bus_space_subregion(aa->aa_iot, *aa->aa_ioh,
    153  1.1  kiyohara 				aa->aa_offset, aa->aa_size, &sc->sc_ioh) != 0) {
    154  1.1  kiyohara 		aprint_error_dev(self, "can't map registers\n");
    155  1.1  kiyohara 		return;
    156  1.1  kiyohara 	}
    157  1.1  kiyohara 	sc->sc_iot = aa->aa_iot;
    158  1.1  kiyohara 
    159  1.1  kiyohara 	if (!prop_dictionary_get_uint32(dict, "width", &width) ||
    160  1.1  kiyohara 	    !prop_dictionary_get_uint32(dict, "height", &height) ||
    161  1.1  kiyohara 	    !prop_dictionary_get_uint32(dict, "addr", &addr)) {
    162  1.1  kiyohara 		aprint_error_dev(self, "can't get properties\n");
    163  1.1  kiyohara 		return;
    164  1.1  kiyohara 	}
    165  1.1  kiyohara 	sc->sc_buffer = addr;
    166  1.1  kiyohara 	pmap_extract(pmap_kernel(), addr, &paddr);
    167  1.1  kiyohara 
    168  1.1  kiyohara 	/* Setup palette data */
    169  1.1  kiyohara 	depth = WMLCD_DEFAULT_DEPTH;
    170  1.1  kiyohara 	if (depth == 2)
    171  1.1  kiyohara 		palette = palette_2bpp;
    172  1.1  kiyohara 	else
    173  1.1  kiyohara 		palette = palette_4bpp;
    174  1.1  kiyohara 	for (i = 0; i < LCD_PALETTE_SIZE; i++)
    175  1.1  kiyohara 		*((uint8_t *)addr + i) = palette[i];
    176  1.1  kiyohara 	*(uint16_t *)addr |= (depth >> 1) << 12;
    177  1.1  kiyohara 
    178  1.1  kiyohara 	lcdctl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LCDCTL);
    179  1.1  kiyohara 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDCTL, lcdctl & ~LCDCTL_EN);
    180  1.1  kiyohara 
    181  1.1  kiyohara 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDDBAR1, paddr);
    182  1.1  kiyohara 
    183  1.1  kiyohara 	lcdctl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LCDCTL);
    184  1.1  kiyohara 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDCTL,
    185  1.1  kiyohara 	    lcdctl | LCDCTL_EN | LCDCTL_BW);
    186  1.1  kiyohara 
    187  1.1  kiyohara 	aprint_normal_dev(self,
    188  1.1  kiyohara 	    ": %dx%d pixels, %d bpp mono\n", width, height, 1 << depth);
    189  1.1  kiyohara 
    190  1.1  kiyohara 	ri = &sc->sc_ri;
    191  1.1  kiyohara 	ri->ri_depth = depth;
    192  1.1  kiyohara 	ri->ri_bits = (void *)(addr + LCD_PALETTE_SIZE);
    193  1.1  kiyohara 	ri->ri_width = width;
    194  1.1  kiyohara 	ri->ri_height = height;
    195  1.1  kiyohara 	ri->ri_stride = width * ri->ri_depth / 8/*bits*/;
    196  1.1  kiyohara 	ri->ri_flg = RI_FORCEMONO | RI_CLEAR | RI_CENTER;
    197  1.1  kiyohara 
    198  1.1  kiyohara 	if (is_console) {
    199  1.1  kiyohara 		long defattr;
    200  1.1  kiyohara 
    201  1.1  kiyohara 		if (rasops_init(ri, 0, 0) < 0)
    202  1.1  kiyohara 			panic("rasops_init failed");
    203  1.1  kiyohara 
    204  1.1  kiyohara 		if (ri->ri_depth == 4) {
    205  1.1  kiyohara 			/* XXXXX: Create color map. */
    206  1.1  kiyohara 			ri->ri_devcmap[0] = 0;
    207  1.1  kiyohara 			for (i = 1; i < 15; i++) {
    208  1.1  kiyohara 				c = (i + 0xc) & 0xf;
    209  1.1  kiyohara 				ri->ri_devcmap[i] =
    210  1.1  kiyohara 				    c | (c << 8) | (c << 16) | (c << 24);
    211  1.1  kiyohara 			}
    212  1.1  kiyohara 		}
    213  1.1  kiyohara 		ri->ri_devcmap[15] = -1;
    214  1.1  kiyohara 
    215  1.1  kiyohara 		wmlcd_descr.ncols = ri->ri_cols;
    216  1.1  kiyohara 		wmlcd_descr.nrows = ri->ri_rows;
    217  1.1  kiyohara 		wmlcd_descr.textops = &ri->ri_ops;
    218  1.1  kiyohara 		wmlcd_descr.capabilities = ri->ri_caps;
    219  1.1  kiyohara 
    220  1.1  kiyohara 		if ((ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr) != 0)
    221  1.1  kiyohara 			panic("allocattr failed");
    222  1.1  kiyohara 		wsdisplay_cnattach(&wmlcd_descr, ri, ri->ri_ccol, ri->ri_crow,
    223  1.1  kiyohara 		    defattr);
    224  1.1  kiyohara 	}
    225  1.1  kiyohara 
    226  1.1  kiyohara 	waa.console = is_console;
    227  1.1  kiyohara 	waa.scrdata = &wmlcd_screen_list;
    228  1.1  kiyohara 	waa.accessops = &wmlcd_accessops;
    229  1.1  kiyohara 	waa.accesscookie = sc;
    230  1.1  kiyohara 
    231  1.3   thorpej 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
    232  1.1  kiyohara }
    233  1.1  kiyohara 
    234  1.1  kiyohara static int
    235  1.1  kiyohara wmlcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
    236  1.1  kiyohara {
    237  1.1  kiyohara 	struct wmlcd_softc *sc = v;
    238  1.1  kiyohara 	struct wsdisplay_fbinfo *wsdisp_info;
    239  1.1  kiyohara 
    240  1.1  kiyohara 	switch (cmd) {
    241  1.1  kiyohara 	case WSDISPLAYIO_GTYPE:
    242  1.1  kiyohara 		*(int *)data = WSDISPLAY_TYPE_WINDERMERE;
    243  1.1  kiyohara 		return 0;
    244  1.1  kiyohara 
    245  1.1  kiyohara 	case WSDISPLAYIO_GINFO:
    246  1.1  kiyohara 		wsdisp_info = (struct wsdisplay_fbinfo *)data;
    247  1.1  kiyohara 		wsdisp_info->height = sc->sc_ri.ri_height;
    248  1.1  kiyohara 		wsdisp_info->width = sc->sc_ri.ri_width;
    249  1.1  kiyohara 		wsdisp_info->depth = sc->sc_ri.ri_depth;
    250  1.1  kiyohara 		wsdisp_info->cmsize = 0;
    251  1.1  kiyohara 		return 0;
    252  1.1  kiyohara 
    253  1.1  kiyohara 	case WSDISPLAYIO_GVIDEO:
    254  1.1  kiyohara 		if (1)	/* XXXX */
    255  1.1  kiyohara 			*(int *)data = WSDISPLAYIO_VIDEO_ON;
    256  1.1  kiyohara 		else
    257  1.1  kiyohara 			*(int *)data = WSDISPLAYIO_VIDEO_OFF;
    258  1.1  kiyohara 		return 0;
    259  1.1  kiyohara 
    260  1.1  kiyohara 	case WSDISPLAYIO_SVIDEO:
    261  1.1  kiyohara 		if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
    262  1.1  kiyohara 			/* XXXX: turn on */
    263  1.1  kiyohara 		} else {
    264  1.1  kiyohara 			/* XXXX: turn off */
    265  1.1  kiyohara 		}
    266  1.1  kiyohara 		return 0;
    267  1.1  kiyohara 
    268  1.1  kiyohara 	case WSDISPLAYIO_LINEBYTES:
    269  1.1  kiyohara 		*(int *)data = sc->sc_ri.ri_stride;
    270  1.1  kiyohara 		return 0;
    271  1.1  kiyohara 	}
    272  1.1  kiyohara 
    273  1.1  kiyohara 	return EPASSTHROUGH;
    274  1.1  kiyohara }
    275  1.1  kiyohara 
    276  1.1  kiyohara static paddr_t
    277  1.1  kiyohara wmlcd_mmap(void *v, void *vs, off_t off, int prot)
    278  1.1  kiyohara {
    279  1.1  kiyohara 	struct wmlcd_softc *sc = v;
    280  1.1  kiyohara 
    281  1.1  kiyohara 	if (off < 0 || sc->sc_ri.ri_stride * sc->sc_ri.ri_height <= off)
    282  1.1  kiyohara 		return -1;
    283  1.1  kiyohara 
    284  1.1  kiyohara 	return (paddr_t)sc->sc_ri.ri_bits + off;
    285  1.1  kiyohara }
    286  1.1  kiyohara 
    287  1.1  kiyohara static int
    288  1.1  kiyohara wmlcd_alloc_screen(void *v, const struct wsscreen_descr *scr, void **cookiep,
    289  1.1  kiyohara 		   int *curxp, int *curyp, long *attrp)
    290  1.1  kiyohara {
    291  1.1  kiyohara printf("%s\n", __func__);
    292  1.1  kiyohara return -1;
    293  1.1  kiyohara }
    294  1.1  kiyohara 
    295  1.1  kiyohara static void
    296  1.1  kiyohara wmlcd_free_screen(void *v, void *cookie)
    297  1.1  kiyohara {
    298  1.1  kiyohara printf("%s\n", __func__);
    299  1.1  kiyohara }
    300  1.1  kiyohara 
    301  1.1  kiyohara static int
    302  1.1  kiyohara wmlcd_show_screen(void *v, void *cookie, int waitok,
    303  1.1  kiyohara 		  void (*func)(void *, int, int), void *arg)
    304  1.1  kiyohara {
    305  1.1  kiyohara printf("%s\n", __func__);
    306  1.1  kiyohara return -1;
    307  1.1  kiyohara }
    308  1.1  kiyohara 
    309  1.1  kiyohara int
    310  1.1  kiyohara wmlcd_cnattach(void)
    311  1.1  kiyohara {
    312  1.1  kiyohara 
    313  1.1  kiyohara 	is_console = 1;
    314  1.1  kiyohara 	return 0;
    315  1.1  kiyohara }
    316