Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / hpcarm / dev / ipaq_lcd.c
blobcecb25e4b243f190860cdad3d4af0de91f79ca0d
1 /* $NetBSD: ipaq_lcd.c,v 1.17 2008/04/28 20:23:21 martin Exp $ */
3 /*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ichiro FUKUHARA (ichiro@ichiro.org).
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: ipaq_lcd.c,v 1.17 2008/04/28 20:23:21 martin Exp $");
35 #define IPAQ_LCD_DEBUG
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/time.h>
42 #include <sys/device.h>
44 #include <uvm/uvm_extern.h>
46 #include <dev/wscons/wsconsio.h>
48 #include <machine/bootinfo.h>
49 #include <machine/bus.h>
50 #include <machine/intr.h>
51 #include <arm/cpufunc.h>
52 #include <arm/arm32/katelib.h>
54 #include <arm/sa11x0/sa11x0_reg.h>
55 #include <arm/sa11x0/sa11x0_gpioreg.h>
57 #include <hpcarm/dev/ipaq_gpioreg.h>
58 #include <hpcarm/dev/ipaq_saipvar.h>
59 #include <hpcarm/dev/ipaq_lcdreg.h>
60 #include <hpcarm/dev/ipaq_lcdvar.h>
62 #ifdef IPAQ_LCD_DEBUG
63 #define DPRINTFN(n, x) if (ipaqlcddebug > (n)) aprint_normal x
64 int ipaqlcddebug = 0xff;
65 #else
66 #define DPRINTFN(n, x)
67 #endif
68 #define DPRINTF(x) DPRINTFN(0, x)
70 static int ipaqlcd_match(device_t, cfdata_t, void *);
71 static void ipaqlcd_attach(device_t, device_t, void *);
72 static void ipaqlcd_init(struct ipaqlcd_softc *);
73 static int ipaqlcd_fbinit(struct ipaqlcd_softc *);
74 static int ipaqlcd_ioctl(void *, u_long, void *, int, struct lwp *);
75 static paddr_t ipaqlcd_mmap(void *, off_t, int);
77 #if defined __mips__ || defined __sh__ || defined __arm__
78 #define __BTOP(x) ((paddr_t)(x) >> PGSHIFT)
79 #define __PTOB(x) ((paddr_t)(x) << PGSHIFT)
80 #else
81 #error "define btop, ptob."
82 #endif
84 CFATTACH_DECL_NEW(ipaqlcd, sizeof(struct ipaqlcd_softc),
85 ipaqlcd_match, ipaqlcd_attach, NULL, NULL);
87 struct hpcfb_accessops ipaqlcd_ha = {
88 ipaqlcd_ioctl, ipaqlcd_mmap
90 static int console_flag = 0;
92 static int
93 ipaqlcd_match(device_t parent, cfdata_t match, void *aux)
95 return (1);
98 void
99 ipaqlcd_attach(device_t parent, device_t self, void *aux)
101 struct ipaqlcd_softc *sc = device_private(self);
102 struct hpcfb_attach_args ha;
103 struct ipaq_softc *psc = device_private(parent);
105 sc->sc_dev = self;
106 sc->sc_iot = psc->sc_iot;
107 sc->sc_parent = psc;
109 ipaqlcd_init(sc);
110 ipaqlcd_fbinit(sc);
112 aprint_normal("\n");
113 aprint_normal_dev(self, "iPAQ internal LCD controller\n");
115 DPRINTF(("framebuffer_baseaddr=%lx\n", (u_long)bootinfo->fb_addr));
117 ha.ha_console = console_flag;
118 ha.ha_accessops = &ipaqlcd_ha;
119 ha.ha_accessctx = sc;
120 ha.ha_curfbconf = 0;
121 ha.ha_nfbconf = 1;
122 ha.ha_fbconflist = &sc->sc_fbconf;
123 ha.ha_curdspconf = 0;
124 ha.ha_ndspconf = 1;
125 ha.ha_dspconflist = &sc->sc_dspconf;
127 config_found(sc->sc_dev, &ha, hpcfbprint);
130 void
131 ipaqlcd_init(struct ipaqlcd_softc *sc)
133 /* Initialization of Extended GPIO */
134 sc->sc_parent->ipaq_egpio |= EGPIO_LCD_INIT;
135 bus_space_write_2(sc->sc_iot, sc->sc_parent->sc_egpioh,
136 0, sc->sc_parent->ipaq_egpio);
138 if (bus_space_map(sc->sc_iot, SALCD_BASE, SALCD_NPORTS,
139 0, &sc->sc_ioh))
140 panic("ipaqlcd_init:Cannot map registers");
142 bootinfo->fb_addr = (void *)
143 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_BA1);
146 * Initialize LCD Control Register 0 - 3
147 * must initialize DMA Channel Base Address Register
148 * before enabling LCD(LEN = 1)
150 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
151 SALCD_CR1, IPAQ_LCCR1);
152 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
153 SALCD_CR2, IPAQ_LCCR2);
154 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
155 SALCD_CR3, IPAQ_LCCR3);
156 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
157 SALCD_CR0, IPAQ_LCCR0);
159 DPRINTF(("\n"
160 "DMA_BASE= %08x : DMA_CUR = %08x \n"
161 "LCCR0 = %08x : LCCR1 = %08x \n"
162 "LCCR2 = %08x : LCCR3 = %08x",
163 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_BA1),
164 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_CA1),
165 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_CR0),
166 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_CR1),
167 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_CR2),
168 bus_space_read_4(sc->sc_iot, sc->sc_ioh, SALCD_CR3)));
173 ipaqlcd_fbinit(struct ipaqlcd_softc *sc)
175 struct hpcfb_fbconf *fb;
177 fb = &sc->sc_fbconf;
179 /* Initialize fb */
180 memset(fb, 0, sizeof(*fb));
182 fb->hf_conf_index = 0; /* configuration index */
183 fb->hf_nconfs = 1;
184 strcpy(fb->hf_name, "built-in video");
185 strcpy(fb->hf_conf_name, "LCD");
186 /* configuration name */
187 fb->hf_height = bootinfo->fb_height;
188 fb->hf_width = bootinfo->fb_width;
190 if (bus_space_map(sc->sc_iot, (bus_addr_t)bootinfo->fb_addr,
191 bootinfo->fb_height * bootinfo->fb_line_bytes,
192 0, &fb->hf_baseaddr)) {
193 aprint_normal("unable to map framebuffer\n");
194 return (-1);
197 fb->hf_offset = (u_long)bootinfo->fb_addr -
198 __PTOB(__BTOP(bootinfo->fb_addr));
199 /* frame buffer start offset */
200 fb->hf_bytes_per_line = bootinfo->fb_line_bytes;
201 fb->hf_nplanes = 1;
202 fb->hf_bytes_per_plane = bootinfo->fb_height *
203 bootinfo->fb_line_bytes;
205 fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
206 fb->hf_access_flags |= HPCFB_ACCESS_WORD;
207 fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
209 switch (bootinfo->fb_type) {
211 * gray scale
213 case BIFB_D2_M2L_3:
214 case BIFB_D2_M2L_3x2:
215 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
216 case BIFB_D2_M2L_0:
217 case BIFB_D2_M2L_0x2:
218 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
219 break;
220 case BIFB_D4_M2L_F:
221 case BIFB_D4_M2L_Fx2:
222 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
223 case BIFB_D4_M2L_0:
224 case BIFB_D4_M2L_0x2:
225 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
226 break;
228 * indexed color
230 case BIFB_D8_FF:
231 case BIFB_D8_00:
232 fb->hf_offset = 0x200;
233 break;
235 * RGB color
237 case BIFB_D16_FFFF:
238 case BIFB_D16_0000:
239 fb->hf_class = HPCFB_CLASS_RGBCOLOR;
240 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
241 fb->hf_order_flags = HPCFB_REVORDER_BYTE;
242 fb->hf_pack_width = 16;
243 fb->hf_pixels_per_pack = 1;
244 fb->hf_pixel_width = 16;
246 fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
247 fb->hf_u.hf_rgb.hf_flags = 0;
248 /* reserved for future use */
249 fb->hf_u.hf_rgb.hf_red_width = 5;
250 fb->hf_u.hf_rgb.hf_red_shift = 11;
251 fb->hf_u.hf_rgb.hf_green_width = 6;
252 fb->hf_u.hf_rgb.hf_green_shift = 5;
253 fb->hf_u.hf_rgb.hf_blue_width = 5;
254 fb->hf_u.hf_rgb.hf_blue_shift = 0;
255 fb->hf_u.hf_rgb.hf_alpha_width = 0;
256 fb->hf_u.hf_rgb.hf_alpha_shift = 0;
257 break;
258 default :
259 aprint_normal("unknown type (=%d).\n",
260 bootinfo->fb_type);
261 return (-1);
262 break;
265 return(0);
269 ipaqlcd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
271 struct ipaqlcd_softc *sc = (struct ipaqlcd_softc *)v;
272 struct hpcfb_fbconf *fbconf;
273 struct hpcfb_dspconf *dspconf;
274 struct wsdisplay_cmap *cmap;
275 struct wsdisplay_param *dispparam;
277 switch (cmd) {
278 case WSDISPLAYIO_GETCMAP:
279 cmap = (struct wsdisplay_cmap*)data;
281 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
282 sc->sc_fbconf.hf_pack_width != 8 ||
283 256 <= cmap->index ||
284 256 < (cmap->index + cmap->count))
285 return (EINVAL);
286 return (0);
287 case WSDISPLAYIO_PUTCMAP:
288 return (EINVAL);
289 case WSDISPLAYIO_GETPARAM:
290 dispparam = (struct wsdisplay_param*)data;
291 switch (dispparam->param) {
292 case WSDISPLAYIO_PARAM_BACKLIGHT:
293 DPRINTF(("ipaqlcd_ioctl: GETPARAM:BACKLIGHT\n"));
294 return (EINVAL);
295 case WSDISPLAYIO_PARAM_CONTRAST:
296 DPRINTF(("ipaqlcd_ioctl: GETPARAM:CONTRAST\n"));
297 return (EINVAL);
298 case WSDISPLAYIO_PARAM_BRIGHTNESS:
299 DPRINTF(("ipaqlcd_ioctl: GETPARAM:BRIGHTNESS\n"));
300 return (EINVAL);
301 default:
302 return (EINVAL);
304 return (0);
305 case WSDISPLAYIO_SETPARAM:
306 dispparam = (struct wsdisplay_param*)data;
307 switch (dispparam->param) {
308 case WSDISPLAYIO_PARAM_BACKLIGHT:
309 DPRINTF(("ipaqlcd_ioctl: GETPARAM:BACKLIGHT\n"));
310 return (EINVAL);
311 case WSDISPLAYIO_PARAM_CONTRAST:
312 DPRINTF(("ipaqlcd_ioctl: GETPARAM:CONTRAST\n"));
313 return (EINVAL);
314 case WSDISPLAYIO_PARAM_BRIGHTNESS:
315 DPRINTF(("ipaqlcd_ioctl: GETPARAM:BRIGHTNESS\n"));
316 return (EINVAL);
317 default:
318 return (EINVAL);
320 return (0);
322 case HPCFBIO_GCONF:
323 fbconf = (struct hpcfb_fbconf *)data;
324 if (fbconf->hf_conf_index != 0 &&
325 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
326 return (EINVAL);
328 *fbconf = sc->sc_fbconf; /* structure assignment */
329 return (0);
330 case HPCFBIO_SCONF:
331 fbconf = (struct hpcfb_fbconf *)data;
332 if (fbconf->hf_conf_index != 0 &&
333 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
334 return (EINVAL);
337 * nothing to do because we have only one configuration
339 return (0);
340 case HPCFBIO_GDSPCONF:
341 dspconf = (struct hpcfb_dspconf *)data;
342 if ((dspconf->hd_unit_index != 0 &&
343 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
344 (dspconf->hd_conf_index != 0 &&
345 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
346 return (EINVAL);
348 *dspconf = sc->sc_dspconf; /* structure assignment */
349 return (0);
350 case HPCFBIO_SDSPCONF:
351 dspconf = (struct hpcfb_dspconf *)data;
352 if ((dspconf->hd_unit_index != 0 &&
353 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
354 (dspconf->hd_conf_index != 0 &&
355 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
356 return (EINVAL);
359 * nothing to do
360 * because we have only one unit and one configuration
362 return (0);
364 case HPCFBIO_GOP:
365 case HPCFBIO_SOP:
366 return (EINVAL);
368 return (EPASSTHROUGH);
371 paddr_t
372 ipaqlcd_mmap(void *ctx, off_t offset, int prot)
374 struct ipaqlcd_softc *sc = (struct ipaqlcd_softc *)ctx;
376 if (offset < 0 ||
377 (sc->sc_fbconf.hf_bytes_per_plane +
378 sc->sc_fbconf.hf_offset) < offset)
379 return -1;
381 return __BTOP((u_long)bootinfo->fb_addr + offset);