wmlcd.c revision 1.3 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