Home | History | Annotate | Line # | Download | only in clps711x
      1 /*      $NetBSD: clpslcd.c,v 1.3 2021/08/07 16:18:43 thorpej Exp $      */
      2 /*
      3  * Copyright (c) 2013 KIYOHARA Takashi
      4  * 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  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  * POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #include <sys/cdefs.h>
     28 __KERNEL_RCSID(0, "$NetBSD: clpslcd.c,v 1.3 2021/08/07 16:18:43 thorpej Exp $");
     29 
     30 #include "rnd.h"
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/errno.h>
     36 
     37 #include <uvm/uvm_extern.h>
     38 
     39 #include <arm/clps711x/clps711xreg.h>
     40 #include <arm/clps711x/clpssocvar.h>
     41 
     42 #include <dev/cons.h>
     43 #include <dev/wscons/wsconsio.h>
     44 #include <dev/wscons/wsdisplayvar.h>
     45 #include <dev/rasops/rasops.h>
     46 
     47 #include "locators.h"
     48 
     49 #define CLPSLCD_DEFAULT_DEPTH	4
     50 
     51 static int is_console;
     52 struct clpslcd_softc {
     53 	device_t sc_dev;
     54 
     55 	bus_space_tag_t sc_iot;
     56 	bus_space_handle_t sc_ioh;
     57 
     58 	vaddr_t sc_buffer;
     59 
     60 	struct rasops_info sc_ri;
     61 };
     62 
     63 static int clpslcd_match(device_t, cfdata_t, void *);
     64 static void clpslcd_attach(device_t, device_t, void *);
     65 
     66 /* wsdisplay functions */
     67 static int clpslcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
     68 static paddr_t clpslcd_mmap(void *, void *, off_t, int);
     69 static int clpslcd_alloc_screen(void *, const struct wsscreen_descr *, void **,
     70 				int *, int *, long *);
     71 static void clpslcd_free_screen(void *, void *);
     72 static int clpslcd_show_screen(void *, void *, int,
     73 			       void (*)(void *, int, int), void *);
     74 
     75 CFATTACH_DECL_NEW(clpslcd, sizeof(struct clpslcd_softc),
     76     clpslcd_match, clpslcd_attach, NULL, NULL);
     77 
     78 
     79 static struct wsscreen_descr clpslcd_descr = {
     80 	.name = "clpslcd",
     81 	.fontwidth = 8,
     82 	.fontheight = 16,
     83 	.capabilities = WSSCREEN_WSCOLORS,
     84 };
     85 static const struct wsscreen_descr *clpslcd_descrs[] = {
     86 	&clpslcd_descr
     87 };
     88 
     89 static const struct wsscreen_list clpslcd_screen_list = {
     90 	.nscreens = __arraycount(clpslcd_descrs),
     91 	.screens = clpslcd_descrs,
     92 };
     93 
     94 struct wsdisplay_accessops clpslcd_accessops = {
     95 	clpslcd_ioctl,
     96 	clpslcd_mmap,
     97 	clpslcd_alloc_screen,
     98 	clpslcd_free_screen,
     99 	clpslcd_show_screen,
    100 	NULL,
    101 	NULL,
    102 	NULL,
    103 };
    104 
    105 /* ARGSUSED */
    106 static int
    107 clpslcd_match(device_t parent, cfdata_t match, void *aux)
    108 {
    109 
    110 	return 1;
    111 }
    112 
    113 /* ARGSUSED */
    114 static void
    115 clpslcd_attach(device_t parent, device_t self, void *aux)
    116 {
    117 	struct clpslcd_softc *sc = device_private(self);
    118 	struct clpssoc_attach_args *aa = aux;
    119 	struct wsemuldisplaydev_attach_args waa;
    120 	prop_dictionary_t dict = device_properties(self);
    121 	struct rasops_info *ri;
    122 	uint32_t syscon, lcdcon, depth, width, height, addr;
    123 	int i;
    124 
    125 	aprint_naive("\n");
    126 	aprint_normal("\n");
    127 
    128 	sc->sc_dev = self;
    129 	sc->sc_iot = aa->aa_iot;
    130 	sc->sc_ioh = *aa->aa_ioh;
    131 
    132 	if (!prop_dictionary_get_uint32(dict, "width", &width) ||
    133 	    !prop_dictionary_get_uint32(dict, "height", &height) ||
    134 	    !prop_dictionary_get_uint32(dict, "addr", &addr)) {
    135 		aprint_error_dev(self, "can't get properties\n");
    136 		return;
    137 	}
    138 	KASSERT(addr == 0xc0000000);
    139 
    140 	sc->sc_buffer = addr;
    141 
    142 	depth = CLPSLCD_DEFAULT_DEPTH;
    143 	lcdcon =
    144 	    LCDCON_GSEN |
    145 	    LCDCON_ACP(13) |
    146 	    LCDCON_PP(width * height) |
    147 	    LCDCON_LL(width) |
    148 	    LCDCON_VBS(width * height * depth);
    149 	if (depth == 4)
    150 		lcdcon |= LCDCON_GSMD;
    151 
    152 	syscon = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PS711X_SYSCON);
    153 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_SYSCON,
    154 	    syscon | SYSCON_LCDEN);
    155 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_LCDCON, lcdcon);
    156 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_PALLSW, 0x54321fc0);
    157 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PS711X_PALMSW, 0xedba9876);
    158 
    159 	aprint_normal_dev(self,
    160 	    ": %dx%d pixels, %d bpp mono\n", width, height, depth);
    161 
    162 	ri = &sc->sc_ri;
    163 	ri->ri_depth = depth;
    164 	ri->ri_bits = (void *)addr;
    165 	ri->ri_width = width;
    166 	ri->ri_height = height;
    167 	ri->ri_stride = width * ri->ri_depth / 8/*bits*/;
    168 	ri->ri_flg = RI_FORCEMONO | RI_CLEAR | RI_CENTER;
    169 
    170 	if (is_console) {
    171 		long defattr;
    172 
    173 		if (rasops_init(ri, 0, 0) < 0)
    174 			panic("rasops_init failed");
    175 
    176 		if (ri->ri_depth == 4) {
    177 			/* XXXXX: Create color map. */
    178 			ri->ri_devcmap[0] = 0;
    179 			for (i = 1; i < 15; i++) {
    180 				ri->ri_devcmap[i] =
    181 				    i | (i << 8) | (i << 16) | (i << 24);
    182 			}
    183 		}
    184 		ri->ri_devcmap[15] = -1;
    185 
    186 		clpslcd_descr.ncols = ri->ri_cols;
    187 		clpslcd_descr.nrows = ri->ri_rows;
    188 		clpslcd_descr.textops = &ri->ri_ops;
    189 		clpslcd_descr.capabilities = ri->ri_caps;
    190 
    191 		if ((ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr) != 0)
    192 			panic("allocattr failed");
    193 		wsdisplay_cnattach(&clpslcd_descr, ri, ri->ri_ccol, ri->ri_crow,
    194 		    defattr);
    195 	}
    196 
    197 	waa.console = is_console;
    198 	waa.scrdata = &clpslcd_screen_list;
    199 	waa.accessops = &clpslcd_accessops;
    200 	waa.accesscookie = sc;
    201 
    202 	config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
    203 }
    204 
    205 static int
    206 clpslcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
    207 	      struct lwp *l)
    208 {
    209 	struct clpslcd_softc *sc = v;
    210 	struct wsdisplay_fbinfo *wsdisp_info;
    211 
    212 	switch (cmd) {
    213 	case WSDISPLAYIO_GTYPE:
    214 		*(int *)data = WSDISPLAY_TYPE_CLPS711X;
    215 		return 0;
    216 
    217 	case WSDISPLAYIO_GINFO:
    218 		wsdisp_info = (struct wsdisplay_fbinfo *)data;
    219 		wsdisp_info->height = sc->sc_ri.ri_height;
    220 		wsdisp_info->width = sc->sc_ri.ri_width;
    221 		wsdisp_info->depth = sc->sc_ri.ri_depth;
    222 		wsdisp_info->cmsize = 0;
    223 		return 0;
    224 
    225 	case WSDISPLAYIO_GVIDEO:
    226 		if (1)	/* XXXX */
    227 			*(int *)data = WSDISPLAYIO_VIDEO_ON;
    228 		else
    229 			*(int *)data = WSDISPLAYIO_VIDEO_OFF;
    230 		return 0;
    231 
    232 	case WSDISPLAYIO_SVIDEO:
    233 		if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
    234 			/* XXXX: turn on */
    235 		} else {
    236 			/* XXXX: turn off */
    237 		}
    238 		return 0;
    239 
    240 	case WSDISPLAYIO_LINEBYTES:
    241 		*(int *)data = sc->sc_ri.ri_stride;
    242 		return 0;
    243 	}
    244 
    245 	return EPASSTHROUGH;
    246 }
    247 
    248 static paddr_t
    249 clpslcd_mmap(void *v, void *vs, off_t off, int prot)
    250 {
    251 	struct clpslcd_softc *sc = v;
    252 
    253 	if (off < 0 || sc->sc_ri.ri_stride * sc->sc_ri.ri_height <= off)
    254 		return -1;
    255 
    256 	return (paddr_t)sc->sc_ri.ri_bits + off;
    257 }
    258 
    259 static int
    260 clpslcd_alloc_screen(void *v, const struct wsscreen_descr *scr, void **cookiep,
    261 		   int *curxp, int *curyp, long *attrp)
    262 {
    263 printf("%s\n", __func__);
    264 return -1;
    265 }
    266 
    267 static void
    268 clpslcd_free_screen(void *v, void *cookie)
    269 {
    270 printf("%s\n", __func__);
    271 }
    272 
    273 static int
    274 clpslcd_show_screen(void *v, void *cookie, int waitok,
    275 		  void (*func)(void *, int, int), void *arg)
    276 {
    277 printf("%s\n", __func__);
    278 return -1;
    279 }
    280 
    281 int
    282 clpslcd_cnattach(void)
    283 {
    284 
    285 	is_console = 1;
    286 	return 0;
    287 }
    288