wmlcd.c revision 1.1.4.2 1 1.1.4.2 tls /* $NetBSD: wmlcd.c,v 1.1.4.2 2013/06/23 06:20:03 tls Exp $ */
2 1.1.4.2 tls /*
3 1.1.4.2 tls * Copyright (c) 2013 KIYOHARA Takashi
4 1.1.4.2 tls * All rights reserved.
5 1.1.4.2 tls *
6 1.1.4.2 tls * Redistribution and use in source and binary forms, with or without
7 1.1.4.2 tls * modification, are permitted provided that the following conditions
8 1.1.4.2 tls * are met:
9 1.1.4.2 tls * 1. Redistributions of source code must retain the above copyright
10 1.1.4.2 tls * notice, this list of conditions and the following disclaimer.
11 1.1.4.2 tls * 2. Redistributions in binary form must reproduce the above copyright
12 1.1.4.2 tls * notice, this list of conditions and the following disclaimer in the
13 1.1.4.2 tls * documentation and/or other materials provided with the distribution.
14 1.1.4.2 tls *
15 1.1.4.2 tls * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1.4.2 tls * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1.4.2 tls * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1.4.2 tls * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1.4.2 tls * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1.4.2 tls * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1.4.2 tls * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1.4.2 tls * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1.4.2 tls * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1.4.2 tls * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1.4.2 tls * POSSIBILITY OF SUCH DAMAGE.
26 1.1.4.2 tls */
27 1.1.4.2 tls #include <sys/cdefs.h>
28 1.1.4.2 tls __KERNEL_RCSID(0, "$NetBSD: wmlcd.c,v 1.1.4.2 2013/06/23 06:20:03 tls Exp $");
29 1.1.4.2 tls
30 1.1.4.2 tls #include "rnd.h"
31 1.1.4.2 tls
32 1.1.4.2 tls #include <sys/param.h>
33 1.1.4.2 tls #include <sys/bus.h>
34 1.1.4.2 tls #include <sys/device.h>
35 1.1.4.2 tls #include <sys/errno.h>
36 1.1.4.2 tls
37 1.1.4.2 tls #include <uvm/uvm_extern.h>
38 1.1.4.2 tls
39 1.1.4.2 tls #include <epoc32/windermere/windermerereg.h>
40 1.1.4.2 tls #include <epoc32/windermere/windermerevar.h>
41 1.1.4.2 tls
42 1.1.4.2 tls #include <dev/cons.h>
43 1.1.4.2 tls #include <dev/wscons/wsconsio.h>
44 1.1.4.2 tls #include <dev/wscons/wsdisplayvar.h>
45 1.1.4.2 tls #include <dev/rasops/rasops.h>
46 1.1.4.2 tls
47 1.1.4.2 tls #include "locators.h"
48 1.1.4.2 tls
49 1.1.4.2 tls #define LCD_SIZE 0x100
50 1.1.4.2 tls
51 1.1.4.2 tls static int is_console;
52 1.1.4.2 tls struct wmlcd_softc {
53 1.1.4.2 tls device_t sc_dev;
54 1.1.4.2 tls
55 1.1.4.2 tls bus_space_tag_t sc_iot;
56 1.1.4.2 tls bus_space_handle_t sc_ioh;
57 1.1.4.2 tls
58 1.1.4.2 tls vaddr_t sc_buffer;
59 1.1.4.2 tls
60 1.1.4.2 tls struct rasops_info sc_ri;
61 1.1.4.2 tls };
62 1.1.4.2 tls
63 1.1.4.2 tls static int wmlcd_match(device_t, cfdata_t, void *);
64 1.1.4.2 tls static void wmlcd_attach(device_t, device_t, void *);
65 1.1.4.2 tls
66 1.1.4.2 tls /* wsdisplay functions */
67 1.1.4.2 tls static int wmlcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
68 1.1.4.2 tls static paddr_t wmlcd_mmap(void *, void *, off_t, int);
69 1.1.4.2 tls static int wmlcd_alloc_screen(void *, const struct wsscreen_descr *, void **,
70 1.1.4.2 tls int *, int *, long *);
71 1.1.4.2 tls static void wmlcd_free_screen(void *, void *);
72 1.1.4.2 tls static int wmlcd_show_screen(void *, void *, int,
73 1.1.4.2 tls void (*)(void *, int, int), void *);
74 1.1.4.2 tls
75 1.1.4.2 tls CFATTACH_DECL_NEW(wmlcd, sizeof(struct wmlcd_softc),
76 1.1.4.2 tls wmlcd_match, wmlcd_attach, NULL, NULL);
77 1.1.4.2 tls
78 1.1.4.2 tls
79 1.1.4.2 tls #define WMLCD_DEFAULT_DEPTH 4
80 1.1.4.2 tls /* Linux like palette data */
81 1.1.4.2 tls const static char palette_2bpp[] = {
82 1.1.4.2 tls 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00,
83 1.1.4.2 tls 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 1.1.4.2 tls 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 1.1.4.2 tls 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 1.1.4.2 tls };
87 1.1.4.2 tls const static char palette_4bpp[] = {
88 1.1.4.2 tls 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x07, 0x00,
89 1.1.4.2 tls 0x03, 0x00, 0x04, 0x00, 0x06, 0x00, 0x0a, 0x00,
90 1.1.4.2 tls 0x05, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x0c, 0x00,
91 1.1.4.2 tls 0x08, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x0f, 0x00,
92 1.1.4.2 tls };
93 1.1.4.2 tls
94 1.1.4.2 tls static struct wsscreen_descr wmlcd_descr = {
95 1.1.4.2 tls .name = "wmlcd",
96 1.1.4.2 tls .fontwidth = 8,
97 1.1.4.2 tls .fontheight = 16,
98 1.1.4.2 tls .capabilities = WSSCREEN_WSCOLORS,
99 1.1.4.2 tls };
100 1.1.4.2 tls static const struct wsscreen_descr *wmlcd_descrs[] = {
101 1.1.4.2 tls &wmlcd_descr
102 1.1.4.2 tls };
103 1.1.4.2 tls
104 1.1.4.2 tls static const struct wsscreen_list wmlcd_screen_list = {
105 1.1.4.2 tls .nscreens = __arraycount(wmlcd_descrs),
106 1.1.4.2 tls .screens = wmlcd_descrs,
107 1.1.4.2 tls };
108 1.1.4.2 tls
109 1.1.4.2 tls struct wsdisplay_accessops wmlcd_accessops = {
110 1.1.4.2 tls wmlcd_ioctl,
111 1.1.4.2 tls wmlcd_mmap,
112 1.1.4.2 tls wmlcd_alloc_screen,
113 1.1.4.2 tls wmlcd_free_screen,
114 1.1.4.2 tls wmlcd_show_screen,
115 1.1.4.2 tls NULL,
116 1.1.4.2 tls NULL,
117 1.1.4.2 tls NULL,
118 1.1.4.2 tls };
119 1.1.4.2 tls
120 1.1.4.2 tls /* ARGSUSED */
121 1.1.4.2 tls static int
122 1.1.4.2 tls wmlcd_match(device_t parent, cfdata_t match, void *aux)
123 1.1.4.2 tls {
124 1.1.4.2 tls struct windermere_attach_args *aa = aux;
125 1.1.4.2 tls
126 1.1.4.2 tls /* Wildcard not accept */
127 1.1.4.2 tls if (aa->aa_offset == WINDERMERECF_OFFSET_DEFAULT)
128 1.1.4.2 tls return 0;
129 1.1.4.2 tls
130 1.1.4.2 tls aa->aa_size = LCD_SIZE;
131 1.1.4.2 tls return 1;
132 1.1.4.2 tls }
133 1.1.4.2 tls
134 1.1.4.2 tls /* ARGSUSED */
135 1.1.4.2 tls static void
136 1.1.4.2 tls wmlcd_attach(device_t parent, device_t self, void *aux)
137 1.1.4.2 tls {
138 1.1.4.2 tls struct wmlcd_softc *sc = device_private(self);
139 1.1.4.2 tls struct windermere_attach_args *aa = aux;
140 1.1.4.2 tls struct wsemuldisplaydev_attach_args waa;
141 1.1.4.2 tls prop_dictionary_t dict = device_properties(self);
142 1.1.4.2 tls paddr_t paddr;
143 1.1.4.2 tls struct rasops_info *ri;
144 1.1.4.2 tls uint32_t lcdctl, width, height, addr, depth;
145 1.1.4.2 tls int c, i;
146 1.1.4.2 tls const char *palette;
147 1.1.4.2 tls
148 1.1.4.2 tls aprint_naive("\n");
149 1.1.4.2 tls aprint_normal("\n");
150 1.1.4.2 tls
151 1.1.4.2 tls sc->sc_dev = self;
152 1.1.4.2 tls if (windermere_bus_space_subregion(aa->aa_iot, *aa->aa_ioh,
153 1.1.4.2 tls aa->aa_offset, aa->aa_size, &sc->sc_ioh) != 0) {
154 1.1.4.2 tls aprint_error_dev(self, "can't map registers\n");
155 1.1.4.2 tls return;
156 1.1.4.2 tls }
157 1.1.4.2 tls sc->sc_iot = aa->aa_iot;
158 1.1.4.2 tls
159 1.1.4.2 tls if (!prop_dictionary_get_uint32(dict, "width", &width) ||
160 1.1.4.2 tls !prop_dictionary_get_uint32(dict, "height", &height) ||
161 1.1.4.2 tls !prop_dictionary_get_uint32(dict, "addr", &addr)) {
162 1.1.4.2 tls aprint_error_dev(self, "can't get properties\n");
163 1.1.4.2 tls return;
164 1.1.4.2 tls }
165 1.1.4.2 tls sc->sc_buffer = addr;
166 1.1.4.2 tls pmap_extract(pmap_kernel(), addr, &paddr);
167 1.1.4.2 tls
168 1.1.4.2 tls /* Setup palette data */
169 1.1.4.2 tls depth = WMLCD_DEFAULT_DEPTH;
170 1.1.4.2 tls if (depth == 2)
171 1.1.4.2 tls palette = palette_2bpp;
172 1.1.4.2 tls else
173 1.1.4.2 tls palette = palette_4bpp;
174 1.1.4.2 tls for (i = 0; i < LCD_PALETTE_SIZE; i++)
175 1.1.4.2 tls *((uint8_t *)addr + i) = palette[i];
176 1.1.4.2 tls *(uint16_t *)addr |= (depth >> 1) << 12;
177 1.1.4.2 tls
178 1.1.4.2 tls lcdctl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LCDCTL);
179 1.1.4.2 tls bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDCTL, lcdctl & ~LCDCTL_EN);
180 1.1.4.2 tls
181 1.1.4.2 tls bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDDBAR1, paddr);
182 1.1.4.2 tls
183 1.1.4.2 tls lcdctl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LCDCTL);
184 1.1.4.2 tls bus_space_write_4(sc->sc_iot, sc->sc_ioh, LCDCTL,
185 1.1.4.2 tls lcdctl | LCDCTL_EN | LCDCTL_BW);
186 1.1.4.2 tls
187 1.1.4.2 tls aprint_normal_dev(self,
188 1.1.4.2 tls ": %dx%d pixels, %d bpp mono\n", width, height, 1 << depth);
189 1.1.4.2 tls
190 1.1.4.2 tls ri = &sc->sc_ri;
191 1.1.4.2 tls ri->ri_depth = depth;
192 1.1.4.2 tls ri->ri_bits = (void *)(addr + LCD_PALETTE_SIZE);
193 1.1.4.2 tls ri->ri_width = width;
194 1.1.4.2 tls ri->ri_height = height;
195 1.1.4.2 tls ri->ri_stride = width * ri->ri_depth / 8/*bits*/;
196 1.1.4.2 tls ri->ri_flg = RI_FORCEMONO | RI_CLEAR | RI_CENTER;
197 1.1.4.2 tls
198 1.1.4.2 tls if (is_console) {
199 1.1.4.2 tls long defattr;
200 1.1.4.2 tls
201 1.1.4.2 tls if (rasops_init(ri, 0, 0) < 0)
202 1.1.4.2 tls panic("rasops_init failed");
203 1.1.4.2 tls
204 1.1.4.2 tls if (ri->ri_depth == 4) {
205 1.1.4.2 tls /* XXXXX: Create color map. */
206 1.1.4.2 tls ri->ri_devcmap[0] = 0;
207 1.1.4.2 tls for (i = 1; i < 15; i++) {
208 1.1.4.2 tls c = (i + 0xc) & 0xf;
209 1.1.4.2 tls ri->ri_devcmap[i] =
210 1.1.4.2 tls c | (c << 8) | (c << 16) | (c << 24);
211 1.1.4.2 tls }
212 1.1.4.2 tls }
213 1.1.4.2 tls ri->ri_devcmap[15] = -1;
214 1.1.4.2 tls
215 1.1.4.2 tls wmlcd_descr.ncols = ri->ri_cols;
216 1.1.4.2 tls wmlcd_descr.nrows = ri->ri_rows;
217 1.1.4.2 tls wmlcd_descr.textops = &ri->ri_ops;
218 1.1.4.2 tls wmlcd_descr.capabilities = ri->ri_caps;
219 1.1.4.2 tls
220 1.1.4.2 tls if ((ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr) != 0)
221 1.1.4.2 tls panic("allocattr failed");
222 1.1.4.2 tls wsdisplay_cnattach(&wmlcd_descr, ri, ri->ri_ccol, ri->ri_crow,
223 1.1.4.2 tls defattr);
224 1.1.4.2 tls }
225 1.1.4.2 tls
226 1.1.4.2 tls waa.console = is_console;
227 1.1.4.2 tls waa.scrdata = &wmlcd_screen_list;
228 1.1.4.2 tls waa.accessops = &wmlcd_accessops;
229 1.1.4.2 tls waa.accesscookie = sc;
230 1.1.4.2 tls
231 1.1.4.2 tls config_found(self, &waa, wsemuldisplaydevprint);
232 1.1.4.2 tls }
233 1.1.4.2 tls
234 1.1.4.2 tls static int
235 1.1.4.2 tls wmlcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
236 1.1.4.2 tls {
237 1.1.4.2 tls struct wmlcd_softc *sc = v;
238 1.1.4.2 tls struct wsdisplay_fbinfo *wsdisp_info;
239 1.1.4.2 tls
240 1.1.4.2 tls switch (cmd) {
241 1.1.4.2 tls case WSDISPLAYIO_GTYPE:
242 1.1.4.2 tls *(int *)data = WSDISPLAY_TYPE_WINDERMERE;
243 1.1.4.2 tls return 0;
244 1.1.4.2 tls
245 1.1.4.2 tls case WSDISPLAYIO_GINFO:
246 1.1.4.2 tls wsdisp_info = (struct wsdisplay_fbinfo *)data;
247 1.1.4.2 tls wsdisp_info->height = sc->sc_ri.ri_height;
248 1.1.4.2 tls wsdisp_info->width = sc->sc_ri.ri_width;
249 1.1.4.2 tls wsdisp_info->depth = sc->sc_ri.ri_depth;
250 1.1.4.2 tls wsdisp_info->cmsize = 0;
251 1.1.4.2 tls return 0;
252 1.1.4.2 tls
253 1.1.4.2 tls case WSDISPLAYIO_GVIDEO:
254 1.1.4.2 tls if (1) /* XXXX */
255 1.1.4.2 tls *(int *)data = WSDISPLAYIO_VIDEO_ON;
256 1.1.4.2 tls else
257 1.1.4.2 tls *(int *)data = WSDISPLAYIO_VIDEO_OFF;
258 1.1.4.2 tls return 0;
259 1.1.4.2 tls
260 1.1.4.2 tls case WSDISPLAYIO_SVIDEO:
261 1.1.4.2 tls if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
262 1.1.4.2 tls /* XXXX: turn on */
263 1.1.4.2 tls } else {
264 1.1.4.2 tls /* XXXX: turn off */
265 1.1.4.2 tls }
266 1.1.4.2 tls return 0;
267 1.1.4.2 tls
268 1.1.4.2 tls case WSDISPLAYIO_LINEBYTES:
269 1.1.4.2 tls *(int *)data = sc->sc_ri.ri_stride;
270 1.1.4.2 tls return 0;
271 1.1.4.2 tls }
272 1.1.4.2 tls
273 1.1.4.2 tls return EPASSTHROUGH;
274 1.1.4.2 tls }
275 1.1.4.2 tls
276 1.1.4.2 tls static paddr_t
277 1.1.4.2 tls wmlcd_mmap(void *v, void *vs, off_t off, int prot)
278 1.1.4.2 tls {
279 1.1.4.2 tls struct wmlcd_softc *sc = v;
280 1.1.4.2 tls
281 1.1.4.2 tls if (off < 0 || sc->sc_ri.ri_stride * sc->sc_ri.ri_height <= off)
282 1.1.4.2 tls return -1;
283 1.1.4.2 tls
284 1.1.4.2 tls return (paddr_t)sc->sc_ri.ri_bits + off;
285 1.1.4.2 tls }
286 1.1.4.2 tls
287 1.1.4.2 tls static int
288 1.1.4.2 tls wmlcd_alloc_screen(void *v, const struct wsscreen_descr *scr, void **cookiep,
289 1.1.4.2 tls int *curxp, int *curyp, long *attrp)
290 1.1.4.2 tls {
291 1.1.4.2 tls printf("%s\n", __func__);
292 1.1.4.2 tls return -1;
293 1.1.4.2 tls }
294 1.1.4.2 tls
295 1.1.4.2 tls static void
296 1.1.4.2 tls wmlcd_free_screen(void *v, void *cookie)
297 1.1.4.2 tls {
298 1.1.4.2 tls printf("%s\n", __func__);
299 1.1.4.2 tls }
300 1.1.4.2 tls
301 1.1.4.2 tls static int
302 1.1.4.2 tls wmlcd_show_screen(void *v, void *cookie, int waitok,
303 1.1.4.2 tls void (*func)(void *, int, int), void *arg)
304 1.1.4.2 tls {
305 1.1.4.2 tls printf("%s\n", __func__);
306 1.1.4.2 tls return -1;
307 1.1.4.2 tls }
308 1.1.4.2 tls
309 1.1.4.2 tls int
310 1.1.4.2 tls wmlcd_cnattach(void)
311 1.1.4.2 tls {
312 1.1.4.2 tls
313 1.1.4.2 tls is_console = 1;
314 1.1.4.2 tls return 0;
315 1.1.4.2 tls }
316