g42xxeb_lcd.c revision 1.9 1 /* $NetBSD: g42xxeb_lcd.c,v 1.9 2008/04/29 06:53:02 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2001, 2002, 2005 Genetec corp.
5 * All rights reserved.
6 *
7 * LCD driver for Genetec G4250EB-X002.
8 * Written by Hiroyuki Bessho for Genetec corp.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include "opt_g42xxlcd.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/uio.h>
37 #include <sys/malloc.h>
38
39 #include <dev/cons.h>
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wscons_callbacks.h>
43
44 #include <machine/bus.h>
45 #include <arm/sa11x0/sa11x0_var.h>
46 #include <arm/xscale/pxa2x0var.h>
47 #include <arm/xscale/pxa2x0reg.h>
48 #include <arm/xscale/pxa2x0_lcd.h>
49
50 #include <arch/evbarm/g42xxeb/g42xxeb_reg.h>
51 #include <arch/evbarm/g42xxeb/g42xxeb_var.h>
52
53 #include "wsdisplay.h"
54 #include "ioconf.h"
55
56 int lcd_match( struct device *, struct cfdata *, void *);
57 void lcd_attach( struct device *, struct device *, void *);
58 int lcdintr(void *);
59
60 #if NWSDISPLAY > 0
61
62 /*
63 * wsdisplay glue
64 */
65 struct pxa2x0_wsscreen_descr lcd_bpp16_screen = {
66 {
67 "bpp16", 0, 0,
68 &pxa2x0_lcd_emulops,
69 0, 0,
70 WSSCREEN_WSCOLORS,
71 },
72 16 /* bits per pixel */
73 }, lcd_bpp8_screen = {
74 {
75 "bpp8", 0, 0,
76 &pxa2x0_lcd_emulops,
77 0, 0,
78 WSSCREEN_WSCOLORS,
79 },
80 8 /* bits per pixel */
81 }, lcd_bpp4_screen = {
82 {
83 "bpp4", 0, 0,
84 &pxa2x0_lcd_emulops,
85 0, 0,
86 WSSCREEN_WSCOLORS,
87 },
88 4 /* bits per pixel */
89 };
90
91
92 static const struct wsscreen_descr *lcd_scr_descr[] = {
93 &lcd_bpp4_screen.c,
94 &lcd_bpp8_screen.c,
95 &lcd_bpp16_screen.c,
96 };
97
98 const struct wsscreen_list lcd_screen_list = {
99 sizeof lcd_scr_descr / sizeof lcd_scr_descr[0],
100 lcd_scr_descr
101 };
102
103 int lcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
104
105 int lcd_show_screen(void *, void *, int,
106 void (*)(void *, int, int), void *);
107
108 const struct wsdisplay_accessops lcd_accessops = {
109 lcd_ioctl,
110 pxa2x0_lcd_mmap,
111 pxa2x0_lcd_alloc_screen,
112 pxa2x0_lcd_free_screen,
113 lcd_show_screen,
114 NULL, /* load_font */
115 };
116
117 #else
118 /*
119 * Interface to LCD framebuffer without wscons
120 */
121 dev_type_open(lcdopen);
122 dev_type_close(lcdclose);
123 dev_type_ioctl(lcdioctl);
124 dev_type_mmap(lcdmmap);
125 const struct cdevsw lcd_cdevsw = {
126 lcdopen, lcdclose, noread, nowrite,
127 lcdioctl, nostop, notty, nopoll, lcdmmap, D_TTY
128 };
129
130 #endif
131
132 CFATTACH_DECL(lcd_obio, sizeof (struct pxa2x0_lcd_softc), lcd_match, lcd_attach,
133 NULL, NULL);
134
135 int
136 lcd_match( struct device *parent, struct cfdata *cf, void *aux )
137 {
138 return 1;
139 }
140
141 #ifdef G4250_LCD_NEC_NL3224BC35
142 /* NEC's QVGA LCD */
143 static const struct lcd_panel_geometry nec_NL3224BC35 =
144 {
145 320, /* Width */
146 240, /* Height */
147 0, /* No extra lines */
148
149 LCDPANEL_SINGLE|LCDPANEL_ACTIVE|LCDPANEL_PCP|
150 LCDPANEL_VSP|LCDPANEL_HSP,
151 7, /* clock divider, 6.25MHz at 100MHz */
152 0xff, /* AC bias pin freq */
153
154 6, /* horizontal sync pulse width */
155 70, /* BLW */
156 7, /* ELW */
157
158 10, /* vertical sync pulse width */
159 11, /* BFW */
160 1, /* EFW */
161 };
162 #endif
163
164 #ifdef G4250_LCD_TOSHIBA_LTM035
165 const struct lcd_panel_geometry toshiba_LTM035 =
166 {
167 240, /* Width */
168 320, /* Height */
169 0, /* No extra lines */
170
171 LCDPANEL_SINGLE|LCDPANEL_ACTIVE| /* LCDPANEL_PCP| */
172 LCDPANEL_VSP|LCDPANEL_HSP,
173 11, /* clock divider, 4.5 MHz at 100 MHz */
174 /* required: 4.28..4.7 MHz */
175 0xff, /* AC bias pin freq */
176
177 4, /* horizontal sync pulse width */
178 8, /* BLW (back porch) */
179 4, /* ELW (front porch) */
180
181 2, /* vertical sync pulse width */
182 2, /* BFW (back porch) */
183 3, /* EFW (front porch) */
184
185 };
186 #endif /* G4250_LCD_TOSHIBA_LTM035 */
187
188 void lcd_attach( struct device *parent, struct device *self, void *aux )
189 {
190 struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)self;
191
192 #ifdef G4250_LCD_TOSHIBA_LTM035
193 # define PANEL toshiba_LTM035
194 #else
195 # define PANEL nec_NL3224BC35
196 #endif
197
198 pxa2x0_lcd_attach_sub(sc, aux, &PANEL);
199
200
201 #if NWSDISPLAY > 0
202
203 {
204 struct wsemuldisplaydev_attach_args aa;
205
206 /* make wsdisplay screen list */
207 pxa2x0_lcd_setup_wsscreen(&lcd_bpp16_screen, &PANEL, NULL);
208 pxa2x0_lcd_setup_wsscreen(&lcd_bpp8_screen, &PANEL, NULL);
209 pxa2x0_lcd_setup_wsscreen(&lcd_bpp4_screen, &PANEL, NULL);
210
211 aa.console = 0;
212 aa.scrdata = &lcd_screen_list;
213 aa.accessops = &lcd_accessops;
214 aa.accesscookie = sc;
215
216 printf("\n");
217
218 (void) config_found(self, &aa, wsemuldisplaydevprint);
219 }
220 #else
221 {
222 struct pxa2x0_lcd_screen *screen;
223 int error;
224
225 error = pxa2x0_lcd_new_screen( sc, 16, &screen );
226 if (error == 0) {
227 sc->active = screen;
228 pxa2x0_lcd_start_dma(sc, screen);
229 }
230
231 printf("\n");
232 }
233 #endif
234
235 #undef PANEL
236
237 }
238
239 #if NWSDISPLAY > 0
240
241 int
242 lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
243 {
244 struct obio_softc *osc =
245 (struct obio_softc *) device_parent((struct device *)v);
246 uint16_t reg;
247
248 switch (cmd) {
249 case WSDISPLAYIO_SVIDEO:
250 reg = bus_space_read_2(osc->sc_iot, osc->sc_obioreg_ioh,
251 G42XXEB_LCDCTL);
252 if (*(int *)data == WSDISPLAYIO_VIDEO_ON)
253 reg |= LCDCTL_BL_ON;
254 else
255 reg &= ~LCDCTL_BL_ON;
256 bus_space_write_2(osc->sc_iot, osc->sc_obioreg_ioh,
257 G42XXEB_LCDCTL, reg);
258 bus_space_write_1(osc->sc_iot, osc->sc_obioreg_ioh,
259 G42XXEB_LED, reg);
260 printf("LCD control: %x\n", reg);
261 break; /* turn on/off LCD controller */
262 }
263
264 return pxa2x0_lcd_ioctl(v, vs, cmd, data, flag, l);
265 }
266
267 int
268 lcd_show_screen(void *v, void *cookie, int waitok,
269 void (*cb)(void *, int, int), void *cbarg)
270 {
271 struct obio_softc *osc =
272 (struct obio_softc *) device_parent((struct device *)v);
273 uint16_t reg;
274
275 pxa2x0_lcd_show_screen(v,cookie,waitok,cb,cbarg);
276
277 /* Turn on LCD backlight.
278 XXX: with fixed blightness. want new ioctl to set blightness. */
279 reg = bus_space_read_2(osc->sc_iot, osc->sc_obioreg_ioh, G42XXEB_LCDCTL);
280 bus_space_write_2(osc->sc_iot, osc->sc_obioreg_ioh, G42XXEB_LCDCTL,
281 (reg & ~LCDCTL_BL_PWN) | 0x4000 | LCDCTL_BL_ON);
282
283 return 0;
284 }
285
286
287
288 #else /* NWSDISPLAY==0 */
289
290 int
291 lcdopen(dev_t dev, int oflags, int devtype, struct lwp *l)
292 {
293 return 0;
294 }
295
296 int
297 lcdclose(dev_t dev, int fflag, int devtype, struct lwp *l)
298 {
299 return 0;
300 }
301
302 paddr_t
303 lcdmmap(dev_t dev, off_t offset, int size)
304 {
305 struct pxa2x0_lcd_softc *sc = device_lookup(&lcd_cd, minor(dev));
306 struct pxa2x0_lcd_screen *scr = sc->active;
307
308 return bus_dmamem_mmap( &pxa2x0_bus_dma_tag, scr->segs, scr->nsegs,
309 offset, 0, BUS_DMA_WAITOK|BUS_DMA_COHERENT );
310 }
311
312 int
313 lcdioctl(dev_t dev, u_long cmd, void *data,
314 int fflag, struct lwp *l)
315 {
316 return EOPNOTSUPP;
317 }
318
319 #endif /* NWSDISPLAY>0 */
320