hyperfb.c revision 1.1 1 /* $NetBSD: hyperfb.c,v 1.1 2024/07/12 08:43:08 macallan Exp $ */
2
3 /*
4 * Copyright (c) 2024 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * a native driver for HCRX / hyperdrive cards
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.1 2024/07/12 08:43:08 macallan Exp $");
35
36 #include "opt_cputype.h"
37 #include "opt_hyperfb.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42
43 #include <sys/bus.h>
44 #include <machine/cpu.h>
45 #include <machine/iomod.h>
46 #include <machine/autoconf.h>
47
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wsfont/wsfont.h>
51 #include <dev/rasops/rasops.h>
52 #include <dev/wscons/wsdisplay_vconsvar.h>
53 #include <dev/wscons/wsdisplay_glyphcachevar.h>
54
55 #include <dev/ic/stireg.h>
56 #include <dev/ic/stivar.h>
57
58 #include <hppa/dev/cpudevs.h>
59 #include <hppa/hppa/machdep.h>
60
61 #ifdef HYPERFB_DEBUG
62 #define DPRINTF printf
63 #else
64 #define DPRINTF if (0) printf
65 #endif
66
67 #define STI_ROMSIZE (sizeof(struct sti_dd) * 4)
68
69 #define HCRX_FBOFFSET 0x01000000
70 #define HCRX_FBLEN 0x01000000
71 #define HCRX_REGOFFSET 0x00100000
72 #define HCRX_REGLEN 0x00280000
73
74 #define HCRX_CONFIG_24BIT 0x100
75
76 #define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES 4
77 #define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE 8
78 #define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE 10
79 #define HYPERBOWL_MODE2_8_24 15
80
81 int hyperfb_match(device_t, cfdata_t, void *);
82 void hyperfb_attach(device_t, device_t, void *);
83
84 struct hyperfb_softc {
85 device_t sc_dev;
86 bus_space_tag_t sc_iot;
87 bus_addr_t sc_base;
88 bus_space_handle_t sc_hfb, sc_hreg;
89 void *sc_fb;
90
91 int sc_width, sc_height;
92 int sc_locked, sc_is_console, sc_24bit;
93 struct vcons_screen sc_console_screen;
94 struct wsscreen_descr sc_defaultscreen_descr;
95 const struct wsscreen_descr *sc_screens[1];
96 struct wsscreen_list sc_screenlist;
97 struct vcons_data vd;
98 int sc_mode;
99 void (*sc_putchar)(void *, int, int, u_int, long);
100 u_char sc_cmap_red[256];
101 u_char sc_cmap_green[256];
102 u_char sc_cmap_blue[256];
103 kmutex_t sc_hwlock;
104 uint32_t sc_hwmode;
105 #define HW_FB 0
106 #define HW_FILL 1
107 #define HW_BLIT 2
108 uint32_t sc_rect_colour, sc_rect_height;
109 /* cursor stuff */
110 int sc_cursor_x, sc_cursor_y;
111 int sc_hot_x, sc_hot_y, sc_enabled;
112 int sc_video_on;
113 glyphcache sc_gc;
114 };
115
116 extern struct cfdriver hyperfb_cd;
117
118 CFATTACH_DECL_NEW(hyperfb, sizeof(struct hyperfb_softc), hyperfb_match,
119 hyperfb_attach, NULL, NULL);
120
121 void hyperfb_setup_fb(struct hyperfb_softc *);
122 static void hyperfb_init_screen(void *, struct vcons_screen *,
123 int, long *);
124 static int hyperfb_ioctl(void *, void *, u_long, void *, int,
125 struct lwp *);
126 static paddr_t hyperfb_mmap(void *, void *, off_t, int);
127
128 static int hyperfb_putcmap(struct hyperfb_softc *, struct wsdisplay_cmap *);
129 static int hyperfb_getcmap(struct hyperfb_softc *, struct wsdisplay_cmap *);
130 static void hyperfb_restore_palette(struct hyperfb_softc *);
131 static int hyperfb_putpalreg(struct hyperfb_softc *, uint8_t, uint8_t,
132 uint8_t, uint8_t);
133 void hyperfb_setup(struct hyperfb_softc *);
134 static void hyperfb_set_video(struct hyperfb_softc *, int);
135
136 #define ngle_bt458_write(sc, r, v) \
137 hyperfb_write4(sc, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
138
139 struct wsdisplay_accessops hyperfb_accessops = {
140 hyperfb_ioctl,
141 hyperfb_mmap,
142 NULL, /* alloc_screen */
143 NULL, /* free_screen */
144 NULL, /* show_screen */
145 NULL, /* load_font */
146 NULL, /* pollc */
147 NULL /* scroll */
148 };
149
150 static inline uint32_t
151 hyperfb_read4(struct hyperfb_softc *sc, uint32_t offset)
152 {
153 return bus_space_read_4(sc->sc_iot, sc->sc_hreg, offset);
154 }
155
156 static inline uint8_t
157 hyperfb_read1(struct hyperfb_softc *sc, uint32_t offset)
158 {
159 return bus_space_read_1(sc->sc_iot, sc->sc_hreg, offset);
160 }
161
162 static inline void
163 hyperfb_write4(struct hyperfb_softc *sc, uint32_t offset, uint32_t val)
164 {
165 bus_space_write_4(sc->sc_iot, sc->sc_hreg, offset, val);
166 }
167
168 static inline void
169 hyperfb_write1(struct hyperfb_softc *sc, uint32_t offset, uint8_t val)
170 {
171 bus_space_write_1(sc->sc_iot, sc->sc_hreg, offset, val);
172 }
173
174 static inline void
175 hyperfb_wait(struct hyperfb_softc *sc)
176 {
177 uint8_t stat;
178
179 do {
180 stat = hyperfb_read1(sc, NGLE_REG_15b0);
181 if (stat == 0)
182 stat = hyperfb_read1(sc, NGLE_REG_15b0);
183 } while (stat != 0);
184 }
185
186 void
187 hyperfb_setup_fb(struct hyperfb_softc *sc)
188 {
189
190 hyperfb_wait(sc);
191 hyperfb_write4(sc, NGLE_REG_10, 0x13602000); /* 8bit */
192 hyperfb_write4(sc, NGLE_REG_14, 0x83000300);
193 hyperfb_wait(sc);
194 hyperfb_write1(sc, NGLE_REG_16b1, 1);
195 sc->sc_hwmode = HW_FB;
196 }
197
198 int
199 hyperfb_match(device_t parent, cfdata_t cf, void *aux)
200 {
201 struct confargs *ca = aux;
202 bus_space_handle_t romh;
203 paddr_t rom;
204 uint32_t id = 0;
205 u_char devtype;
206 int rv = 0, romunmapped = 0;
207
208 if (ca->ca_type.iodc_type != HPPA_TYPE_FIO)
209 return 0;
210
211 /* these need further checking for the graphics id */
212 if (ca->ca_type.iodc_sv_model != HPPA_FIO_GSGC &&
213 ca->ca_type.iodc_sv_model != HPPA_FIO_SGC)
214 return 0;
215
216 if (ca->ca_naddrs > 0)
217 rom = ca->ca_addrs[0].addr;
218 else
219 rom = ca->ca_hpa;
220
221 DPRINTF("%s: hpa=%x, rom=%x\n", __func__, (uint)ca->ca_hpa,
222 (uint)rom);
223
224 /* if it does not map, probably part of the lasi space */
225 if (bus_space_map(ca->ca_iot, rom, STI_ROMSIZE, 0, &romh)) {
226 DPRINTF("%s: can't map rom space (%d)\n", __func__, rv);
227
228 if ((rom & HPPA_IOBEGIN) == HPPA_IOBEGIN) {
229 romh = rom;
230 romunmapped++;
231 } else {
232 /* in this case nobody has no freaking idea */
233 return 0;
234 }
235 }
236
237 devtype = bus_space_read_1(ca->ca_iot, romh, 3);
238 DPRINTF("%s: devtype=%d\n", __func__, devtype);
239 rv = 1;
240 switch (devtype) {
241 case STI_DEVTYPE4:
242 id = bus_space_read_4(ca->ca_iot, romh, STI_DEV4_DD_GRID);
243 break;
244 case STI_DEVTYPE1:
245 id = (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
246 + 3) << 24) |
247 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
248 + 7) << 16) |
249 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
250 + 11) << 8) |
251 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
252 + 15));
253 break;
254 default:
255 DPRINTF("%s: unknown type (%x)\n", __func__, devtype);
256 rv = 0;
257 }
258
259 if (id == STI_DD_HCRX)
260 rv = 100; /* beat out sti */
261
262 ca->ca_addrs[ca->ca_naddrs].addr = rom;
263 ca->ca_addrs[ca->ca_naddrs].size = sti_rom_size(ca->ca_iot, romh);
264 ca->ca_naddrs++;
265
266 if (!romunmapped)
267 bus_space_unmap(ca->ca_iot, romh, STI_ROMSIZE);
268 return rv;
269 }
270
271 void
272 hyperfb_attach(device_t parent, device_t self, void *aux)
273 {
274 struct hyperfb_softc *sc = device_private(self);
275 struct confargs *ca = aux;
276 struct rasops_info *ri;
277 struct wsemuldisplaydev_attach_args aa;
278 bus_space_handle_t hrom;
279 hppa_hpa_t consaddr;
280 long defattr;
281 int pagezero_cookie;
282 paddr_t rom;
283 uint32_t config;
284
285 pagezero_cookie = hppa_pagezero_map();
286 consaddr = (hppa_hpa_t)PAGE0->mem_cons.pz_hpa;
287 hppa_pagezero_unmap(pagezero_cookie);
288
289 sc->sc_dev = self;
290 sc->sc_base = ca->ca_hpa;
291 sc->sc_iot = ca->ca_iot;
292 sc->sc_is_console =(ca->ca_hpa == consaddr);
293 sc->sc_width = 1280;
294 sc->sc_height = 1024;
295
296 /* we can *not* be interrupted when doing colour map accesses */
297 mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH);
298
299 /* we stashed rom addr/len into the last slot during probe */
300 rom = ca->ca_addrs[ca->ca_naddrs - 1].addr;
301
302 if (bus_space_map(sc->sc_iot,
303 sc->sc_base + HCRX_FBOFFSET, HCRX_FBLEN,
304 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
305 &sc->sc_hfb)) {
306 aprint_error_dev(sc->sc_dev, "failed to map the framebuffer\n");
307 return;
308 }
309 sc->sc_fb = bus_space_vaddr(sc->sc_iot, sc->sc_hfb);
310
311 if (bus_space_map(sc->sc_iot,
312 sc->sc_base + HCRX_REGOFFSET, HCRX_REGLEN, 0, &sc->sc_hreg)) {
313 aprint_error_dev(sc->sc_dev, "failed to map registers\n");
314 return;
315 }
316
317 /*
318 * we really only need the first word so we can grab the config bits
319 * between the bytes
320 */
321 if (bus_space_map(sc->sc_iot,
322 rom, 4, 0, &hrom)) {
323 aprint_error_dev(sc->sc_dev, "failed to map ROM, assuming 8bit\n");
324 config = 0;
325 } else {
326 /* alright, we got the ROM. now do the idle dance. */
327 volatile uint32_t r = hyperfb_read4(sc, NGLE_REG_15);
328 __USE(r);
329 hyperfb_wait(sc);
330 config = bus_space_read_4(sc->sc_iot, hrom, 0);
331 bus_space_unmap(sc->sc_iot, hrom, 4);
332 }
333 sc->sc_24bit = ((config & HCRX_CONFIG_24BIT) != 0);
334
335 printf(" %s\n", sc->sc_24bit ? "HCRX24" : "HCRX");
336 #ifdef HP7300LC_CPU
337 /*
338 * PCXL2: enable accel I/O for this space, see PCX-L2 ERS "ACCEL_IO".
339 * "pcxl2_ers.{ps,pdf}", (section / chapter . rel. page / abs. page)
340 * 8.7.4 / 8-12 / 92, 11.3.14 / 11-14 / 122 and 14.8 / 14-5 / 203.
341 */
342 if (hppa_cpu_info->hci_cputype == hpcxl2
343 && ca->ca_hpa >= PCXL2_ACCEL_IO_START
344 && ca->ca_hpa <= PCXL2_ACCEL_IO_END)
345 eaio_l2(PCXL2_ACCEL_IO_ADDR2MASK(ca->ca_hpa));
346 #endif /* HP7300LC_CPU */
347
348 hyperfb_setup(sc);
349 hyperfb_setup_fb(sc);
350
351 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
352 "default",
353 0, 0,
354 NULL,
355 8, 16,
356 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
357 WSSCREEN_RESIZE,
358 NULL
359 };
360
361 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
362 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
363 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
364 sc->sc_locked = 0;
365
366 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
367 &hyperfb_accessops);
368 sc->vd.init_screen = hyperfb_init_screen;
369 sc->vd.show_screen_cookie = &sc->sc_gc;
370 sc->vd.show_screen_cb = glyphcache_adapt;
371
372 ri = &sc->sc_console_screen.scr_ri;
373
374 //sc->sc_gc.gc_bitblt = hyperfb_bitblt;
375 //sc->sc_gc.gc_blitcookie = sc;
376 //sc->sc_gc.gc_rop = RopSrc;
377
378 if (sc->sc_is_console) {
379 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
380 &defattr);
381 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
382
383 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
384 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
385 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
386 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
387
388 #if 0
389 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
390 sc->sc_scr.fbheight - sc->sc_height - 5,
391 sc->sc_scr.fbwidth,
392 ri->ri_font->fontwidth,
393 ri->ri_font->fontheight,
394 defattr);
395 #endif
396 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
397 defattr);
398 #if 0
399 hyperfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
400 ri->ri_devcmap[(defattr >> 16) & 0xff]);
401 #endif
402 vcons_replay_msgbuf(&sc->sc_console_screen);
403 } else {
404 /*
405 * since we're not the console we can postpone the rest
406 * until someone actually allocates a screen for us
407 */
408 if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
409 /* do some minimal setup to avoid weirdnesses later */
410 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
411 &defattr);
412 } else
413 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
414
415 #if 0
416 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
417 sc->sc_scr.fbheight - sc->sc_height - 5,
418 sc->sc_scr.fbwidth,
419 ri->ri_font->fontwidth,
420 ri->ri_font->fontheight,
421 defattr);
422 #endif
423 }
424
425 hyperfb_restore_palette(sc);
426
427 /* no suspend/resume support yet */
428 if (!pmf_device_register(sc->sc_dev, NULL, NULL))
429 aprint_error_dev(sc->sc_dev,
430 "couldn't establish power handler\n");
431
432 aa.console = sc->sc_is_console;
433 aa.scrdata = &sc->sc_screenlist;
434 aa.accessops = &hyperfb_accessops;
435 aa.accesscookie = &sc->vd;
436
437 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE);
438
439 }
440
441 static void
442 hyperfb_init_screen(void *cookie, struct vcons_screen *scr,
443 int existing, long *defattr)
444 {
445 struct hyperfb_softc *sc = cookie;
446 struct rasops_info *ri = &scr->scr_ri;
447
448 ri->ri_depth = 8;
449 ri->ri_width = 1280;
450 ri->ri_height = 1024;
451 ri->ri_stride = 2048;
452 ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB /*|
453 RI_ENABLE_ALPHA | RI_PREFER_ALPHA*/;
454
455 ri->ri_bits = (void *)sc->sc_fb;
456 rasops_init(ri, 0, 0);
457 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
458 WSSCREEN_RESIZE;
459 scr->scr_flags |= VCONS_LOADFONT | VCONS_DONT_READ;
460
461 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
462 sc->sc_width / ri->ri_font->fontwidth);
463
464 ri->ri_hw = scr;
465 #if 0
466 sc->sc_putchar = ri->ri_ops.putchar;
467 ri->ri_ops.copyrows = gftfb_copyrows;
468 ri->ri_ops.copycols = gftfb_copycols;
469 ri->ri_ops.eraserows = gftfb_eraserows;
470 ri->ri_ops.erasecols = gftfb_erasecols;
471 ri->ri_ops.cursor = gftfb_cursor;
472 ri->ri_ops.putchar = gftfb_putchar;
473 #endif
474 }
475
476 static int
477 hyperfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
478 struct lwp *l)
479 {
480 struct vcons_data *vd = v;
481 struct hyperfb_softc *sc = vd->cookie;
482 struct wsdisplay_fbinfo *wdf;
483 struct vcons_screen *ms = vd->active;
484
485 switch (cmd) {
486 case WSDISPLAYIO_GTYPE:
487 *(u_int *)data = WSDISPLAY_TYPE_STI;
488 return 0;
489
490 case WSDISPLAYIO_GINFO:
491 if (ms == NULL)
492 return ENODEV;
493 wdf = (void *)data;
494 wdf->height = ms->scr_ri.ri_height;
495 wdf->width = ms->scr_ri.ri_width;
496 wdf->depth = ms->scr_ri.ri_depth;
497 wdf->cmsize = 256;
498 return 0;
499
500 case WSDISPLAYIO_GETCMAP:
501 return hyperfb_getcmap(sc,
502 (struct wsdisplay_cmap *)data);
503
504 case WSDISPLAYIO_PUTCMAP:
505 return hyperfb_putcmap(sc,
506 (struct wsdisplay_cmap *)data);
507 case WSDISPLAYIO_LINEBYTES:
508 *(u_int *)data = 2048;
509 return 0;
510
511 case WSDISPLAYIO_SMODE: {
512 int new_mode = *(int*)data;
513 if (new_mode != sc->sc_mode) {
514 sc->sc_mode = new_mode;
515 if(new_mode == WSDISPLAYIO_MODE_EMUL) {
516 hyperfb_setup(sc);
517 hyperfb_restore_palette(sc);
518 #if 0
519 glyphcache_wipe(&sc->sc_gc);
520 hyperfb_rectfill(sc, 0, 0, sc->sc_width,
521 sc->sc_height, ms->scr_ri.ri_devcmap[
522 (ms->scr_defattr >> 16) & 0xff]);
523 #endif
524 vcons_redraw_screen(ms);
525 hyperfb_set_video(sc, 1);
526 }
527 }
528 }
529 return 0;
530
531 case WSDISPLAYIO_GET_FBINFO:
532 {
533 struct wsdisplayio_fbinfo *fbi = data;
534 int ret;
535
536 ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
537 fbi->fbi_fbsize = sc->sc_height * 2048;
538 return ret;
539 }
540
541 #if 0
542 case WSDISPLAYIO_GCURPOS:
543 {
544 struct wsdisplay_curpos *cp = (void *)data;
545
546 cp->x = sc->sc_cursor_x;
547 cp->y = sc->sc_cursor_y;
548 }
549 return 0;
550
551 case WSDISPLAYIO_SCURPOS:
552 {
553 struct wsdisplay_curpos *cp = (void *)data;
554
555 gftfb_move_cursor(sc, cp->x, cp->y);
556 }
557 return 0;
558
559 case WSDISPLAYIO_GCURMAX:
560 {
561 struct wsdisplay_curpos *cp = (void *)data;
562
563 cp->x = 64;
564 cp->y = 64;
565 }
566 return 0;
567
568 case WSDISPLAYIO_SCURSOR:
569 {
570 struct wsdisplay_cursor *cursor = (void *)data;
571
572 return gftfb_do_cursor(sc, cursor);
573 }
574 #endif
575
576 case WSDISPLAYIO_SVIDEO:
577 hyperfb_set_video(sc, *(int *)data);
578 return 0;
579 case WSDISPLAYIO_GVIDEO:
580 return sc->sc_video_on ?
581 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF;
582 }
583 return EPASSTHROUGH;
584 }
585
586 static paddr_t
587 hyperfb_mmap(void *v, void *vs, off_t offset, int prot)
588 {
589 struct vcons_data *vd = v;
590 struct hyperfb_softc *sc = vd->cookie;
591 paddr_t pa = -1;
592
593
594 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
595 return -1;
596
597 if (offset >= 0 || offset < 2048 * 1024) {
598 /* framebuffer */
599 pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_FBOFFSET, offset,
600 prot, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
601 } else if (offset >= 0x80000000 && offset < 0x8040000) {
602 /* blitter registers etc. */
603 pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_REGOFFSET,
604 offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR);
605 }
606
607 return pa;
608 }
609
610 static int
611 hyperfb_putcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
612 {
613 u_char *r, *g, *b;
614 u_int index = cm->index;
615 u_int count = cm->count;
616 int i, error;
617 u_char rbuf[256], gbuf[256], bbuf[256];
618
619 if (cm->index >= 256 || cm->count > 256 ||
620 (cm->index + cm->count) > 256)
621 return EINVAL;
622 error = copyin(cm->red, &rbuf[index], count);
623 if (error)
624 return error;
625 error = copyin(cm->green, &gbuf[index], count);
626 if (error)
627 return error;
628 error = copyin(cm->blue, &bbuf[index], count);
629 if (error)
630 return error;
631
632 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
633 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
634 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
635
636 r = &sc->sc_cmap_red[index];
637 g = &sc->sc_cmap_green[index];
638 b = &sc->sc_cmap_blue[index];
639
640 for (i = 0; i < count; i++) {
641 hyperfb_putpalreg(sc, index, *r, *g, *b);
642 index++;
643 r++, g++, b++;
644 }
645 return 0;
646 }
647
648 static int
649 hyperfb_getcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
650 {
651 u_int index = cm->index;
652 u_int count = cm->count;
653 int error;
654
655 if (index >= 255 || count > 256 || index + count > 256)
656 return EINVAL;
657
658 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
659 if (error)
660 return error;
661 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
662 if (error)
663 return error;
664 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
665 if (error)
666 return error;
667
668 return 0;
669 }
670
671 static void
672 hyperfb_restore_palette(struct hyperfb_softc *sc)
673 {
674 uint8_t cmap[768];
675 int i, j;
676
677 j = 0;
678 rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap));
679 for (i = 0; i < 256; i++) {
680 sc->sc_cmap_red[i] = cmap[j];
681 sc->sc_cmap_green[i] = cmap[j + 1];
682 sc->sc_cmap_blue[i] = cmap[j + 2];
683 hyperfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]);
684 j += 3;
685 }
686 }
687
688 static int
689 hyperfb_putpalreg(struct hyperfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
690 uint8_t b)
691 {
692
693 mutex_enter(&sc->sc_hwlock);
694 hyperfb_wait(sc);
695 hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000);
696 hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
697 hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
698
699 hyperfb_wait(sc);
700 hyperfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2));
701 hyperfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b);
702
703 hyperfb_write4(sc, NGLE_REG_2, 0x400);
704 hyperfb_write4(sc, NGLE_REG_38, 0x82000100);
705 hyperfb_setup_fb(sc);
706 mutex_exit(&sc->sc_hwlock);
707 return 0;
708 }
709
710 void
711 hyperfb_setup(struct hyperfb_softc *sc)
712 {
713 int i;
714 uint32_t reg;
715
716 sc->sc_hwmode = HW_FB;
717 sc->sc_hot_x = 0;
718 sc->sc_hot_y = 0;
719 sc->sc_enabled = 0;
720 sc->sc_video_on = 1;
721
722 #if 0
723 sc->sc_rect_colour = 0xf0000000;
724 sc->sc_rect_height = 0;
725 #endif
726
727 /* set Bt458 read mask register to all planes */
728 /* XXX I'm not sure HCRX even has one of these */
729 hyperfb_wait(sc);
730 ngle_bt458_write(sc, 0x08, 0x04);
731 ngle_bt458_write(sc, 0x0a, 0xff);
732
733 reg = hyperfb_read4(sc, NGLE_REG_32);
734 DPRINTF("planereg %08x\n", reg);
735 hyperfb_write4(sc, NGLE_REG_32, 0xffff0000);
736
737 hyperfb_setup_fb(sc);
738
739 /* attr. planes */
740 hyperfb_wait(sc);
741 hyperfb_write4(sc, NGLE_REG_11, 0x2ea0d000);
742 hyperfb_write4(sc, NGLE_REG_14, 0x23000302);
743 hyperfb_write4(sc, NGLE_REG_12, NGLE_BUFF1_CMAP0);
744 hyperfb_write4(sc, NGLE_REG_8, 0xffffffff);
745
746 hyperfb_wait(sc);
747 hyperfb_write4(sc, NGLE_REG_6, 0x00000000);
748 hyperfb_write4(sc, NGLE_REG_9,
749 (sc->sc_width << 16) | sc->sc_height);
750 /*
751 * blit into offscreen memory to force flush previous - apparently
752 * some chips have a bug this works around
753 */
754 hyperfb_write4(sc, NGLE_REG_6, 0x05000000);
755 hyperfb_write4(sc, NGLE_REG_9, 0x00040001);
756
757 hyperfb_wait(sc);
758 hyperfb_write4(sc, NGLE_REG_12, 0x00000000);
759
760 hyperfb_setup_fb(sc);
761
762 /* make sure video output is enabled */
763 hyperfb_wait(sc);
764 hyperfb_write4(sc, NGLE_REG_33,
765 hyperfb_read4(sc, NGLE_REG_33) | 0x0a000000);
766
767 /* hyperbowl */
768 hyperfb_wait(sc);
769 if(sc->sc_24bit) {
770 /* write must happen twice because hw bug */
771 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE);
772 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE);
773 hyperfb_write4(sc, NGLE_REG_39, HYPERBOWL_MODE2_8_24);
774 hyperfb_write4(sc, NGLE_REG_42, 0x014c0148); /* Set lut 0 to be the direct color */
775 hyperfb_write4(sc, NGLE_REG_43, 0x404c4048);
776 hyperfb_write4(sc, NGLE_REG_44, 0x034c0348);
777 hyperfb_write4(sc, NGLE_REG_45, 0x444c4448);
778 } else {
779 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
780 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
781
782 hyperfb_write4(sc, NGLE_REG_42, 0);
783 hyperfb_write4(sc, NGLE_REG_43, 0);
784 hyperfb_write4(sc, NGLE_REG_44, 0);
785 hyperfb_write4(sc, NGLE_REG_45, 0);
786 }
787 /* cursor mask */
788 hyperfb_wait(sc);
789 hyperfb_write4(sc, NGLE_REG_30, 0);
790 for (i = 0; i < 64; i++) {
791 hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
792 hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
793 }
794
795 /* cursor image */
796 hyperfb_wait(sc);
797 hyperfb_write4(sc, NGLE_REG_30, 0x80);
798 for (i = 0; i < 64; i++) {
799 hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
800 hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
801 }
802
803 /* colour map - doesn't work yet*/
804 hyperfb_wait(sc);
805 hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000);
806 hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
807 hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
808 hyperfb_wait(sc);
809 hyperfb_write4(sc, NGLE_REG_3, 0);
810 hyperfb_write4(sc, NGLE_REG_4, 0);
811 hyperfb_write4(sc, NGLE_REG_4, 0);
812 hyperfb_write4(sc, NGLE_REG_4, 0x000000ff); /* BG */
813 hyperfb_write4(sc, NGLE_REG_4, 0x00ff0000); /* FG */
814 hyperfb_wait(sc);
815 hyperfb_write4(sc, NGLE_REG_2, 0);
816 hyperfb_write4(sc, NGLE_REG_1, 0x80008004);
817 hyperfb_setup_fb(sc);
818
819 //hyperfb_write4(sc, NGLE_REG_29, 0x80200020);
820
821 //gftfb_move_cursor(sc, 100, 100);
822
823 }
824
825 static void
826 hyperfb_set_video(struct hyperfb_softc *sc, int on)
827 {
828 uint32_t reg;
829
830 if (sc->sc_video_on == on)
831 return;
832
833 sc->sc_video_on = on;
834
835 hyperfb_wait(sc);
836 reg = hyperfb_read4(sc, NGLE_REG_33);
837
838 if (on) {
839 hyperfb_write4(sc, NGLE_REG_33, reg | 0x0a000000);
840 } else {
841 hyperfb_write4(sc, NGLE_REG_33, reg & ~0x0a000000);
842 }
843 }
844