Index: stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c =================================================================== --- stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 356109) +++ stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 356110) @@ -1,870 +1,851 @@ /*- * Copyright (c) 2012 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mbox_if.h" struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb bcmfb_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define BCMFB_FONT_HEIGHT 16 #define BCMFB_FONT_WIDTH 8 #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 24 struct bcmsc_softc { /* Videoadpater part */ video_adapter_t va; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int fbswap; int initialized; }; static struct bcmsc_softc bcmsc; static struct ofw_compat_data compat_data[] = { {"broadcom,bcm2835-fb", 1}, {"brcm,bcm2708-fb", 1}, {NULL, 0} }; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); static void bcmfb_update_margins(video_adapter_t *adp); static int bcmfb_configure(int); static int bcm_fb_probe(device_t dev) { int error; if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); device_set_desc(dev, "BCM2835 framebuffer device"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); return (BUS_PROBE_DEFAULT); } static int bcm_fb_attach(device_t dev) { struct bcm2835_fb_config fb; struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter( "bcmfb", 0)); if (sc != NULL) device_set_softc(dev, sc); else sc = device_get_softc(dev); memset(&fb, 0, sizeof(fb)); if (bcm2835_mbox_fb_get_w_h(&fb) != 0) return (ENXIO); fb.bpp = FB_DEPTH; fb.vxres = fb.xres; fb.vyres = fb.yres; fb.xoffset = fb.yoffset = 0; if (bcm2835_mbox_fb_init(&fb) != 0) return (ENXIO); sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size); sc->fb_paddr = fb.base; sc->fb_size = fb.size; sc->depth = fb.bpp; sc->stride = fb.pitch; sc->width = fb.xres; sc->height = fb.yres; bcmfb_update_margins(&sc->va); if (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) { device_printf(dev, "failed to attach syscons\n"); return (ENXIO); } device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); device_printf(dev, "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", sc->fbswap, fb.pitch, fb.base, fb.size); return (0); } static device_method_t bcm_fb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcm_fb_probe), DEVMETHOD(device_attach, bcm_fb_attach), { 0, 0 } }; static devclass_t bcm_fb_devclass; static driver_t bcm_fb_driver = { "fb", bcm_fb_methods, sizeof(struct bcmsc_softc), }; DRIVER_MODULE(bcm2835fb, ofwbus, bcm_fb_driver, bcm_fb_devclass, 0, 0); DRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0); /* * Video driver routines and glue. */ static vi_probe_t bcmfb_probe; static vi_init_t bcmfb_init; static vi_get_info_t bcmfb_get_info; static vi_query_mode_t bcmfb_query_mode; static vi_set_mode_t bcmfb_set_mode; static vi_save_font_t bcmfb_save_font; static vi_load_font_t bcmfb_load_font; static vi_show_font_t bcmfb_show_font; static vi_save_palette_t bcmfb_save_palette; static vi_load_palette_t bcmfb_load_palette; static vi_set_border_t bcmfb_set_border; static vi_save_state_t bcmfb_save_state; static vi_load_state_t bcmfb_load_state; static vi_set_win_org_t bcmfb_set_win_org; static vi_read_hw_cursor_t bcmfb_read_hw_cursor; static vi_set_hw_cursor_t bcmfb_set_hw_cursor; static vi_set_hw_cursor_shape_t bcmfb_set_hw_cursor_shape; static vi_blank_display_t bcmfb_blank_display; static vi_mmap_t bcmfb_mmap; static vi_ioctl_t bcmfb_ioctl; static vi_clear_t bcmfb_clear; static vi_fill_rect_t bcmfb_fill_rect; static vi_bitblt_t bcmfb_bitblt; static vi_diag_t bcmfb_diag; static vi_save_cursor_palette_t bcmfb_save_cursor_palette; static vi_load_cursor_palette_t bcmfb_load_cursor_palette; static vi_copy_t bcmfb_copy; static vi_putp_t bcmfb_putp; static vi_putc_t bcmfb_putc; static vi_puts_t bcmfb_puts; static vi_putm_t bcmfb_putm; static video_switch_t bcmfbvidsw = { .probe = bcmfb_probe, .init = bcmfb_init, .get_info = bcmfb_get_info, .query_mode = bcmfb_query_mode, .set_mode = bcmfb_set_mode, .save_font = bcmfb_save_font, .load_font = bcmfb_load_font, .show_font = bcmfb_show_font, .save_palette = bcmfb_save_palette, .load_palette = bcmfb_load_palette, .set_border = bcmfb_set_border, .save_state = bcmfb_save_state, .load_state = bcmfb_load_state, .set_win_org = bcmfb_set_win_org, .read_hw_cursor = bcmfb_read_hw_cursor, .set_hw_cursor = bcmfb_set_hw_cursor, .set_hw_cursor_shape = bcmfb_set_hw_cursor_shape, .blank_display = bcmfb_blank_display, .mmap = bcmfb_mmap, .ioctl = bcmfb_ioctl, .clear = bcmfb_clear, .fill_rect = bcmfb_fill_rect, .bitblt = bcmfb_bitblt, .diag = bcmfb_diag, .save_cursor_palette = bcmfb_save_cursor_palette, .load_cursor_palette = bcmfb_load_cursor_palette, .copy = bcmfb_copy, .putp = bcmfb_putp, .putc = bcmfb_putc, .puts = bcmfb_puts, .putm = bcmfb_putm, }; VIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure); static vr_init_t bcmrend_init; static vr_clear_t bcmrend_clear; static vr_draw_border_t bcmrend_draw_border; static vr_draw_t bcmrend_draw; static vr_set_cursor_t bcmrend_set_cursor; static vr_draw_cursor_t bcmrend_draw_cursor; static vr_blink_cursor_t bcmrend_blink_cursor; static vr_set_mouse_t bcmrend_set_mouse; static vr_draw_mouse_t bcmrend_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t bcmrend = { bcmrend_init, bcmrend_clear, bcmrend_draw_border, bcmrend_draw, bcmrend_set_cursor, bcmrend_draw_cursor, bcmrend_blink_cursor, bcmrend_set_mouse, bcmrend_draw_mouse }; RENDERER(bcmfb, 0, bcmrend, gfb_set); RENDERER_MODULE(bcmfb, gfb_set); static void bcmrend_init(scr_stat* scp) { } static void bcmrend_clear(scr_stat* scp, int c, int attr) { } static void bcmrend_draw_border(scr_stat* scp, int color) { } static void bcmrend_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { int bytes, col, i, j, row; struct bcmsc_softc *sc; uint8_t *addr; video_adapter_t *adp; adp = scp->sc->adp; sc = (struct bcmsc_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); bytes = sc->depth / 8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { switch (sc->depth) { case 32: case 24: addr[bytes*j + 2] ^= 0xff; /* FALLTHROUGH */ case 16: addr[bytes*j + 1] ^= 0xff; addr[bytes*j] ^= 0xff; break; default: break; } } addr += sc->stride; } } static void bcmrend_blink_cursor(scr_stat* scp, int at, int flip) { } static void bcmrend_set_mouse(scr_stat* scp) { } static void bcmrend_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t bcmfb_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void bcmfb_update_margins(video_adapter_t *adp) { struct bcmsc_softc *sc; video_info_t *vi; sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; } static int bcmfb_configure(int flags) { char bootargs[2048], *n, *p, *v; pcell_t cell; phandle_t chosen, display, root; struct bcmsc_softc *sc; sc = &bcmsc; if (sc->initialized) return (0); sc->width = 0; sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try * to fetch data from FDT bootargs, FDT display data and * finally go with defaults if everything else has failed. */ chosen = OF_finddevice("/chosen"); if (chosen != 0 && OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { p = bootargs; while ((v = strsep(&p, " ")) != NULL) { if (*v == '\0') continue; n = strsep(&v, "="); if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL) sc->width = (unsigned int)strtol(v, NULL, 0); else if (strcmp(n, "bcm2708_fb.fbheight") == 0 && v != NULL) sc->height = (unsigned int)strtol(v, NULL, 0); else if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL) if (*v == '1') sc->fbswap = 1; } } root = OF_finddevice("/"); if ((root != 0) && (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { if (sc->width == 0) { if ((OF_getencprop(display, "broadcom,width", &cell, sizeof(cell))) > 0) sc->width = cell; } if (sc->height == 0) { if ((OF_getprop(display, "broadcom,height", &cell, sizeof(cell))) > 0) sc->height = cell; } } if (sc->width == 0) sc->width = FB_WIDTH; if (sc->height == 0) sc->height = FB_HEIGHT; bcmfb_init(0, &sc->va, 0); sc->initialized = 1; return (0); } static int bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int bcmfb_init(int unit, video_adapter_t *adp, int flags) { struct bcmsc_softc *sc; video_info_t *vi; sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "bcmfb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = BCMFB_FONT_HEIGHT; vi->vi_cwidth = BCMFB_FONT_WIDTH; vi->vi_width = sc->width / vi->vi_cwidth; vi->vi_height = sc->height / vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; adp->va_window = (vm_offset_t) bcmfb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int bcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int bcmfb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int bcmfb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int bcmfb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int bcmfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; sc->font = data; return (0); } static int bcmfb_show_font(video_adapter_t *adp, int page) { return (0); } static int bcmfb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_set_border(video_adapter_t *adp, int border) { return (bcmfb_blank_display(adp, border)); } static int bcmfb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int bcmfb_load_state(video_adapter_t *adp, void *p) { return (0); } static int bcmfb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int bcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int bcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int bcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int bcmfb_blank_display(video_adapter_t *adp, int mode) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct bcmsc_softc *sc; struct fbtype *fb; sc = (struct bcmsc_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int bcmfb_clear(video_adapter_t *adp) { return (bcmfb_blank_display(adp, 0)); } static int bcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int bcmfb_bitblt(video_adapter_t *adp, ...) { return (0); } static int bcmfb_diag(video_adapter_t *adp, int level) { return (0); } static int bcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { int bytes, col, i, j, k, row; struct bcmsc_softc *sc; u_char *p; uint8_t *addr, fg, bg, color; uint16_t rgb; sc = (struct bcmsc_softc *)adp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*BCMFB_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; bytes = sc->depth / 8; for (i = 0; i < BCMFB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 32: case 24: if (sc->fbswap) { addr[bytes * j + 0] = bcmfb_palette[color].b; addr[bytes * j + 1] = bcmfb_palette[color].g; addr[bytes * j + 2] = bcmfb_palette[color].r; } else { addr[bytes * j + 0] = bcmfb_palette[color].r; addr[bytes * j + 1] = bcmfb_palette[color].g; addr[bytes * j + 2] = bcmfb_palette[color].b; } if (sc->depth == 32) addr[bytes * j + 3] = bcmfb_palette[color].a; break; case 16: rgb = (bcmfb_palette[color].r >> 3) << 11; rgb |= (bcmfb_palette[color].g >> 2) << 5; rgb |= (bcmfb_palette[color].b >> 3); addr[bytes * j] = rgb & 0xff; addr[bytes * j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int bcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int bcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t bcmdummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure); Index: stable/11/sys/arm/freescale/imx/imx51_ipuv3.c =================================================================== --- stable/11/sys/arm/freescale/imx/imx51_ipuv3.c (revision 356109) +++ stable/11/sys/arm/freescale/imx/imx51_ipuv3.c (revision 356110) @@ -1,897 +1,878 @@ /*- * Copyright (c) 2012 Oleksandr Tymoshenko * Copyright (c) 2012, 2013 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Oleksandr Rybalko * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IMX51_IPU_HSP_CLOCK 665000000 #define IPU3FB_FONT_HEIGHT 16 struct ipu3sc_softc { device_t dev; bus_addr_t pbase; bus_addr_t vbase; bus_space_tag_t iot; bus_space_handle_t ioh; bus_space_handle_t cm_ioh; bus_space_handle_t dp_ioh; bus_space_handle_t di0_ioh; bus_space_handle_t di1_ioh; bus_space_handle_t dctmpl_ioh; bus_space_handle_t dc_ioh; bus_space_handle_t dmfc_ioh; bus_space_handle_t idmac_ioh; bus_space_handle_t cpmem_ioh; }; struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; int bpp; int depth; unsigned int height; unsigned int width; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; static struct ipu3sc_softc *ipu3sc_softc; static struct video_adapter_softc va_softc; /* FIXME: not only 2 bytes color supported */ static uint16_t colors[16] = { 0x0000, /* black */ 0x001f, /* blue */ 0x07e0, /* green */ 0x07ff, /* cyan */ 0xf800, /* red */ 0xf81f, /* magenta */ 0x3800, /* brown */ 0xc618, /* light grey */ 0xc618, /* XXX: dark grey */ 0x001f, /* XXX: light blue */ 0x07e0, /* XXX: light green */ 0x07ff, /* XXX: light cyan */ 0xf800, /* XXX: light red */ 0xf81f, /* XXX: light magenta */ 0xffe0, /* yellow */ 0xffff, /* white */ }; static uint32_t colors_24[16] = { 0x000000,/* Black */ 0x000080,/* Blue */ 0x008000,/* Green */ 0x008080,/* Cyan */ 0x800000,/* Red */ 0x800080,/* Magenta */ 0xcc6600,/* brown */ 0xC0C0C0,/* Silver */ 0x808080,/* Gray */ 0x0000FF,/* Light Blue */ 0x00FF00,/* Light Green */ 0x00FFFF,/* Light Cyan */ 0xFF0000,/* Light Red */ 0xFF00FF,/* Light Magenta */ 0xFFFF00,/* Yellow */ 0xFFFFFF,/* White */ }; #define IPUV3_READ(ipuv3, module, reg) \ bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg)) #define IPUV3_WRITE(ipuv3, module, reg, val) \ bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val)) #define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40) #define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20) #define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000) #define IMX_IPU_DP0 0 #define IMX_IPU_DP1 1 #define CPMEM_CHANNEL(_dp, _ch, _w) \ (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \ CPMEM_WORD_OFFSET(_w)) #define CPMEM_OFFSET(_dp, _ch, _w, _o) \ (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o)) #define IPUV3_DEBUG 100 #ifdef IPUV3_DEBUG #define SUBMOD_DUMP_REG(_sc, _m, _l) \ { \ int i; \ printf("*** " #_m " ***\n"); \ for (i = 0; i <= (_l); i += 4) { \ if ((i % 32) == 0) \ printf("%04x: ", i & 0xffff); \ printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \ ((i + 4) % 32)?' ':'\n'); \ } \ printf("\n"); \ } #endif #ifdef IPUV3_DEBUG int ipuv3_debug = IPUV3_DEBUG; #define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else #else #define DPRINTFN(n,x) #endif static int ipu3_fb_probe(device_t); static int ipu3_fb_attach(device_t); static int ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size) { sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0); sc->pbase = vtophys(sc->vbase); return (0); } static void ipu3_fb_init(void *arg) { struct ipu3sc_softc *sc = arg; struct video_adapter_softc *va_sc = &va_softc; uint64_t w0sh96; uint32_t w1sh96; /* FW W0[137:125] - 96 = [41:29] */ /* FH W0[149:138] - 96 = [53:42] */ w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16)); w0sh96 <<= 32; w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12)); va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1; va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1; /* SLY W1[115:102] - 96 = [19:6] */ w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12)); va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1; printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride); va_sc->fb_size = va_sc->height * va_sc->stride; ipu3_fb_malloc(sc, va_sc->fb_size); /* DP1 + config_ch_23 + word_2 */ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0), ((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff); IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4), ((sc->pbase >> 3) >> 3) & 0xffffffff); va_sc->fb_addr = (intptr_t)sc->vbase; va_sc->fb_paddr = (intptr_t)sc->pbase; va_sc->bpp = va_sc->stride / va_sc->width; va_sc->depth = va_sc->bpp * 8; } static int ipu3_fb_probe(device_t dev) { int error; if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "fsl,ipu3")) return (ENXIO); device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); return (BUS_PROBE_DEFAULT); } static int ipu3_fb_attach(device_t dev) { struct ipu3sc_softc *sc = device_get_softc(dev); bus_space_tag_t iot; bus_space_handle_t ioh; phandle_t node; pcell_t reg; int err; uintptr_t base; if (ipu3sc_softc) return (ENXIO); ipu3sc_softc = sc; if (bootverbose) device_printf(dev, "clock gate status is %d\n", imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT)); sc->dev = dev; err = (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); if (err) { device_printf(dev, "failed to attach syscons\n"); goto fail; } sc = device_get_softc(dev); sc->iot = iot = fdtbus_bs_tag; /* * Retrieve the device address based on the start address in the * DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register * address, so we just subtract IPU_CM_BASE to get the offset at which * the IPU device was memory mapped. * On i.MX53, the offset is 0. */ node = ofw_bus_get_node(dev); if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0) base = 0; else base = reg - IPU_CM_BASE(0); /* map controller registers */ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh); if (err) goto fail_retarn_cm; sc->cm_ioh = ioh; /* map Display Multi FIFO Controller registers */ err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh); if (err) goto fail_retarn_dmfc; sc->dmfc_ioh = ioh; /* map Display Interface 0 registers */ err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh); if (err) goto fail_retarn_di0; sc->di0_ioh = ioh; /* map Display Interface 1 registers */ err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh); if (err) goto fail_retarn_di1; sc->di1_ioh = ioh; /* map Display Processor registers */ err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh); if (err) goto fail_retarn_dp; sc->dp_ioh = ioh; /* map Display Controller registers */ err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh); if (err) goto fail_retarn_dc; sc->dc_ioh = ioh; /* map Image DMA Controller registers */ err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0, &ioh); if (err) goto fail_retarn_idmac; sc->idmac_ioh = ioh; /* map CPMEM registers */ err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0, &ioh); if (err) goto fail_retarn_cpmem; sc->cpmem_ioh = ioh; /* map DCTEMPL registers */ err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0, &ioh); if (err) goto fail_retarn_dctmpl; sc->dctmpl_ioh = ioh; #ifdef notyet sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO, ipuv3intr, sc); if (sc->ih == NULL) { device_printf(sc->dev, "unable to establish interrupt at irq %d\n", IMX51_INT_IPUV3); return (ENXIO); } #endif /* * We have to wait until interrupts are enabled. * Mailbox relies on it to get data from VideoCore */ ipu3_fb_init(sc); return (0); fail: return (ENXIO); fail_retarn_dctmpl: bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE); fail_retarn_cpmem: bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE); fail_retarn_idmac: bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE); fail_retarn_dp: bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE); fail_retarn_dc: bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE); fail_retarn_di1: bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE); fail_retarn_di0: bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE); fail_retarn_dmfc: bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE); fail_retarn_cm: device_printf(sc->dev, "failed to map registers (errno=%d)\n", err); return (err); } static device_method_t ipu3_fb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ipu3_fb_probe), DEVMETHOD(device_attach, ipu3_fb_attach), { 0, 0 } }; static devclass_t ipu3_fb_devclass; static driver_t ipu3_fb_driver = { "fb", ipu3_fb_methods, sizeof(struct ipu3sc_softc), }; DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0); /* * Video driver routines and glue. */ static int ipu3fb_configure(int); static vi_probe_t ipu3fb_probe; static vi_init_t ipu3fb_init; static vi_get_info_t ipu3fb_get_info; static vi_query_mode_t ipu3fb_query_mode; static vi_set_mode_t ipu3fb_set_mode; static vi_save_font_t ipu3fb_save_font; static vi_load_font_t ipu3fb_load_font; static vi_show_font_t ipu3fb_show_font; static vi_save_palette_t ipu3fb_save_palette; static vi_load_palette_t ipu3fb_load_palette; static vi_set_border_t ipu3fb_set_border; static vi_save_state_t ipu3fb_save_state; static vi_load_state_t ipu3fb_load_state; static vi_set_win_org_t ipu3fb_set_win_org; static vi_read_hw_cursor_t ipu3fb_read_hw_cursor; static vi_set_hw_cursor_t ipu3fb_set_hw_cursor; static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape; static vi_blank_display_t ipu3fb_blank_display; static vi_mmap_t ipu3fb_mmap; static vi_ioctl_t ipu3fb_ioctl; static vi_clear_t ipu3fb_clear; static vi_fill_rect_t ipu3fb_fill_rect; static vi_bitblt_t ipu3fb_bitblt; static vi_diag_t ipu3fb_diag; static vi_save_cursor_palette_t ipu3fb_save_cursor_palette; static vi_load_cursor_palette_t ipu3fb_load_cursor_palette; static vi_copy_t ipu3fb_copy; static vi_putp_t ipu3fb_putp; static vi_putc_t ipu3fb_putc; static vi_puts_t ipu3fb_puts; static vi_putm_t ipu3fb_putm; static video_switch_t ipu3fbvidsw = { .probe = ipu3fb_probe, .init = ipu3fb_init, .get_info = ipu3fb_get_info, .query_mode = ipu3fb_query_mode, .set_mode = ipu3fb_set_mode, .save_font = ipu3fb_save_font, .load_font = ipu3fb_load_font, .show_font = ipu3fb_show_font, .save_palette = ipu3fb_save_palette, .load_palette = ipu3fb_load_palette, .set_border = ipu3fb_set_border, .save_state = ipu3fb_save_state, .load_state = ipu3fb_load_state, .set_win_org = ipu3fb_set_win_org, .read_hw_cursor = ipu3fb_read_hw_cursor, .set_hw_cursor = ipu3fb_set_hw_cursor, .set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape, .blank_display = ipu3fb_blank_display, .mmap = ipu3fb_mmap, .ioctl = ipu3fb_ioctl, .clear = ipu3fb_clear, .fill_rect = ipu3fb_fill_rect, .bitblt = ipu3fb_bitblt, .diag = ipu3fb_diag, .save_cursor_palette = ipu3fb_save_cursor_palette, .load_cursor_palette = ipu3fb_load_cursor_palette, .copy = ipu3fb_copy, .putp = ipu3fb_putp, .putc = ipu3fb_putc, .puts = ipu3fb_puts, .putm = ipu3fb_putm, }; VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(ipu3fb, 0, txtrndrsw, gfb_set); RENDERER_MODULE(ipu3fb, gfb_set); static uint16_t ipu3fb_static_window[ROW*COL]; extern u_char dflt_font_16[]; static int ipu3fb_configure(int flags) { struct video_adapter_softc *sc; sc = &va_softc; if (sc->initialized) return 0; sc->width = 640; sc->height = 480; sc->bpp = 2; sc->stride = sc->width * sc->bpp; ipu3fb_init(0, &sc->va, 0); sc->initialized = 1; return (0); } static int ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int ipu3fb_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "ipu3fb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = IPU3FB_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) ipu3fb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; adp->va_line_width = sc->stride; adp->va_buffer_size = sc->fb_size; vid_register(&sc->va); return (0); } static int ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int ipu3fb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int ipu3fb_show_font(video_adapter_t *adp, int page) { return (0); } static int ipu3fb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_set_border(video_adapter_t *adp, int border) { return (ipu3fb_blank_display(adp, border)); } static int ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int ipu3fb_load_state(video_adapter_t *adp, void *p) { return (0); } static int ipu3fb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int ipu3fb_blank_display(video_adapter_t *adp, int mode) { return (0); } static int ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride * sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct video_adapter_softc *sc; struct fbtype *fb; sc = (struct video_adapter_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; case FBIOSCURSOR: return (ENODEV); default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int ipu3fb_clear(video_adapter_t *adp) { return (ipu3fb_blank_display(adp, 0)); } static int ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int ipu3fb_bitblt(video_adapter_t *adp, ...) { return (0); } static int ipu3fb_diag(video_adapter_t *adp, int level) { return (0); } static int ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int col, row, bpp; int b, i, j, k; uint8_t *addr; u_char *p; uint32_t fg, bg, color; sc = (struct video_adapter_softc *)adp; bpp = sc->bpp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c * IPU3FB_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin) * (sc->stride) + bpp * (col + sc->xmargin); if (bpp == 2) { bg = colors[(a >> 4) & 0x0f]; fg = colors[a & 0x0f]; } else if (bpp == 3) { bg = colors_24[(a >> 4) & 0x0f]; fg = colors_24[a & 0x0f]; } else { return (ENXIO); } for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; /* FIXME: BPP maybe different */ for (b = 0; b < bpp; b ++) addr[bpp * j + b] = (color >> (b << 3)) & 0xff; } addr += (sc->stride); } return (0); } static int ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t ipu3dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure); Index: stable/11/sys/arm/ti/am335x/am335x_lcd_syscons.c =================================================================== --- stable/11/sys/arm/ti/am335x/am335x_lcd_syscons.c (revision 356109) +++ stable/11/sys/arm/ti/am335x/am335x_lcd_syscons.c (revision 356110) @@ -1,790 +1,771 @@ /*- * Copyright (c) 2013 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "am335x_lcd.h" struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; int console; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb am335x_syscons_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define AM335X_FONT_HEIGHT 16 #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 24 static struct video_adapter_softc va_softc; static int am335x_syscons_configure(int flags); /* * Video driver routines and glue. */ static vi_probe_t am335x_syscons_probe; static vi_init_t am335x_syscons_init; static vi_get_info_t am335x_syscons_get_info; static vi_query_mode_t am335x_syscons_query_mode; static vi_set_mode_t am335x_syscons_set_mode; static vi_save_font_t am335x_syscons_save_font; static vi_load_font_t am335x_syscons_load_font; static vi_show_font_t am335x_syscons_show_font; static vi_save_palette_t am335x_syscons_save_palette; static vi_load_palette_t am335x_syscons_load_palette; static vi_set_border_t am335x_syscons_set_border; static vi_save_state_t am335x_syscons_save_state; static vi_load_state_t am335x_syscons_load_state; static vi_set_win_org_t am335x_syscons_set_win_org; static vi_read_hw_cursor_t am335x_syscons_read_hw_cursor; static vi_set_hw_cursor_t am335x_syscons_set_hw_cursor; static vi_set_hw_cursor_shape_t am335x_syscons_set_hw_cursor_shape; static vi_blank_display_t am335x_syscons_blank_display; static vi_mmap_t am335x_syscons_mmap; static vi_ioctl_t am335x_syscons_ioctl; static vi_clear_t am335x_syscons_clear; static vi_fill_rect_t am335x_syscons_fill_rect; static vi_bitblt_t am335x_syscons_bitblt; static vi_diag_t am335x_syscons_diag; static vi_save_cursor_palette_t am335x_syscons_save_cursor_palette; static vi_load_cursor_palette_t am335x_syscons_load_cursor_palette; static vi_copy_t am335x_syscons_copy; static vi_putp_t am335x_syscons_putp; static vi_putc_t am335x_syscons_putc; static vi_puts_t am335x_syscons_puts; static vi_putm_t am335x_syscons_putm; static video_switch_t am335x_sysconsvidsw = { .probe = am335x_syscons_probe, .init = am335x_syscons_init, .get_info = am335x_syscons_get_info, .query_mode = am335x_syscons_query_mode, .set_mode = am335x_syscons_set_mode, .save_font = am335x_syscons_save_font, .load_font = am335x_syscons_load_font, .show_font = am335x_syscons_show_font, .save_palette = am335x_syscons_save_palette, .load_palette = am335x_syscons_load_palette, .set_border = am335x_syscons_set_border, .save_state = am335x_syscons_save_state, .load_state = am335x_syscons_load_state, .set_win_org = am335x_syscons_set_win_org, .read_hw_cursor = am335x_syscons_read_hw_cursor, .set_hw_cursor = am335x_syscons_set_hw_cursor, .set_hw_cursor_shape = am335x_syscons_set_hw_cursor_shape, .blank_display = am335x_syscons_blank_display, .mmap = am335x_syscons_mmap, .ioctl = am335x_syscons_ioctl, .clear = am335x_syscons_clear, .fill_rect = am335x_syscons_fill_rect, .bitblt = am335x_syscons_bitblt, .diag = am335x_syscons_diag, .save_cursor_palette = am335x_syscons_save_cursor_palette, .load_cursor_palette = am335x_syscons_load_cursor_palette, .copy = am335x_syscons_copy, .putp = am335x_syscons_putp, .putc = am335x_syscons_putc, .puts = am335x_syscons_puts, .putm = am335x_syscons_putm, }; VIDEO_DRIVER(am335x_syscons, am335x_sysconsvidsw, am335x_syscons_configure); static vr_init_t am335x_rend_init; static vr_clear_t am335x_rend_clear; static vr_draw_border_t am335x_rend_draw_border; static vr_draw_t am335x_rend_draw; static vr_set_cursor_t am335x_rend_set_cursor; static vr_draw_cursor_t am335x_rend_draw_cursor; static vr_blink_cursor_t am335x_rend_blink_cursor; static vr_set_mouse_t am335x_rend_set_mouse; static vr_draw_mouse_t am335x_rend_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t am335x_rend = { am335x_rend_init, am335x_rend_clear, am335x_rend_draw_border, am335x_rend_draw, am335x_rend_set_cursor, am335x_rend_draw_cursor, am335x_rend_blink_cursor, am335x_rend_set_mouse, am335x_rend_draw_mouse }; RENDERER(am335x_syscons, 0, am335x_rend, gfb_set); RENDERER_MODULE(am335x_syscons, gfb_set); static void am335x_rend_init(scr_stat* scp) { } static void am335x_rend_clear(scr_stat* scp, int c, int attr) { } static void am335x_rend_draw_border(scr_stat* scp, int color) { } static void am335x_rend_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void am335x_rend_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void am335x_rend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { video_adapter_t* adp = scp->sc->adp; struct video_adapter_softc *sc; int row, col; uint8_t *addr; int i, j, bytes; sc = (struct video_adapter_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); bytes = sc->depth/8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { switch (sc->depth) { case 32: case 24: addr[bytes*j + 2] ^= 0xff; /* FALLTHROUGH */ case 16: addr[bytes*j + 1] ^= 0xff; addr[bytes*j] ^= 0xff; break; default: break; } } addr += sc->stride; } } static void am335x_rend_blink_cursor(scr_stat* scp, int at, int flip) { } static void am335x_rend_set_mouse(scr_stat* scp) { } static void am335x_rend_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t am335x_syscons_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void am335x_syscons_update_margins(video_adapter_t *adp) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; } static phandle_t am335x_syscons_find_panel_node(phandle_t start) { phandle_t child; phandle_t result; for (child = OF_child(start); child != 0; child = OF_peer(child)) { if (fdt_is_compatible(child, "ti,am335x-lcd")) return (child); if ((result = am335x_syscons_find_panel_node(child))) return (result); } return (0); } static int am335x_syscons_configure(int flags) { struct video_adapter_softc *va_sc; va_sc = &va_softc; phandle_t display, root; pcell_t cell; if (va_sc->initialized) return (0); va_sc->width = 0; va_sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try * to fetch data from FDT and go with defaults if failed */ root = OF_finddevice("/"); if ((root != 0) && (display = am335x_syscons_find_panel_node(root))) { if ((OF_getencprop(display, "panel_width", &cell, sizeof(cell))) > 0) va_sc->width = cell; if ((OF_getencprop(display, "panel_height", &cell, sizeof(cell))) > 0) va_sc->height = cell; } if (va_sc->width == 0) va_sc->width = FB_WIDTH; if (va_sc->height == 0) va_sc->height = FB_HEIGHT; am335x_syscons_init(0, &va_sc->va, 0); va_sc->initialized = 1; return (0); } static int am335x_syscons_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int am335x_syscons_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "am335x_syscons", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = AM335X_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) am335x_syscons_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int am335x_syscons_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int am335x_syscons_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int am335x_syscons_set_mode(video_adapter_t *adp, int mode) { return (0); } static int am335x_syscons_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int am335x_syscons_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int am335x_syscons_show_font(video_adapter_t *adp, int page) { return (0); } static int am335x_syscons_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_set_border(video_adapter_t *adp, int border) { return (am335x_syscons_blank_display(adp, border)); } static int am335x_syscons_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int am335x_syscons_load_state(video_adapter_t *adp, void *p) { return (0); } static int am335x_syscons_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int am335x_syscons_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int am335x_syscons_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int am335x_syscons_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int am335x_syscons_blank_display(video_adapter_t *adp, int mode) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int am335x_syscons_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int am335x_syscons_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct video_adapter_softc *sc; struct fbtype *fb; sc = (struct video_adapter_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int am335x_syscons_clear(video_adapter_t *adp) { return (am335x_syscons_blank_display(adp, 0)); } static int am335x_syscons_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int am335x_syscons_bitblt(video_adapter_t *adp, ...) { return (0); } static int am335x_syscons_diag(video_adapter_t *adp, int level) { return (0); } static int am335x_syscons_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int am335x_syscons_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int am335x_syscons_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int row; int col; int i, j, k; uint8_t *addr; u_char *p; uint8_t fg, bg, color; uint16_t rgb; sc = (struct video_adapter_softc *)adp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*AM335X_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; for (i = 0; i < AM335X_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 32: addr[4*j+0] = am335x_syscons_palette[color].r; addr[4*j+1] = am335x_syscons_palette[color].g; addr[4*j+2] = am335x_syscons_palette[color].b; addr[4*j+3] = am335x_syscons_palette[color].a; break; case 24: addr[3*j] = am335x_syscons_palette[color].r; addr[3*j+1] = am335x_syscons_palette[color].g; addr[3*j+2] = am335x_syscons_palette[color].b; break; case 16: rgb = (am335x_syscons_palette[color].r >> 3) << 11; rgb |= (am335x_syscons_palette[color].g >> 2) << 5; rgb |= (am335x_syscons_palette[color].b >> 3); addr[2*j] = rgb & 0xff; addr[2*j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int am335x_syscons_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) am335x_syscons_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int am335x_syscons_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } /* Initialization function */ int am335x_lcd_syscons_setup(vm_offset_t vaddr, vm_paddr_t paddr, struct panel_info *panel) { struct video_adapter_softc *va_sc = &va_softc; va_sc->fb_addr = vaddr; va_sc->fb_paddr = paddr; va_sc->depth = panel->bpp; va_sc->stride = panel->bpp*panel->panel_width/8; va_sc->width = panel->panel_width; va_sc->height = panel->panel_height; va_sc->fb_size = va_sc->width * va_sc->height * va_sc->depth/8; am335x_syscons_update_margins(&va_sc->va); return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t am335x_dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(am335x_dummy, am335x_dummysw, dummy_kbd_configure); Index: stable/11/sys/arm/versatile/versatile_clcd.c =================================================================== --- stable/11/sys/arm/versatile/versatile_clcd.c (revision 356109) +++ stable/11/sys/arm/versatile/versatile_clcd.c (revision 356110) @@ -1,942 +1,923 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012-2017 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PL110_VENDOR_ARM926PXP 1 #define CLCD_MODE_RGB888 0x0 #define CLCD_MODE_RGB555 0x01 #define CLCD_MODE_RBG565 0x02 #define CLCD_MODE_RGB565 0x03 #define CLCDC_TIMING0 0x00 #define CLCDC_TIMING1 0x04 #define CLCDC_TIMING2 0x08 #define CLCDC_TIMING3 0x0C #define CLCDC_TIMING3 0x0C #define CLCDC_UPBASE 0x10 #define CLCDC_LPBASE 0x14 #ifdef PL110_VENDOR_ARM926PXP #define CLCDC_CONTROL 0x18 #define CLCDC_IMSC 0x1C #else #define CLCDC_IMSC 0x18 #define CLCDC_CONTROL 0x1C #endif #define CONTROL_WATERMARK (1 << 16) #define CONTROL_VCOMP_VS (0 << 12) #define CONTROL_VCOMP_BP (1 << 12) #define CONTROL_VCOMP_SAV (2 << 12) #define CONTROL_VCOMP_FP (3 << 12) #define CONTROL_PWR (1 << 11) #define CONTROL_BEPO (1 << 10) #define CONTROL_BEBO (1 << 9) #define CONTROL_BGR (1 << 8) #define CONTROL_DUAL (1 << 7) #define CONTROL_MONO8 (1 << 6) #define CONTROL_TFT (1 << 5) #define CONTROL_BW (1 << 4) #define CONTROL_BPP1 (0x00 << 1) #define CONTROL_BPP2 (0x01 << 1) #define CONTROL_BPP4 (0x02 << 1) #define CONTROL_BPP8 (0x03 << 1) #define CONTROL_BPP16 (0x04 << 1) #define CONTROL_BPP24 (0x05 << 1) #define CONTROL_EN (1 << 0) #define CLCDC_RIS 0x20 #define CLCDC_MIS 0x24 #define INTR_MBERR (1 << 4) #define INTR_VCOMP (1 << 3) #define INTR_LNB (1 << 2) #define INTR_FUF (1 << 1) #define CLCDC_ICR 0x28 #ifdef DEBUG #define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ printf(fmt,##args); } while (0) #else #define dprintf(fmt, args...) #endif #define versatile_clcdc_read_4(sc, reg) \ bus_read_4((sc)->mem_res, (reg)) #define versatile_clcdc_write_4(sc, reg, val) \ bus_write_4((sc)->mem_res, (reg), (val)) struct versatile_clcdc_softc { struct resource* mem_res; struct mtx mtx; int width; int height; int mode; bus_dma_tag_t dma_tag; bus_dmamap_t dma_map; bus_addr_t fb_phys; uint8_t *fb_base; }; struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; int console; intptr_t fb_addr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb versatilefb_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 16 #define VERSATILE_FONT_HEIGHT 16 static struct video_adapter_softc va_softc; static int versatilefb_configure(int); static void versatilefb_update_margins(video_adapter_t *adp); static void versatile_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) { bus_addr_t *addr; if (err) return; addr = (bus_addr_t*)arg; *addr = segs[0].ds_addr; } static int versatile_clcdc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "arm,pl110")) { device_set_desc(dev, "PL110 CLCD controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int versatile_clcdc_attach(device_t dev) { struct versatile_clcdc_softc *sc = device_get_softc(dev); struct video_adapter_softc *va_sc = &va_softc; int err, rid; uint32_t reg; int clcdid; int dma_size; /* Request memory resources */ rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "could not allocate memory resources\n"); return (ENXIO); } err = versatile_scm_reg_read_4(SCM_CLCD, ®); if (err) { device_printf(dev, "failed to read SCM register\n"); goto fail; } clcdid = (reg >> SCM_CLCD_CLCDID_SHIFT) & SCM_CLCD_CLCDID_MASK; switch (clcdid) { case 31: device_printf(dev, "QEMU VGA 640x480\n"); sc->width = 640; sc->height = 480; break; default: device_printf(dev, "Unsupported: %d\n", clcdid); goto fail; } reg &= ~SCM_CLCD_LCD_MODE_MASK; reg |= CLCD_MODE_RGB565; sc->mode = CLCD_MODE_RGB565; versatile_scm_reg_write_4(SCM_CLCD, reg); dma_size = sc->width*sc->height*2; /* * Power on LCD */ reg |= SCM_CLCD_PWR3V5VSWITCH | SCM_CLCD_NLCDIOON; versatile_scm_reg_write_4(SCM_CLCD, reg); /* * XXX: hardcoded timing for VGA. For other modes/panels * we need to keep table of timing register values */ /* * XXX: set SYS_OSC1 */ versatile_clcdc_write_4(sc, CLCDC_TIMING0, 0x3F1F3F9C); versatile_clcdc_write_4(sc, CLCDC_TIMING1, 0x090B61DF); versatile_clcdc_write_4(sc, CLCDC_TIMING2, 0x067F1800); /* XXX: timing 3? */ /* * Now allocate framebuffer memory */ err = bus_dma_tag_create( bus_get_dma_tag(dev), 4, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ dma_size, 1, /* maxsize, nsegments */ dma_size, 0, /* maxsegsize, flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->dma_tag); err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_base, 0, &sc->dma_map); if (err) { device_printf(dev, "cannot allocate framebuffer\n"); goto fail; } err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_base, dma_size, versatile_fb_dmamap_cb, &sc->fb_phys, BUS_DMA_NOWAIT); if (err) { device_printf(dev, "cannot load DMA map\n"); goto fail; } /* Make sure it's blank */ memset(sc->fb_base, 0x00, dma_size); versatile_clcdc_write_4(sc, CLCDC_UPBASE, sc->fb_phys); err = (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); if (err) { device_printf(dev, "failed to attach syscons\n"); goto fail; } /* * XXX: hardcoded for VGA */ reg = CONTROL_VCOMP_BP | CONTROL_TFT | CONTROL_BGR | CONTROL_EN; reg |= CONTROL_BPP16; versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); DELAY(20); reg |= CONTROL_PWR; versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); va_sc->fb_addr = (vm_offset_t)sc->fb_base; va_sc->fb_size = dma_size; va_sc->width = sc->width; va_sc->height = sc->height; va_sc->depth = 16; va_sc->stride = sc->width * 2; versatilefb_update_margins(&va_sc->va); return (0); fail: if (sc->fb_base) bus_dmamem_free(sc->dma_tag, sc->fb_base, sc->dma_map); if (sc->dma_tag) bus_dma_tag_destroy(sc->dma_tag); return (err); } static device_method_t versatile_clcdc_methods[] = { DEVMETHOD(device_probe, versatile_clcdc_probe), DEVMETHOD(device_attach, versatile_clcdc_attach), DEVMETHOD_END }; static driver_t versatile_clcdc_driver = { "clcdc", versatile_clcdc_methods, sizeof(struct versatile_clcdc_softc), }; static devclass_t versatile_clcdc_devclass; DRIVER_MODULE(versatile_clcdc, simplebus, versatile_clcdc_driver, versatile_clcdc_devclass, 0, 0); /* * Video driver routines and glue. */ static vi_probe_t versatilefb_probe; static vi_init_t versatilefb_init; static vi_get_info_t versatilefb_get_info; static vi_query_mode_t versatilefb_query_mode; static vi_set_mode_t versatilefb_set_mode; static vi_save_font_t versatilefb_save_font; static vi_load_font_t versatilefb_load_font; static vi_show_font_t versatilefb_show_font; static vi_save_palette_t versatilefb_save_palette; static vi_load_palette_t versatilefb_load_palette; static vi_set_border_t versatilefb_set_border; static vi_save_state_t versatilefb_save_state; static vi_load_state_t versatilefb_load_state; static vi_set_win_org_t versatilefb_set_win_org; static vi_read_hw_cursor_t versatilefb_read_hw_cursor; static vi_set_hw_cursor_t versatilefb_set_hw_cursor; static vi_set_hw_cursor_shape_t versatilefb_set_hw_cursor_shape; static vi_blank_display_t versatilefb_blank_display; static vi_mmap_t versatilefb_mmap; static vi_ioctl_t versatilefb_ioctl; static vi_clear_t versatilefb_clear; static vi_fill_rect_t versatilefb_fill_rect; static vi_bitblt_t versatilefb_bitblt; static vi_diag_t versatilefb_diag; static vi_save_cursor_palette_t versatilefb_save_cursor_palette; static vi_load_cursor_palette_t versatilefb_load_cursor_palette; static vi_copy_t versatilefb_copy; static vi_putp_t versatilefb_putp; static vi_putc_t versatilefb_putc; static vi_puts_t versatilefb_puts; static vi_putm_t versatilefb_putm; static video_switch_t versatilefbvidsw = { .probe = versatilefb_probe, .init = versatilefb_init, .get_info = versatilefb_get_info, .query_mode = versatilefb_query_mode, .set_mode = versatilefb_set_mode, .save_font = versatilefb_save_font, .load_font = versatilefb_load_font, .show_font = versatilefb_show_font, .save_palette = versatilefb_save_palette, .load_palette = versatilefb_load_palette, .set_border = versatilefb_set_border, .save_state = versatilefb_save_state, .load_state = versatilefb_load_state, .set_win_org = versatilefb_set_win_org, .read_hw_cursor = versatilefb_read_hw_cursor, .set_hw_cursor = versatilefb_set_hw_cursor, .set_hw_cursor_shape = versatilefb_set_hw_cursor_shape, .blank_display = versatilefb_blank_display, .mmap = versatilefb_mmap, .ioctl = versatilefb_ioctl, .clear = versatilefb_clear, .fill_rect = versatilefb_fill_rect, .bitblt = versatilefb_bitblt, .diag = versatilefb_diag, .save_cursor_palette = versatilefb_save_cursor_palette, .load_cursor_palette = versatilefb_load_cursor_palette, .copy = versatilefb_copy, .putp = versatilefb_putp, .putc = versatilefb_putc, .puts = versatilefb_puts, .putm = versatilefb_putm, }; VIDEO_DRIVER(versatilefb, versatilefbvidsw, versatilefb_configure); static vr_init_t clcdr_init; static vr_clear_t clcdr_clear; static vr_draw_border_t clcdr_draw_border; static vr_draw_t clcdr_draw; static vr_set_cursor_t clcdr_set_cursor; static vr_draw_cursor_t clcdr_draw_cursor; static vr_blink_cursor_t clcdr_blink_cursor; static vr_set_mouse_t clcdr_set_mouse; static vr_draw_mouse_t clcdr_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t clcdrend = { clcdr_init, clcdr_clear, clcdr_draw_border, clcdr_draw, clcdr_set_cursor, clcdr_draw_cursor, clcdr_blink_cursor, clcdr_set_mouse, clcdr_draw_mouse }; RENDERER(versatilefb, 0, clcdrend, gfb_set); RENDERER_MODULE(versatilefb, gfb_set); static void clcdr_init(scr_stat* scp) { } static void clcdr_clear(scr_stat* scp, int c, int attr) { } static void clcdr_draw_border(scr_stat* scp, int color) { } static void clcdr_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void clcdr_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void clcdr_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { video_adapter_t* adp = scp->sc->adp; struct video_adapter_softc *sc; int row, col; uint8_t *addr; int i,j; sc = (struct video_adapter_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { addr[2*j] ^= 0xff; addr[2*j + 1] ^= 0xff; } addr += sc->stride; } } static void clcdr_blink_cursor(scr_stat* scp, int at, int flip) { } static void clcdr_set_mouse(scr_stat* scp) { } static void clcdr_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t versatilefb_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void versatilefb_update_margins(video_adapter_t *adp) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; } static int versatilefb_configure(int flags) { struct video_adapter_softc *va_sc; va_sc = &va_softc; if (va_sc->initialized) return (0); va_sc->width = FB_WIDTH; va_sc->height = FB_HEIGHT; va_sc->depth = FB_DEPTH; versatilefb_init(0, &va_sc->va, 0); va_sc->initialized = 1; return (0); } static int versatilefb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int versatilefb_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "versatilefb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = VERSATILE_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) versatilefb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int versatilefb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int versatilefb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int versatilefb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int versatilefb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int versatilefb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int versatilefb_show_font(video_adapter_t *adp, int page) { return (0); } static int versatilefb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_set_border(video_adapter_t *adp, int border) { return (versatilefb_blank_display(adp, border)); } static int versatilefb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int versatilefb_load_state(video_adapter_t *adp, void *p) { return (0); } static int versatilefb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int versatilefb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int versatilefb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int versatilefb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int versatilefb_blank_display(video_adapter_t *adp, int mode) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int versatilefb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_addr + offset; return (0); } return (EINVAL); } static int versatilefb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (0); } static int versatilefb_clear(video_adapter_t *adp) { return (versatilefb_blank_display(adp, 0)); } static int versatilefb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int versatilefb_bitblt(video_adapter_t *adp, ...) { return (0); } static int versatilefb_diag(video_adapter_t *adp, int level) { return (0); } static int versatilefb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int versatilefb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int row; int col; int i, j, k; uint8_t *addr; u_char *p; uint8_t fg, bg, color; uint16_t rgb; sc = (struct video_adapter_softc *)adp; if (sc->fb_addr == 0) return (0); if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*VERSATILE_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 16: rgb = (versatilefb_palette[color].r >> 3) << 11; rgb |= (versatilefb_palette[color].g >> 2) << 5; rgb |= (versatilefb_palette[color].b >> 3); addr[2*j] = rgb & 0xff; addr[2*j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int versatilefb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) versatilefb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int versatilefb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t bcmdummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure); Index: stable/11/sys/dev/terasic/mtl/terasic_mtl_syscons.c =================================================================== --- stable/11/sys/dev/terasic/mtl/terasic_mtl_syscons.c (revision 356109) +++ stable/11/sys/dev/terasic/mtl/terasic_mtl_syscons.c (revision 356110) @@ -1,490 +1,474 @@ /*- * Copyright (c) 2012 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Terasic Multitouch LCD (MTL) syscons driver. Implement syscons(4)'s * video_switch_t KPI using MTL's text frame buffer. In principle, we could * actually implement sc_rndr_sw_t, since the MTL text frame buffer implements * a VGA-like memory mapping. However, this requires a lot more book-keeping * with only minor performance improvements (avoiding indirection), as well as * introducing potential endianness issues. Instead we accept one additional * memory copy between a software frame buffer and the hardware frame buffer * and the generic frame buffer (gfb) framework. */ MALLOC_DEFINE(M_TERASIC_MTL, "mtl_syscons", "MTL syscons frame buffer"); /* * Run early so that boot-time console support can be initialised before * newbus gets around to configuring syscons. * * XXXRW: We may need to do more here in order to see earlier boot messages. */ static int terasic_mtl_syscons_configure(int flags) { printf("%s: not yet\n", __func__); return (0); } static int terasic_mtl_vidsw_probe(int unit, video_adapter_t **adp, void *args, int flags) { printf("%s: not yet\n", __func__); return (0); } static int terasic_mtl_vidsw_init(int unit, video_adapter_t *adp, int flags) { struct terasic_mtl_softc *sc; video_info_t *vi; sc = (struct terasic_mtl_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "terasic_mtl_syscons", -1, unit); vi->vi_width = TERASIC_MTL_COLS; if (vi->vi_width > COL) vi->vi_width = COL; vi->vi_height = TERASIC_MTL_ROWS; if (vi->vi_height > ROW) vi->vi_height = ROW; /* * XXXRW: It's not quite clear how these should be initialised. */ vi->vi_cwidth = 0; vi->vi_cheight = 0; vi->vi_flags = V_INFO_COLOR; vi->vi_mem_model = V_INFO_MM_OTHER; /* * Software text frame buffer from which we update the actual MTL * frame buffer when asked to. */ adp->va_window = (vm_offset_t)sc->mtl_text_soft; /* * Declare video adapter capabilities -- at this point, simply color * support, as MTL doesn't support screen borders, font loading, or * mode changes. * * XXXRW: It's unclear if V_ADP_INITIALIZED is needed here; other * syscons(4) drivers are inconsistent about this and * V_ADP_REGISTERED. */ adp->va_flags |= V_ADP_COLOR | V_ADP_INITIALIZED; if (vid_register(adp) < 0) { device_printf(sc->mtl_dev, "%s: vid_register failed\n", __func__); return (ENXIO); } adp->va_flags |= V_ADP_REGISTERED; return (0); } static int terasic_mtl_vidsw_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int terasic_mtl_vidsw_query_mode(video_adapter_t *adp, video_info_t *info) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_mode(video_adapter_t *adp, int mode) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_show_font(video_adapter_t *adp, int page) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_border(video_adapter_t *adp, int border) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_state(video_adapter_t *adp, void *p, size_t size) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_state(video_adapter_t *adp, void *p) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_win_org(video_adapter_t *adp, off_t offset) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_read_hw_cursor(video_adapter_t *adp, int *colp, int *rowp) { struct terasic_mtl_softc *sc; uint8_t col, row; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_textcursor_get(sc, &col, &row); *colp = col; *rowp = row; return (0); } static int terasic_mtl_vidsw_set_hw_cursor(video_adapter_t *adp, int col, int row) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_textcursor_set(sc, col, row); return (0); } static int terasic_mtl_vidsw_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_blank_display(video_adapter_t *adp, int mode) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_blank(sc); return (0); } static int terasic_mtl_vidsw_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (fb_commonioctl(adp, cmd, data)); } static int terasic_mtl_vidsw_clear(video_adapter_t *adp) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; printf("%s: not yet terasic_mtl_io_clear(sc);\n", __func__); return (0); } static int terasic_mtl_vidsw_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_bitblt(video_adapter_t *adp, ...) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_diag(video_adapter_t *adp, int level) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_cursor_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_cursor_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct terasic_mtl_softc *sc; u_int col, row; sc = (struct terasic_mtl_softc *)adp; col = (off % adp->va_info.vi_width); row = (off / adp->va_info.vi_width); terasic_mtl_text_putc(sc, col, row, c, a); return (0); } static int terasic_mtl_vidsw_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) vidd_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int terasic_mtl_vidsw_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { printf("%s: not yet\n", __func__); return (ENODEV); } -/* - * XXXRW: For historical reasons, syscons can't register video consoles - * without a keyboard implementation. Provide a dummy. - */ -static keyboard_switch_t terasic_mtl_keyboard_switch; - -static int -terasic_mtl_kbd_configure(int flags) -{ - - return (0); -} - -KEYBOARD_DRIVER(mtl_kbd, terasic_mtl_keyboard_switch, - terasic_mtl_kbd_configure); - int terasic_mtl_syscons_attach(struct terasic_mtl_softc *sc) { int error; sc->mtl_text_soft = malloc(sizeof(uint16_t) * TERASIC_MTL_ROWS * TERASIC_MTL_COLS, M_TERASIC_MTL, M_WAITOK | M_ZERO); error = terasic_mtl_vidsw_init(0, &sc->mtl_va, 0); if (error) goto out; error = sc_attach_unit(sc->mtl_unit, device_get_flags(sc->mtl_dev) | SC_AUTODETECT_KBD); if (error) device_printf(sc->mtl_dev, "%s: sc_attach_unit failed (%d)\n", __func__, error); out: if (error) free(sc->mtl_text_soft, M_TERASIC_MTL); return (error); } void terasic_mtl_syscons_detach(struct terasic_mtl_softc *sc) { free(sc->mtl_text_soft, M_TERASIC_MTL); panic("%s: not supported by syscons", __func__); } static video_switch_t terasic_mtl_vidsw = { .probe = terasic_mtl_vidsw_probe, .init = terasic_mtl_vidsw_init, .get_info = terasic_mtl_vidsw_get_info, .query_mode = terasic_mtl_vidsw_query_mode, .set_mode = terasic_mtl_vidsw_set_mode, .save_font = terasic_mtl_vidsw_save_font, .load_font = terasic_mtl_vidsw_load_font, .show_font = terasic_mtl_vidsw_show_font, .save_palette = terasic_mtl_vidsw_save_palette, .load_palette = terasic_mtl_vidsw_load_palette, .set_border = terasic_mtl_vidsw_set_border, .save_state = terasic_mtl_vidsw_save_state, .load_state = terasic_mtl_vidsw_load_state, .set_win_org = terasic_mtl_vidsw_set_win_org, .read_hw_cursor = terasic_mtl_vidsw_read_hw_cursor, .set_hw_cursor = terasic_mtl_vidsw_set_hw_cursor, .set_hw_cursor_shape = terasic_mtl_vidsw_set_hw_cursor_shape, .blank_display = terasic_mtl_vidsw_blank_display, .mmap = terasic_mtl_vidsw_mmap, .ioctl = terasic_mtl_vidsw_ioctl, .clear = terasic_mtl_vidsw_clear, .fill_rect = terasic_mtl_vidsw_fill_rect, .bitblt = terasic_mtl_vidsw_bitblt, .diag = terasic_mtl_vidsw_diag, .save_cursor_palette = terasic_mtl_vidsw_save_cursor_palette, .load_cursor_palette = terasic_mtl_vidsw_load_cursor_palette, .copy = terasic_mtl_vidsw_copy, .putp = terasic_mtl_vidsw_putp, .putc = terasic_mtl_vidsw_putc, .puts = terasic_mtl_vidsw_puts, .putm = terasic_mtl_vidsw_putm, }; VIDEO_DRIVER(terasic_mtl_syscons, terasic_mtl_vidsw, terasic_mtl_syscons_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(terasic_mtl_syscons, 0, txtrndrsw, gfb_set); RENDERER_MODULE(terasic_mtl_syscons, gfb_set); Index: stable/11/sys/powerpc/ofw/ofw_syscons.c =================================================================== --- stable/11/sys/powerpc/ofw/ofw_syscons.c (revision 356109) +++ stable/11/sys/powerpc/ofw/ofw_syscons.c (revision 356110) @@ -1,1102 +1,1083 @@ /*- * Copyright (c) 2003 Peter Grehan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int ofwfb_ignore_mmap_checks = 1; static int ofwfb_reset_on_switch = 1; static SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb"); SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW, &ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking"); SYSCTL_INT(_hw_ofwfb, OID_AUTO, reset_on_mode_switch, CTLFLAG_RW, &ofwfb_reset_on_switch, 0, "reset the framebuffer driver on mode switch"); extern u_char dflt_font_16[]; extern u_char dflt_font_14[]; extern u_char dflt_font_8[]; static int ofwfb_configure(int flags); static vi_probe_t ofwfb_probe; static vi_init_t ofwfb_init; static vi_get_info_t ofwfb_get_info; static vi_query_mode_t ofwfb_query_mode; static vi_set_mode_t ofwfb_set_mode; static vi_save_font_t ofwfb_save_font; static vi_load_font_t ofwfb_load_font; static vi_show_font_t ofwfb_show_font; static vi_save_palette_t ofwfb_save_palette; static vi_load_palette_t ofwfb_load_palette; static vi_set_border_t ofwfb_set_border; static vi_save_state_t ofwfb_save_state; static vi_load_state_t ofwfb_load_state; static vi_set_win_org_t ofwfb_set_win_org; static vi_read_hw_cursor_t ofwfb_read_hw_cursor; static vi_set_hw_cursor_t ofwfb_set_hw_cursor; static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape; static vi_blank_display_t ofwfb_blank_display; static vi_mmap_t ofwfb_mmap; static vi_ioctl_t ofwfb_ioctl; static vi_clear_t ofwfb_clear; static vi_fill_rect_t ofwfb_fill_rect; static vi_bitblt_t ofwfb_bitblt; static vi_diag_t ofwfb_diag; static vi_save_cursor_palette_t ofwfb_save_cursor_palette; static vi_load_cursor_palette_t ofwfb_load_cursor_palette; static vi_copy_t ofwfb_copy; static vi_putp_t ofwfb_putp; static vi_putc_t ofwfb_putc; static vi_puts_t ofwfb_puts; static vi_putm_t ofwfb_putm; static video_switch_t ofwfbvidsw = { .probe = ofwfb_probe, .init = ofwfb_init, .get_info = ofwfb_get_info, .query_mode = ofwfb_query_mode, .set_mode = ofwfb_set_mode, .save_font = ofwfb_save_font, .load_font = ofwfb_load_font, .show_font = ofwfb_show_font, .save_palette = ofwfb_save_palette, .load_palette = ofwfb_load_palette, .set_border = ofwfb_set_border, .save_state = ofwfb_save_state, .load_state = ofwfb_load_state, .set_win_org = ofwfb_set_win_org, .read_hw_cursor = ofwfb_read_hw_cursor, .set_hw_cursor = ofwfb_set_hw_cursor, .set_hw_cursor_shape = ofwfb_set_hw_cursor_shape, .blank_display = ofwfb_blank_display, .mmap = ofwfb_mmap, .ioctl = ofwfb_ioctl, .clear = ofwfb_clear, .fill_rect = ofwfb_fill_rect, .bitblt = ofwfb_bitblt, .diag = ofwfb_diag, .save_cursor_palette = ofwfb_save_cursor_palette, .load_cursor_palette = ofwfb_load_cursor_palette, .copy = ofwfb_copy, .putp = ofwfb_putp, .putc = ofwfb_putc, .puts = ofwfb_puts, .putm = ofwfb_putm, }; /* * bitmap depth-specific routines */ static vi_blank_display_t ofwfb_blank_display8; static vi_putc_t ofwfb_putc8; static vi_putm_t ofwfb_putm8; static vi_set_border_t ofwfb_set_border8; static vi_blank_display_t ofwfb_blank_display32; static vi_putc_t ofwfb_putc32; static vi_putm_t ofwfb_putm32; static vi_set_border_t ofwfb_set_border32; VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(ofwfb, 0, txtrndrsw, gfb_set); RENDERER_MODULE(ofwfb, gfb_set); /* * Define the iso6429-1983 colormap */ static struct { uint8_t red; uint8_t green; uint8_t blue; } ofwfb_cmap[16] = { /* # R G B Color */ /* - - - - ----- */ { 0x00, 0x00, 0x00 }, /* 0 0 0 0 Black */ { 0x00, 0x00, 0xaa }, /* 1 0 0 2/3 Blue */ { 0x00, 0xaa, 0x00 }, /* 2 0 2/3 0 Green */ { 0x00, 0xaa, 0xaa }, /* 3 0 2/3 2/3 Cyan */ { 0xaa, 0x00, 0x00 }, /* 4 2/3 0 0 Red */ { 0xaa, 0x00, 0xaa }, /* 5 2/3 0 2/3 Magenta */ { 0xaa, 0x55, 0x00 }, /* 6 2/3 1/3 0 Brown */ { 0xaa, 0xaa, 0xaa }, /* 7 2/3 2/3 2/3 White */ { 0x55, 0x55, 0x55 }, /* 8 1/3 1/3 1/3 Gray */ { 0x55, 0x55, 0xff }, /* 9 1/3 1/3 1 Bright Blue */ { 0x55, 0xff, 0x55 }, /* 10 1/3 1 1/3 Bright Green */ { 0x55, 0xff, 0xff }, /* 11 1/3 1 1 Bright Cyan */ { 0xff, 0x55, 0x55 }, /* 12 1 1/3 1/3 Bright Red */ { 0xff, 0x55, 0xff }, /* 13 1 1/3 1 Bright Magenta */ { 0xff, 0xff, 0x80 }, /* 14 1 1 1/3 Bright Yellow */ { 0xff, 0xff, 0xff } /* 15 1 1 1 Bright White */ }; #define TODO printf("%s: unimplemented\n", __func__) static u_int16_t ofwfb_static_window[ROW*COL]; static struct ofwfb_softc ofwfb_softc; static __inline int ofwfb_background(uint8_t attr) { return (attr >> 4); } static __inline int ofwfb_foreground(uint8_t attr) { return (attr & 0x0f); } static u_int ofwfb_pix32(struct ofwfb_softc *sc, int attr) { u_int retval; if (sc->sc_tag == &bs_le_tag) retval = (ofwfb_cmap[attr].red << 16) | (ofwfb_cmap[attr].green << 8) | ofwfb_cmap[attr].blue; else retval = (ofwfb_cmap[attr].blue << 16) | (ofwfb_cmap[attr].green << 8) | ofwfb_cmap[attr].red; return (retval); } static int ofwfb_configure(int flags) { struct ofwfb_softc *sc; phandle_t chosen; ihandle_t stdout; phandle_t node; uint32_t fb_phys; int depth; int disable; int len; int i; char type[16]; static int done = 0; disable = 0; TUNABLE_INT_FETCH("hw.syscons.disable", &disable); if (disable != 0) return (0); if (done != 0) return (0); done = 1; sc = &ofwfb_softc; chosen = OF_finddevice("/chosen"); OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); node = OF_instance_to_package(stdout); if (node == -1) { /* * The "/chosen/stdout" does not exist try * using "screen" directly. */ node = OF_finddevice("screen"); } OF_getprop(node, "device_type", type, sizeof(type)); if (strcmp(type, "display") != 0) return (0); /* Only support 8 and 32-bit framebuffers */ OF_getprop(node, "depth", &depth, sizeof(depth)); if (depth == 8) { sc->sc_blank = ofwfb_blank_display8; sc->sc_putc = ofwfb_putc8; sc->sc_putm = ofwfb_putm8; sc->sc_set_border = ofwfb_set_border8; } else if (depth == 32) { sc->sc_blank = ofwfb_blank_display32; sc->sc_putc = ofwfb_putc32; sc->sc_putm = ofwfb_putm32; sc->sc_set_border = ofwfb_set_border32; } else return (0); if (OF_getproplen(node, "height") != sizeof(sc->sc_height) || OF_getproplen(node, "width") != sizeof(sc->sc_width) || OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride)) return (0); sc->sc_depth = depth; sc->sc_node = node; sc->sc_console = 1; OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height)); OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width)); OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride)); /* * Get the PCI addresses of the adapter. The node may be the * child of the PCI device: in that case, try the parent for * the assigned-addresses property. */ len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); if (len == -1) { len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); } if (len == -1) len = 0; sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register); /* * Grab the physical address of the framebuffer, and then map it * into our memory space. If the MMU is not yet up, it will be * remapped for us when relocation turns on. * * XXX We assume #address-cells is 1 at this point. */ if (OF_getproplen(node, "address") == sizeof(fb_phys)) { OF_getprop(node, "address", &fb_phys, sizeof(fb_phys)); sc->sc_tag = &bs_be_tag; bus_space_map(sc->sc_tag, fb_phys, sc->sc_height * sc->sc_stride, BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr); } else { /* * Some IBM systems don't have an address property. Try to * guess the framebuffer region from the assigned addresses. * This is ugly, but there doesn't seem to be an alternative. * Linux does the same thing. */ fb_phys = sc->sc_num_pciaddrs; for (i = 0; i < sc->sc_num_pciaddrs; i++) { /* If it is too small, not the framebuffer */ if (sc->sc_pciaddrs[i].size_lo < sc->sc_stride*sc->sc_height) continue; /* If it is not memory, it isn't either */ if (!(sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_SPACE_MEM32)) continue; /* This could be the framebuffer */ fb_phys = i; /* If it is prefetchable, it certainly is */ if (sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) break; } if (fb_phys == sc->sc_num_pciaddrs) return (0); OF_decode_addr(node, fb_phys, &sc->sc_tag, &sc->sc_addr, NULL); } ofwfb_init(0, &sc->sc_va, 0); return (0); } static int ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { TODO; return (0); } static int ofwfb_init(int unit, video_adapter_t *adp, int flags) { struct ofwfb_softc *sc; video_info_t *vi; int cborder; int font_height; sc = (struct ofwfb_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "ofwfb", -1, unit); /* The default font size can be overridden by loader */ font_height = 16; TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height); if (font_height == 8) { sc->sc_font = dflt_font_8; sc->sc_font_height = 8; } else if (font_height == 14) { sc->sc_font = dflt_font_14; sc->sc_font_height = 14; } else { /* default is 8x16 */ sc->sc_font = dflt_font_16; sc->sc_font_height = 16; } /* The user can set a border in chars - default is 1 char width */ cborder = 1; TUNABLE_INT_FETCH("hw.syscons.border", &cborder); vi->vi_cheight = sc->sc_font_height; vi->vi_width = sc->sc_width/8 - 2*cborder; vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder; vi->vi_cwidth = 8; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; /* * Avoid huge amounts of conditional code in syscons by * defining a dummy h/w text display buffer. */ adp->va_window = (vm_offset_t) ofwfb_static_window; /* * Enable future font-loading and flag color support, as well as * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called * when the X server shuts down. This enables us to get the console * back when X disappears. */ adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE; ofwfb_set_mode(&sc->sc_va, 0); vid_register(&sc->sc_va); return (0); } static int ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int ofwfb_query_mode(video_adapter_t *adp, video_info_t *info) { TODO; return (0); } static int ofwfb_set_mode(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; char name[64]; ihandle_t ih; int i, retval; sc = (struct ofwfb_softc *)adp; if (ofwfb_reset_on_switch) { /* * Open the display device, which will initialize it. */ memset(name, 0, sizeof(name)); OF_package_to_path(sc->sc_node, name, sizeof(name)); ih = OF_open(name); if (sc->sc_depth == 8) { /* * Install the ISO6429 colormap - older OFW systems * don't do this by default */ for (i = 0; i < 16; i++) { OF_call_method("color!", ih, 4, 1, ofwfb_cmap[i].red, ofwfb_cmap[i].green, ofwfb_cmap[i].blue, i, &retval); } } } ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON); return (0); } static int ofwfb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { TODO; return (0); } static int ofwfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; /* * syscons code has already determined that current width/height * are unchanged for this new font */ sc->sc_font = data; return (0); } static int ofwfb_show_font(video_adapter_t *adp, int page) { return (0); } static int ofwfb_save_palette(video_adapter_t *adp, u_char *palette) { /* TODO; */ return (0); } static int ofwfb_load_palette(video_adapter_t *adp, u_char *palette) { /* TODO; */ return (0); } static int ofwfb_set_border8(video_adapter_t *adp, int border) { struct ofwfb_softc *sc; int i, j; uint8_t *addr; uint8_t bground; sc = (struct ofwfb_softc *)adp; bground = ofwfb_background(border); /* Set top margin */ addr = (uint8_t *) sc->sc_addr; for (i = 0; i < sc->sc_ymargin; i++) { for (j = 0; j < sc->sc_width; j++) { *(addr + j) = bground; } addr += sc->sc_stride; } /* bottom margin */ addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride; for (i = 0; i < sc->sc_ymargin; i++) { for (j = 0; j < sc->sc_width; j++) { *(addr + j) = bground; } addr += sc->sc_stride; } /* remaining left and right borders */ addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride; for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) { for (j = 0; j < sc->sc_xmargin; j++) { *(addr + j) = bground; *(addr + j + sc->sc_width - sc->sc_xmargin) = bground; } addr += sc->sc_stride; } return (0); } static int ofwfb_set_border32(video_adapter_t *adp, int border) { /* XXX Be lazy for now and blank entire screen */ return (ofwfb_blank_display32(adp, border)); } static int ofwfb_set_border(video_adapter_t *adp, int border) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_set_border)(adp, border)); } static int ofwfb_save_state(video_adapter_t *adp, void *p, size_t size) { TODO; return (0); } static int ofwfb_load_state(video_adapter_t *adp, void *p) { TODO; return (0); } static int ofwfb_set_win_org(video_adapter_t *adp, off_t offset) { TODO; return (0); } static int ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = 0; *row = 0; return (0); } static int ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int ofwfb_blank_display8(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; int i; uint32_t *addr; uint32_t color; uint32_t end; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *) sc->sc_addr; end = (sc->sc_stride/4) * sc->sc_height; /* Splat 4 pixels at once. */ color = (ofwfb_background(SC_NORM_ATTR) << 24) | (ofwfb_background(SC_NORM_ATTR) << 16) | (ofwfb_background(SC_NORM_ATTR) << 8) | (ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < end; i++) *(addr + i) = color; return (0); } static int ofwfb_blank_display32(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; int i; uint32_t *addr, blank; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *) sc->sc_addr; blank = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++) *(addr + i) = blank; return (0); } static int ofwfb_blank_display(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_blank)(adp, mode)); } static int ofwfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct ofwfb_softc *sc; int i; sc = (struct ofwfb_softc *)adp; /* * Make sure the requested address lies within the PCI device's * assigned addrs */ for (i = 0; i < sc->sc_num_pciaddrs; i++) if (offset >= sc->sc_pciaddrs[i].phys_lo && offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo)) { /* * If this is a prefetchable BAR, we can (and should) * enable write-combining. */ if (sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) *memattr = VM_MEMATTR_WRITE_COMBINING; *paddr = offset; return (0); } /* * Hack for Radeon... */ if (ofwfb_ignore_mmap_checks) { *paddr = offset; return (0); } /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->sc_stride*sc->sc_height) { *paddr = sc->sc_addr + offset; return (0); } /* * Error if we didn't have a better idea. */ if (sc->sc_num_pciaddrs == 0) return (ENOMEM); return (EINVAL); } static int ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (0); } static int ofwfb_clear(video_adapter_t *adp) { TODO; return (0); } static int ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { TODO; return (0); } static int ofwfb_bitblt(video_adapter_t *adp, ...) { TODO; return (0); } static int ofwfb_diag(video_adapter_t *adp, int level) { TODO; return (0); } static int ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { TODO; return (0); } static int ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { TODO; return (0); } static int ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { TODO; return (0); } static int ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { TODO; return (0); } static int ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; int row; int col; int i; uint32_t *addr; u_char *p, fg, bg; union { uint32_t l; uint8_t c[4]; } ch1, ch2; sc = (struct ofwfb_softc *)adp; row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->sc_font + c*sc->sc_font_height; addr = (u_int32_t *)((uintptr_t)sc->sc_addr + (row + sc->sc_ymargin)*sc->sc_stride + col + sc->sc_xmargin); fg = ofwfb_foreground(a); bg = ofwfb_background(a); for (i = 0; i < sc->sc_font_height; i++) { u_char fline = p[i]; /* * Assume that there is more background than foreground * in characters and init accordingly */ ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg; /* * Calculate 2 x 4-chars at a time, and then * write these out. */ if (fline & 0x80) ch1.c[0] = fg; if (fline & 0x40) ch1.c[1] = fg; if (fline & 0x20) ch1.c[2] = fg; if (fline & 0x10) ch1.c[3] = fg; if (fline & 0x08) ch2.c[0] = fg; if (fline & 0x04) ch2.c[1] = fg; if (fline & 0x02) ch2.c[2] = fg; if (fline & 0x01) ch2.c[3] = fg; addr[0] = ch1.l; addr[1] = ch2.l; addr += (sc->sc_stride / sizeof(u_int32_t)); } return (0); } static int ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; int row; int col; int i, j, k; uint32_t *addr, fg, bg; u_char *p; sc = (struct ofwfb_softc *)adp; row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->sc_font + c*sc->sc_font_height; addr = (uint32_t *)sc->sc_addr + (row + sc->sc_ymargin)*(sc->sc_stride/4) + col + sc->sc_xmargin; fg = ofwfb_pix32(sc, ofwfb_foreground(a)); bg = ofwfb_pix32(sc, ofwfb_background(a)); for (i = 0; i < sc->sc_font_height; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) *(addr + j) = bg; else *(addr + j) = fg; } addr += (sc->sc_stride/4); } return (0); } static int ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_putc)(adp, off, c, a)); } static int ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) { ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); } return (0); } static int ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size, width)); } static int ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; int i, j, k; uint8_t *addr; u_char fg, bg; sc = (struct ofwfb_softc *)adp; addr = (u_int8_t *)((uintptr_t)sc->sc_addr + (y + sc->sc_ymargin)*sc->sc_stride + x + sc->sc_xmargin); fg = ofwfb_foreground(SC_NORM_ATTR); bg = ofwfb_background(SC_NORM_ATTR); for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) { /* * Calculate 2 x 4-chars at a time, and then * write these out. */ for (j = 0, k = width; j < 8; j++, k--) { if (x + j >= sc->sc_width - 2*sc->sc_xmargin) continue; if (pixel_image[i] & (1 << k)) addr[j] = (addr[j] == fg) ? bg : fg; } addr += (sc->sc_stride / sizeof(u_int8_t)); } return (0); } static int ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; int i, j, k; uint32_t fg, bg; uint32_t *addr; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *)sc->sc_addr + (y + sc->sc_ymargin)*(sc->sc_stride/4) + x + sc->sc_xmargin; fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR)); bg = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) { for (j = 0, k = width; j < 8; j++, k--) { if (x + j >= sc->sc_width - 2*sc->sc_xmargin) continue; if (pixel_image[i] & (1 << k)) *(addr + j) = (*(addr + j) == fg) ? bg : fg; } addr += (sc->sc_stride/4); } return (0); } /* * Define the syscons nexus device attachment */ static void ofwfb_scidentify(driver_t *driver, device_t parent) { device_t child; /* * Add with a priority guaranteed to make it last on * the device list */ child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0); } static int ofwfb_scprobe(device_t dev) { int error; device_set_desc(dev, "System console"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); /* This is a fake device, so make sure we added it ourselves */ return (BUS_PROBE_NOWILDCARD); } static int ofwfb_scattach(device_t dev) { return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); } static device_method_t ofwfb_sc_methods[] = { DEVMETHOD(device_identify, ofwfb_scidentify), DEVMETHOD(device_probe, ofwfb_scprobe), DEVMETHOD(device_attach, ofwfb_scattach), { 0, 0 } }; static driver_t ofwfb_sc_driver = { SC_DRIVER_NAME, ofwfb_sc_methods, sizeof(sc_softc_t), }; static devclass_t sc_devclass; DRIVER_MODULE(ofwfb, nexus, ofwfb_sc_driver, sc_devclass, 0, 0); /* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(dummy, dummysw, dummy_kbd_configure); - -/* * Utility routines from */ void ofwfb_bcopy(const void *s, void *d, size_t c) { bcopy(s, d, c); } void ofwfb_bzero(void *d, size_t c) { bzero(d, c); } void ofwfb_fillw(int pat, void *base, size_t cnt) { u_int16_t *bptr = base; while (cnt--) *bptr++ = pat; } u_int16_t ofwfb_readw(u_int16_t *addr) { return (*addr); } void ofwfb_writew(u_int16_t *addr, u_int16_t val) { *addr = val; } Index: stable/11 =================================================================== --- stable/11 (revision 356109) +++ stable/11 (revision 356110) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r355936,356045 Index: stable/12/sys/arm/broadcom/bcm2835/bcm2835_fb.c =================================================================== --- stable/12/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 356109) +++ stable/12/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 356110) @@ -1,871 +1,852 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mbox_if.h" struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb bcmfb_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define BCMFB_FONT_HEIGHT 16 #define BCMFB_FONT_WIDTH 8 #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 24 struct bcmsc_softc { /* Videoadpater part */ video_adapter_t va; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int fbswap; int initialized; }; static struct bcmsc_softc bcmsc; static struct ofw_compat_data compat_data[] = { {"broadcom,bcm2835-fb", 1}, {"brcm,bcm2708-fb", 1}, {NULL, 0} }; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); static void bcmfb_update_margins(video_adapter_t *adp); static int bcmfb_configure(int); static int bcm_fb_probe(device_t dev) { int error; if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); device_set_desc(dev, "BCM2835 framebuffer device"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); return (BUS_PROBE_DEFAULT); } static int bcm_fb_attach(device_t dev) { struct bcm2835_fb_config fb; struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter( "bcmfb", 0)); if (sc != NULL) device_set_softc(dev, sc); else sc = device_get_softc(dev); memset(&fb, 0, sizeof(fb)); if (bcm2835_mbox_fb_get_w_h(&fb) != 0) return (ENXIO); fb.bpp = FB_DEPTH; fb.vxres = fb.xres; fb.vyres = fb.yres; fb.xoffset = fb.yoffset = 0; if (bcm2835_mbox_fb_init(&fb) != 0) return (ENXIO); sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size); sc->fb_paddr = fb.base; sc->fb_size = fb.size; sc->depth = fb.bpp; sc->stride = fb.pitch; sc->width = fb.xres; sc->height = fb.yres; bcmfb_update_margins(&sc->va); if (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) { device_printf(dev, "failed to attach syscons\n"); return (ENXIO); } device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); device_printf(dev, "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", sc->fbswap, fb.pitch, fb.base, fb.size); return (0); } static device_method_t bcm_fb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcm_fb_probe), DEVMETHOD(device_attach, bcm_fb_attach), { 0, 0 } }; static devclass_t bcm_fb_devclass; static driver_t bcm_fb_driver = { "fb", bcm_fb_methods, sizeof(struct bcmsc_softc), }; DRIVER_MODULE(bcm2835fb, ofwbus, bcm_fb_driver, bcm_fb_devclass, 0, 0); DRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0); /* * Video driver routines and glue. */ static vi_probe_t bcmfb_probe; static vi_init_t bcmfb_init; static vi_get_info_t bcmfb_get_info; static vi_query_mode_t bcmfb_query_mode; static vi_set_mode_t bcmfb_set_mode; static vi_save_font_t bcmfb_save_font; static vi_load_font_t bcmfb_load_font; static vi_show_font_t bcmfb_show_font; static vi_save_palette_t bcmfb_save_palette; static vi_load_palette_t bcmfb_load_palette; static vi_set_border_t bcmfb_set_border; static vi_save_state_t bcmfb_save_state; static vi_load_state_t bcmfb_load_state; static vi_set_win_org_t bcmfb_set_win_org; static vi_read_hw_cursor_t bcmfb_read_hw_cursor; static vi_set_hw_cursor_t bcmfb_set_hw_cursor; static vi_set_hw_cursor_shape_t bcmfb_set_hw_cursor_shape; static vi_blank_display_t bcmfb_blank_display; static vi_mmap_t bcmfb_mmap; static vi_ioctl_t bcmfb_ioctl; static vi_clear_t bcmfb_clear; static vi_fill_rect_t bcmfb_fill_rect; static vi_bitblt_t bcmfb_bitblt; static vi_diag_t bcmfb_diag; static vi_save_cursor_palette_t bcmfb_save_cursor_palette; static vi_load_cursor_palette_t bcmfb_load_cursor_palette; static vi_copy_t bcmfb_copy; static vi_putp_t bcmfb_putp; static vi_putc_t bcmfb_putc; static vi_puts_t bcmfb_puts; static vi_putm_t bcmfb_putm; static video_switch_t bcmfbvidsw = { .probe = bcmfb_probe, .init = bcmfb_init, .get_info = bcmfb_get_info, .query_mode = bcmfb_query_mode, .set_mode = bcmfb_set_mode, .save_font = bcmfb_save_font, .load_font = bcmfb_load_font, .show_font = bcmfb_show_font, .save_palette = bcmfb_save_palette, .load_palette = bcmfb_load_palette, .set_border = bcmfb_set_border, .save_state = bcmfb_save_state, .load_state = bcmfb_load_state, .set_win_org = bcmfb_set_win_org, .read_hw_cursor = bcmfb_read_hw_cursor, .set_hw_cursor = bcmfb_set_hw_cursor, .set_hw_cursor_shape = bcmfb_set_hw_cursor_shape, .blank_display = bcmfb_blank_display, .mmap = bcmfb_mmap, .ioctl = bcmfb_ioctl, .clear = bcmfb_clear, .fill_rect = bcmfb_fill_rect, .bitblt = bcmfb_bitblt, .diag = bcmfb_diag, .save_cursor_palette = bcmfb_save_cursor_palette, .load_cursor_palette = bcmfb_load_cursor_palette, .copy = bcmfb_copy, .putp = bcmfb_putp, .putc = bcmfb_putc, .puts = bcmfb_puts, .putm = bcmfb_putm, }; VIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure); static vr_init_t bcmrend_init; static vr_clear_t bcmrend_clear; static vr_draw_border_t bcmrend_draw_border; static vr_draw_t bcmrend_draw; static vr_set_cursor_t bcmrend_set_cursor; static vr_draw_cursor_t bcmrend_draw_cursor; static vr_blink_cursor_t bcmrend_blink_cursor; static vr_set_mouse_t bcmrend_set_mouse; static vr_draw_mouse_t bcmrend_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t bcmrend = { bcmrend_init, bcmrend_clear, bcmrend_draw_border, bcmrend_draw, bcmrend_set_cursor, bcmrend_draw_cursor, bcmrend_blink_cursor, bcmrend_set_mouse, bcmrend_draw_mouse }; RENDERER(bcmfb, 0, bcmrend, gfb_set); RENDERER_MODULE(bcmfb, gfb_set); static void bcmrend_init(scr_stat* scp) { } static void bcmrend_clear(scr_stat* scp, int c, int attr) { } static void bcmrend_draw_border(scr_stat* scp, int color) { } static void bcmrend_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { int bytes, col, i, j, row; struct bcmsc_softc *sc; uint8_t *addr; video_adapter_t *adp; adp = scp->sc->adp; sc = (struct bcmsc_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); bytes = sc->depth / 8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { switch (sc->depth) { case 32: case 24: addr[bytes*j + 2] ^= 0xff; /* FALLTHROUGH */ case 16: addr[bytes*j + 1] ^= 0xff; addr[bytes*j] ^= 0xff; break; default: break; } } addr += sc->stride; } } static void bcmrend_blink_cursor(scr_stat* scp, int at, int flip) { } static void bcmrend_set_mouse(scr_stat* scp) { } static void bcmrend_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t bcmfb_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void bcmfb_update_margins(video_adapter_t *adp) { struct bcmsc_softc *sc; video_info_t *vi; sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; } static int bcmfb_configure(int flags) { char bootargs[2048], *n, *p, *v; pcell_t cell; phandle_t chosen, display, root; struct bcmsc_softc *sc; sc = &bcmsc; if (sc->initialized) return (0); sc->width = 0; sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try * to fetch data from FDT bootargs, FDT display data and * finally go with defaults if everything else has failed. */ chosen = OF_finddevice("/chosen"); if (chosen != -1 && OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { p = bootargs; while ((v = strsep(&p, " ")) != NULL) { if (*v == '\0') continue; n = strsep(&v, "="); if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL) sc->width = (unsigned int)strtol(v, NULL, 0); else if (strcmp(n, "bcm2708_fb.fbheight") == 0 && v != NULL) sc->height = (unsigned int)strtol(v, NULL, 0); else if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL) if (*v == '1') sc->fbswap = 1; } } root = OF_finddevice("/"); if ((root != -1) && (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { if (sc->width == 0) { if ((OF_getencprop(display, "broadcom,width", &cell, sizeof(cell))) > 0) sc->width = cell; } if (sc->height == 0) { if ((OF_getencprop(display, "broadcom,height", &cell, sizeof(cell))) > 0) sc->height = cell; } } if (sc->width == 0) sc->width = FB_WIDTH; if (sc->height == 0) sc->height = FB_HEIGHT; bcmfb_init(0, &sc->va, 0); sc->initialized = 1; return (0); } static int bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int bcmfb_init(int unit, video_adapter_t *adp, int flags) { struct bcmsc_softc *sc; video_info_t *vi; sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "bcmfb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = BCMFB_FONT_HEIGHT; vi->vi_cwidth = BCMFB_FONT_WIDTH; vi->vi_width = sc->width / vi->vi_cwidth; vi->vi_height = sc->height / vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; adp->va_window = (vm_offset_t) bcmfb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int bcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int bcmfb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int bcmfb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int bcmfb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int bcmfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; sc->font = data; return (0); } static int bcmfb_show_font(video_adapter_t *adp, int page) { return (0); } static int bcmfb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_set_border(video_adapter_t *adp, int border) { return (bcmfb_blank_display(adp, border)); } static int bcmfb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int bcmfb_load_state(video_adapter_t *adp, void *p) { return (0); } static int bcmfb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int bcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int bcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int bcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int bcmfb_blank_display(video_adapter_t *adp, int mode) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct bcmsc_softc *sc; sc = (struct bcmsc_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct bcmsc_softc *sc; struct fbtype *fb; sc = (struct bcmsc_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int bcmfb_clear(video_adapter_t *adp) { return (bcmfb_blank_display(adp, 0)); } static int bcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int bcmfb_bitblt(video_adapter_t *adp, ...) { return (0); } static int bcmfb_diag(video_adapter_t *adp, int level) { return (0); } static int bcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int bcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { int bytes, col, i, j, k, row; struct bcmsc_softc *sc; u_char *p; uint8_t *addr, fg, bg, color; uint16_t rgb; sc = (struct bcmsc_softc *)adp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*BCMFB_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; bytes = sc->depth / 8; for (i = 0; i < BCMFB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 32: case 24: if (sc->fbswap) { addr[bytes * j + 0] = bcmfb_palette[color].b; addr[bytes * j + 1] = bcmfb_palette[color].g; addr[bytes * j + 2] = bcmfb_palette[color].r; } else { addr[bytes * j + 0] = bcmfb_palette[color].r; addr[bytes * j + 1] = bcmfb_palette[color].g; addr[bytes * j + 2] = bcmfb_palette[color].b; } if (sc->depth == 32) addr[bytes * j + 3] = bcmfb_palette[color].a; break; case 16: rgb = (bcmfb_palette[color].r >> 3) << 11; rgb |= (bcmfb_palette[color].g >> 2) << 5; rgb |= (bcmfb_palette[color].b >> 3); addr[bytes * j] = rgb & 0xff; addr[bytes * j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int bcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int bcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t bcmdummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure); Index: stable/12/sys/arm/freescale/imx/imx51_ipuv3.c =================================================================== --- stable/12/sys/arm/freescale/imx/imx51_ipuv3.c (revision 356109) +++ stable/12/sys/arm/freescale/imx/imx51_ipuv3.c (revision 356110) @@ -1,899 +1,880 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012 Oleksandr Tymoshenko * Copyright (c) 2012, 2013 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Oleksandr Rybalko * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IMX51_IPU_HSP_CLOCK 665000000 #define IPU3FB_FONT_HEIGHT 16 struct ipu3sc_softc { device_t dev; bus_addr_t pbase; bus_addr_t vbase; bus_space_tag_t iot; bus_space_handle_t ioh; bus_space_handle_t cm_ioh; bus_space_handle_t dp_ioh; bus_space_handle_t di0_ioh; bus_space_handle_t di1_ioh; bus_space_handle_t dctmpl_ioh; bus_space_handle_t dc_ioh; bus_space_handle_t dmfc_ioh; bus_space_handle_t idmac_ioh; bus_space_handle_t cpmem_ioh; }; struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; int bpp; int depth; unsigned int height; unsigned int width; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; static struct ipu3sc_softc *ipu3sc_softc; static struct video_adapter_softc va_softc; /* FIXME: not only 2 bytes color supported */ static uint16_t colors[16] = { 0x0000, /* black */ 0x001f, /* blue */ 0x07e0, /* green */ 0x07ff, /* cyan */ 0xf800, /* red */ 0xf81f, /* magenta */ 0x3800, /* brown */ 0xc618, /* light grey */ 0xc618, /* XXX: dark grey */ 0x001f, /* XXX: light blue */ 0x07e0, /* XXX: light green */ 0x07ff, /* XXX: light cyan */ 0xf800, /* XXX: light red */ 0xf81f, /* XXX: light magenta */ 0xffe0, /* yellow */ 0xffff, /* white */ }; static uint32_t colors_24[16] = { 0x000000,/* Black */ 0x000080,/* Blue */ 0x008000,/* Green */ 0x008080,/* Cyan */ 0x800000,/* Red */ 0x800080,/* Magenta */ 0xcc6600,/* brown */ 0xC0C0C0,/* Silver */ 0x808080,/* Gray */ 0x0000FF,/* Light Blue */ 0x00FF00,/* Light Green */ 0x00FFFF,/* Light Cyan */ 0xFF0000,/* Light Red */ 0xFF00FF,/* Light Magenta */ 0xFFFF00,/* Yellow */ 0xFFFFFF,/* White */ }; #define IPUV3_READ(ipuv3, module, reg) \ bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg)) #define IPUV3_WRITE(ipuv3, module, reg, val) \ bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val)) #define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40) #define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20) #define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000) #define IMX_IPU_DP0 0 #define IMX_IPU_DP1 1 #define CPMEM_CHANNEL(_dp, _ch, _w) \ (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \ CPMEM_WORD_OFFSET(_w)) #define CPMEM_OFFSET(_dp, _ch, _w, _o) \ (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o)) #define IPUV3_DEBUG 100 #ifdef IPUV3_DEBUG #define SUBMOD_DUMP_REG(_sc, _m, _l) \ { \ int i; \ printf("*** " #_m " ***\n"); \ for (i = 0; i <= (_l); i += 4) { \ if ((i % 32) == 0) \ printf("%04x: ", i & 0xffff); \ printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \ ((i + 4) % 32)?' ':'\n'); \ } \ printf("\n"); \ } #endif #ifdef IPUV3_DEBUG int ipuv3_debug = IPUV3_DEBUG; #define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else #else #define DPRINTFN(n,x) #endif static int ipu3_fb_probe(device_t); static int ipu3_fb_attach(device_t); static int ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size) { sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0); sc->pbase = vtophys(sc->vbase); return (0); } static void ipu3_fb_init(void *arg) { struct ipu3sc_softc *sc = arg; struct video_adapter_softc *va_sc = &va_softc; uint64_t w0sh96; uint32_t w1sh96; /* FW W0[137:125] - 96 = [41:29] */ /* FH W0[149:138] - 96 = [53:42] */ w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16)); w0sh96 <<= 32; w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12)); va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1; va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1; /* SLY W1[115:102] - 96 = [19:6] */ w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12)); va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1; printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride); va_sc->fb_size = va_sc->height * va_sc->stride; ipu3_fb_malloc(sc, va_sc->fb_size); /* DP1 + config_ch_23 + word_2 */ IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0), ((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff); IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4), ((sc->pbase >> 3) >> 3) & 0xffffffff); va_sc->fb_addr = (intptr_t)sc->vbase; va_sc->fb_paddr = (intptr_t)sc->pbase; va_sc->bpp = va_sc->stride / va_sc->width; va_sc->depth = va_sc->bpp * 8; } static int ipu3_fb_probe(device_t dev) { int error; if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "fsl,ipu3")) return (ENXIO); device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); return (BUS_PROBE_DEFAULT); } static int ipu3_fb_attach(device_t dev) { struct ipu3sc_softc *sc = device_get_softc(dev); bus_space_tag_t iot; bus_space_handle_t ioh; phandle_t node; pcell_t reg; int err; uintptr_t base; if (ipu3sc_softc) return (ENXIO); ipu3sc_softc = sc; if (bootverbose) device_printf(dev, "clock gate status is %d\n", imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT)); sc->dev = dev; err = (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); if (err) { device_printf(dev, "failed to attach syscons\n"); goto fail; } sc = device_get_softc(dev); sc->iot = iot = fdtbus_bs_tag; /* * Retrieve the device address based on the start address in the * DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register * address, so we just subtract IPU_CM_BASE to get the offset at which * the IPU device was memory mapped. * On i.MX53, the offset is 0. */ node = ofw_bus_get_node(dev); if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0) base = 0; else base = reg - IPU_CM_BASE(0); /* map controller registers */ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh); if (err) goto fail_retarn_cm; sc->cm_ioh = ioh; /* map Display Multi FIFO Controller registers */ err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh); if (err) goto fail_retarn_dmfc; sc->dmfc_ioh = ioh; /* map Display Interface 0 registers */ err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh); if (err) goto fail_retarn_di0; sc->di0_ioh = ioh; /* map Display Interface 1 registers */ err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh); if (err) goto fail_retarn_di1; sc->di1_ioh = ioh; /* map Display Processor registers */ err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh); if (err) goto fail_retarn_dp; sc->dp_ioh = ioh; /* map Display Controller registers */ err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh); if (err) goto fail_retarn_dc; sc->dc_ioh = ioh; /* map Image DMA Controller registers */ err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0, &ioh); if (err) goto fail_retarn_idmac; sc->idmac_ioh = ioh; /* map CPMEM registers */ err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0, &ioh); if (err) goto fail_retarn_cpmem; sc->cpmem_ioh = ioh; /* map DCTEMPL registers */ err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0, &ioh); if (err) goto fail_retarn_dctmpl; sc->dctmpl_ioh = ioh; #ifdef notyet sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO, ipuv3intr, sc); if (sc->ih == NULL) { device_printf(sc->dev, "unable to establish interrupt at irq %d\n", IMX51_INT_IPUV3); return (ENXIO); } #endif /* * We have to wait until interrupts are enabled. * Mailbox relies on it to get data from VideoCore */ ipu3_fb_init(sc); return (0); fail: return (ENXIO); fail_retarn_dctmpl: bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE); fail_retarn_cpmem: bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE); fail_retarn_idmac: bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE); fail_retarn_dp: bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE); fail_retarn_dc: bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE); fail_retarn_di1: bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE); fail_retarn_di0: bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE); fail_retarn_dmfc: bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE); fail_retarn_cm: device_printf(sc->dev, "failed to map registers (errno=%d)\n", err); return (err); } static device_method_t ipu3_fb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ipu3_fb_probe), DEVMETHOD(device_attach, ipu3_fb_attach), { 0, 0 } }; static devclass_t ipu3_fb_devclass; static driver_t ipu3_fb_driver = { "fb", ipu3_fb_methods, sizeof(struct ipu3sc_softc), }; DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0); /* * Video driver routines and glue. */ static int ipu3fb_configure(int); static vi_probe_t ipu3fb_probe; static vi_init_t ipu3fb_init; static vi_get_info_t ipu3fb_get_info; static vi_query_mode_t ipu3fb_query_mode; static vi_set_mode_t ipu3fb_set_mode; static vi_save_font_t ipu3fb_save_font; static vi_load_font_t ipu3fb_load_font; static vi_show_font_t ipu3fb_show_font; static vi_save_palette_t ipu3fb_save_palette; static vi_load_palette_t ipu3fb_load_palette; static vi_set_border_t ipu3fb_set_border; static vi_save_state_t ipu3fb_save_state; static vi_load_state_t ipu3fb_load_state; static vi_set_win_org_t ipu3fb_set_win_org; static vi_read_hw_cursor_t ipu3fb_read_hw_cursor; static vi_set_hw_cursor_t ipu3fb_set_hw_cursor; static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape; static vi_blank_display_t ipu3fb_blank_display; static vi_mmap_t ipu3fb_mmap; static vi_ioctl_t ipu3fb_ioctl; static vi_clear_t ipu3fb_clear; static vi_fill_rect_t ipu3fb_fill_rect; static vi_bitblt_t ipu3fb_bitblt; static vi_diag_t ipu3fb_diag; static vi_save_cursor_palette_t ipu3fb_save_cursor_palette; static vi_load_cursor_palette_t ipu3fb_load_cursor_palette; static vi_copy_t ipu3fb_copy; static vi_putp_t ipu3fb_putp; static vi_putc_t ipu3fb_putc; static vi_puts_t ipu3fb_puts; static vi_putm_t ipu3fb_putm; static video_switch_t ipu3fbvidsw = { .probe = ipu3fb_probe, .init = ipu3fb_init, .get_info = ipu3fb_get_info, .query_mode = ipu3fb_query_mode, .set_mode = ipu3fb_set_mode, .save_font = ipu3fb_save_font, .load_font = ipu3fb_load_font, .show_font = ipu3fb_show_font, .save_palette = ipu3fb_save_palette, .load_palette = ipu3fb_load_palette, .set_border = ipu3fb_set_border, .save_state = ipu3fb_save_state, .load_state = ipu3fb_load_state, .set_win_org = ipu3fb_set_win_org, .read_hw_cursor = ipu3fb_read_hw_cursor, .set_hw_cursor = ipu3fb_set_hw_cursor, .set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape, .blank_display = ipu3fb_blank_display, .mmap = ipu3fb_mmap, .ioctl = ipu3fb_ioctl, .clear = ipu3fb_clear, .fill_rect = ipu3fb_fill_rect, .bitblt = ipu3fb_bitblt, .diag = ipu3fb_diag, .save_cursor_palette = ipu3fb_save_cursor_palette, .load_cursor_palette = ipu3fb_load_cursor_palette, .copy = ipu3fb_copy, .putp = ipu3fb_putp, .putc = ipu3fb_putc, .puts = ipu3fb_puts, .putm = ipu3fb_putm, }; VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(ipu3fb, 0, txtrndrsw, gfb_set); RENDERER_MODULE(ipu3fb, gfb_set); static uint16_t ipu3fb_static_window[ROW*COL]; extern u_char dflt_font_16[]; static int ipu3fb_configure(int flags) { struct video_adapter_softc *sc; sc = &va_softc; if (sc->initialized) return 0; sc->width = 640; sc->height = 480; sc->bpp = 2; sc->stride = sc->width * sc->bpp; ipu3fb_init(0, &sc->va, 0); sc->initialized = 1; return (0); } static int ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int ipu3fb_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "ipu3fb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = IPU3FB_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) ipu3fb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; adp->va_line_width = sc->stride; adp->va_buffer_size = sc->fb_size; vid_register(&sc->va); return (0); } static int ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int ipu3fb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int ipu3fb_show_font(video_adapter_t *adp, int page) { return (0); } static int ipu3fb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_set_border(video_adapter_t *adp, int border) { return (ipu3fb_blank_display(adp, border)); } static int ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int ipu3fb_load_state(video_adapter_t *adp, void *p) { return (0); } static int ipu3fb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int ipu3fb_blank_display(video_adapter_t *adp, int mode) { return (0); } static int ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride * sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct video_adapter_softc *sc; struct fbtype *fb; sc = (struct video_adapter_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; case FBIOSCURSOR: return (ENODEV); default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int ipu3fb_clear(video_adapter_t *adp) { return (ipu3fb_blank_display(adp, 0)); } static int ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int ipu3fb_bitblt(video_adapter_t *adp, ...) { return (0); } static int ipu3fb_diag(video_adapter_t *adp, int level) { return (0); } static int ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int col, row, bpp; int b, i, j, k; uint8_t *addr; u_char *p; uint32_t fg, bg, color; sc = (struct video_adapter_softc *)adp; bpp = sc->bpp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c * IPU3FB_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin) * (sc->stride) + bpp * (col + sc->xmargin); if (bpp == 2) { bg = colors[(a >> 4) & 0x0f]; fg = colors[a & 0x0f]; } else if (bpp == 3) { bg = colors_24[(a >> 4) & 0x0f]; fg = colors_24[a & 0x0f]; } else { return (ENXIO); } for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; /* FIXME: BPP maybe different */ for (b = 0; b < bpp; b ++) addr[bpp * j + b] = (color >> (b << 3)) & 0xff; } addr += (sc->stride); } return (0); } static int ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t ipu3dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure); Index: stable/12/sys/arm/ti/am335x/am335x_lcd_syscons.c =================================================================== --- stable/12/sys/arm/ti/am335x/am335x_lcd_syscons.c (revision 356109) +++ stable/12/sys/arm/ti/am335x/am335x_lcd_syscons.c (revision 356110) @@ -1,791 +1,772 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2013 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "am335x_lcd.h" struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; int console; intptr_t fb_addr; intptr_t fb_paddr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb am335x_syscons_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define AM335X_FONT_HEIGHT 16 #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 24 static struct video_adapter_softc va_softc; static int am335x_syscons_configure(int flags); /* * Video driver routines and glue. */ static vi_probe_t am335x_syscons_probe; static vi_init_t am335x_syscons_init; static vi_get_info_t am335x_syscons_get_info; static vi_query_mode_t am335x_syscons_query_mode; static vi_set_mode_t am335x_syscons_set_mode; static vi_save_font_t am335x_syscons_save_font; static vi_load_font_t am335x_syscons_load_font; static vi_show_font_t am335x_syscons_show_font; static vi_save_palette_t am335x_syscons_save_palette; static vi_load_palette_t am335x_syscons_load_palette; static vi_set_border_t am335x_syscons_set_border; static vi_save_state_t am335x_syscons_save_state; static vi_load_state_t am335x_syscons_load_state; static vi_set_win_org_t am335x_syscons_set_win_org; static vi_read_hw_cursor_t am335x_syscons_read_hw_cursor; static vi_set_hw_cursor_t am335x_syscons_set_hw_cursor; static vi_set_hw_cursor_shape_t am335x_syscons_set_hw_cursor_shape; static vi_blank_display_t am335x_syscons_blank_display; static vi_mmap_t am335x_syscons_mmap; static vi_ioctl_t am335x_syscons_ioctl; static vi_clear_t am335x_syscons_clear; static vi_fill_rect_t am335x_syscons_fill_rect; static vi_bitblt_t am335x_syscons_bitblt; static vi_diag_t am335x_syscons_diag; static vi_save_cursor_palette_t am335x_syscons_save_cursor_palette; static vi_load_cursor_palette_t am335x_syscons_load_cursor_palette; static vi_copy_t am335x_syscons_copy; static vi_putp_t am335x_syscons_putp; static vi_putc_t am335x_syscons_putc; static vi_puts_t am335x_syscons_puts; static vi_putm_t am335x_syscons_putm; static video_switch_t am335x_sysconsvidsw = { .probe = am335x_syscons_probe, .init = am335x_syscons_init, .get_info = am335x_syscons_get_info, .query_mode = am335x_syscons_query_mode, .set_mode = am335x_syscons_set_mode, .save_font = am335x_syscons_save_font, .load_font = am335x_syscons_load_font, .show_font = am335x_syscons_show_font, .save_palette = am335x_syscons_save_palette, .load_palette = am335x_syscons_load_palette, .set_border = am335x_syscons_set_border, .save_state = am335x_syscons_save_state, .load_state = am335x_syscons_load_state, .set_win_org = am335x_syscons_set_win_org, .read_hw_cursor = am335x_syscons_read_hw_cursor, .set_hw_cursor = am335x_syscons_set_hw_cursor, .set_hw_cursor_shape = am335x_syscons_set_hw_cursor_shape, .blank_display = am335x_syscons_blank_display, .mmap = am335x_syscons_mmap, .ioctl = am335x_syscons_ioctl, .clear = am335x_syscons_clear, .fill_rect = am335x_syscons_fill_rect, .bitblt = am335x_syscons_bitblt, .diag = am335x_syscons_diag, .save_cursor_palette = am335x_syscons_save_cursor_palette, .load_cursor_palette = am335x_syscons_load_cursor_palette, .copy = am335x_syscons_copy, .putp = am335x_syscons_putp, .putc = am335x_syscons_putc, .puts = am335x_syscons_puts, .putm = am335x_syscons_putm, }; VIDEO_DRIVER(am335x_syscons, am335x_sysconsvidsw, am335x_syscons_configure); static vr_init_t am335x_rend_init; static vr_clear_t am335x_rend_clear; static vr_draw_border_t am335x_rend_draw_border; static vr_draw_t am335x_rend_draw; static vr_set_cursor_t am335x_rend_set_cursor; static vr_draw_cursor_t am335x_rend_draw_cursor; static vr_blink_cursor_t am335x_rend_blink_cursor; static vr_set_mouse_t am335x_rend_set_mouse; static vr_draw_mouse_t am335x_rend_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t am335x_rend = { am335x_rend_init, am335x_rend_clear, am335x_rend_draw_border, am335x_rend_draw, am335x_rend_set_cursor, am335x_rend_draw_cursor, am335x_rend_blink_cursor, am335x_rend_set_mouse, am335x_rend_draw_mouse }; RENDERER(am335x_syscons, 0, am335x_rend, gfb_set); RENDERER_MODULE(am335x_syscons, gfb_set); static void am335x_rend_init(scr_stat* scp) { } static void am335x_rend_clear(scr_stat* scp, int c, int attr) { } static void am335x_rend_draw_border(scr_stat* scp, int color) { } static void am335x_rend_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void am335x_rend_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void am335x_rend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { video_adapter_t* adp = scp->sc->adp; struct video_adapter_softc *sc; int row, col; uint8_t *addr; int i, j, bytes; sc = (struct video_adapter_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); bytes = sc->depth/8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { switch (sc->depth) { case 32: case 24: addr[bytes*j + 2] ^= 0xff; /* FALLTHROUGH */ case 16: addr[bytes*j + 1] ^= 0xff; addr[bytes*j] ^= 0xff; break; default: break; } } addr += sc->stride; } } static void am335x_rend_blink_cursor(scr_stat* scp, int at, int flip) { } static void am335x_rend_set_mouse(scr_stat* scp) { } static void am335x_rend_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t am335x_syscons_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void am335x_syscons_update_margins(video_adapter_t *adp) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; } static phandle_t am335x_syscons_find_panel_node(phandle_t start) { phandle_t child; phandle_t result; for (child = OF_child(start); child != 0; child = OF_peer(child)) { if (ofw_bus_node_is_compatible(child, "ti,am335x-lcd")) return (child); if ((result = am335x_syscons_find_panel_node(child))) return (result); } return (0); } static int am335x_syscons_configure(int flags) { struct video_adapter_softc *va_sc; va_sc = &va_softc; phandle_t display, root; pcell_t cell; if (va_sc->initialized) return (0); va_sc->width = 0; va_sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try * to fetch data from FDT and go with defaults if failed */ root = OF_finddevice("/"); if ((root != -1) && (display = am335x_syscons_find_panel_node(root))) { if ((OF_getencprop(display, "panel_width", &cell, sizeof(cell))) > 0) va_sc->width = cell; if ((OF_getencprop(display, "panel_height", &cell, sizeof(cell))) > 0) va_sc->height = cell; } if (va_sc->width == 0) va_sc->width = FB_WIDTH; if (va_sc->height == 0) va_sc->height = FB_HEIGHT; am335x_syscons_init(0, &va_sc->va, 0); va_sc->initialized = 1; return (0); } static int am335x_syscons_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int am335x_syscons_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "am335x_syscons", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = AM335X_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) am335x_syscons_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int am335x_syscons_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int am335x_syscons_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int am335x_syscons_set_mode(video_adapter_t *adp, int mode) { return (0); } static int am335x_syscons_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int am335x_syscons_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int am335x_syscons_show_font(video_adapter_t *adp, int page) { return (0); } static int am335x_syscons_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_set_border(video_adapter_t *adp, int border) { return (am335x_syscons_blank_display(adp, border)); } static int am335x_syscons_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int am335x_syscons_load_state(video_adapter_t *adp, void *p) { return (0); } static int am335x_syscons_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int am335x_syscons_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int am335x_syscons_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int am335x_syscons_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int am335x_syscons_blank_display(video_adapter_t *adp, int mode) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int am335x_syscons_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_paddr + offset; return (0); } return (EINVAL); } static int am335x_syscons_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { struct video_adapter_softc *sc; struct fbtype *fb; sc = (struct video_adapter_softc *)adp; switch (cmd) { case FBIOGTYPE: fb = (struct fbtype *)data; fb->fb_type = FBTYPE_PCIMISC; fb->fb_height = sc->height; fb->fb_width = sc->width; fb->fb_depth = sc->depth; if (sc->depth <= 1 || sc->depth > 8) fb->fb_cmsize = 0; else fb->fb_cmsize = 1 << sc->depth; fb->fb_size = sc->fb_size; break; default: return (fb_commonioctl(adp, cmd, data)); } return (0); } static int am335x_syscons_clear(video_adapter_t *adp) { return (am335x_syscons_blank_display(adp, 0)); } static int am335x_syscons_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int am335x_syscons_bitblt(video_adapter_t *adp, ...) { return (0); } static int am335x_syscons_diag(video_adapter_t *adp, int level) { return (0); } static int am335x_syscons_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int am335x_syscons_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int am335x_syscons_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int am335x_syscons_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int row; int col; int i, j, k; uint8_t *addr; u_char *p; uint8_t fg, bg, color; uint16_t rgb; sc = (struct video_adapter_softc *)adp; if (sc->fb_addr == 0) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*AM335X_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; for (i = 0; i < AM335X_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 32: addr[4*j+0] = am335x_syscons_palette[color].r; addr[4*j+1] = am335x_syscons_palette[color].g; addr[4*j+2] = am335x_syscons_palette[color].b; addr[4*j+3] = am335x_syscons_palette[color].a; break; case 24: addr[3*j] = am335x_syscons_palette[color].r; addr[3*j+1] = am335x_syscons_palette[color].g; addr[3*j+2] = am335x_syscons_palette[color].b; break; case 16: rgb = (am335x_syscons_palette[color].r >> 3) << 11; rgb |= (am335x_syscons_palette[color].g >> 2) << 5; rgb |= (am335x_syscons_palette[color].b >> 3); addr[2*j] = rgb & 0xff; addr[2*j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int am335x_syscons_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) am335x_syscons_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int am335x_syscons_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } /* Initialization function */ int am335x_lcd_syscons_setup(vm_offset_t vaddr, vm_paddr_t paddr, struct panel_info *panel) { struct video_adapter_softc *va_sc = &va_softc; va_sc->fb_addr = vaddr; va_sc->fb_paddr = paddr; va_sc->depth = panel->bpp; va_sc->stride = panel->bpp*panel->panel_width/8; va_sc->width = panel->panel_width; va_sc->height = panel->panel_height; va_sc->fb_size = va_sc->width * va_sc->height * va_sc->depth/8; am335x_syscons_update_margins(&va_sc->va); return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t am335x_dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(am335x_dummy, am335x_dummysw, dummy_kbd_configure); Index: stable/12/sys/arm/versatile/versatile_clcd.c =================================================================== --- stable/12/sys/arm/versatile/versatile_clcd.c (revision 356109) +++ stable/12/sys/arm/versatile/versatile_clcd.c (revision 356110) @@ -1,941 +1,922 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012-2017 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PL110_VENDOR_ARM926PXP 1 #define CLCD_MODE_RGB888 0x0 #define CLCD_MODE_RGB555 0x01 #define CLCD_MODE_RBG565 0x02 #define CLCD_MODE_RGB565 0x03 #define CLCDC_TIMING0 0x00 #define CLCDC_TIMING1 0x04 #define CLCDC_TIMING2 0x08 #define CLCDC_TIMING3 0x0C #define CLCDC_TIMING3 0x0C #define CLCDC_UPBASE 0x10 #define CLCDC_LPBASE 0x14 #ifdef PL110_VENDOR_ARM926PXP #define CLCDC_CONTROL 0x18 #define CLCDC_IMSC 0x1C #else #define CLCDC_IMSC 0x18 #define CLCDC_CONTROL 0x1C #endif #define CONTROL_WATERMARK (1 << 16) #define CONTROL_VCOMP_VS (0 << 12) #define CONTROL_VCOMP_BP (1 << 12) #define CONTROL_VCOMP_SAV (2 << 12) #define CONTROL_VCOMP_FP (3 << 12) #define CONTROL_PWR (1 << 11) #define CONTROL_BEPO (1 << 10) #define CONTROL_BEBO (1 << 9) #define CONTROL_BGR (1 << 8) #define CONTROL_DUAL (1 << 7) #define CONTROL_MONO8 (1 << 6) #define CONTROL_TFT (1 << 5) #define CONTROL_BW (1 << 4) #define CONTROL_BPP1 (0x00 << 1) #define CONTROL_BPP2 (0x01 << 1) #define CONTROL_BPP4 (0x02 << 1) #define CONTROL_BPP8 (0x03 << 1) #define CONTROL_BPP16 (0x04 << 1) #define CONTROL_BPP24 (0x05 << 1) #define CONTROL_EN (1 << 0) #define CLCDC_RIS 0x20 #define CLCDC_MIS 0x24 #define INTR_MBERR (1 << 4) #define INTR_VCOMP (1 << 3) #define INTR_LNB (1 << 2) #define INTR_FUF (1 << 1) #define CLCDC_ICR 0x28 #ifdef DEBUG #define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ printf(fmt,##args); } while (0) #else #define dprintf(fmt, args...) #endif #define versatile_clcdc_read_4(sc, reg) \ bus_read_4((sc)->mem_res, (reg)) #define versatile_clcdc_write_4(sc, reg, val) \ bus_write_4((sc)->mem_res, (reg), (val)) struct versatile_clcdc_softc { struct resource* mem_res; struct mtx mtx; int width; int height; int mode; bus_dma_tag_t dma_tag; bus_dmamap_t dma_map; bus_addr_t fb_phys; uint8_t *fb_base; }; struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; int console; intptr_t fb_addr; unsigned int fb_size; unsigned int height; unsigned int width; unsigned int depth; unsigned int stride; unsigned int xmargin; unsigned int ymargin; unsigned char *font; int initialized; }; struct argb { uint8_t a; uint8_t r; uint8_t g; uint8_t b; }; static struct argb versatilefb_palette[16] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x00, 0xaa, 0x00}, {0x00, 0x00, 0xaa, 0xaa}, {0x00, 0xaa, 0x00, 0x00}, {0x00, 0xaa, 0x00, 0xaa}, {0x00, 0xaa, 0x55, 0x00}, {0x00, 0xaa, 0xaa, 0xaa}, {0x00, 0x55, 0x55, 0x55}, {0x00, 0x55, 0x55, 0xff}, {0x00, 0x55, 0xff, 0x55}, {0x00, 0x55, 0xff, 0xff}, {0x00, 0xff, 0x55, 0x55}, {0x00, 0xff, 0x55, 0xff}, {0x00, 0xff, 0xff, 0x55}, {0x00, 0xff, 0xff, 0xff} }; /* mouse pointer from dev/syscons/scgfbrndr.c */ static u_char mouse_pointer[16] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; #define FB_WIDTH 640 #define FB_HEIGHT 480 #define FB_DEPTH 16 #define VERSATILE_FONT_HEIGHT 16 static struct video_adapter_softc va_softc; static int versatilefb_configure(int); static void versatilefb_update_margins(video_adapter_t *adp); static void versatile_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) { bus_addr_t *addr; if (err) return; addr = (bus_addr_t*)arg; *addr = segs[0].ds_addr; } static int versatile_clcdc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "arm,pl110")) { device_set_desc(dev, "PL110 CLCD controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int versatile_clcdc_attach(device_t dev) { struct versatile_clcdc_softc *sc = device_get_softc(dev); struct video_adapter_softc *va_sc = &va_softc; int err, rid; uint32_t reg; int clcdid; int dma_size; /* Request memory resources */ rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "could not allocate memory resources\n"); return (ENXIO); } err = versatile_scm_reg_read_4(SCM_CLCD, ®); if (err) { device_printf(dev, "failed to read SCM register\n"); goto fail; } clcdid = (reg >> SCM_CLCD_CLCDID_SHIFT) & SCM_CLCD_CLCDID_MASK; switch (clcdid) { case 31: device_printf(dev, "QEMU VGA 640x480\n"); sc->width = 640; sc->height = 480; break; default: device_printf(dev, "Unsupported: %d\n", clcdid); goto fail; } reg &= ~SCM_CLCD_LCD_MODE_MASK; reg |= CLCD_MODE_RGB565; sc->mode = CLCD_MODE_RGB565; versatile_scm_reg_write_4(SCM_CLCD, reg); dma_size = sc->width*sc->height*2; /* * Power on LCD */ reg |= SCM_CLCD_PWR3V5VSWITCH | SCM_CLCD_NLCDIOON; versatile_scm_reg_write_4(SCM_CLCD, reg); /* * XXX: hardcoded timing for VGA. For other modes/panels * we need to keep table of timing register values */ /* * XXX: set SYS_OSC1 */ versatile_clcdc_write_4(sc, CLCDC_TIMING0, 0x3F1F3F9C); versatile_clcdc_write_4(sc, CLCDC_TIMING1, 0x090B61DF); versatile_clcdc_write_4(sc, CLCDC_TIMING2, 0x067F1800); /* XXX: timing 3? */ /* * Now allocate framebuffer memory */ err = bus_dma_tag_create( bus_get_dma_tag(dev), 4, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ dma_size, 1, /* maxsize, nsegments */ dma_size, 0, /* maxsegsize, flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->dma_tag); err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_base, 0, &sc->dma_map); if (err) { device_printf(dev, "cannot allocate framebuffer\n"); goto fail; } err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_base, dma_size, versatile_fb_dmamap_cb, &sc->fb_phys, BUS_DMA_NOWAIT); if (err) { device_printf(dev, "cannot load DMA map\n"); goto fail; } /* Make sure it's blank */ memset(sc->fb_base, 0x00, dma_size); versatile_clcdc_write_4(sc, CLCDC_UPBASE, sc->fb_phys); err = (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); if (err) { device_printf(dev, "failed to attach syscons\n"); goto fail; } /* * XXX: hardcoded for VGA */ reg = CONTROL_VCOMP_BP | CONTROL_TFT | CONTROL_BGR | CONTROL_EN; reg |= CONTROL_BPP16; versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); DELAY(20); reg |= CONTROL_PWR; versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); va_sc->fb_addr = (vm_offset_t)sc->fb_base; va_sc->fb_size = dma_size; va_sc->width = sc->width; va_sc->height = sc->height; va_sc->depth = 16; va_sc->stride = sc->width * 2; versatilefb_update_margins(&va_sc->va); return (0); fail: if (sc->fb_base) bus_dmamem_free(sc->dma_tag, sc->fb_base, sc->dma_map); if (sc->dma_tag) bus_dma_tag_destroy(sc->dma_tag); return (err); } static device_method_t versatile_clcdc_methods[] = { DEVMETHOD(device_probe, versatile_clcdc_probe), DEVMETHOD(device_attach, versatile_clcdc_attach), DEVMETHOD_END }; static driver_t versatile_clcdc_driver = { "clcdc", versatile_clcdc_methods, sizeof(struct versatile_clcdc_softc), }; static devclass_t versatile_clcdc_devclass; DRIVER_MODULE(versatile_clcdc, simplebus, versatile_clcdc_driver, versatile_clcdc_devclass, 0, 0); /* * Video driver routines and glue. */ static vi_probe_t versatilefb_probe; static vi_init_t versatilefb_init; static vi_get_info_t versatilefb_get_info; static vi_query_mode_t versatilefb_query_mode; static vi_set_mode_t versatilefb_set_mode; static vi_save_font_t versatilefb_save_font; static vi_load_font_t versatilefb_load_font; static vi_show_font_t versatilefb_show_font; static vi_save_palette_t versatilefb_save_palette; static vi_load_palette_t versatilefb_load_palette; static vi_set_border_t versatilefb_set_border; static vi_save_state_t versatilefb_save_state; static vi_load_state_t versatilefb_load_state; static vi_set_win_org_t versatilefb_set_win_org; static vi_read_hw_cursor_t versatilefb_read_hw_cursor; static vi_set_hw_cursor_t versatilefb_set_hw_cursor; static vi_set_hw_cursor_shape_t versatilefb_set_hw_cursor_shape; static vi_blank_display_t versatilefb_blank_display; static vi_mmap_t versatilefb_mmap; static vi_ioctl_t versatilefb_ioctl; static vi_clear_t versatilefb_clear; static vi_fill_rect_t versatilefb_fill_rect; static vi_bitblt_t versatilefb_bitblt; static vi_diag_t versatilefb_diag; static vi_save_cursor_palette_t versatilefb_save_cursor_palette; static vi_load_cursor_palette_t versatilefb_load_cursor_palette; static vi_copy_t versatilefb_copy; static vi_putp_t versatilefb_putp; static vi_putc_t versatilefb_putc; static vi_puts_t versatilefb_puts; static vi_putm_t versatilefb_putm; static video_switch_t versatilefbvidsw = { .probe = versatilefb_probe, .init = versatilefb_init, .get_info = versatilefb_get_info, .query_mode = versatilefb_query_mode, .set_mode = versatilefb_set_mode, .save_font = versatilefb_save_font, .load_font = versatilefb_load_font, .show_font = versatilefb_show_font, .save_palette = versatilefb_save_palette, .load_palette = versatilefb_load_palette, .set_border = versatilefb_set_border, .save_state = versatilefb_save_state, .load_state = versatilefb_load_state, .set_win_org = versatilefb_set_win_org, .read_hw_cursor = versatilefb_read_hw_cursor, .set_hw_cursor = versatilefb_set_hw_cursor, .set_hw_cursor_shape = versatilefb_set_hw_cursor_shape, .blank_display = versatilefb_blank_display, .mmap = versatilefb_mmap, .ioctl = versatilefb_ioctl, .clear = versatilefb_clear, .fill_rect = versatilefb_fill_rect, .bitblt = versatilefb_bitblt, .diag = versatilefb_diag, .save_cursor_palette = versatilefb_save_cursor_palette, .load_cursor_palette = versatilefb_load_cursor_palette, .copy = versatilefb_copy, .putp = versatilefb_putp, .putc = versatilefb_putc, .puts = versatilefb_puts, .putm = versatilefb_putm, }; VIDEO_DRIVER(versatilefb, versatilefbvidsw, versatilefb_configure); static vr_init_t clcdr_init; static vr_clear_t clcdr_clear; static vr_draw_border_t clcdr_draw_border; static vr_draw_t clcdr_draw; static vr_set_cursor_t clcdr_set_cursor; static vr_draw_cursor_t clcdr_draw_cursor; static vr_blink_cursor_t clcdr_blink_cursor; static vr_set_mouse_t clcdr_set_mouse; static vr_draw_mouse_t clcdr_draw_mouse; /* * We use our own renderer; this is because we must emulate a hardware * cursor. */ static sc_rndr_sw_t clcdrend = { clcdr_init, clcdr_clear, clcdr_draw_border, clcdr_draw, clcdr_set_cursor, clcdr_draw_cursor, clcdr_blink_cursor, clcdr_set_mouse, clcdr_draw_mouse }; RENDERER(versatilefb, 0, clcdrend, gfb_set); RENDERER_MODULE(versatilefb, gfb_set); static void clcdr_init(scr_stat* scp) { } static void clcdr_clear(scr_stat* scp, int c, int attr) { } static void clcdr_draw_border(scr_stat* scp, int color) { } static void clcdr_draw(scr_stat* scp, int from, int count, int flip) { video_adapter_t* adp = scp->sc->adp; int i, c, a; if (!flip) { /* Normal printing */ vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); } else { /* This is for selections and such: invert the color attribute */ for (i = count; i-- > 0; ++from) { c = sc_vtb_getc(&scp->vtb, from); a = sc_vtb_geta(&scp->vtb, from) >> 8; vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); } } } static void clcdr_set_cursor(scr_stat* scp, int base, int height, int blink) { } static void clcdr_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { video_adapter_t* adp = scp->sc->adp; struct video_adapter_softc *sc; int row, col; uint8_t *addr; int i,j; sc = (struct video_adapter_softc *)adp; if (scp->curs_attr.height <= 0) return; if (sc->fb_addr == 0) return; if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return; /* calculate the coordinates in the video buffer */ row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { addr[2*j] ^= 0xff; addr[2*j + 1] ^= 0xff; } addr += sc->stride; } } static void clcdr_blink_cursor(scr_stat* scp, int at, int flip) { } static void clcdr_set_mouse(scr_stat* scp) { } static void clcdr_draw_mouse(scr_stat* scp, int x, int y, int on) { vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); } static uint16_t versatilefb_static_window[ROW*COL]; extern u_char dflt_font_16[]; /* * Update videoadapter settings after changing resolution */ static void versatilefb_update_margins(video_adapter_t *adp) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; } static int versatilefb_configure(int flags) { struct video_adapter_softc *va_sc; va_sc = &va_softc; if (va_sc->initialized) return (0); va_sc->width = FB_WIDTH; va_sc->height = FB_HEIGHT; va_sc->depth = FB_DEPTH; versatilefb_init(0, &va_sc->va, 0); va_sc->initialized = 1; return (0); } static int versatilefb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { return (0); } static int versatilefb_init(int unit, video_adapter_t *adp, int flags) { struct video_adapter_softc *sc; video_info_t *vi; sc = (struct video_adapter_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "versatilefb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = VERSATILE_FONT_HEIGHT; vi->vi_cwidth = 8; vi->vi_width = sc->width/8; vi->vi_height = sc->height/vi->vi_cheight; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; adp->va_window = (vm_offset_t) versatilefb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; vid_register(&sc->va); return (0); } static int versatilefb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int versatilefb_query_mode(video_adapter_t *adp, video_info_t *info) { return (0); } static int versatilefb_set_mode(video_adapter_t *adp, int mode) { return (0); } static int versatilefb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { return (0); } static int versatilefb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; sc->font = data; return (0); } static int versatilefb_show_font(video_adapter_t *adp, int page) { return (0); } static int versatilefb_save_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_load_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_set_border(video_adapter_t *adp, int border) { return (versatilefb_blank_display(adp, border)); } static int versatilefb_save_state(video_adapter_t *adp, void *p, size_t size) { return (0); } static int versatilefb_load_state(video_adapter_t *adp, void *p) { return (0); } static int versatilefb_set_win_org(video_adapter_t *adp, off_t offset) { return (0); } static int versatilefb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = *row = 0; return (0); } static int versatilefb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int versatilefb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int versatilefb_blank_display(video_adapter_t *adp, int mode) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); return (0); } static int versatilefb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct video_adapter_softc *sc; sc = (struct video_adapter_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->stride*sc->height) { *paddr = sc->fb_addr + offset; return (0); } return (EINVAL); } static int versatilefb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (0); } static int versatilefb_clear(video_adapter_t *adp) { return (versatilefb_blank_display(adp, 0)); } static int versatilefb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { return (0); } static int versatilefb_bitblt(video_adapter_t *adp, ...) { return (0); } static int versatilefb_diag(video_adapter_t *adp, int level) { return (0); } static int versatilefb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { return (0); } static int versatilefb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { return (0); } static int versatilefb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { return (0); } static int versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct video_adapter_softc *sc; int row; int col; int i, j, k; uint8_t *addr; u_char *p; uint8_t fg, bg, color; uint16_t rgb; sc = (struct video_adapter_softc *)adp; if (sc->fb_addr == 0) return (0); if (off >= adp->va_info.vi_width * adp->va_info.vi_height) return (0); row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->font + c*VERSATILE_FONT_HEIGHT; addr = (uint8_t *)sc->fb_addr + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); fg = a & 0xf ; bg = (a >> 4) & 0xf; for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) color = bg; else color = fg; switch (sc->depth) { case 16: rgb = (versatilefb_palette[color].r >> 3) << 11; rgb |= (versatilefb_palette[color].g >> 2) << 5; rgb |= (versatilefb_palette[color].b >> 3); addr[2*j] = rgb & 0xff; addr[2*j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; } } addr += (sc->stride); } return (0); } static int versatilefb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) versatilefb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int versatilefb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { return (0); } - -/* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t bcmdummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure); Index: stable/12/sys/dev/terasic/mtl/terasic_mtl_syscons.c =================================================================== --- stable/12/sys/dev/terasic/mtl/terasic_mtl_syscons.c (revision 356109) +++ stable/12/sys/dev/terasic/mtl/terasic_mtl_syscons.c (revision 356110) @@ -1,492 +1,476 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Terasic Multitouch LCD (MTL) syscons driver. Implement syscons(4)'s * video_switch_t KPI using MTL's text frame buffer. In principle, we could * actually implement sc_rndr_sw_t, since the MTL text frame buffer implements * a VGA-like memory mapping. However, this requires a lot more book-keeping * with only minor performance improvements (avoiding indirection), as well as * introducing potential endianness issues. Instead we accept one additional * memory copy between a software frame buffer and the hardware frame buffer * and the generic frame buffer (gfb) framework. */ MALLOC_DEFINE(M_TERASIC_MTL, "mtl_syscons", "MTL syscons frame buffer"); /* * Run early so that boot-time console support can be initialised before * newbus gets around to configuring syscons. * * XXXRW: We may need to do more here in order to see earlier boot messages. */ static int terasic_mtl_syscons_configure(int flags) { printf("%s: not yet\n", __func__); return (0); } static int terasic_mtl_vidsw_probe(int unit, video_adapter_t **adp, void *args, int flags) { printf("%s: not yet\n", __func__); return (0); } static int terasic_mtl_vidsw_init(int unit, video_adapter_t *adp, int flags) { struct terasic_mtl_softc *sc; video_info_t *vi; sc = (struct terasic_mtl_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "terasic_mtl_syscons", -1, unit); vi->vi_width = TERASIC_MTL_COLS; if (vi->vi_width > COL) vi->vi_width = COL; vi->vi_height = TERASIC_MTL_ROWS; if (vi->vi_height > ROW) vi->vi_height = ROW; /* * XXXRW: It's not quite clear how these should be initialised. */ vi->vi_cwidth = 0; vi->vi_cheight = 0; vi->vi_flags = V_INFO_COLOR; vi->vi_mem_model = V_INFO_MM_OTHER; /* * Software text frame buffer from which we update the actual MTL * frame buffer when asked to. */ adp->va_window = (vm_offset_t)sc->mtl_text_soft; /* * Declare video adapter capabilities -- at this point, simply color * support, as MTL doesn't support screen borders, font loading, or * mode changes. * * XXXRW: It's unclear if V_ADP_INITIALIZED is needed here; other * syscons(4) drivers are inconsistent about this and * V_ADP_REGISTERED. */ adp->va_flags |= V_ADP_COLOR | V_ADP_INITIALIZED; if (vid_register(adp) < 0) { device_printf(sc->mtl_dev, "%s: vid_register failed\n", __func__); return (ENXIO); } adp->va_flags |= V_ADP_REGISTERED; return (0); } static int terasic_mtl_vidsw_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int terasic_mtl_vidsw_query_mode(video_adapter_t *adp, video_info_t *info) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_mode(video_adapter_t *adp, int mode) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_show_font(video_adapter_t *adp, int page) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_border(video_adapter_t *adp, int border) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_state(video_adapter_t *adp, void *p, size_t size) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_state(video_adapter_t *adp, void *p) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_set_win_org(video_adapter_t *adp, off_t offset) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_read_hw_cursor(video_adapter_t *adp, int *colp, int *rowp) { struct terasic_mtl_softc *sc; uint8_t col, row; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_textcursor_get(sc, &col, &row); *colp = col; *rowp = row; return (0); } static int terasic_mtl_vidsw_set_hw_cursor(video_adapter_t *adp, int col, int row) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_textcursor_set(sc, col, row); return (0); } static int terasic_mtl_vidsw_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_blank_display(video_adapter_t *adp, int mode) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; terasic_mtl_reg_blank(sc); return (0); } static int terasic_mtl_vidsw_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (fb_commonioctl(adp, cmd, data)); } static int terasic_mtl_vidsw_clear(video_adapter_t *adp) { struct terasic_mtl_softc *sc; sc = (struct terasic_mtl_softc *)adp; printf("%s: not yet terasic_mtl_io_clear(sc);\n", __func__); return (0); } static int terasic_mtl_vidsw_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_bitblt(video_adapter_t *adp, ...) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_diag(video_adapter_t *adp, int level) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_save_cursor_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_load_cursor_palette(video_adapter_t *adp, u_char *palette) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { printf("%s: not yet\n", __func__); return (ENODEV); } static int terasic_mtl_vidsw_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct terasic_mtl_softc *sc; u_int col, row; sc = (struct terasic_mtl_softc *)adp; col = (off % adp->va_info.vi_width); row = (off / adp->va_info.vi_width); terasic_mtl_text_putc(sc, col, row, c, a); return (0); } static int terasic_mtl_vidsw_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) vidd_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); return (0); } static int terasic_mtl_vidsw_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { printf("%s: not yet\n", __func__); return (ENODEV); } -/* - * XXXRW: For historical reasons, syscons can't register video consoles - * without a keyboard implementation. Provide a dummy. - */ -static keyboard_switch_t terasic_mtl_keyboard_switch; - -static int -terasic_mtl_kbd_configure(int flags) -{ - - return (0); -} - -KEYBOARD_DRIVER(mtl_kbd, terasic_mtl_keyboard_switch, - terasic_mtl_kbd_configure); - int terasic_mtl_syscons_attach(struct terasic_mtl_softc *sc) { int error; sc->mtl_text_soft = malloc(sizeof(uint16_t) * TERASIC_MTL_ROWS * TERASIC_MTL_COLS, M_TERASIC_MTL, M_WAITOK | M_ZERO); error = terasic_mtl_vidsw_init(0, &sc->mtl_va, 0); if (error) goto out; error = sc_attach_unit(sc->mtl_unit, device_get_flags(sc->mtl_dev) | SC_AUTODETECT_KBD); if (error) device_printf(sc->mtl_dev, "%s: sc_attach_unit failed (%d)\n", __func__, error); out: if (error) free(sc->mtl_text_soft, M_TERASIC_MTL); return (error); } void terasic_mtl_syscons_detach(struct terasic_mtl_softc *sc) { free(sc->mtl_text_soft, M_TERASIC_MTL); panic("%s: not supported by syscons", __func__); } static video_switch_t terasic_mtl_vidsw = { .probe = terasic_mtl_vidsw_probe, .init = terasic_mtl_vidsw_init, .get_info = terasic_mtl_vidsw_get_info, .query_mode = terasic_mtl_vidsw_query_mode, .set_mode = terasic_mtl_vidsw_set_mode, .save_font = terasic_mtl_vidsw_save_font, .load_font = terasic_mtl_vidsw_load_font, .show_font = terasic_mtl_vidsw_show_font, .save_palette = terasic_mtl_vidsw_save_palette, .load_palette = terasic_mtl_vidsw_load_palette, .set_border = terasic_mtl_vidsw_set_border, .save_state = terasic_mtl_vidsw_save_state, .load_state = terasic_mtl_vidsw_load_state, .set_win_org = terasic_mtl_vidsw_set_win_org, .read_hw_cursor = terasic_mtl_vidsw_read_hw_cursor, .set_hw_cursor = terasic_mtl_vidsw_set_hw_cursor, .set_hw_cursor_shape = terasic_mtl_vidsw_set_hw_cursor_shape, .blank_display = terasic_mtl_vidsw_blank_display, .mmap = terasic_mtl_vidsw_mmap, .ioctl = terasic_mtl_vidsw_ioctl, .clear = terasic_mtl_vidsw_clear, .fill_rect = terasic_mtl_vidsw_fill_rect, .bitblt = terasic_mtl_vidsw_bitblt, .diag = terasic_mtl_vidsw_diag, .save_cursor_palette = terasic_mtl_vidsw_save_cursor_palette, .load_cursor_palette = terasic_mtl_vidsw_load_cursor_palette, .copy = terasic_mtl_vidsw_copy, .putp = terasic_mtl_vidsw_putp, .putc = terasic_mtl_vidsw_putc, .puts = terasic_mtl_vidsw_puts, .putm = terasic_mtl_vidsw_putm, }; VIDEO_DRIVER(terasic_mtl_syscons, terasic_mtl_vidsw, terasic_mtl_syscons_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(terasic_mtl_syscons, 0, txtrndrsw, gfb_set); RENDERER_MODULE(terasic_mtl_syscons, gfb_set); Index: stable/12/sys/powerpc/ofw/ofw_syscons.c =================================================================== --- stable/12/sys/powerpc/ofw/ofw_syscons.c (revision 356109) +++ stable/12/sys/powerpc/ofw/ofw_syscons.c (revision 356110) @@ -1,1104 +1,1085 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003 Peter Grehan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int ofwfb_ignore_mmap_checks = 1; static int ofwfb_reset_on_switch = 1; static SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb"); SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW, &ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking"); SYSCTL_INT(_hw_ofwfb, OID_AUTO, reset_on_mode_switch, CTLFLAG_RW, &ofwfb_reset_on_switch, 0, "reset the framebuffer driver on mode switch"); extern u_char dflt_font_16[]; extern u_char dflt_font_14[]; extern u_char dflt_font_8[]; static int ofwfb_configure(int flags); static vi_probe_t ofwfb_probe; static vi_init_t ofwfb_init; static vi_get_info_t ofwfb_get_info; static vi_query_mode_t ofwfb_query_mode; static vi_set_mode_t ofwfb_set_mode; static vi_save_font_t ofwfb_save_font; static vi_load_font_t ofwfb_load_font; static vi_show_font_t ofwfb_show_font; static vi_save_palette_t ofwfb_save_palette; static vi_load_palette_t ofwfb_load_palette; static vi_set_border_t ofwfb_set_border; static vi_save_state_t ofwfb_save_state; static vi_load_state_t ofwfb_load_state; static vi_set_win_org_t ofwfb_set_win_org; static vi_read_hw_cursor_t ofwfb_read_hw_cursor; static vi_set_hw_cursor_t ofwfb_set_hw_cursor; static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape; static vi_blank_display_t ofwfb_blank_display; static vi_mmap_t ofwfb_mmap; static vi_ioctl_t ofwfb_ioctl; static vi_clear_t ofwfb_clear; static vi_fill_rect_t ofwfb_fill_rect; static vi_bitblt_t ofwfb_bitblt; static vi_diag_t ofwfb_diag; static vi_save_cursor_palette_t ofwfb_save_cursor_palette; static vi_load_cursor_palette_t ofwfb_load_cursor_palette; static vi_copy_t ofwfb_copy; static vi_putp_t ofwfb_putp; static vi_putc_t ofwfb_putc; static vi_puts_t ofwfb_puts; static vi_putm_t ofwfb_putm; static video_switch_t ofwfbvidsw = { .probe = ofwfb_probe, .init = ofwfb_init, .get_info = ofwfb_get_info, .query_mode = ofwfb_query_mode, .set_mode = ofwfb_set_mode, .save_font = ofwfb_save_font, .load_font = ofwfb_load_font, .show_font = ofwfb_show_font, .save_palette = ofwfb_save_palette, .load_palette = ofwfb_load_palette, .set_border = ofwfb_set_border, .save_state = ofwfb_save_state, .load_state = ofwfb_load_state, .set_win_org = ofwfb_set_win_org, .read_hw_cursor = ofwfb_read_hw_cursor, .set_hw_cursor = ofwfb_set_hw_cursor, .set_hw_cursor_shape = ofwfb_set_hw_cursor_shape, .blank_display = ofwfb_blank_display, .mmap = ofwfb_mmap, .ioctl = ofwfb_ioctl, .clear = ofwfb_clear, .fill_rect = ofwfb_fill_rect, .bitblt = ofwfb_bitblt, .diag = ofwfb_diag, .save_cursor_palette = ofwfb_save_cursor_palette, .load_cursor_palette = ofwfb_load_cursor_palette, .copy = ofwfb_copy, .putp = ofwfb_putp, .putc = ofwfb_putc, .puts = ofwfb_puts, .putm = ofwfb_putm, }; /* * bitmap depth-specific routines */ static vi_blank_display_t ofwfb_blank_display8; static vi_putc_t ofwfb_putc8; static vi_putm_t ofwfb_putm8; static vi_set_border_t ofwfb_set_border8; static vi_blank_display_t ofwfb_blank_display32; static vi_putc_t ofwfb_putc32; static vi_putm_t ofwfb_putm32; static vi_set_border_t ofwfb_set_border32; VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure); extern sc_rndr_sw_t txtrndrsw; RENDERER(ofwfb, 0, txtrndrsw, gfb_set); RENDERER_MODULE(ofwfb, gfb_set); /* * Define the iso6429-1983 colormap */ static struct { uint8_t red; uint8_t green; uint8_t blue; } ofwfb_cmap[16] = { /* # R G B Color */ /* - - - - ----- */ { 0x00, 0x00, 0x00 }, /* 0 0 0 0 Black */ { 0x00, 0x00, 0xaa }, /* 1 0 0 2/3 Blue */ { 0x00, 0xaa, 0x00 }, /* 2 0 2/3 0 Green */ { 0x00, 0xaa, 0xaa }, /* 3 0 2/3 2/3 Cyan */ { 0xaa, 0x00, 0x00 }, /* 4 2/3 0 0 Red */ { 0xaa, 0x00, 0xaa }, /* 5 2/3 0 2/3 Magenta */ { 0xaa, 0x55, 0x00 }, /* 6 2/3 1/3 0 Brown */ { 0xaa, 0xaa, 0xaa }, /* 7 2/3 2/3 2/3 White */ { 0x55, 0x55, 0x55 }, /* 8 1/3 1/3 1/3 Gray */ { 0x55, 0x55, 0xff }, /* 9 1/3 1/3 1 Bright Blue */ { 0x55, 0xff, 0x55 }, /* 10 1/3 1 1/3 Bright Green */ { 0x55, 0xff, 0xff }, /* 11 1/3 1 1 Bright Cyan */ { 0xff, 0x55, 0x55 }, /* 12 1 1/3 1/3 Bright Red */ { 0xff, 0x55, 0xff }, /* 13 1 1/3 1 Bright Magenta */ { 0xff, 0xff, 0x80 }, /* 14 1 1 1/3 Bright Yellow */ { 0xff, 0xff, 0xff } /* 15 1 1 1 Bright White */ }; #define TODO printf("%s: unimplemented\n", __func__) static u_int16_t ofwfb_static_window[ROW*COL]; static struct ofwfb_softc ofwfb_softc; static __inline int ofwfb_background(uint8_t attr) { return (attr >> 4); } static __inline int ofwfb_foreground(uint8_t attr) { return (attr & 0x0f); } static u_int ofwfb_pix32(struct ofwfb_softc *sc, int attr) { u_int retval; if (sc->sc_tag == &bs_le_tag) retval = (ofwfb_cmap[attr].red << 16) | (ofwfb_cmap[attr].green << 8) | ofwfb_cmap[attr].blue; else retval = (ofwfb_cmap[attr].blue << 16) | (ofwfb_cmap[attr].green << 8) | ofwfb_cmap[attr].red; return (retval); } static int ofwfb_configure(int flags) { struct ofwfb_softc *sc; phandle_t chosen; ihandle_t stdout; phandle_t node; uint32_t fb_phys; int depth; int disable; int len; int i; char type[16]; static int done = 0; disable = 0; TUNABLE_INT_FETCH("hw.syscons.disable", &disable); if (disable != 0) return (0); if (done != 0) return (0); done = 1; sc = &ofwfb_softc; chosen = OF_finddevice("/chosen"); OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); node = OF_instance_to_package(stdout); if (node == -1) { /* * The "/chosen/stdout" does not exist try * using "screen" directly. */ node = OF_finddevice("screen"); } OF_getprop(node, "device_type", type, sizeof(type)); if (strcmp(type, "display") != 0) return (0); /* Only support 8 and 32-bit framebuffers */ OF_getprop(node, "depth", &depth, sizeof(depth)); if (depth == 8) { sc->sc_blank = ofwfb_blank_display8; sc->sc_putc = ofwfb_putc8; sc->sc_putm = ofwfb_putm8; sc->sc_set_border = ofwfb_set_border8; } else if (depth == 32) { sc->sc_blank = ofwfb_blank_display32; sc->sc_putc = ofwfb_putc32; sc->sc_putm = ofwfb_putm32; sc->sc_set_border = ofwfb_set_border32; } else return (0); if (OF_getproplen(node, "height") != sizeof(sc->sc_height) || OF_getproplen(node, "width") != sizeof(sc->sc_width) || OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride)) return (0); sc->sc_depth = depth; sc->sc_node = node; sc->sc_console = 1; OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height)); OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width)); OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride)); /* * Get the PCI addresses of the adapter. The node may be the * child of the PCI device: in that case, try the parent for * the assigned-addresses property. */ len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); if (len == -1) { len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); } if (len == -1) len = 0; sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register); /* * Grab the physical address of the framebuffer, and then map it * into our memory space. If the MMU is not yet up, it will be * remapped for us when relocation turns on. * * XXX We assume #address-cells is 1 at this point. */ if (OF_getproplen(node, "address") == sizeof(fb_phys)) { OF_getprop(node, "address", &fb_phys, sizeof(fb_phys)); sc->sc_tag = &bs_be_tag; bus_space_map(sc->sc_tag, fb_phys, sc->sc_height * sc->sc_stride, BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr); } else { /* * Some IBM systems don't have an address property. Try to * guess the framebuffer region from the assigned addresses. * This is ugly, but there doesn't seem to be an alternative. * Linux does the same thing. */ fb_phys = sc->sc_num_pciaddrs; for (i = 0; i < sc->sc_num_pciaddrs; i++) { /* If it is too small, not the framebuffer */ if (sc->sc_pciaddrs[i].size_lo < sc->sc_stride*sc->sc_height) continue; /* If it is not memory, it isn't either */ if (!(sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_SPACE_MEM32)) continue; /* This could be the framebuffer */ fb_phys = i; /* If it is prefetchable, it certainly is */ if (sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) break; } if (fb_phys == sc->sc_num_pciaddrs) return (0); OF_decode_addr(node, fb_phys, &sc->sc_tag, &sc->sc_addr, NULL); } ofwfb_init(0, &sc->sc_va, 0); return (0); } static int ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) { TODO; return (0); } static int ofwfb_init(int unit, video_adapter_t *adp, int flags) { struct ofwfb_softc *sc; video_info_t *vi; int cborder; int font_height; sc = (struct ofwfb_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "ofwfb", -1, unit); /* The default font size can be overridden by loader */ font_height = 16; TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height); if (font_height == 8) { sc->sc_font = dflt_font_8; sc->sc_font_height = 8; } else if (font_height == 14) { sc->sc_font = dflt_font_14; sc->sc_font_height = 14; } else { /* default is 8x16 */ sc->sc_font = dflt_font_16; sc->sc_font_height = 16; } /* The user can set a border in chars - default is 1 char width */ cborder = 1; TUNABLE_INT_FETCH("hw.syscons.border", &cborder); vi->vi_cheight = sc->sc_font_height; vi->vi_width = sc->sc_width/8 - 2*cborder; vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder; vi->vi_cwidth = 8; /* * Clamp width/height to syscons maximums */ if (vi->vi_width > COL) vi->vi_width = COL; if (vi->vi_height > ROW) vi->vi_height = ROW; sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; /* * Avoid huge amounts of conditional code in syscons by * defining a dummy h/w text display buffer. */ adp->va_window = (vm_offset_t) ofwfb_static_window; /* * Enable future font-loading and flag color support, as well as * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called * when the X server shuts down. This enables us to get the console * back when X disappears. */ adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE; ofwfb_set_mode(&sc->sc_va, 0); vid_register(&sc->sc_va); return (0); } static int ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) { bcopy(&adp->va_info, info, sizeof(*info)); return (0); } static int ofwfb_query_mode(video_adapter_t *adp, video_info_t *info) { TODO; return (0); } static int ofwfb_set_mode(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; char name[64]; ihandle_t ih; int i, retval; sc = (struct ofwfb_softc *)adp; if (ofwfb_reset_on_switch) { /* * Open the display device, which will initialize it. */ memset(name, 0, sizeof(name)); OF_package_to_path(sc->sc_node, name, sizeof(name)); ih = OF_open(name); if (sc->sc_depth == 8) { /* * Install the ISO6429 colormap - older OFW systems * don't do this by default */ for (i = 0; i < 16; i++) { OF_call_method("color!", ih, 4, 1, ofwfb_cmap[i].red, ofwfb_cmap[i].green, ofwfb_cmap[i].blue, i, &retval); } } } ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON); return (0); } static int ofwfb_save_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { TODO; return (0); } static int ofwfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; /* * syscons code has already determined that current width/height * are unchanged for this new font */ sc->sc_font = data; return (0); } static int ofwfb_show_font(video_adapter_t *adp, int page) { return (0); } static int ofwfb_save_palette(video_adapter_t *adp, u_char *palette) { /* TODO; */ return (0); } static int ofwfb_load_palette(video_adapter_t *adp, u_char *palette) { /* TODO; */ return (0); } static int ofwfb_set_border8(video_adapter_t *adp, int border) { struct ofwfb_softc *sc; int i, j; uint8_t *addr; uint8_t bground; sc = (struct ofwfb_softc *)adp; bground = ofwfb_background(border); /* Set top margin */ addr = (uint8_t *) sc->sc_addr; for (i = 0; i < sc->sc_ymargin; i++) { for (j = 0; j < sc->sc_width; j++) { *(addr + j) = bground; } addr += sc->sc_stride; } /* bottom margin */ addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride; for (i = 0; i < sc->sc_ymargin; i++) { for (j = 0; j < sc->sc_width; j++) { *(addr + j) = bground; } addr += sc->sc_stride; } /* remaining left and right borders */ addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride; for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) { for (j = 0; j < sc->sc_xmargin; j++) { *(addr + j) = bground; *(addr + j + sc->sc_width - sc->sc_xmargin) = bground; } addr += sc->sc_stride; } return (0); } static int ofwfb_set_border32(video_adapter_t *adp, int border) { /* XXX Be lazy for now and blank entire screen */ return (ofwfb_blank_display32(adp, border)); } static int ofwfb_set_border(video_adapter_t *adp, int border) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_set_border)(adp, border)); } static int ofwfb_save_state(video_adapter_t *adp, void *p, size_t size) { TODO; return (0); } static int ofwfb_load_state(video_adapter_t *adp, void *p) { TODO; return (0); } static int ofwfb_set_win_org(video_adapter_t *adp, off_t offset) { TODO; return (0); } static int ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { *col = 0; *row = 0; return (0); } static int ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row) { return (0); } static int ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { return (0); } static int ofwfb_blank_display8(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; int i; uint32_t *addr; uint32_t color; uint32_t end; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *) sc->sc_addr; end = (sc->sc_stride/4) * sc->sc_height; /* Splat 4 pixels at once. */ color = (ofwfb_background(SC_NORM_ATTR) << 24) | (ofwfb_background(SC_NORM_ATTR) << 16) | (ofwfb_background(SC_NORM_ATTR) << 8) | (ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < end; i++) *(addr + i) = color; return (0); } static int ofwfb_blank_display32(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; int i; uint32_t *addr, blank; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *) sc->sc_addr; blank = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++) *(addr + i) = blank; return (0); } static int ofwfb_blank_display(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_blank)(adp, mode)); } static int ofwfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct ofwfb_softc *sc; int i; sc = (struct ofwfb_softc *)adp; /* * Make sure the requested address lies within the PCI device's * assigned addrs */ for (i = 0; i < sc->sc_num_pciaddrs; i++) if (offset >= sc->sc_pciaddrs[i].phys_lo && offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo)) { /* * If this is a prefetchable BAR, we can (and should) * enable write-combining. */ if (sc->sc_pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) *memattr = VM_MEMATTR_WRITE_COMBINING; *paddr = offset; return (0); } /* * Hack for Radeon... */ if (ofwfb_ignore_mmap_checks) { *paddr = offset; return (0); } /* * This might be a legacy VGA mem request: if so, just point it at the * framebuffer, since it shouldn't be touched */ if (offset < sc->sc_stride*sc->sc_height) { *paddr = sc->sc_addr + offset; return (0); } /* * Error if we didn't have a better idea. */ if (sc->sc_num_pciaddrs == 0) return (ENOMEM); return (EINVAL); } static int ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { return (0); } static int ofwfb_clear(video_adapter_t *adp) { TODO; return (0); } static int ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { TODO; return (0); } static int ofwfb_bitblt(video_adapter_t *adp, ...) { TODO; return (0); } static int ofwfb_diag(video_adapter_t *adp, int level) { TODO; return (0); } static int ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) { TODO; return (0); } static int ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) { TODO; return (0); } static int ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { TODO; return (0); } static int ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { TODO; return (0); } static int ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; int row; int col; int i; uint32_t *addr; u_char *p, fg, bg; union { uint32_t l; uint8_t c[4]; } ch1, ch2; sc = (struct ofwfb_softc *)adp; row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->sc_font + c*sc->sc_font_height; addr = (u_int32_t *)((uintptr_t)sc->sc_addr + (row + sc->sc_ymargin)*sc->sc_stride + col + sc->sc_xmargin); fg = ofwfb_foreground(a); bg = ofwfb_background(a); for (i = 0; i < sc->sc_font_height; i++) { u_char fline = p[i]; /* * Assume that there is more background than foreground * in characters and init accordingly */ ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg; /* * Calculate 2 x 4-chars at a time, and then * write these out. */ if (fline & 0x80) ch1.c[0] = fg; if (fline & 0x40) ch1.c[1] = fg; if (fline & 0x20) ch1.c[2] = fg; if (fline & 0x10) ch1.c[3] = fg; if (fline & 0x08) ch2.c[0] = fg; if (fline & 0x04) ch2.c[1] = fg; if (fline & 0x02) ch2.c[2] = fg; if (fline & 0x01) ch2.c[3] = fg; addr[0] = ch1.l; addr[1] = ch2.l; addr += (sc->sc_stride / sizeof(u_int32_t)); } return (0); } static int ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; int row; int col; int i, j, k; uint32_t *addr, fg, bg; u_char *p; sc = (struct ofwfb_softc *)adp; row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; p = sc->sc_font + c*sc->sc_font_height; addr = (uint32_t *)sc->sc_addr + (row + sc->sc_ymargin)*(sc->sc_stride/4) + col + sc->sc_xmargin; fg = ofwfb_pix32(sc, ofwfb_foreground(a)); bg = ofwfb_pix32(sc, ofwfb_background(a)); for (i = 0; i < sc->sc_font_height; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) *(addr + j) = bg; else *(addr + j) = fg; } addr += (sc->sc_stride/4); } return (0); } static int ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_putc)(adp, off, c, a)); } static int ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) { int i; for (i = 0; i < len; i++) { ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); } return (0); } static int ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; sc = (struct ofwfb_softc *)adp; return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size, width)); } static int ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; int i, j, k; uint8_t *addr; u_char fg, bg; sc = (struct ofwfb_softc *)adp; addr = (u_int8_t *)((uintptr_t)sc->sc_addr + (y + sc->sc_ymargin)*sc->sc_stride + x + sc->sc_xmargin); fg = ofwfb_foreground(SC_NORM_ATTR); bg = ofwfb_background(SC_NORM_ATTR); for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) { /* * Calculate 2 x 4-chars at a time, and then * write these out. */ for (j = 0, k = width; j < 8; j++, k--) { if (x + j >= sc->sc_width - 2*sc->sc_xmargin) continue; if (pixel_image[i] & (1 << k)) addr[j] = (addr[j] == fg) ? bg : fg; } addr += (sc->sc_stride / sizeof(u_int8_t)); } return (0); } static int ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, uint32_t pixel_mask, int size, int width) { struct ofwfb_softc *sc; int i, j, k; uint32_t fg, bg; uint32_t *addr; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *)sc->sc_addr + (y + sc->sc_ymargin)*(sc->sc_stride/4) + x + sc->sc_xmargin; fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR)); bg = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) { for (j = 0, k = width; j < 8; j++, k--) { if (x + j >= sc->sc_width - 2*sc->sc_xmargin) continue; if (pixel_image[i] & (1 << k)) *(addr + j) = (*(addr + j) == fg) ? bg : fg; } addr += (sc->sc_stride/4); } return (0); } /* * Define the syscons nexus device attachment */ static void ofwfb_scidentify(driver_t *driver, device_t parent) { device_t child; /* * Add with a priority guaranteed to make it last on * the device list */ child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0); } static int ofwfb_scprobe(device_t dev) { int error; device_set_desc(dev, "System console"); error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); /* This is a fake device, so make sure we added it ourselves */ return (BUS_PROBE_NOWILDCARD); } static int ofwfb_scattach(device_t dev) { return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); } static device_method_t ofwfb_sc_methods[] = { DEVMETHOD(device_identify, ofwfb_scidentify), DEVMETHOD(device_probe, ofwfb_scprobe), DEVMETHOD(device_attach, ofwfb_scattach), { 0, 0 } }; static driver_t ofwfb_sc_driver = { SC_DRIVER_NAME, ofwfb_sc_methods, sizeof(sc_softc_t), }; static devclass_t sc_devclass; DRIVER_MODULE(ofwfb, nexus, ofwfb_sc_driver, sc_devclass, 0, 0); /* - * Define a stub keyboard driver in case one hasn't been - * compiled into the kernel - */ -#include -#include - -static int dummy_kbd_configure(int flags); - -keyboard_switch_t dummysw; - -static int -dummy_kbd_configure(int flags) -{ - - return (0); -} -KEYBOARD_DRIVER(dummy, dummysw, dummy_kbd_configure); - -/* * Utility routines from */ void ofwfb_bcopy(const void *s, void *d, size_t c) { bcopy(s, d, c); } void ofwfb_bzero(void *d, size_t c) { bzero(d, c); } void ofwfb_fillw(int pat, void *base, size_t cnt) { u_int16_t *bptr = base; while (cnt--) *bptr++ = pat; } u_int16_t ofwfb_readw(u_int16_t *addr) { return (*addr); } void ofwfb_writew(u_int16_t *addr, u_int16_t val) { *addr = val; } Index: stable/12 =================================================================== --- stable/12 (revision 356109) +++ stable/12 (revision 356110) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r355936,356045