1 1.18 thorpej /* $NetBSD: lubbock_lcd.c,v 1.18 2023/12/20 13:55:18 thorpej Exp $ */ 2 1.1 bsh 3 1.1 bsh /* 4 1.1 bsh * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. 5 1.1 bsh * Written by Hiroyuki Bessho for Genetec Corporation. 6 1.1 bsh * 7 1.1 bsh * Redistribution and use in source and binary forms, with or without 8 1.1 bsh * modification, are permitted provided that the following conditions 9 1.1 bsh * are met: 10 1.1 bsh * 1. Redistributions of source code must retain the above copyright 11 1.1 bsh * notice, this list of conditions and the following disclaimer. 12 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 bsh * notice, this list of conditions and the following disclaimer in the 14 1.1 bsh * documentation and/or other materials provided with the distribution. 15 1.1 bsh * 3. The name of Genetec Corporation may not be used to endorse or 16 1.1 bsh * promote products derived from this software without specific prior 17 1.1 bsh * written permission. 18 1.1 bsh * 19 1.1 bsh * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 20 1.1 bsh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 bsh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 bsh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 23 1.1 bsh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 bsh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 bsh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 bsh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 bsh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 bsh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 bsh * POSSIBILITY OF SUCH DAMAGE. 30 1.1 bsh */ 31 1.1 bsh 32 1.1 bsh /* 33 1.1 bsh * LCD driver for Intel Lubbock. 34 1.1 bsh * 35 1.1 bsh * Controlling LCD is almost completely done through PXA2X0's 36 1.1 bsh * integrated LCD controller. Codes for it is arm/xscale/pxa2x0_lcd.c. 37 1.1 bsh * 38 1.1 bsh * Codes in this file provide platform specific things including: 39 1.1 bsh * LCD on/off switch in on-board PLD register. 40 1.1 bsh * LCD panel geometry 41 1.1 bsh */ 42 1.1 bsh #include <sys/cdefs.h> 43 1.18 thorpej __KERNEL_RCSID(0, "$NetBSD: lubbock_lcd.c,v 1.18 2023/12/20 13:55:18 thorpej Exp $"); 44 1.1 bsh 45 1.1 bsh #include <sys/param.h> 46 1.1 bsh #include <sys/systm.h> 47 1.1 bsh #include <sys/conf.h> 48 1.1 bsh #include <sys/uio.h> 49 1.1 bsh 50 1.1 bsh #include <dev/cons.h> 51 1.1 bsh #include <dev/wscons/wsconsio.h> 52 1.1 bsh #include <dev/wscons/wsdisplayvar.h> 53 1.1 bsh #include <dev/wscons/wscons_callbacks.h> 54 1.1 bsh 55 1.12 dyoung #include <sys/bus.h> 56 1.1 bsh #include <arm/xscale/pxa2x0var.h> 57 1.1 bsh #include <arm/xscale/pxa2x0reg.h> 58 1.1 bsh #include <arm/xscale/pxa2x0_lcd.h> 59 1.1 bsh 60 1.1 bsh #include <arch/evbarm/lubbock/lubbock_reg.h> 61 1.1 bsh #include <arch/evbarm/lubbock/lubbock_var.h> 62 1.1 bsh 63 1.1 bsh #include "wsdisplay.h" 64 1.1 bsh 65 1.9 nonaka int lcd_match(device_t, cfdata_t, void *); 66 1.9 nonaka void lcd_attach(device_t, device_t, void *); 67 1.1 bsh int lcdintr(void *); 68 1.1 bsh 69 1.1 bsh #if NWSDISPLAY > 0 70 1.1 bsh 71 1.1 bsh /* 72 1.1 bsh * wsdisplay glue 73 1.1 bsh */ 74 1.1 bsh struct pxa2x0_wsscreen_descr lcd_bpp16_screen = { 75 1.1 bsh { 76 1.1 bsh "bpp16", 0, 0, 77 1.1 bsh &pxa2x0_lcd_emulops, 78 1.1 bsh 0, 0, 79 1.1 bsh WSSCREEN_WSCOLORS, 80 1.1 bsh }, 81 1.1 bsh 16 /* bits per pixel */ 82 1.1 bsh }, lcd_bpp8_screen = { 83 1.1 bsh { 84 1.1 bsh "bpp8", 0, 0, 85 1.1 bsh &pxa2x0_lcd_emulops, 86 1.1 bsh 0, 0, 87 1.1 bsh WSSCREEN_WSCOLORS, 88 1.1 bsh }, 89 1.1 bsh 8 /* bits per pixel */ 90 1.1 bsh }, lcd_bpp4_screen = { 91 1.1 bsh { 92 1.1 bsh "bpp4", 0, 0, 93 1.1 bsh &pxa2x0_lcd_emulops, 94 1.1 bsh 0, 0, 95 1.1 bsh WSSCREEN_WSCOLORS, 96 1.1 bsh }, 97 1.1 bsh 4 /* bits per pixel */ 98 1.1 bsh }; 99 1.1 bsh 100 1.1 bsh 101 1.1 bsh static const struct wsscreen_descr *lcd_scr_descr[] = { 102 1.1 bsh #if 0 103 1.1 bsh /* bpp4 needs a patch to rasops4 */ 104 1.1 bsh &lcd_bpp4_screen.c, 105 1.1 bsh #endif 106 1.1 bsh &lcd_bpp8_screen.c, 107 1.1 bsh &lcd_bpp16_screen.c, 108 1.1 bsh }; 109 1.1 bsh 110 1.1 bsh const struct wsscreen_list lcd_screen_list = { 111 1.1 bsh sizeof lcd_scr_descr / sizeof lcd_scr_descr[0], 112 1.1 bsh lcd_scr_descr 113 1.1 bsh }; 114 1.1 bsh 115 1.7 christos int lcd_ioctl(void *, void *, u_long, void *, int, struct lwp *); 116 1.1 bsh 117 1.1 bsh int lcd_show_screen(void *, void *, int, 118 1.1 bsh void (*)(void *, int, int), void *); 119 1.1 bsh 120 1.1 bsh const struct wsdisplay_accessops lcd_accessops = { 121 1.1 bsh lcd_ioctl, 122 1.1 bsh pxa2x0_lcd_mmap, 123 1.1 bsh pxa2x0_lcd_alloc_screen, 124 1.1 bsh pxa2x0_lcd_free_screen, 125 1.1 bsh lcd_show_screen, 126 1.1 bsh NULL, /* load_font */ 127 1.1 bsh }; 128 1.1 bsh 129 1.1 bsh #else 130 1.1 bsh /* 131 1.1 bsh * Interface to LCD framebuffer without wscons 132 1.1 bsh */ 133 1.1 bsh dev_type_open(lcdopen); 134 1.1 bsh dev_type_close(lcdclose); 135 1.1 bsh dev_type_ioctl(lcdioctl); 136 1.1 bsh dev_type_mmap(lcdmmap); 137 1.1 bsh const struct cdevsw lcd_cdevsw = { 138 1.14 dholland .d_open = lcdopen, 139 1.14 dholland .d_close = lcdclose, 140 1.14 dholland .d_read = noread, 141 1.14 dholland .d_write = nowrite, 142 1.14 dholland .d_ioctl = lcdioctl, 143 1.14 dholland .d_stop = nostop, 144 1.14 dholland .d_tty = notty, 145 1.14 dholland .d_poll = nopoll, 146 1.14 dholland .d_mmap = lcdmmap, 147 1.14 dholland .d_kqfilter = nokqfilter, 148 1.15 dholland .d_discard = nodiscard, 149 1.14 dholland .d_flag = D_TTY 150 1.1 bsh }; 151 1.1 bsh 152 1.1 bsh #endif 153 1.1 bsh 154 1.9 nonaka CFATTACH_DECL_NEW(lcd_obio, sizeof (struct pxa2x0_lcd_softc), lcd_match, 155 1.1 bsh lcd_attach, NULL, NULL); 156 1.1 bsh 157 1.1 bsh int 158 1.9 nonaka lcd_match( device_t parent, cfdata_t cf, void *aux ) 159 1.1 bsh { 160 1.1 bsh return 1; 161 1.1 bsh } 162 1.1 bsh 163 1.1 bsh static const struct lcd_panel_geometry sharp_LM8V31 = 164 1.1 bsh { 165 1.1 bsh 640, /* Width */ 166 1.1 bsh 480, /* Height */ 167 1.1 bsh 0, /* No extra lines */ 168 1.1 bsh 169 1.1 bsh LCDPANEL_DUAL|LCDPANEL_PASSIVE|LCDPANEL_PCP, 170 1.1 bsh 10, /* clock divider */ 171 1.1 bsh 0xff, /* AC bias pin freq */ 172 1.1 bsh 173 1.1 bsh 2, /* horizontal sync pulse width */ 174 1.1 bsh 3, /* BLW */ 175 1.1 bsh 3, /* ELW */ 176 1.1 bsh 177 1.1 bsh 1, /* vertical sync pulse width */ 178 1.1 bsh 0, /* BFW */ 179 1.1 bsh 0, /* EFW */ 180 1.1 bsh 181 1.1 bsh }; 182 1.1 bsh 183 1.9 nonaka void lcd_attach( device_t parent, device_t self, void *aux ) 184 1.1 bsh { 185 1.9 nonaka struct pxa2x0_lcd_softc *sc = device_private(self); 186 1.11 bsh struct obio_attach_args *oba = aux; 187 1.11 bsh struct pxaip_attach_args paa; 188 1.9 nonaka 189 1.9 nonaka sc->dev = self; 190 1.1 bsh 191 1.11 bsh paa.pxa_name = "obio"; 192 1.11 bsh paa.pxa_iot = oba->oba_iot; 193 1.11 bsh paa.pxa_addr = oba->oba_addr; 194 1.11 bsh paa.pxa_size = 0; /* XXX */ 195 1.11 bsh paa.pxa_intr = oba->oba_intr; 196 1.11 bsh 197 1.11 bsh pxa2x0_lcd_attach_sub(sc, &paa, &sharp_LM8V31); 198 1.1 bsh 199 1.1 bsh 200 1.1 bsh #if NWSDISPLAY > 0 201 1.1 bsh 202 1.1 bsh { 203 1.1 bsh struct wsemuldisplaydev_attach_args aa; 204 1.1 bsh 205 1.1 bsh /* make wsdisplay screen list */ 206 1.1 bsh pxa2x0_lcd_setup_wsscreen( &lcd_bpp16_screen, &sharp_LM8V31, NULL ); 207 1.1 bsh pxa2x0_lcd_setup_wsscreen( &lcd_bpp8_screen, &sharp_LM8V31, NULL ); 208 1.1 bsh pxa2x0_lcd_setup_wsscreen( &lcd_bpp4_screen, &sharp_LM8V31, NULL ); 209 1.1 bsh 210 1.1 bsh aa.console = 0; 211 1.1 bsh aa.scrdata = &lcd_screen_list; 212 1.1 bsh aa.accessops = &lcd_accessops; 213 1.1 bsh aa.accesscookie = sc; 214 1.1 bsh 215 1.16 thorpej (void) config_found(self, &aa, wsemuldisplaydevprint, 216 1.17 thorpej CFARGS_NONE); 217 1.1 bsh } 218 1.1 bsh #else 219 1.1 bsh { 220 1.6 nonaka struct pxa2x0_lcd_screen *screen; 221 1.6 nonaka int error; 222 1.1 bsh 223 1.6 nonaka error = pxa2x0_lcd_new_screen( sc, 8, &screen ); 224 1.6 nonaka if( error == 0 ){ 225 1.1 bsh sc->active = screen; 226 1.1 bsh pxa2x0_lcd_start_dma( sc, screen ); 227 1.1 bsh } 228 1.1 bsh } 229 1.1 bsh #endif 230 1.1 bsh 231 1.1 bsh } 232 1.1 bsh 233 1.1 bsh #if NWSDISPLAY > 0 234 1.1 bsh 235 1.1 bsh int 236 1.7 christos lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 237 1.1 bsh { 238 1.13 chs struct pxa2x0_lcd_softc *sc = v; 239 1.10 rjs struct obio_softc *osc = device_private(device_parent(sc->dev)); 240 1.1 bsh uint16_t reg; 241 1.1 bsh 242 1.1 bsh switch (cmd) { 243 1.1 bsh case WSDISPLAYIO_SVIDEO: 244 1.1 bsh reg = bus_space_read_2( osc->sc_iot, osc->sc_obioreg_ioh, 245 1.1 bsh LUBBOCK_MISCWR ); 246 1.1 bsh if( *(int *)data == WSDISPLAYIO_VIDEO_ON ) 247 1.1 bsh reg |= MISCWR_LCDDISP; 248 1.1 bsh else 249 1.1 bsh reg &= ~MISCWR_LCDDISP; 250 1.1 bsh bus_space_write_2( osc->sc_iot, osc->sc_obioreg_ioh, 251 1.1 bsh LUBBOCK_MISCWR, reg ); 252 1.1 bsh break; /* turn on/off LCD controller */ 253 1.1 bsh } 254 1.1 bsh 255 1.5 jmmv return pxa2x0_lcd_ioctl( v, vs, cmd, data, flag, l ); 256 1.1 bsh } 257 1.1 bsh 258 1.1 bsh int 259 1.1 bsh lcd_show_screen(void *v, void *cookie, int waitok, 260 1.1 bsh void (*cb)(void *, int, int), void *cbarg) 261 1.1 bsh { 262 1.13 chs struct pxa2x0_lcd_softc *sc = v; 263 1.10 rjs struct obio_softc *osc = device_private(device_parent(sc->dev)); 264 1.1 bsh 265 1.1 bsh pxa2x0_lcd_show_screen(v,cookie,waitok,cb,cbarg); 266 1.1 bsh 267 1.1 bsh /* Turn on LCD */ 268 1.1 bsh bus_space_write_4( osc->sc_iot, osc->sc_obioreg_ioh, LUBBOCK_MISCWR, 269 1.1 bsh MISCWR_LCDDISP | 270 1.1 bsh bus_space_read_4( osc->sc_iot, osc->sc_obioreg_ioh, LUBBOCK_MISCWR ) ); 271 1.1 bsh 272 1.1 bsh return (0); 273 1.1 bsh } 274 1.1 bsh 275 1.1 bsh 276 1.1 bsh 277 1.1 bsh #else /* NWSDISPLAY==0 */ 278 1.1 bsh 279 1.1 bsh int 280 1.2 christos lcdopen( dev_t dev, int oflags, int devtype, struct lwp *l ) 281 1.1 bsh { 282 1.1 bsh return 0; 283 1.1 bsh } 284 1.1 bsh 285 1.1 bsh int 286 1.2 christos lcdclose( dev_t dev, int fflag, int devtype, struct lwp *l ) 287 1.1 bsh { 288 1.1 bsh return 0; 289 1.1 bsh } 290 1.1 bsh 291 1.1 bsh paddr_t 292 1.1 bsh lcdmmap( dev_t dev, off_t offset, int size ) 293 1.1 bsh { 294 1.8 cegger struct pxa2x0_lcd_softc *sc = 295 1.8 cegger device_lookup_private(&lcd_cd, minor(dev)); 296 1.1 bsh struct pxa2x0_lcd_screen *scr = sc->active; 297 1.1 bsh 298 1.1 bsh return bus_dmamem_mmap( &pxa2x0_bus_dma_tag, scr->segs, scr->nsegs, 299 1.1 bsh offset, 0, BUS_DMA_WAITOK|BUS_DMA_COHERENT ); 300 1.1 bsh } 301 1.1 bsh 302 1.1 bsh int 303 1.7 christos lcdioctl( dev_t dev, u_long cmd, void *data, 304 1.2 christos int fflag, struct lwp *l ) 305 1.1 bsh { 306 1.1 bsh return EOPNOTSUPP; 307 1.1 bsh } 308 1.1 bsh 309 1.1 bsh #endif /* NWSDISPLAY>0 */ 310