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