fb.c revision 1.34 1 1.34 tsutsui /* $NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $ */
2 1.5 tsubai
3 1.5 tsubai /*-
4 1.5 tsubai * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
5 1.1 tsubai *
6 1.1 tsubai * Redistribution and use in source and binary forms, with or without
7 1.1 tsubai * modification, are permitted provided that the following conditions
8 1.1 tsubai * are met:
9 1.1 tsubai * 1. Redistributions of source code must retain the above copyright
10 1.1 tsubai * notice, this list of conditions and the following disclaimer.
11 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 tsubai * notice, this list of conditions and the following disclaimer in the
13 1.1 tsubai * documentation and/or other materials provided with the distribution.
14 1.5 tsubai * 3. The name of the author may not be used to endorse or promote products
15 1.5 tsubai * derived from this software without specific prior written permission.
16 1.1 tsubai *
17 1.5 tsubai * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 1.5 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 1.5 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.5 tsubai * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 1.5 tsubai * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 1.5 tsubai * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 1.5 tsubai * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 1.5 tsubai * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 1.5 tsubai * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 1.5 tsubai * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.1 tsubai */
28 1.34 tsutsui /*-
29 1.34 tsutsui * Copyright (c) 2023 Izumi Tsutsui. All rights reserved.
30 1.34 tsutsui *
31 1.34 tsutsui * Redistribution and use in source and binary forms, with or without
32 1.34 tsutsui * modification, are permitted provided that the following conditions
33 1.34 tsutsui * are met:
34 1.34 tsutsui * 1. Redistributions of source code must retain the above copyright
35 1.34 tsutsui * notice, this list of conditions and the following disclaimer.
36 1.34 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
37 1.34 tsutsui * notice, this list of conditions and the following disclaimer in the
38 1.34 tsutsui * documentation and/or other materials provided with the distribution.
39 1.34 tsutsui *
40 1.34 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
41 1.34 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42 1.34 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43 1.34 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
44 1.34 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 1.34 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
46 1.34 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
47 1.34 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
48 1.34 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
49 1.34 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 1.34 tsutsui */
51 1.17 lukem
52 1.17 lukem #include <sys/cdefs.h>
53 1.34 tsutsui __KERNEL_RCSID(0, "$NetBSD: fb.c,v 1.34 2023/11/04 15:30:52 tsutsui Exp $");
54 1.1 tsubai
55 1.1 tsubai #include <sys/param.h>
56 1.1 tsubai #include <sys/device.h>
57 1.5 tsubai #include <sys/ioctl.h>
58 1.27 thorpej #include <sys/kmem.h>
59 1.1 tsubai #include <sys/systm.h>
60 1.1 tsubai
61 1.5 tsubai #include <uvm/uvm_extern.h>
62 1.5 tsubai
63 1.5 tsubai #include <machine/adrsmap.h>
64 1.16 tsutsui
65 1.16 tsutsui #include <newsmips/dev/hbvar.h>
66 1.1 tsubai
67 1.5 tsubai #include <dev/wscons/wsconsio.h>
68 1.5 tsubai #include <dev/wscons/wsdisplayvar.h>
69 1.5 tsubai #include <dev/rasops/rasops.h>
70 1.5 tsubai
71 1.5 tsubai struct fb_devconfig {
72 1.31 tsutsui uint8_t *dc_fbbase; /* VRAM base address */
73 1.5 tsubai struct rasops_info dc_ri;
74 1.34 tsutsui int dc_model;
75 1.34 tsutsui #define NWB253 0
76 1.34 tsutsui #define LCDM 1
77 1.34 tsutsui int dc_displayid;
78 1.34 tsutsui #define NWP512 0
79 1.34 tsutsui #define NWP518 1
80 1.34 tsutsui #define NWE501 2
81 1.34 tsutsui int dc_size;
82 1.5 tsubai };
83 1.1 tsubai
84 1.1 tsubai struct fb_softc {
85 1.24 tsutsui device_t sc_dev;
86 1.5 tsubai struct fb_devconfig *sc_dc;
87 1.5 tsubai int sc_nscreens;
88 1.1 tsubai };
89 1.1 tsubai
90 1.30 tsutsui static int fb_match(device_t, cfdata_t, void *);
91 1.30 tsutsui static void fb_attach(device_t, device_t, void *);
92 1.5 tsubai
93 1.30 tsutsui static int fb_common_init(struct fb_devconfig *);
94 1.30 tsutsui static int fb_is_console(void);
95 1.5 tsubai
96 1.30 tsutsui static int fb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
97 1.30 tsutsui static paddr_t fb_mmap(void *, void *, off_t, int);
98 1.30 tsutsui static int fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
99 1.30 tsutsui int *, int *, long *);
100 1.30 tsutsui static void fb_free_screen(void *, void *);
101 1.30 tsutsui static int fb_show_screen(void *, void *, int, void (*)(void *, int, int),
102 1.30 tsutsui void *);
103 1.5 tsubai
104 1.5 tsubai void fb_cnattach(void);
105 1.5 tsubai
106 1.34 tsutsui static int fb_set_state(struct fb_softc *, int);
107 1.34 tsutsui
108 1.34 tsutsui static bool fb253_probe(void);
109 1.34 tsutsui static bool fblcdm_probe(void);
110 1.34 tsutsui static bool fb_probe_model(struct fb_devconfig *);
111 1.34 tsutsui static void fb_init(struct fb_devconfig *);
112 1.9 matt static void fb253_init(void);
113 1.34 tsutsui static void fblcdm_init(void);
114 1.1 tsubai
115 1.24 tsutsui CFATTACH_DECL_NEW(fb, sizeof(struct fb_softc),
116 1.14 thorpej fb_match, fb_attach, NULL, NULL);
117 1.5 tsubai
118 1.30 tsutsui static struct fb_devconfig fb_console_dc;
119 1.5 tsubai
120 1.30 tsutsui static struct wsdisplay_accessops fb_accessops = {
121 1.32 tsutsui .ioctl = fb_ioctl,
122 1.32 tsutsui .mmap = fb_mmap,
123 1.32 tsutsui .alloc_screen = fb_alloc_screen,
124 1.32 tsutsui .free_screen = fb_free_screen,
125 1.32 tsutsui .show_screen = fb_show_screen,
126 1.32 tsutsui .load_font = NULL
127 1.5 tsubai };
128 1.5 tsubai
129 1.30 tsutsui static struct wsscreen_descr fb_stdscreen = {
130 1.32 tsutsui .name = "std",
131 1.32 tsutsui .ncols = 0,
132 1.32 tsutsui .nrows = 0,
133 1.32 tsutsui .textops = NULL,
134 1.32 tsutsui .fontwidth = 0,
135 1.32 tsutsui .fontheight = 0,
136 1.32 tsutsui .capabilities = WSSCREEN_REVERSE
137 1.1 tsubai };
138 1.1 tsubai
139 1.30 tsutsui static const struct wsscreen_descr *fb_scrlist[] = {
140 1.5 tsubai &fb_stdscreen
141 1.5 tsubai };
142 1.5 tsubai
143 1.30 tsutsui static struct wsscreen_list fb_screenlist = {
144 1.32 tsutsui .nscreens = __arraycount(fb_scrlist),
145 1.32 tsutsui .screens = fb_scrlist
146 1.5 tsubai };
147 1.1 tsubai
148 1.34 tsutsui #define NWB253_VRAM 0x88000000
149 1.24 tsutsui #define NWB253_CTLREG ((uint16_t *)0xb8ff0000)
150 1.24 tsutsui #define NWB253_CRTREG ((uint16_t *)0xb8fe0000)
151 1.1 tsubai
152 1.34 tsutsui static const char *nwb253dispname[8] = {
153 1.34 tsutsui [NWP512] = "NWB-512",
154 1.34 tsutsui [NWP518] = "NWB-518",
155 1.34 tsutsui [NWE501] = "NWE-501"
156 1.34 tsutsui }; /* XXX ? */
157 1.34 tsutsui
158 1.34 tsutsui #define LCDM_VRAM 0x90200000
159 1.34 tsutsui #define LCDM_PORT ((uint32_t *)0xb0000000)
160 1.34 tsutsui #define LCDM_DIMMER ((uint32_t *)0xb0100000)
161 1.34 tsutsui #define LCDM_DIMMER_ON 0xf0
162 1.34 tsutsui #define LCDM_DIMMER_OFF 0xf1
163 1.34 tsutsui #define LCDM_CTRL ((uint8_t *)0xbff50000) /* XXX no macro in 4.4BSD */
164 1.34 tsutsui #define LCDM_CRTC ((uint8_t *)0xbff60000)
165 1.5 tsubai
166 1.30 tsutsui static int
167 1.24 tsutsui fb_match(device_t parent, cfdata_t cf, void *aux)
168 1.1 tsubai {
169 1.16 tsutsui struct hb_attach_args *ha = aux;
170 1.1 tsubai
171 1.16 tsutsui if (strcmp(ha->ha_name, "fb") != 0)
172 1.1 tsubai return 0;
173 1.1 tsubai
174 1.34 tsutsui if (fb253_probe() && ha->ha_addr == NWB253_VRAM)
175 1.34 tsutsui return 1;
176 1.34 tsutsui if (fblcdm_probe() && ha->ha_addr == LCDM_VRAM)
177 1.34 tsutsui return 1;
178 1.1 tsubai
179 1.34 tsutsui return 0;
180 1.1 tsubai }
181 1.1 tsubai
182 1.30 tsutsui static void
183 1.24 tsutsui fb_attach(device_t parent, device_t self, void *aux)
184 1.1 tsubai {
185 1.24 tsutsui struct fb_softc *sc = device_private(self);
186 1.5 tsubai struct wsemuldisplaydev_attach_args waa;
187 1.5 tsubai struct fb_devconfig *dc;
188 1.5 tsubai struct rasops_info *ri;
189 1.5 tsubai int console;
190 1.34 tsutsui const char *devname;
191 1.5 tsubai
192 1.24 tsutsui sc->sc_dev = self;
193 1.24 tsutsui
194 1.5 tsubai console = fb_is_console();
195 1.5 tsubai
196 1.5 tsubai if (console) {
197 1.5 tsubai dc = &fb_console_dc;
198 1.5 tsubai ri = &dc->dc_ri;
199 1.25 tsutsui ri->ri_flg &= ~RI_NO_AUTO;
200 1.5 tsubai sc->sc_nscreens = 1;
201 1.5 tsubai } else {
202 1.27 thorpej dc = kmem_zalloc(sizeof(struct fb_devconfig), KM_SLEEP);
203 1.5 tsubai
204 1.34 tsutsui fb_probe_model(dc);
205 1.5 tsubai fb_common_init(dc);
206 1.5 tsubai ri = &dc->dc_ri;
207 1.5 tsubai
208 1.5 tsubai /* clear screen */
209 1.5 tsubai (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0);
210 1.5 tsubai
211 1.34 tsutsui fb_init(dc);
212 1.5 tsubai }
213 1.5 tsubai sc->sc_dc = dc;
214 1.5 tsubai
215 1.34 tsutsui switch (dc->dc_model) {
216 1.34 tsutsui case NWB253:
217 1.34 tsutsui devname = nwb253dispname[dc->dc_displayid];
218 1.34 tsutsui break;
219 1.34 tsutsui case LCDM:
220 1.34 tsutsui devname = "LCD-MONO";
221 1.34 tsutsui break;
222 1.34 tsutsui default:
223 1.34 tsutsui /* should not be here */
224 1.34 tsutsui devname = "unknown";
225 1.34 tsutsui break;
226 1.34 tsutsui }
227 1.34 tsutsui aprint_normal(": %s, %d x %d, %dbpp\n", devname,
228 1.5 tsubai ri->ri_width, ri->ri_height, ri->ri_depth);
229 1.5 tsubai
230 1.5 tsubai waa.console = console;
231 1.5 tsubai waa.scrdata = &fb_screenlist;
232 1.5 tsubai waa.accessops = &fb_accessops;
233 1.5 tsubai waa.accesscookie = sc;
234 1.1 tsubai
235 1.29 thorpej config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
236 1.1 tsubai }
237 1.1 tsubai
238 1.34 tsutsui static bool
239 1.34 tsutsui fb253_probe(void)
240 1.34 tsutsui {
241 1.34 tsutsui
242 1.34 tsutsui if (hb_badaddr(NWB253_CTLREG, 2) || hb_badaddr(NWB253_CRTREG, 2))
243 1.34 tsutsui return false;
244 1.34 tsutsui if ((*(volatile uint16_t *)NWB253_CTLREG & 7) != 4)
245 1.34 tsutsui return false;
246 1.34 tsutsui
247 1.34 tsutsui return true;
248 1.34 tsutsui }
249 1.34 tsutsui
250 1.34 tsutsui static bool
251 1.34 tsutsui fblcdm_probe(void)
252 1.34 tsutsui {
253 1.34 tsutsui
254 1.34 tsutsui if (hb_badaddr(LCDM_CTRL, 1))
255 1.34 tsutsui return false;
256 1.34 tsutsui if (*(volatile uint8_t *)LCDM_CTRL != 0xff)
257 1.34 tsutsui return false;
258 1.34 tsutsui
259 1.34 tsutsui return true;
260 1.34 tsutsui }
261 1.34 tsutsui
262 1.34 tsutsui static bool
263 1.34 tsutsui fb_probe_model(struct fb_devconfig *dc)
264 1.34 tsutsui {
265 1.34 tsutsui
266 1.34 tsutsui if (fb253_probe()) {
267 1.34 tsutsui volatile uint16_t *ctlreg = NWB253_CTLREG;
268 1.34 tsutsui
269 1.34 tsutsui dc->dc_model = NWB253;
270 1.34 tsutsui dc->dc_displayid = (*ctlreg >> 8) & 0xf;
271 1.34 tsutsui return true;
272 1.34 tsutsui }
273 1.34 tsutsui if (fblcdm_probe()) {
274 1.34 tsutsui dc->dc_model = LCDM;
275 1.34 tsutsui dc->dc_displayid = 0; /* no variant */
276 1.34 tsutsui return true;
277 1.34 tsutsui }
278 1.34 tsutsui
279 1.34 tsutsui return false;
280 1.34 tsutsui }
281 1.34 tsutsui
282 1.30 tsutsui static int
283 1.19 tsutsui fb_common_init(struct fb_devconfig *dc)
284 1.1 tsubai {
285 1.5 tsubai struct rasops_info *ri = &dc->dc_ri;
286 1.34 tsutsui int width, height, stride, xoff, yoff, cols, rows;
287 1.5 tsubai
288 1.34 tsutsui switch (dc->dc_model) {
289 1.34 tsutsui case NWB253:
290 1.34 tsutsui dc->dc_fbbase = (uint8_t *)NWB253_VRAM;
291 1.34 tsutsui
292 1.34 tsutsui switch (dc->dc_displayid) {
293 1.34 tsutsui case NWP512:
294 1.34 tsutsui width = 816;
295 1.34 tsutsui height = 1024;
296 1.34 tsutsui break;
297 1.34 tsutsui case NWP518:
298 1.34 tsutsui case NWE501:
299 1.34 tsutsui default:
300 1.34 tsutsui width = 1024;
301 1.34 tsutsui height = 768;
302 1.34 tsutsui break;
303 1.34 tsutsui }
304 1.34 tsutsui stride = 2048 / 8;
305 1.34 tsutsui dc->dc_size = stride * 2048;
306 1.34 tsutsui break;
307 1.5 tsubai
308 1.34 tsutsui case LCDM:
309 1.34 tsutsui dc->dc_fbbase = (uint8_t *)LCDM_VRAM;
310 1.34 tsutsui width = 1120;
311 1.34 tsutsui height = 780;
312 1.34 tsutsui stride = width / 8;
313 1.34 tsutsui dc->dc_size = stride * height;
314 1.5 tsubai break;
315 1.34 tsutsui
316 1.18 dsl default:
317 1.34 tsutsui panic("fb: no valid framebuffer");
318 1.1 tsubai }
319 1.1 tsubai
320 1.34 tsutsui /* initialize rasops */
321 1.34 tsutsui
322 1.5 tsubai ri->ri_width = width;
323 1.5 tsubai ri->ri_height = height;
324 1.5 tsubai ri->ri_depth = 1;
325 1.34 tsutsui ri->ri_stride = stride;
326 1.5 tsubai ri->ri_bits = dc->dc_fbbase;
327 1.5 tsubai ri->ri_flg = RI_FULLCLEAR;
328 1.25 tsutsui if (dc == &fb_console_dc)
329 1.25 tsutsui ri->ri_flg |= RI_NO_AUTO;
330 1.5 tsubai
331 1.5 tsubai rasops_init(ri, 24, 80);
332 1.5 tsubai rows = (height - 2) / ri->ri_font->fontheight;
333 1.5 tsubai cols = ((width - 2) / ri->ri_font->fontwidth) & ~7;
334 1.5 tsubai xoff = ((width - cols * ri->ri_font->fontwidth) / 2 / 8) & ~3;
335 1.5 tsubai yoff = (height - rows * ri->ri_font->fontheight) / 2;
336 1.5 tsubai rasops_reconfig(ri, rows, cols);
337 1.15 tsutsui
338 1.5 tsubai ri->ri_xorigin = xoff;
339 1.5 tsubai ri->ri_yorigin = yoff;
340 1.5 tsubai ri->ri_bits = dc->dc_fbbase + xoff + ri->ri_stride * yoff;
341 1.15 tsutsui
342 1.5 tsubai fb_stdscreen.nrows = ri->ri_rows;
343 1.33 tsutsui fb_stdscreen.ncols = ri->ri_cols;
344 1.5 tsubai fb_stdscreen.textops = &ri->ri_ops;
345 1.5 tsubai fb_stdscreen.capabilities = ri->ri_caps;
346 1.1 tsubai
347 1.1 tsubai return 0;
348 1.1 tsubai }
349 1.1 tsubai
350 1.30 tsutsui static int
351 1.19 tsutsui fb_is_console(void)
352 1.1 tsubai {
353 1.5 tsubai volatile u_int *dipsw = (void *)DIP_SWITCH;
354 1.1 tsubai
355 1.5 tsubai if (*dipsw & 7) /* XXX right? */
356 1.5 tsubai return 1;
357 1.1 tsubai
358 1.1 tsubai return 0;
359 1.1 tsubai }
360 1.1 tsubai
361 1.30 tsutsui static int
362 1.23 christos fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
363 1.1 tsubai {
364 1.5 tsubai struct fb_softc *sc = v;
365 1.5 tsubai struct fb_devconfig *dc = sc->sc_dc;
366 1.5 tsubai struct wsdisplay_fbinfo *wdf;
367 1.1 tsubai
368 1.5 tsubai switch (cmd) {
369 1.5 tsubai case WSDISPLAYIO_GTYPE:
370 1.5 tsubai *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */
371 1.5 tsubai return 0;
372 1.1 tsubai
373 1.5 tsubai case WSDISPLAYIO_GINFO:
374 1.5 tsubai wdf = (void *)data;
375 1.5 tsubai wdf->height = dc->dc_ri.ri_height;
376 1.5 tsubai wdf->width = dc->dc_ri.ri_width;
377 1.5 tsubai wdf->depth = dc->dc_ri.ri_depth;
378 1.34 tsutsui wdf->cmsize = 0;
379 1.5 tsubai return 0;
380 1.1 tsubai
381 1.26 tsutsui case WSDISPLAYIO_LINEBYTES:
382 1.26 tsutsui *(u_int *)data = dc->dc_ri.ri_stride;
383 1.26 tsutsui return 0;
384 1.26 tsutsui
385 1.5 tsubai case WSDISPLAYIO_SVIDEO:
386 1.34 tsutsui return fb_set_state(sc, *(int *)data);
387 1.1 tsubai
388 1.5 tsubai case WSDISPLAYIO_GETCMAP:
389 1.5 tsubai case WSDISPLAYIO_PUTCMAP:
390 1.11 thorpej break;
391 1.1 tsubai }
392 1.10 atatat return EPASSTHROUGH;
393 1.1 tsubai }
394 1.1 tsubai
395 1.34 tsutsui static int
396 1.34 tsutsui fb_set_state(struct fb_softc *sc, int state)
397 1.34 tsutsui {
398 1.34 tsutsui struct fb_devconfig *dc = sc->sc_dc;
399 1.34 tsutsui volatile uint16_t *ctlreg;
400 1.34 tsutsui volatile uint32_t *dimmerreg;
401 1.34 tsutsui
402 1.34 tsutsui if (state != WSDISPLAYIO_VIDEO_OFF && state != WSDISPLAYIO_VIDEO_ON)
403 1.34 tsutsui return EINVAL;
404 1.34 tsutsui
405 1.34 tsutsui switch (dc->dc_model) {
406 1.34 tsutsui case NWB253:
407 1.34 tsutsui if (state == WSDISPLAYIO_VIDEO_OFF) {
408 1.34 tsutsui ctlreg = NWB253_CTLREG;
409 1.34 tsutsui *ctlreg = 0; /* stop crtc */
410 1.34 tsutsui } else {
411 1.34 tsutsui fb253_init();
412 1.34 tsutsui }
413 1.34 tsutsui break;
414 1.34 tsutsui case LCDM:
415 1.34 tsutsui dimmerreg = LCDM_DIMMER;
416 1.34 tsutsui if (state == WSDISPLAYIO_VIDEO_OFF) {
417 1.34 tsutsui *dimmerreg = LCDM_DIMMER_OFF;
418 1.34 tsutsui } else {
419 1.34 tsutsui *dimmerreg = LCDM_DIMMER_ON;
420 1.34 tsutsui }
421 1.34 tsutsui break;
422 1.34 tsutsui default:
423 1.34 tsutsui /* should not be here */
424 1.34 tsutsui break;
425 1.34 tsutsui }
426 1.34 tsutsui return 0;
427 1.34 tsutsui }
428 1.34 tsutsui
429 1.30 tsutsui static paddr_t
430 1.22 jmmv fb_mmap(void *v, void *vs, off_t offset, int prot)
431 1.1 tsubai {
432 1.5 tsubai struct fb_softc *sc = v;
433 1.5 tsubai struct fb_devconfig *dc = sc->sc_dc;
434 1.1 tsubai
435 1.34 tsutsui if (offset >= dc->dc_size || offset < 0)
436 1.1 tsubai return -1;
437 1.1 tsubai
438 1.5 tsubai return mips_btop((int)dc->dc_fbbase + offset);
439 1.5 tsubai }
440 1.1 tsubai
441 1.30 tsutsui static int
442 1.19 tsutsui fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep,
443 1.19 tsutsui int *ccolp, int *crowp, long *attrp)
444 1.5 tsubai {
445 1.5 tsubai struct fb_softc *sc = v;
446 1.5 tsubai struct rasops_info *ri = &sc->sc_dc->dc_ri;
447 1.5 tsubai long defattr;
448 1.5 tsubai
449 1.5 tsubai if (sc->sc_nscreens > 0)
450 1.5 tsubai return ENOMEM;
451 1.5 tsubai
452 1.5 tsubai *cookiep = ri;
453 1.5 tsubai *ccolp = *crowp = 0;
454 1.12 junyoung (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
455 1.5 tsubai *attrp = defattr;
456 1.5 tsubai sc->sc_nscreens++;
457 1.1 tsubai
458 1.5 tsubai return 0;
459 1.1 tsubai }
460 1.1 tsubai
461 1.30 tsutsui static void
462 1.19 tsutsui fb_free_screen(void *v, void *cookie)
463 1.1 tsubai {
464 1.5 tsubai struct fb_softc *sc = v;
465 1.5 tsubai
466 1.5 tsubai if (sc->sc_dc == &fb_console_dc)
467 1.24 tsutsui panic("%s: console", __func__);
468 1.5 tsubai
469 1.5 tsubai sc->sc_nscreens--;
470 1.1 tsubai }
471 1.1 tsubai
472 1.30 tsutsui static int
473 1.19 tsutsui fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
474 1.19 tsutsui void *cbarg)
475 1.1 tsubai {
476 1.19 tsutsui
477 1.5 tsubai return 0;
478 1.1 tsubai }
479 1.1 tsubai
480 1.5 tsubai void
481 1.19 tsutsui fb_cnattach(void)
482 1.1 tsubai {
483 1.5 tsubai struct fb_devconfig *dc = &fb_console_dc;
484 1.5 tsubai struct rasops_info *ri = &dc->dc_ri;
485 1.5 tsubai long defattr;
486 1.5 tsubai
487 1.5 tsubai if (!fb_is_console())
488 1.5 tsubai return;
489 1.5 tsubai
490 1.34 tsutsui if (!fb_probe_model(dc))
491 1.34 tsutsui return;
492 1.34 tsutsui
493 1.5 tsubai fb_common_init(dc);
494 1.34 tsutsui fb_init(dc);
495 1.34 tsutsui
496 1.34 tsutsui /*
497 1.34 tsutsui * Wait CRTC output or LCD backlight become settled
498 1.34 tsutsui * before starting to print kernel greeting messages.
499 1.34 tsutsui */
500 1.34 tsutsui delay(500 * 1000);
501 1.5 tsubai
502 1.12 junyoung (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
503 1.5 tsubai wsdisplay_cnattach(&fb_stdscreen, ri, 0, ri->ri_rows - 1, defattr);
504 1.5 tsubai }
505 1.5 tsubai
506 1.34 tsutsui static void
507 1.34 tsutsui fb_init(struct fb_devconfig *dc)
508 1.34 tsutsui {
509 1.34 tsutsui
510 1.34 tsutsui switch (dc->dc_model) {
511 1.34 tsutsui case NWB253:
512 1.34 tsutsui fb253_init();
513 1.34 tsutsui break;
514 1.34 tsutsui case LCDM:
515 1.34 tsutsui fblcdm_init();
516 1.34 tsutsui break;
517 1.34 tsutsui default:
518 1.34 tsutsui /* should not be here */
519 1.34 tsutsui break;
520 1.34 tsutsui }
521 1.34 tsutsui }
522 1.34 tsutsui
523 1.19 tsutsui static const uint8_t
524 1.5 tsubai nwp512_data1[] = {
525 1.5 tsubai 0x00, 0x44,
526 1.5 tsubai 0x01, 0x33,
527 1.5 tsubai 0x02, 0x3c,
528 1.5 tsubai 0x03, 0x38,
529 1.5 tsubai 0x04, 0x84,
530 1.5 tsubai 0x05, 0x03,
531 1.5 tsubai 0x06, 0x80,
532 1.5 tsubai 0x07, 0x80,
533 1.5 tsubai 0x08, 0x10,
534 1.5 tsubai 0x09, 0x07,
535 1.5 tsubai 0x0a, 0x20,
536 1.5 tsubai 0x0c, 0x00,
537 1.5 tsubai 0x0d, 0x00,
538 1.5 tsubai 0x1b, 0x03
539 1.5 tsubai };
540 1.1 tsubai
541 1.19 tsutsui static const uint8_t
542 1.5 tsubai nwp512_data2[] = {
543 1.5 tsubai 0x1e, 0x08,
544 1.5 tsubai 0x20, 0x08,
545 1.5 tsubai 0x21, 0x0d
546 1.5 tsubai };
547 1.1 tsubai
548 1.19 tsutsui static const uint8_t
549 1.5 tsubai nwp518_data1[] = {
550 1.5 tsubai 0x00, 0x52,
551 1.5 tsubai 0x01, 0x40,
552 1.5 tsubai 0x02, 0x4a,
553 1.5 tsubai 0x03, 0x49,
554 1.5 tsubai 0x04, 0x63,
555 1.5 tsubai 0x05, 0x02,
556 1.5 tsubai 0x06, 0x60,
557 1.5 tsubai 0x07, 0x60,
558 1.5 tsubai 0x08, 0x10,
559 1.5 tsubai 0x09, 0x07,
560 1.5 tsubai 0x0a, 0x20,
561 1.5 tsubai 0x0c, 0x00,
562 1.5 tsubai 0x0d, 0x00,
563 1.5 tsubai 0x1b, 0x04
564 1.5 tsubai };
565 1.1 tsubai
566 1.19 tsutsui static const uint8_t
567 1.5 tsubai nwp518_data2[] = {
568 1.5 tsubai 0x1e, 0x08,
569 1.5 tsubai 0x20, 0x00,
570 1.5 tsubai 0x21, 0x00
571 1.5 tsubai };
572 1.1 tsubai
573 1.19 tsutsui static const uint8_t
574 1.5 tsubai nwe501_data1[] = {
575 1.5 tsubai 0x00, 0x4b,
576 1.5 tsubai 0x01, 0x40,
577 1.5 tsubai 0x02, 0x4a,
578 1.5 tsubai 0x03, 0x43,
579 1.5 tsubai 0x04, 0x64,
580 1.5 tsubai 0x05, 0x02,
581 1.5 tsubai 0x06, 0x60,
582 1.5 tsubai 0x07, 0x60,
583 1.5 tsubai 0x08, 0x10,
584 1.5 tsubai 0x09, 0x07,
585 1.5 tsubai 0x0a, 0x20,
586 1.5 tsubai 0x0c, 0x00,
587 1.5 tsubai 0x0d, 0x00,
588 1.5 tsubai 0x1b, 0x04
589 1.5 tsubai };
590 1.1 tsubai
591 1.19 tsutsui static const uint8_t
592 1.5 tsubai nwe501_data2[] = {
593 1.5 tsubai 0x1e, 0x08,
594 1.5 tsubai 0x20, 0x00,
595 1.5 tsubai 0x21, 0x00
596 1.5 tsubai };
597 1.1 tsubai
598 1.19 tsutsui static const uint8_t
599 1.5 tsubai *crtc_data[3][2] = {
600 1.5 tsubai { nwp512_data1, nwp512_data2 },
601 1.5 tsubai { nwp518_data1, nwp518_data2 },
602 1.5 tsubai { nwe501_data1, nwe501_data2 }
603 1.5 tsubai };
604 1.1 tsubai
605 1.1 tsubai static void
606 1.9 matt fb253_init(void)
607 1.1 tsubai {
608 1.24 tsutsui volatile uint16_t *ctlreg = NWB253_CTLREG;
609 1.24 tsutsui volatile uint16_t *crtreg = NWB253_CRTREG;
610 1.8 tsubai int id = (*ctlreg >> 8) & 0xf;
611 1.19 tsutsui const uint8_t *p;
612 1.5 tsubai int i;
613 1.5 tsubai
614 1.5 tsubai *ctlreg = 0; /* stop crtc */
615 1.5 tsubai delay(10);
616 1.5 tsubai
617 1.5 tsubai /* initialize crtc without R3{0,1,2} */
618 1.5 tsubai p = crtc_data[id][0];
619 1.5 tsubai for (i = 0; i < 28; i++) {
620 1.5 tsubai *crtreg++ = *p++;
621 1.5 tsubai delay(10);
622 1.5 tsubai }
623 1.5 tsubai
624 1.5 tsubai *ctlreg = 0x02; /* start crtc */
625 1.5 tsubai delay(10);
626 1.5 tsubai
627 1.5 tsubai /* set crtc control reg */
628 1.5 tsubai p = crtc_data[id][1];
629 1.5 tsubai for (i = 0; i < 6; i++) {
630 1.5 tsubai *crtreg++ = *p++;
631 1.5 tsubai delay(10);
632 1.5 tsubai }
633 1.5 tsubai }
634 1.5 tsubai
635 1.34 tsutsui static const uint8_t lcdcrtc_data[] = {
636 1.34 tsutsui 0, 47,
637 1.34 tsutsui 1, 35,
638 1.34 tsutsui 9, 0,
639 1.34 tsutsui 10, 0,
640 1.34 tsutsui 11, 0,
641 1.34 tsutsui 12, 0,
642 1.34 tsutsui 13, 0,
643 1.34 tsutsui 14, 0,
644 1.34 tsutsui 15, 0,
645 1.34 tsutsui 18, 35,
646 1.34 tsutsui 19, 0x01,
647 1.34 tsutsui 20, 0x85,
648 1.34 tsutsui 21, 0,
649 1.34 tsutsui 22, 0x10
650 1.34 tsutsui };
651 1.34 tsutsui
652 1.34 tsutsui static void
653 1.34 tsutsui fblcdm_init(void)
654 1.34 tsutsui {
655 1.34 tsutsui volatile uint8_t *crtcreg = LCDM_CRTC;
656 1.34 tsutsui volatile uint32_t *portreg = LCDM_PORT;
657 1.34 tsutsui volatile uint32_t *dimmerreg = LCDM_DIMMER;
658 1.34 tsutsui int i;
659 1.34 tsutsui
660 1.34 tsutsui /* initialize crtc */
661 1.34 tsutsui for (i = 0; i < 28; i++) {
662 1.34 tsutsui *crtcreg++ = lcdcrtc_data[i];
663 1.34 tsutsui delay(10);
664 1.34 tsutsui }
665 1.34 tsutsui
666 1.34 tsutsui delay(1000);
667 1.34 tsutsui *portreg = 1;
668 1.34 tsutsui *dimmerreg = LCDM_DIMMER_ON;
669 1.34 tsutsui }
670 1.34 tsutsui
671 1.5 tsubai #if 0
672 1.5 tsubai static struct wsdisplay_font newsrom8x16;
673 1.5 tsubai static struct wsdisplay_font newsrom12x24;
674 1.31 tsutsui static uint8_t fontarea16[96][32];
675 1.31 tsutsui static uint8_t fontarea24[96][96];
676 1.5 tsubai
677 1.5 tsubai void
678 1.19 tsutsui initfont(struct rasops_info *ri)
679 1.5 tsubai {
680 1.5 tsubai int c, x;
681 1.5 tsubai
682 1.5 tsubai for (c = 0; c < 96; c++) {
683 1.5 tsubai x = ((c & 0x1f) | ((c & 0xe0) << 2)) << 7;
684 1.31 tsutsui memcpy(fontarea16 + c, (uint8_t *)0xb8e00000 + x + 96, 32);
685 1.31 tsutsui memcpy(fontarea24 + c, (uint8_t *)0xb8e00000 + x, 96);
686 1.33 tsutsui }
687 1.5 tsubai
688 1.5 tsubai newsrom8x16.name = "rom8x16";
689 1.5 tsubai newsrom8x16.firstchar = 32;
690 1.5 tsubai newsrom8x16.numchars = 96;
691 1.5 tsubai newsrom8x16.encoding = WSDISPLAY_FONTENC_ISO;
692 1.5 tsubai newsrom8x16.fontwidth = 8;
693 1.5 tsubai newsrom8x16.fontheight = 16;
694 1.5 tsubai newsrom8x16.stride = 2;
695 1.5 tsubai newsrom8x16.bitorder = WSDISPLAY_FONTORDER_L2R;
696 1.5 tsubai newsrom8x16.byteorder = WSDISPLAY_FONTORDER_L2R;
697 1.5 tsubai newsrom8x16.data = fontarea16;
698 1.5 tsubai
699 1.5 tsubai newsrom12x24.name = "rom12x24";
700 1.5 tsubai newsrom12x24.firstchar = 32;
701 1.5 tsubai newsrom12x24.numchars = 96;
702 1.5 tsubai newsrom12x24.encoding = WSDISPLAY_FONTENC_ISO;
703 1.5 tsubai newsrom12x24.fontwidth = 12;
704 1.5 tsubai newsrom12x24.fontheight = 24;
705 1.5 tsubai newsrom12x24.stride = 4;
706 1.5 tsubai newsrom12x24.bitorder = WSDISPLAY_FONTORDER_L2R;
707 1.5 tsubai newsrom12x24.byteorder = WSDISPLAY_FONTORDER_L2R;
708 1.5 tsubai newsrom12x24.data = fontarea24;
709 1.5 tsubai
710 1.5 tsubai ri->ri_font = &newsrom8x16;
711 1.5 tsubai ri->ri_font = &newsrom12x24;
712 1.5 tsubai ri->ri_wsfcookie = -1; /* not using wsfont */
713 1.1 tsubai }
714 1.5 tsubai #endif
715