1 1.1 phx /* $NetBSD: zz9k_fb.c,v 1.1 2023/05/03 13:49:30 phx Exp $ */ 2 1.1 phx 3 1.1 phx /* 4 1.1 phx * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 1.1 phx * All rights reserved. 6 1.1 phx * 7 1.1 phx * This code is derived from software contributed to The NetBSD Foundation 8 1.1 phx * by Alain Runa. 9 1.1 phx * 10 1.1 phx * Redistribution and use in source and binary forms, with or without 11 1.1 phx * modification, are permitted provided that the following conditions 12 1.1 phx * are met: 13 1.1 phx * 1. Redistributions of source code must retain the above copyright 14 1.1 phx * notice, this list of conditions and the following disclaimer. 15 1.1 phx * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 phx * notice, this list of conditions and the following disclaimer in the 17 1.1 phx * documentation and/or other materials provided with the distribution. 18 1.1 phx * 19 1.1 phx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 phx * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 phx * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 phx * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 phx * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 phx * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 phx * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 phx * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 phx * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 1.1 phx * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 phx */ 30 1.1 phx 31 1.1 phx #include <sys/cdefs.h> 32 1.1 phx __KERNEL_RCSID(0, "$NetBSD: zz9k_fb.c,v 1.1 2023/05/03 13:49:30 phx Exp $"); 33 1.1 phx 34 1.1 phx /* miscellaneous */ 35 1.1 phx #include <sys/errno.h> /* EPASSTHROUGH */ 36 1.1 phx #include <sys/types.h> /* size_t */ 37 1.1 phx #include <sys/stdint.h> /* uintXX_t */ 38 1.1 phx #include <sys/stdbool.h> /* bool */ 39 1.1 phx 40 1.1 phx /* driver(9) */ 41 1.1 phx #include <sys/param.h> /* NODEV */ 42 1.1 phx #include <sys/device.h> /* CFATTACH_DECL_NEW(), device_priv() */ 43 1.1 phx #include <sys/errno.h> /* EINVAL, ENODEV, EPASSTHROUGH */ 44 1.1 phx 45 1.1 phx /* bus_space(9) and zorro bus */ 46 1.1 phx #include <sys/bus.h> /* bus_space_xxx(), bus_space_xxx_t */ 47 1.1 phx #include <sys/cpu.h> /* kvtop() */ 48 1.1 phx #include <sys/systm.h> /* aprint_xxx() */ 49 1.1 phx 50 1.1 phx /* wsdisplay(9) */ 51 1.1 phx #include <dev/wscons/wsconsio.h> /* WSDISPLAYIO_XXX, wsdisplayio_xxx */ 52 1.1 phx #include <dev/wscons/wsdisplayvar.h> /* wsscreen_xxx, wsdisplay_xxx */ 53 1.1 phx #include <dev/wscons/wsemulvar.h> /* ? */ 54 1.1 phx #include <dev/wscons/wsemul_vt100var.h> /* ? */ 55 1.1 phx 56 1.1 phx /* rasops(9) */ 57 1.1 phx /* #include <dev/wscons/wsdisplayvar.h> */ 58 1.1 phx #include <dev/rasops/rasops.h> /* rasops_unpack_attr(), rasops_info */ 59 1.1 phx 60 1.1 phx /* wsfont(9) */ 61 1.1 phx /* #include <dev/wscons/wsconsio.h> */ /* WSDISPLAYIO_XXX, wsdisplayio_xxx */ 62 1.1 phx #include <dev/wsfont/wsfont.h> /* wsfont_init() */ 63 1.1 phx 64 1.1 phx /* vcons(9) */ 65 1.1 phx #include <dev/wscons/wsdisplay_vconsvar.h> /* vcons_xxx(), vcons_data, 66 1.1 phx vcons_screen */ 67 1.1 phx /* cons(9) */ 68 1.1 phx #include <dev/cons.h> /* consdev, CN_INTERNAL */ 69 1.1 phx 70 1.1 phx /* zz9k and amiga related */ 71 1.1 phx #include <amiga/dev/kbdvar.h> /* kbd_cnattach() */ 72 1.1 phx #include <amiga/dev/zz9kvar.h> /* zz9kbus_attach_args */ 73 1.1 phx #include <amiga/dev/zz9kreg.h> /* ZZ9000 registers */ 74 1.1 phx #include "opt_zz9k_fb.h" /* ZZFB_CONSOLE */ 75 1.1 phx #include "zz9k_fb.h" /* NZZ9K_FB */ 76 1.1 phx #include "kbd.h" /* NKBD */ 77 1.1 phx 78 1.1 phx 79 1.1 phx /* 80 1.1 phx * One can choose different graphics modes and color depths for the different 81 1.1 phx * wsdisplay modes emul (console), mapped (raw) and dumbfb (e.g. X11) here. 82 1.1 phx * Please consult zz9kreg.h for available graphics modes and color depths 83 1.1 phx * supported by the ZZ9000. 84 1.1 phx */ 85 1.1 phx #define ZZFB_SET_CON_MODE ZZ9K_MODE_1280x720 /* Console */ 86 1.1 phx #define ZZFB_SET_CON_BPP ZZ9K_COLOR_8BIT 87 1.1 phx #define ZZFB_SET_GFX_MODE ZZ9K_MODE_1280x720 /* raw FB */ 88 1.1 phx #define ZZFB_SET_GFX_BPP ZZ9K_COLOR_16BIT 89 1.1 phx #define ZZFB_SET_DFB_MODE ZZ9K_MODE_1280x720 /* X11 */ 90 1.1 phx #define ZZFB_SET_DFB_BPP ZZ9K_COLOR_16BIT 91 1.1 phx 92 1.1 phx /* 93 1.1 phx * This defines ZZ9000 scandoubler's capture mode and it is used only in case 94 1.1 phx * the ZZ9000 does not have the early console, but also in X11 video off mode. 95 1.1 phx * NetBSD defaults to NTSC amiga screen, so the scandoubler default is NTSC too. 96 1.1 phx * On a custom configured kernel for a PAL screen, one should consider to change 97 1.1 phx * the capture mode to PAL to get the best result. If the attached monitor does 98 1.1 phx * not support a scandoubled PAL signal in 50Hz, consider using the VGA 800x600 99 1.1 phx * capture mode which is compatible with most monitors and works fine with NTSC 100 1.1 phx * and PAL captures at 60Hz. 101 1.1 phx * Valid values for ZZFB_CAP_MODE: 0: NTSC, 1: PAL, 2:VGA (PAL60) 102 1.1 phx */ 103 1.1 phx #define ZZFB_CAP_MODE 0 104 1.1 phx 105 1.1 phx #if ZZFB_CAP_MODE == 0 106 1.1 phx #define ZZFB_CAPTURE_MODE ZZ9K_MODE_720x480 107 1.1 phx #define ZZFB_DISPLAY_MODE ZZ9K_MODE_720x480 108 1.1 phx #elif ZZFB_CAP_MODE == 1 109 1.1 phx #define ZZFB_CAPTURE_MODE ZZ9K_MODE_720x576p50 110 1.1 phx #define ZZFB_DISPLAY_MODE ZZ9K_MODE_720x576p50 111 1.1 phx #elif ZZFB_CAP_MODE == 2 112 1.1 phx #define ZZFB_CAPTURE_MODE ZZ9K_MODE_800x600 113 1.1 phx #define ZZFB_DISPLAY_MODE ZZ9K_MODE_800x600 114 1.1 phx #endif 115 1.1 phx 116 1.1 phx /* The allmighty softc structure */ 117 1.1 phx struct zzfb_softc { 118 1.1 phx device_t sc_dev; 119 1.1 phx struct bus_space_tag sc_bst; 120 1.1 phx bus_space_tag_t sc_iot; 121 1.1 phx bus_space_handle_t sc_regh; 122 1.1 phx bus_space_handle_t sc_fbh; 123 1.1 phx size_t sc_fbsize; 124 1.1 phx 125 1.1 phx struct vcons_screen sc_console_screen; 126 1.1 phx struct vcons_data sc_vd; 127 1.1 phx struct wsscreen_descr sc_defaultscreen; 128 1.1 phx struct wsscreen_list sc_screenlist; 129 1.1 phx const struct wsscreen_descr *sc_screens[1]; 130 1.1 phx u_int sc_wsmode; 131 1.1 phx 132 1.1 phx uint16_t sc_displaymode; 133 1.1 phx uint16_t sc_colormode; 134 1.1 phx uint16_t sc_width; 135 1.1 phx uint16_t sc_height; 136 1.1 phx uint16_t sc_bpp; 137 1.1 phx uint16_t sc_stride; 138 1.1 phx 139 1.1 phx u_char red[ZZ9K_PALETTE_SIZE]; 140 1.1 phx u_char green[ZZ9K_PALETTE_SIZE]; 141 1.1 phx u_char blue[ZZ9K_PALETTE_SIZE]; 142 1.1 phx 143 1.1 phx bool sc_isconsole; 144 1.1 phx bool sc_isrtg; 145 1.1 phx }; 146 1.1 phx 147 1.1 phx static const struct { 148 1.1 phx const char* name; 149 1.1 phx uint16_t width; 150 1.1 phx uint16_t height; 151 1.1 phx uint16_t scale; 152 1.1 phx } zzfb_modes[] = { /* Hardcoded in firmware */ 153 1.1 phx { "1280x720p60", 1280, 720, ZZ9K_MODE_SCALE_0}, 154 1.1 phx { "800x600p60", 800, 600, ZZ9K_MODE_SCALE_0}, 155 1.1 phx { "640x480p60", 640, 480, ZZ9K_MODE_SCALE_0}, 156 1.1 phx { "1024x768p60", 1024, 768, ZZ9K_MODE_SCALE_0}, 157 1.1 phx { "1280x1024p60", 1280, 1024, ZZ9K_MODE_SCALE_0}, 158 1.1 phx { "1920x1080p60", 1920, 1080, ZZ9K_MODE_SCALE_0}, 159 1.1 phx { "720x576p50", 720, 576, ZZ9K_MODE_SCALE_0}, /* 50 Hz */ 160 1.1 phx { "1920x1080p50", 1920, 1080, ZZ9K_MODE_SCALE_0}, /* 50 Hz */ 161 1.1 phx { "720x480p60", 720, 480, ZZ9K_MODE_SCALE_0}, 162 1.1 phx { "640x512p60", 640, 512, ZZ9K_MODE_SCALE_0}, 163 1.1 phx { "1600x1200p60", 1600, 1200, ZZ9K_MODE_SCALE_0}, 164 1.1 phx { "2560x1444p30", 2560, 1444, ZZ9K_MODE_SCALE_0}, /* 30 Hz */ 165 1.1 phx { "720x576p50-NS-PAL", 720, 576, ZZ9K_MODE_SCALE_0}, /* 50 Hz */ 166 1.1 phx { "720x480p60-NS-PAL", 720, 480, ZZ9K_MODE_SCALE_0}, 167 1.1 phx {"720x576p50-NS-NTSC", 720, 576, ZZ9K_MODE_SCALE_0}, /* 50 Hz */ 168 1.1 phx {"720x480p60-NS-NTSC", 720, 480, ZZ9K_MODE_SCALE_0}, 169 1.1 phx { "640x400p60", 640, 400, ZZ9K_MODE_SCALE_0}, 170 1.1 phx { "1920x800p60", 640, 400, ZZ9K_MODE_SCALE_0} 171 1.1 phx }; 172 1.1 phx 173 1.1 phx static const struct { 174 1.1 phx const char* name; 175 1.1 phx uint16_t bpp; 176 1.1 phx uint16_t mode; 177 1.1 phx uint16_t stride; 178 1.1 phx } zzfb_colors[] = { /* Hardcoded in firmware */ 179 1.1 phx { "8-bit LUT", 8, ZZ9K_MODE_COLOR_8BIT , 1}, 180 1.1 phx { "16-bit RGB565", 16, ZZ9K_MODE_COLOR_16BIT, 2}, 181 1.1 phx {"32-bit BGRA8888", 32, ZZ9K_MODE_COLOR_32BIT, 4}, 182 1.1 phx {"16-bit ARGB1555", 15, ZZ9K_MODE_COLOR_15BIT, 2} 183 1.1 phx }; 184 1.1 phx 185 1.1 phx #define ZZFB_MODES_SIZE (sizeof zzfb_modes / sizeof zzfb_modes[0]) 186 1.1 phx #define ZZFB_COLORS_SIZE (sizeof zzfb_colors / sizeof zzfb_colors[0]) 187 1.1 phx 188 1.1 phx /* functions to set gfx mode, palette and misc stuff to make life easier. */ 189 1.1 phx static void zzfb_set_capture(struct zzfb_softc *sc, uint16_t display_mode, 190 1.1 phx uint16_t capture_mode); 191 1.1 phx static void zzfb_set_mode(struct zzfb_softc *sc, uint16_t display_mode, 192 1.1 phx uint16_t color_mode); 193 1.1 phx static void zzfb_wait_vblank(struct zzfb_softc *sc); 194 1.1 phx static void zzfb_init_palette(struct zzfb_softc *sc); 195 1.1 phx static void zzfb_set_palette(struct zzfb_softc *sc); 196 1.1 phx static void zzfb_clearbg(struct zzfb_softc *sc, uint8_t color_index); 197 1.1 phx static int zzfb_get_fbinfo(struct zzfb_softc *sc, 198 1.1 phx struct wsdisplayio_fbinfo *fbi); 199 1.1 phx 200 1.1 phx /* vcons_data init_screen function */ 201 1.1 phx static void zzfb_init_screen(void *cookie, struct vcons_screen *scr, 202 1.1 phx int existing, long *defattr); 203 1.1 phx 204 1.1 phx /* accelerated raster ops functions */ 205 1.1 phx static void zzfb_eraserows(void *cookie, int row, int nrows, long fillattr); 206 1.1 phx static void zzfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows); 207 1.1 phx static void zzfb_copycols(void *cookie, int row, int srccol, int dstcol, 208 1.1 phx int ncols); 209 1.1 phx static void zzfb_erasecols(void *cookie, int row, int startcol, int ncols, 210 1.1 phx long fillattr); 211 1.1 phx 212 1.1 phx /* blitter support functions*/ 213 1.1 phx static void zzfb_rectfill(struct zzfb_softc *sc, uint16_t x, uint16_t y, 214 1.1 phx uint16_t w, uint16_t h, uint32_t color); 215 1.1 phx static void zzfb_bitblt(struct zzfb_softc *sc, uint16_t x, uint16_t y, 216 1.1 phx uint16_t w, uint16_t h, uint16_t xs, uint16_t ys); 217 1.1 phx 218 1.1 phx /* wsdisplay_accessops stuff */ 219 1.1 phx static paddr_t zzfb_mmap(void *v, void *vs, off_t offset, int prot); 220 1.1 phx static int zzfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 221 1.1 phx struct lwp *l); 222 1.1 phx static int zzfb_getcmap(struct zzfb_softc *sc, struct wsdisplay_cmap *cm); 223 1.1 phx static int zzfb_putcmap(struct zzfb_softc *sc, struct wsdisplay_cmap *cm); 224 1.1 phx struct wsdisplay_accessops zzfb_accessops = 225 1.1 phx {zzfb_ioctl, zzfb_mmap, NULL, NULL, NULL, NULL, NULL, NULL}; 226 1.1 phx 227 1.1 phx /* driver(9) essentials */ 228 1.1 phx static int zzfb_match(device_t parent, cfdata_t match, void *aux); 229 1.1 phx static void zzfb_attach(device_t parent, device_t self, void *aux); 230 1.1 phx CFATTACH_DECL_NEW( 231 1.1 phx zz9k_fb, sizeof(struct zzfb_softc), zzfb_match, zzfb_attach, NULL, NULL ); 232 1.1 phx 233 1.1 phx #ifdef ZZFB_CONSOLE 234 1.1 phx extern bool zz9k_exists; 235 1.1 phx #endif /* ZZFB_CONSOLE */ 236 1.1 phx 237 1.1 phx 238 1.1 phx /* If you build it, they will come... */ 239 1.1 phx 240 1.1 phx static int 241 1.1 phx zzfb_match(device_t parent, cfdata_t match, void *aux) 242 1.1 phx { 243 1.1 phx struct zz9kbus_attach_args *bap = aux; 244 1.1 phx 245 1.1 phx if (strcmp(bap->zzaa_name, "zz9k_fb") != 0) { 246 1.1 phx return 0; 247 1.1 phx } 248 1.1 phx 249 1.1 phx return 1; 250 1.1 phx } 251 1.1 phx 252 1.1 phx static void 253 1.1 phx zzfb_attach(device_t parent, device_t self, void *aux) 254 1.1 phx { 255 1.1 phx struct zz9kbus_attach_args *bap = aux; 256 1.1 phx struct zzfb_softc *sc = device_private(self); 257 1.1 phx struct zz9k_softc *psc = device_private(parent); 258 1.1 phx struct rasops_info *ri; 259 1.1 phx struct wsemuldisplaydev_attach_args ws_aa; 260 1.1 phx long defattr; 261 1.1 phx 262 1.1 phx sc->sc_dev = self; 263 1.1 phx sc->sc_bst.base = bap->zzaa_base; 264 1.1 phx sc->sc_bst.absm = &amiga_bus_stride_1; 265 1.1 phx sc->sc_iot = &sc->sc_bst; 266 1.1 phx sc->sc_regh = psc->sc_regh; 267 1.1 phx 268 1.1 phx if (psc->sc_zsize >= (ZZ9K_FB_BASE + ZZ9K_FB_SIZE)) { 269 1.1 phx sc->sc_fbsize = ZZ9K_FB_SIZE; 270 1.1 phx } else { 271 1.1 phx sc->sc_fbsize = psc->sc_zsize - ZZ9K_FB_BASE; 272 1.1 phx } 273 1.1 phx 274 1.1 phx if (bus_space_map(sc->sc_iot, ZZ9K_FB_BASE, sc->sc_fbsize, 275 1.1 phx BUS_SPACE_MAP_LINEAR, &sc->sc_fbh)) { 276 1.1 phx aprint_error(": Failed to map MNT ZZ9000 framebuffer.\n"); 277 1.1 phx return; 278 1.1 phx } 279 1.1 phx 280 1.1 phx zzfb_set_mode(sc, ZZFB_SET_CON_MODE, ZZFB_SET_CON_BPP); 281 1.1 phx zzfb_init_palette(sc); 282 1.1 phx zzfb_clearbg(sc, WS_DEFAULT_BG); 283 1.1 phx 284 1.1 phx aprint_normal(": Framebuffer resolution: %s, " 285 1.1 phx "depth: %i bpp (%s)\n", zzfb_modes[sc->sc_displaymode].name, 286 1.1 phx sc->sc_bpp, zzfb_colors[sc->sc_colormode].name); 287 1.1 phx 288 1.1 phx aprint_debug_dev(sc->sc_dev, "[DEBUG] registers at %p/%p (pa/va), " 289 1.1 phx "framebuffer at %p/%p (pa/va) with %i MB\n", 290 1.1 phx (void *)kvtop((void *)sc->sc_regh), 291 1.1 phx bus_space_vaddr(sc->sc_iot, sc->sc_regh), 292 1.1 phx (void *)kvtop((void *)sc->sc_fbh), 293 1.1 phx bus_space_vaddr(sc->sc_iot, sc->sc_fbh), 294 1.1 phx sc->sc_fbsize / (1024 * 1024)); 295 1.1 phx 296 1.1 phx sc->sc_defaultscreen = (struct wsscreen_descr) {"default", 0, 0, NULL, 297 1.1 phx 8, 16, WSSCREEN_WSCOLORS | WSSCREEN_HILIT, NULL}; 298 1.1 phx sc->sc_screens[0] = &sc->sc_defaultscreen; 299 1.1 phx sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 300 1.1 phx sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL; 301 1.1 phx 302 1.1 phx vcons_init(&sc->sc_vd, sc, &sc->sc_defaultscreen, &zzfb_accessops); 303 1.1 phx sc->sc_vd.init_screen = zzfb_init_screen; 304 1.1 phx 305 1.1 phx ri = &sc->sc_console_screen.scr_ri; 306 1.1 phx 307 1.1 phx #ifdef ZZFB_CONSOLE 308 1.1 phx sc->sc_isconsole = true; 309 1.1 phx vcons_init_screen(&sc->sc_vd, &sc->sc_console_screen, 1, 310 1.1 phx &defattr); 311 1.1 phx sc->sc_console_screen.scr_flags = VCONS_SCREEN_IS_STATIC; 312 1.1 phx vcons_redraw_screen(&sc->sc_console_screen); 313 1.1 phx 314 1.1 phx sc->sc_defaultscreen.textops = &ri->ri_ops; 315 1.1 phx sc->sc_defaultscreen.capabilities = ri->ri_caps; 316 1.1 phx sc->sc_defaultscreen.nrows = ri->ri_rows; 317 1.1 phx sc->sc_defaultscreen.ncols = ri->ri_cols; 318 1.1 phx 319 1.1 phx wsdisplay_cnattach(&sc->sc_defaultscreen, ri, 0, 0, defattr); 320 1.1 phx vcons_replay_msgbuf(&sc->sc_console_screen); 321 1.1 phx #else 322 1.1 phx sc->sc_isconsole = false; 323 1.1 phx if (sc->sc_console_screen.scr_ri.ri_rows == 0) { 324 1.1 phx vcons_init_screen(&sc->sc_vd, &sc->sc_console_screen, 1, 325 1.1 phx &defattr); 326 1.1 phx } else { 327 1.1 phx (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 328 1.1 phx } 329 1.1 phx zzfb_set_capture(sc, ZZFB_DISPLAY_MODE, ZZFB_CAPTURE_MODE); 330 1.1 phx aprint_normal_dev (sc->sc_dev, "Scandoubler capture: %s, " 331 1.1 phx "display: %s in %s.\n", 332 1.1 phx zzfb_modes[ZZFB_CAPTURE_MODE].name, 333 1.1 phx zzfb_modes[ZZFB_DISPLAY_MODE].name, 334 1.1 phx zzfb_colors[ZZ9K_COLOR_32BIT].name); 335 1.1 phx #endif /* ZZFB_CONSOLE */ 336 1.1 phx 337 1.1 phx ws_aa.console = sc->sc_isconsole; 338 1.1 phx ws_aa.scrdata = &sc->sc_screenlist; 339 1.1 phx ws_aa.accessops = &zzfb_accessops; 340 1.1 phx ws_aa.accesscookie = &sc->sc_vd; 341 1.1 phx 342 1.1 phx config_found(sc->sc_dev, &ws_aa, wsemuldisplaydevprint, CFARGS_NONE); 343 1.1 phx } 344 1.1 phx 345 1.1 phx static void 346 1.1 phx zzfb_init_palette(struct zzfb_softc *sc) 347 1.1 phx { 348 1.1 phx for (int index = 0; index < ZZ9K_PALETTE_SIZE; index++) { 349 1.1 phx sc->red[index] = rasops_cmap[index * 3 + 0]; 350 1.1 phx sc->green[index] = rasops_cmap[index * 3 + 1]; 351 1.1 phx sc->blue[index] = rasops_cmap[index * 3 + 2]; 352 1.1 phx } 353 1.1 phx 354 1.1 phx zzfb_set_palette(sc); 355 1.1 phx } 356 1.1 phx 357 1.1 phx static void 358 1.1 phx zzfb_set_palette(struct zzfb_softc *sc) 359 1.1 phx { 360 1.1 phx uint32_t palette; 361 1.1 phx uint8_t rVal; 362 1.1 phx uint8_t gVal; 363 1.1 phx uint8_t bVal; 364 1.1 phx 365 1.1 phx for (int index = 0; index < ZZ9K_PALETTE_SIZE; index++) { 366 1.1 phx rVal = sc->red[index]; 367 1.1 phx gVal = sc->green[index]; 368 1.1 phx bVal = sc->blue[index]; 369 1.1 phx palette = ((index << 24) | (rVal << 16) | (gVal << 8) | bVal); 370 1.1 phx ZZREG_W(ZZ9K_VIDEO_CTRL_DATA_HI, palette >> 16); 371 1.1 phx ZZREG_W(ZZ9K_VIDEO_CTRL_DATA_LO, palette & 0xFFFF); 372 1.1 phx ZZREG_W(ZZ9K_VIDEO_CTRL_OP, ZZ9K_OP_PALETTE); 373 1.1 phx ZZREG_W(ZZ9K_VIDEO_CTRL_OP, ZZ9K_OP_NOP); 374 1.1 phx } 375 1.1 phx } 376 1.1 phx 377 1.1 phx static void 378 1.1 phx zzfb_init_screen(void *cookie, struct vcons_screen *scr, int existing, 379 1.1 phx long *defattr) 380 1.1 phx { 381 1.1 phx struct zzfb_softc *sc = cookie; 382 1.1 phx struct rasops_info *ri = &scr->scr_ri; 383 1.1 phx 384 1.1 phx scr->scr_flags = VCONS_SCREEN_IS_STATIC; 385 1.1 phx 386 1.1 phx wsfont_init(); 387 1.1 phx 388 1.1 phx ri->ri_bits = (u_char *)bus_space_vaddr(sc->sc_iot, sc->sc_fbh); 389 1.1 phx ri->ri_depth = sc->sc_bpp; 390 1.1 phx ri->ri_width = sc->sc_width; 391 1.1 phx ri->ri_height = sc->sc_height; 392 1.1 phx ri->ri_stride = sc->sc_stride; 393 1.1 phx ri->ri_flg = 0; 394 1.1 phx 395 1.1 phx if (ri->ri_depth == 32) { /* adjust for BGRA8888 */ 396 1.1 phx ri->ri_rnum = 8; /* for other depths default is OK */ 397 1.1 phx ri->ri_gnum = 8; 398 1.1 phx ri->ri_bnum = 8; 399 1.1 phx ri->ri_rpos = 8; /* skip over alpha channel */ 400 1.1 phx ri->ri_gpos = 8 + ri->ri_rnum; 401 1.1 phx ri->ri_bpos = 8 + ri->ri_rnum + ri->ri_gnum; 402 1.1 phx } 403 1.1 phx 404 1.1 phx rasops_init(ri, 0, 0); 405 1.1 phx ri->ri_caps = WSSCREEN_WSCOLORS; 406 1.1 phx rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 407 1.1 phx ri->ri_width / ri->ri_font->fontwidth); 408 1.1 phx ri->ri_hw = scr; 409 1.1 phx 410 1.1 phx ri->ri_ops.eraserows = zzfb_eraserows; 411 1.1 phx ri->ri_ops.copyrows = zzfb_copyrows; 412 1.1 phx ri->ri_ops.erasecols = zzfb_erasecols; 413 1.1 phx ri->ri_ops.copycols = zzfb_copycols; 414 1.1 phx } 415 1.1 phx 416 1.1 phx static void 417 1.1 phx zzfb_set_capture(struct zzfb_softc *sc, uint16_t display_mode, 418 1.1 phx uint16_t capture_mode) 419 1.1 phx { 420 1.1 phx uint16_t panPtrHi; 421 1.1 phx uint16_t panPtrLo; 422 1.1 phx uint16_t new_mode; 423 1.1 phx 424 1.1 phx switch (display_mode) { 425 1.1 phx case ZZ9K_MODE_720x480: /* NTSC */ 426 1.1 phx panPtrHi = ZZ9K_CAPTURE_PAN_NTSC >> 16; 427 1.1 phx panPtrLo = ZZ9K_CAPTURE_PAN_NTSC & 0xFFFF; 428 1.1 phx break; 429 1.1 phx case ZZ9K_MODE_720x576p50: /* PAL */ 430 1.1 phx panPtrHi = ZZ9K_CAPTURE_PAN_PAL >> 16; 431 1.1 phx panPtrLo = ZZ9K_CAPTURE_PAN_PAL & 0xFFFF; 432 1.1 phx break; 433 1.1 phx case ZZ9K_MODE_800x600: /* VGA */ 434 1.1 phx panPtrHi = ZZ9K_CAPTURE_PAN_VGA >> 16; 435 1.1 phx panPtrLo = ZZ9K_CAPTURE_PAN_VGA & 0xFFFF; 436 1.1 phx break; 437 1.1 phx default: 438 1.1 phx aprint_error_dev(sc->sc_dev, "Unsupported scandoubler " 439 1.1 phx "capture and display mode combination.\n"); 440 1.1 phx return; 441 1.1 phx } 442 1.1 phx new_mode = ZZ9K_MODE_SCALE_2 | ZZ9K_MODE_COLOR_32BIT | display_mode; 443 1.1 phx zzfb_wait_vblank(sc); 444 1.1 phx ZZREG_W(ZZ9K_VIDEOCAP_VMODE, capture_mode); 445 1.1 phx ZZREG_W(ZZ9K_BLITTER_USER1, ZZ9K_FEATURE_NONSTANDARD_VSYNC); 446 1.1 phx ZZREG_W(ZZ9K_SET_FEATURE, 0x0000); 447 1.1 phx ZZREG_W(ZZ9K_VIDEO_CAPTURE_MODE, ZZ9K_CAPTURE_ON); 448 1.1 phx ZZREG_W(ZZ9K_BLITTER_X1, 0x0000); 449 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y1, 0x0000); 450 1.1 phx ZZREG_W(ZZ9K_BLITTER_X2, 0x0000); 451 1.1 phx ZZREG_W(ZZ9K_BLITTER_COLORMODE, ZZ9K_COLOR_32BIT); 452 1.1 phx ZZREG_W(ZZ9K_PAN_PTR_HI, panPtrHi); 453 1.1 phx ZZREG_W(ZZ9K_PAN_PTR_LO, panPtrLo); 454 1.1 phx ZZREG_W(ZZ9K_MODE, new_mode); 455 1.1 phx sc->sc_isrtg = false; 456 1.1 phx } 457 1.1 phx 458 1.1 phx void 459 1.1 phx zzfb_set_mode(struct zzfb_softc *sc, uint16_t display_mode, 460 1.1 phx uint16_t color_mode) 461 1.1 phx { 462 1.1 phx uint16_t new_mode; 463 1.1 phx 464 1.1 phx if ((display_mode < 0) || (display_mode >= ZZFB_MODES_SIZE)) 465 1.1 phx display_mode = ZZ9K_MODE_1280x720; 466 1.1 phx 467 1.1 phx sc->sc_width = zzfb_modes[display_mode].width; 468 1.1 phx sc->sc_height = zzfb_modes[display_mode].height; 469 1.1 phx new_mode = zzfb_modes[display_mode].scale; 470 1.1 phx 471 1.1 phx if ((color_mode < 0) || (color_mode >= ZZFB_COLORS_SIZE)) 472 1.1 phx color_mode = ZZ9K_COLOR_8BIT; 473 1.1 phx 474 1.1 phx if ((color_mode == ZZ9K_COLOR_32BIT) && (sc->sc_width > 1920)) 475 1.1 phx color_mode = ZZ9K_COLOR_16BIT; 476 1.1 phx 477 1.1 phx sc->sc_bpp = zzfb_colors[color_mode].bpp; 478 1.1 phx sc->sc_stride = sc->sc_width * zzfb_colors[color_mode].stride; 479 1.1 phx new_mode = new_mode | zzfb_colors[color_mode].mode | display_mode; 480 1.1 phx 481 1.1 phx sc->sc_displaymode = display_mode; 482 1.1 phx sc->sc_colormode = color_mode; 483 1.1 phx 484 1.1 phx zzfb_wait_vblank(sc); 485 1.1 phx ZZREG_W(ZZ9K_VIDEO_CAPTURE_MODE, ZZ9K_CAPTURE_OFF); 486 1.1 phx ZZREG_W(ZZ9K_BLITTER_X1, 0x0000); 487 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y1, 0x0000); 488 1.1 phx ZZREG_W(ZZ9K_BLITTER_X2, 0x0000); 489 1.1 phx ZZREG_W(ZZ9K_BLITTER_COLORMODE, color_mode); 490 1.1 phx ZZREG_W(ZZ9K_BLITTER_SRC_HI, 0x0000); 491 1.1 phx ZZREG_W(ZZ9K_BLITTER_SRC_LO, 0x0000); 492 1.1 phx ZZREG_W(ZZ9K_BLITTER_DST_HI, 0x0000); 493 1.1 phx ZZREG_W(ZZ9K_BLITTER_DST_LO, 0x0000); 494 1.1 phx ZZREG_W(ZZ9K_BLITTER_SPLIT_POS, 0x0000); 495 1.1 phx ZZREG_W(ZZ9K_PAN_PTR_HI, 0x0000); 496 1.1 phx ZZREG_W(ZZ9K_PAN_PTR_LO, 0x0000); 497 1.1 phx ZZREG_W(ZZ9K_MODE, new_mode); 498 1.1 phx sc->sc_isrtg = true; 499 1.1 phx } 500 1.1 phx 501 1.1 phx static void 502 1.1 phx zzfb_wait_vblank(struct zzfb_softc *sc) 503 1.1 phx { 504 1.1 phx uint16_t vb_status = ZZREG_R(ZZ9K_VIDEO_BLANK_STATUS); 505 1.1 phx while (vb_status != 0) 506 1.1 phx vb_status = ZZREG_R(ZZ9K_VIDEO_BLANK_STATUS); 507 1.1 phx while (vb_status == 0) 508 1.1 phx vb_status = ZZREG_R(ZZ9K_VIDEO_BLANK_STATUS); 509 1.1 phx } 510 1.1 phx 511 1.1 phx static void 512 1.1 phx zzfb_clearbg(struct zzfb_softc *sc, uint8_t color_index) 513 1.1 phx { 514 1.1 phx if (color_index >= ZZ9K_PALETTE_SIZE) 515 1.1 phx color_index = 0; 516 1.1 phx 517 1.1 phx uint32_t palette = 0; 518 1.1 phx uint8_t rVal = rasops_cmap[color_index * 3 + 0]; 519 1.1 phx uint8_t gVal = rasops_cmap[color_index * 3 + 1]; 520 1.1 phx uint8_t bVal = rasops_cmap[color_index * 3 + 2]; 521 1.1 phx 522 1.1 phx switch (sc->sc_colormode) { 523 1.1 phx case ZZ9K_COLOR_32BIT: /* BGRA8888 */ 524 1.1 phx palette = ((bVal << 24) | (gVal << 16) | (rVal << 8) | 0xFF); 525 1.1 phx break; 526 1.1 phx case ZZ9K_COLOR_16BIT: /* RGB565 at high word, don't ask why. */ 527 1.1 phx palette = (((rVal & 0xF8) << 8) | 528 1.1 phx ((gVal & 0xFC) << 3) | 529 1.1 phx ((bVal >> 3) & 0x1F) ) << 16; 530 1.1 phx break; 531 1.1 phx case ZZ9K_COLOR_15BIT: /* ARGB1555 at high word, don't ask why. */ 532 1.1 phx palette = ((0x8000) | 533 1.1 phx ((rVal & 0xF8) << 7) | 534 1.1 phx ((gVal & 0xF8) << 2) | 535 1.1 phx ((bVal >> 3) & 0x1F) ) << 16; 536 1.1 phx break; 537 1.1 phx case ZZ9K_COLOR_8BIT: /* 256 LUT */ 538 1.1 phx default: 539 1.1 phx palette = color_index; 540 1.1 phx break; 541 1.1 phx } 542 1.1 phx 543 1.1 phx zzfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, palette); 544 1.1 phx } 545 1.1 phx 546 1.1 phx static void 547 1.1 phx zzfb_rectfill(struct zzfb_softc *sc, uint16_t x, uint16_t y, 548 1.1 phx uint16_t w, uint16_t h, uint32_t color) 549 1.1 phx { 550 1.1 phx ZZREG_W(ZZ9K_BLITTER_X1, x); 551 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y1, y); 552 1.1 phx ZZREG_W(ZZ9K_BLITTER_X2, w); 553 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y2, h); 554 1.1 phx ZZREG_W(ZZ9K_BLITTER_ROW_PITCH, sc->sc_stride >> 2); 555 1.1 phx ZZREG_W(ZZ9K_BLITTER_COLORMODE, sc->sc_colormode); 556 1.1 phx ZZREG_W(ZZ9K_BLITTER_RGB_HI, color >> 16); 557 1.1 phx ZZREG_W(ZZ9K_BLITTER_RGB_LO, color & 0xFFFF); 558 1.1 phx ZZREG_W(ZZ9K_BLITTER_OP_FILLRECT, 0x00FF); 559 1.1 phx } 560 1.1 phx 561 1.1 phx static void 562 1.1 phx zzfb_bitblt(struct zzfb_softc *sc, uint16_t x, uint16_t y, uint16_t w, 563 1.1 phx uint16_t h, uint16_t xs, uint16_t ys) 564 1.1 phx { 565 1.1 phx ZZREG_W(ZZ9K_BLITTER_X1, x); 566 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y1, y); 567 1.1 phx ZZREG_W(ZZ9K_BLITTER_X2, w); 568 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y2, h); 569 1.1 phx ZZREG_W(ZZ9K_BLITTER_X3, xs); 570 1.1 phx ZZREG_W(ZZ9K_BLITTER_Y3, ys); 571 1.1 phx ZZREG_W(ZZ9K_BLITTER_ROW_PITCH, sc->sc_stride >> 2); 572 1.1 phx ZZREG_W(ZZ9K_BLITTER_COLORMODE, (0xFF << 8) | sc->sc_colormode); 573 1.1 phx ZZREG_W(ZZ9K_BLITTER_OP_COPYRECT, ZZ9K_OPT_REGULAR); 574 1.1 phx } 575 1.1 phx 576 1.1 phx static void 577 1.1 phx zzfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 578 1.1 phx { 579 1.1 phx struct rasops_info *ri = cookie; 580 1.1 phx struct vcons_screen *scr = ri->ri_hw; 581 1.1 phx struct zzfb_softc *sc = scr->scr_cookie; 582 1.1 phx int x, y, w, h, ys; 583 1.1 phx 584 1.1 phx if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 585 1.1 phx x = ri->ri_xorigin; 586 1.1 phx ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 587 1.1 phx y = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 588 1.1 phx w = ri->ri_emuwidth; 589 1.1 phx h = ri->ri_font->fontheight * nrows; 590 1.1 phx zzfb_bitblt(sc, x, y, w, h, x, ys); 591 1.1 phx } 592 1.1 phx } 593 1.1 phx 594 1.1 phx static void 595 1.1 phx zzfb_eraserows(void *cookie, int row, int nrows, long fillattr) 596 1.1 phx { 597 1.1 phx struct rasops_info *ri = cookie; 598 1.1 phx struct vcons_screen *scr = ri->ri_hw; 599 1.1 phx struct zzfb_softc *sc = scr->scr_cookie; 600 1.1 phx int x, y, w, h, fg, bg, ul; 601 1.1 phx 602 1.1 phx if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 603 1.1 phx x = ri->ri_xorigin; 604 1.1 phx y = ri->ri_yorigin + ri->ri_font->fontheight * row; 605 1.1 phx w = ri->ri_emuwidth; 606 1.1 phx h = ri->ri_font->fontheight * nrows; 607 1.1 phx rasops_unpack_attr(fillattr, &fg, &bg, &ul); 608 1.1 phx zzfb_rectfill(sc, x, y, w, h, ri->ri_devcmap[bg]); 609 1.1 phx } 610 1.1 phx } 611 1.1 phx 612 1.1 phx static void 613 1.1 phx zzfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 614 1.1 phx { 615 1.1 phx struct rasops_info *ri = cookie; 616 1.1 phx struct vcons_screen *scr = ri->ri_hw; 617 1.1 phx struct zzfb_softc *sc = scr->scr_cookie; 618 1.1 phx int x, y, w, h, xs; 619 1.1 phx 620 1.1 phx if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 621 1.1 phx xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 622 1.1 phx x = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 623 1.1 phx y = ri->ri_yorigin + ri->ri_font->fontheight * row; 624 1.1 phx w = ri->ri_font->fontwidth * ncols; 625 1.1 phx h = ri->ri_font->fontheight; 626 1.1 phx zzfb_bitblt(sc, x, y, w, h, xs, y); 627 1.1 phx } 628 1.1 phx } 629 1.1 phx 630 1.1 phx static void 631 1.1 phx zzfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 632 1.1 phx { 633 1.1 phx struct rasops_info *ri = cookie; 634 1.1 phx struct vcons_screen *scr = ri->ri_hw; 635 1.1 phx struct zzfb_softc *sc = scr->scr_cookie; 636 1.1 phx int x, y, w, h, fg, bg, ul; 637 1.1 phx 638 1.1 phx if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 639 1.1 phx x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 640 1.1 phx y = ri->ri_yorigin + ri->ri_font->fontheight * row; 641 1.1 phx w = ri->ri_font->fontwidth * ncols; 642 1.1 phx h = ri->ri_font->fontheight; 643 1.1 phx rasops_unpack_attr(fillattr, &fg, &bg, &ul); 644 1.1 phx zzfb_rectfill(sc, x, y, w, h, ri->ri_devcmap[bg & 0xf]); 645 1.1 phx } 646 1.1 phx } 647 1.1 phx 648 1.1 phx static int 649 1.1 phx zzfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 650 1.1 phx { 651 1.1 phx int retval = 0; 652 1.1 phx u_int new_wsmode; 653 1.1 phx struct vcons_data *vd = v; 654 1.1 phx struct zzfb_softc *sc = vd->cookie; 655 1.1 phx struct vcons_screen *scr = vd->active; 656 1.1 phx struct wsdisplayio_bus_id *busid; 657 1.1 phx 658 1.1 phx switch (cmd) { 659 1.1 phx case WSDISPLAYIO_GTYPE: 660 1.1 phx *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; 661 1.1 phx break; 662 1.1 phx case WSDISPLAYIO_GET_FBINFO: 663 1.1 phx retval = zzfb_get_fbinfo(sc, (struct wsdisplayio_fbinfo *)data); 664 1.1 phx break; 665 1.1 phx case WSDISPLAYIO_GINFO: 666 1.1 phx ((struct wsdisplay_fbinfo *)data)->width = sc->sc_width; 667 1.1 phx ((struct wsdisplay_fbinfo *)data)->height = sc->sc_height; 668 1.1 phx ((struct wsdisplay_fbinfo *)data)->depth = sc->sc_bpp; 669 1.1 phx ((struct wsdisplay_fbinfo *)data)->cmsize = ZZ9K_PALETTE_SIZE; 670 1.1 phx break; 671 1.1 phx case WSDISPLAYIO_GETCMAP: 672 1.1 phx retval = zzfb_getcmap(sc, (struct wsdisplay_cmap *)data); 673 1.1 phx break; 674 1.1 phx case WSDISPLAYIO_PUTCMAP: 675 1.1 phx retval = zzfb_putcmap(sc, (struct wsdisplay_cmap *)data); 676 1.1 phx break; 677 1.1 phx case WSDISPLAYIO_GVIDEO: 678 1.1 phx *(int *)data = (sc->sc_isrtg == true) ? 679 1.1 phx WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 680 1.1 phx break; 681 1.1 phx case WSDISPLAYIO_SVIDEO: 682 1.1 phx if (*(int *)data == WSDISPLAYIO_VIDEO_ON) { 683 1.1 phx zzfb_set_mode(sc, sc->sc_displaymode, sc->sc_colormode); 684 1.1 phx } else { 685 1.1 phx zzfb_set_capture(sc, ZZFB_DISPLAY_MODE, 686 1.1 phx ZZFB_CAPTURE_MODE); 687 1.1 phx } 688 1.1 phx break; 689 1.1 phx case WSDISPLAYIO_GET_BUSID: 690 1.1 phx busid = data; 691 1.1 phx busid->bus_type = WSDISPLAYIO_BUS_SOC; 692 1.1 phx break; 693 1.1 phx case WSDISPLAYIO_GCURPOS: 694 1.1 phx case WSDISPLAYIO_SCURPOS: 695 1.1 phx case WSDISPLAYIO_GCURMAX: 696 1.1 phx case WSDISPLAYIO_GCURSOR: 697 1.1 phx case WSDISPLAYIO_SCURSOR: 698 1.1 phx retval = EPASSTHROUGH; 699 1.1 phx break; 700 1.1 phx case WSDISPLAYIO_GMODE: 701 1.1 phx *(u_int *)data = sc->sc_wsmode; 702 1.1 phx break; 703 1.1 phx case WSDISPLAYIO_SMODE: 704 1.1 phx new_wsmode = *(u_int *)data; 705 1.1 phx if (new_wsmode != sc->sc_wsmode) { 706 1.1 phx switch (new_wsmode) { 707 1.1 phx case WSDISPLAYIO_MODE_EMUL: 708 1.1 phx zzfb_set_mode(sc, 709 1.1 phx ZZFB_SET_CON_MODE, ZZFB_SET_CON_BPP); 710 1.1 phx zzfb_init_palette(sc); 711 1.1 phx zzfb_clearbg(sc, WS_DEFAULT_BG); 712 1.1 phx vcons_redraw_screen(scr); 713 1.1 phx sc->sc_wsmode = new_wsmode; 714 1.1 phx break; 715 1.1 phx case WSDISPLAYIO_MODE_MAPPED: 716 1.1 phx zzfb_set_mode(sc, 717 1.1 phx ZZFB_SET_GFX_MODE, ZZFB_SET_GFX_BPP); 718 1.1 phx zzfb_clearbg(sc, WSCOL_BLACK); 719 1.1 phx sc->sc_wsmode = new_wsmode; 720 1.1 phx break; 721 1.1 phx case WSDISPLAYIO_MODE_DUMBFB: 722 1.1 phx zzfb_set_mode(sc, 723 1.1 phx ZZFB_SET_DFB_MODE, ZZFB_SET_DFB_BPP); 724 1.1 phx zzfb_clearbg(sc, WSCOL_BLACK); 725 1.1 phx sc->sc_wsmode = new_wsmode; 726 1.1 phx break; 727 1.1 phx default: 728 1.1 phx retval = EINVAL; 729 1.1 phx break; 730 1.1 phx } 731 1.1 phx } else { 732 1.1 phx retval = EINVAL; 733 1.1 phx } 734 1.1 phx break; 735 1.1 phx case WSDISPLAYIO_LINEBYTES: 736 1.1 phx *(u_int *)data = sc->sc_stride; 737 1.1 phx break; 738 1.1 phx case WSDISPLAYIO_GMSGATTRS: 739 1.1 phx case WSDISPLAYIO_SMSGATTRS: 740 1.1 phx case WSDISPLAYIO_GBORDER: 741 1.1 phx case WSDISPLAYIO_SBORDER: 742 1.1 phx case WSDISPLAYIO_GETWSCHAR: 743 1.1 phx case WSDISPLAYIO_PUTWSCHAR: 744 1.1 phx case WSDISPLAYIO_SSPLASH: 745 1.1 phx case WSDISPLAYIO_GET_EDID: 746 1.1 phx case WSDISPLAYIO_SETVERSION: 747 1.1 phx default: 748 1.1 phx retval = EPASSTHROUGH; 749 1.1 phx break; 750 1.1 phx } 751 1.1 phx 752 1.1 phx return retval; 753 1.1 phx } 754 1.1 phx 755 1.1 phx static paddr_t 756 1.1 phx zzfb_mmap(void *v, void *vs, off_t offset, int prot) 757 1.1 phx { 758 1.1 phx struct vcons_data *vd = v; 759 1.1 phx struct zzfb_softc *sc = vd->cookie; 760 1.1 phx 761 1.1 phx if ( (offset >= 0) && (offset < sc->sc_fbsize) ) { 762 1.1 phx return bus_space_mmap( sc->sc_iot, 763 1.1 phx (bus_addr_t)kvtop((void *)sc->sc_fbh), offset, prot, 764 1.1 phx BUS_SPACE_MAP_LINEAR); 765 1.1 phx } else { 766 1.1 phx return -1; 767 1.1 phx } 768 1.1 phx } 769 1.1 phx 770 1.1 phx static int 771 1.1 phx zzfb_get_fbinfo(struct zzfb_softc *sc, struct wsdisplayio_fbinfo *fbi) 772 1.1 phx { 773 1.1 phx uint32_t bpA, bpR, bpG, bpB; 774 1.1 phx 775 1.1 phx switch (sc->sc_bpp) { 776 1.1 phx case 8: 777 1.1 phx bpA = 0; bpR = 0; bpG = 0; bpB = 0; 778 1.1 phx break; 779 1.1 phx case 15: 780 1.1 phx bpA = 1; bpR = 5; bpG = 5; bpB = 5; 781 1.1 phx break; 782 1.1 phx case 16: 783 1.1 phx bpA = 0; bpR = 5; bpG = 6; bpB = 5; 784 1.1 phx break; 785 1.1 phx case 32: 786 1.1 phx bpA = 8; bpR = 8; bpG = 8; bpB = 8; 787 1.1 phx break; 788 1.1 phx default: 789 1.1 phx return EINVAL; 790 1.1 phx } 791 1.1 phx 792 1.1 phx fbi->fbi_flags = 0; 793 1.1 phx fbi->fbi_fboffset = 0; 794 1.1 phx fbi->fbi_fbsize = sc->sc_stride * sc->sc_height; 795 1.1 phx fbi->fbi_width = sc->sc_width; 796 1.1 phx fbi->fbi_height = sc->sc_height; 797 1.1 phx fbi->fbi_stride = sc->sc_stride; 798 1.1 phx fbi->fbi_bitsperpixel = (sc->sc_bpp == 15) ? 16 : sc->sc_bpp; 799 1.1 phx 800 1.1 phx switch (sc->sc_bpp) { 801 1.1 phx case 8: 802 1.1 phx fbi->fbi_pixeltype = WSFB_CI; 803 1.1 phx fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = ZZ9K_PALETTE_SIZE; 804 1.1 phx return 0; 805 1.1 phx case 15: /* ZZ9000 uses ARGB1555 format for 15 bpp */ 806 1.1 phx case 16: /* ZZ9000 uses RGB565 format for 16 bpp */ 807 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = bpB+bpG+bpR; 808 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.red_offset = bpB+bpG; 809 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.green_offset = bpB; 810 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0; 811 1.1 phx break; 812 1.1 phx case 32: /* ZZ9000 uses BGRA8888 format for 32 bpp */ 813 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 814 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.red_offset = bpA; 815 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.green_offset = bpA+bpR; 816 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.blue_offset = bpA+bpR+bpG; 817 1.1 phx break; 818 1.1 phx default: 819 1.1 phx return EINVAL; 820 1.1 phx } 821 1.1 phx 822 1.1 phx fbi->fbi_pixeltype = WSFB_RGB; 823 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.alpha_size = bpA; 824 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.red_size = bpR; 825 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.green_size = bpG; 826 1.1 phx fbi->fbi_subtype.fbi_rgbmasks.blue_size = bpB; 827 1.1 phx 828 1.1 phx return 0; 829 1.1 phx } 830 1.1 phx 831 1.1 phx static int 832 1.1 phx zzfb_getcmap(struct zzfb_softc *sc, struct wsdisplay_cmap *cm) 833 1.1 phx { 834 1.1 phx int retval = 0; 835 1.1 phx u_int index = cm->index; 836 1.1 phx u_int count = cm->count; 837 1.1 phx 838 1.1 phx if (index >= ZZ9K_PALETTE_SIZE || index + count > ZZ9K_PALETTE_SIZE) 839 1.1 phx return EINVAL; 840 1.1 phx 841 1.1 phx retval = copyout(&sc->red[index], cm->red, count); 842 1.1 phx if (retval != 0) 843 1.1 phx return retval; 844 1.1 phx 845 1.1 phx retval = copyout(&sc->green[index], cm->green, count); 846 1.1 phx if (retval != 0) 847 1.1 phx return retval; 848 1.1 phx 849 1.1 phx retval = copyout(&sc->blue[index], cm->blue, count); 850 1.1 phx if (retval != 0) 851 1.1 phx return retval; 852 1.1 phx 853 1.1 phx return retval; 854 1.1 phx } 855 1.1 phx 856 1.1 phx static int 857 1.1 phx zzfb_putcmap(struct zzfb_softc *sc, struct wsdisplay_cmap *cm) 858 1.1 phx { 859 1.1 phx int retval = 0; 860 1.1 phx u_int index = cm->index; 861 1.1 phx u_int count = cm->count; 862 1.1 phx 863 1.1 phx if (index >= ZZ9K_PALETTE_SIZE || index + count > ZZ9K_PALETTE_SIZE) 864 1.1 phx return EINVAL; 865 1.1 phx 866 1.1 phx retval = copyin(cm->red, &sc->red[index], count); 867 1.1 phx if (retval != 0) 868 1.1 phx return retval; 869 1.1 phx 870 1.1 phx retval = copyin(cm->green, &sc->green[index], count); 871 1.1 phx if (retval != 0) 872 1.1 phx return retval; 873 1.1 phx 874 1.1 phx retval = copyin(cm->blue, &sc->blue[index], count); 875 1.1 phx if (retval != 0) 876 1.1 phx return retval; 877 1.1 phx 878 1.1 phx zzfb_set_palette(sc); 879 1.1 phx return retval; 880 1.1 phx } 881 1.1 phx 882 1.1 phx /* 883 1.1 phx * Early console handling, associated with amiga/conf.c file which holds a 884 1.1 phx * table of all console devices. The below functions ensures that ZZ9000 becomes 885 1.1 phx * wsdisplay0 and wskbd0 gets attached to it. 886 1.1 phx */ 887 1.1 phx 888 1.1 phx /* early console handling */ 889 1.1 phx void zzfb_cnprobe(struct consdev *cd); 890 1.1 phx void zzfb_cninit(struct consdev *cd); 891 1.1 phx void zzfb_cnpollc(dev_t cd, int on); 892 1.1 phx void zzfb_cnputc(dev_t cd, int ch); 893 1.1 phx int zzfb_cngetc(dev_t cd); 894 1.1 phx 895 1.1 phx void 896 1.1 phx zzfb_cnprobe(struct consdev *cd) 897 1.1 phx { 898 1.1 phx #ifdef ZZFB_CONSOLE 899 1.1 phx if (zz9k_exists == true) { 900 1.1 phx cd->cn_pri = CN_INTERNAL; 901 1.1 phx } else { 902 1.1 phx cd->cn_pri = CN_DEAD; 903 1.1 phx } 904 1.1 phx cd->cn_dev = NODEV; 905 1.1 phx #endif /* ZZFB_CONSOLE */ 906 1.1 phx } 907 1.1 phx 908 1.1 phx void 909 1.1 phx zzfb_cninit(struct consdev *cd) 910 1.1 phx { 911 1.1 phx #if defined ZZFB_CONSOLE && NKBD > 0 912 1.1 phx /* tell kbd device it is used as console keyboard */ 913 1.1 phx if (zz9k_exists == true) 914 1.1 phx kbd_cnattach(); 915 1.1 phx #endif /* ZZFB_CONSOLE && NKBD > 0 */ 916 1.1 phx } 917 1.1 phx 918 1.1 phx void 919 1.1 phx zzfb_cnpollc(dev_t cd, int on) 920 1.1 phx { 921 1.1 phx } 922 1.1 phx 923 1.1 phx void 924 1.1 phx zzfb_cnputc(dev_t cd, int ch) 925 1.1 phx { 926 1.1 phx } 927 1.1 phx 928 1.1 phx int 929 1.1 phx zzfb_cngetc(dev_t cd) 930 1.1 phx { 931 1.1 phx return 0; 932 1.1 phx } 933