[BACK]Return to r128fb.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/r128fb.c, Revision 1.39

1.39    ! macallan    1: /*     $NetBSD: r128fb.c,v 1.38 2013/10/09 17:18:23 macallan Exp $     */
1.1       macallan    2:
                      3: /*
1.36      macallan    4:  * Copyright (c) 2007, 2012 Michael Lorenz
1.1       macallan    5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: /*
                     29:  * A console driver for ATI Rage 128 graphics controllers
                     30:  * tested on macppc only so far
                     31:  */
                     32:
                     33: #include <sys/cdefs.h>
1.39    ! macallan   34: __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1.38 2013/10/09 17:18:23 macallan Exp $");
1.1       macallan   35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/kernel.h>
                     39: #include <sys/device.h>
                     40: #include <sys/malloc.h>
                     41: #include <sys/lwp.h>
                     42: #include <sys/kauth.h>
                     43:
                     44: #include <dev/videomode/videomode.h>
                     45:
                     46: #include <dev/pci/pcivar.h>
                     47: #include <dev/pci/pcireg.h>
                     48: #include <dev/pci/pcidevs.h>
                     49: #include <dev/pci/pciio.h>
                     50: #include <dev/pci/r128fbreg.h>
                     51:
                     52: #include <dev/wscons/wsdisplayvar.h>
                     53: #include <dev/wscons/wsconsio.h>
                     54: #include <dev/wsfont/wsfont.h>
                     55: #include <dev/rasops/rasops.h>
                     56: #include <dev/wscons/wsdisplay_vconsvar.h>
1.20      cegger     57: #include <dev/pci/wsdisplay_pci.h>
1.29      macallan   58: #include <dev/wscons/wsdisplay_glyphcachevar.h>
1.1       macallan   59:
                     60: #include <dev/i2c/i2cvar.h>
                     61:
1.11      macallan   62: #include "opt_r128fb.h"
1.22      macallan   63: #include "opt_vcons.h"
1.11      macallan   64:
                     65: #ifdef R128FB_DEBUG
                     66: #define DPRINTF printf
                     67: #else
                     68: #define DPRINTF while(0) printf
                     69: #endif
                     70:
1.1       macallan   71: struct r128fb_softc {
                     72:        device_t sc_dev;
                     73:
                     74:        pci_chipset_tag_t sc_pc;
                     75:        pcitag_t sc_pcitag;
                     76:
                     77:        bus_space_tag_t sc_memt;
                     78:        bus_space_tag_t sc_iot;
                     79:
                     80:        bus_space_handle_t sc_regh;
                     81:        bus_addr_t sc_fb, sc_reg;
                     82:        bus_size_t sc_fbsize, sc_regsize;
                     83:
                     84:        int sc_width, sc_height, sc_depth, sc_stride;
1.14      macallan   85:        int sc_locked, sc_have_backlight, sc_bl_level, sc_bl_on;
1.1       macallan   86:        struct vcons_screen sc_console_screen;
                     87:        struct wsscreen_descr sc_defaultscreen_descr;
                     88:        const struct wsscreen_descr *sc_screens[1];
                     89:        struct wsscreen_list sc_screenlist;
                     90:        struct vcons_data vd;
                     91:        int sc_mode;
                     92:        u_char sc_cmap_red[256];
                     93:        u_char sc_cmap_green[256];
                     94:        u_char sc_cmap_blue[256];
                     95:        /* engine stuff */
                     96:        uint32_t sc_master_cntl;
1.29      macallan   97:        glyphcache sc_gc;
1.1       macallan   98: };
                     99:
                    100: static int     r128fb_match(device_t, cfdata_t, void *);
                    101: static void    r128fb_attach(device_t, device_t, void *);
                    102:
                    103: CFATTACH_DECL_NEW(r128fb, sizeof(struct r128fb_softc),
                    104:     r128fb_match, r128fb_attach, NULL, NULL);
                    105:
                    106: static int     r128fb_ioctl(void *, void *, u_long, void *, int,
                    107:                             struct lwp *);
                    108: static paddr_t r128fb_mmap(void *, void *, off_t, int);
                    109: static void    r128fb_init_screen(void *, struct vcons_screen *, int, long *);
                    110:
                    111: static int     r128fb_putcmap(struct r128fb_softc *, struct wsdisplay_cmap *);
                    112: static int     r128fb_getcmap(struct r128fb_softc *, struct wsdisplay_cmap *);
                    113: static void    r128fb_restore_palette(struct r128fb_softc *);
                    114: static int     r128fb_putpalreg(struct r128fb_softc *, uint8_t, uint8_t,
                    115:                            uint8_t, uint8_t);
                    116:
                    117: static void    r128fb_init(struct r128fb_softc *);
                    118: static void    r128fb_flush_engine(struct r128fb_softc *);
                    119: static void    r128fb_rectfill(struct r128fb_softc *, int, int, int, int,
                    120:                            uint32_t);
1.29      macallan  121: static void    r128fb_bitblt(void *, int, int, int, int, int,
1.1       macallan  122:                            int, int);
                    123:
                    124: static void    r128fb_cursor(void *, int, int, int);
                    125: static void    r128fb_putchar(void *, int, int, u_int, long);
1.24      macallan  126: static void    r128fb_putchar_aa(void *, int, int, u_int, long);
1.1       macallan  127: static void    r128fb_copycols(void *, int, int, int, int);
                    128: static void    r128fb_erasecols(void *, int, int, int, long);
                    129: static void    r128fb_copyrows(void *, int, int, int);
                    130: static void    r128fb_eraserows(void *, int, int, long);
                    131:
1.11      macallan  132: static void    r128fb_brightness_up(device_t);
                    133: static void    r128fb_brightness_down(device_t);
1.14      macallan  134: /* set backlight level */
1.11      macallan  135: static void    r128fb_set_backlight(struct r128fb_softc *, int);
1.14      macallan  136: /* turn backlight on and off without messing with the level */
                    137: static void    r128fb_switch_backlight(struct r128fb_softc *, int);
1.11      macallan  138:
1.1       macallan  139: struct wsdisplay_accessops r128fb_accessops = {
                    140:        r128fb_ioctl,
                    141:        r128fb_mmap,
                    142:        NULL,   /* alloc_screen */
                    143:        NULL,   /* free_screen */
                    144:        NULL,   /* show_screen */
                    145:        NULL,   /* load_font */
                    146:        NULL,   /* pollc */
                    147:        NULL    /* scroll */
                    148: };
                    149:
                    150: static inline void
                    151: r128fb_wait(struct r128fb_softc *sc, int slots)
                    152: {
                    153:        uint32_t reg;
                    154:
                    155:        do {
                    156:                reg = (bus_space_read_4(sc->sc_memt, sc->sc_regh,
                    157:                    R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK);
                    158:        } while (reg <= slots);
                    159: }
                    160:
                    161: static void
                    162: r128fb_flush_engine(struct r128fb_softc *sc)
                    163: {
                    164:        uint32_t reg;
                    165:
                    166:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_PC_NGUI_CTLSTAT);
                    167:        reg |= R128_PC_FLUSH_ALL;
                    168:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PC_NGUI_CTLSTAT, reg);
                    169:        do {
                    170:                reg = bus_space_read_4(sc->sc_memt, sc->sc_regh,
                    171:                    R128_PC_NGUI_CTLSTAT);
                    172:        } while (reg & R128_PC_BUSY);
                    173: }
                    174:
                    175: static int
                    176: r128fb_match(device_t parent, cfdata_t match, void *aux)
                    177: {
                    178:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    179:
1.5       macallan  180:        if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
1.1       macallan  181:                return 0;
                    182:        if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_ATI)
                    183:                return 0;
                    184:
1.5       macallan  185:        /* only cards tested on so far - likely need a list */
                    186:        if ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_RAGE1AGP4XT) ||
1.6       jmcneill  187:            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_RAGE3AGP4XT) ||
1.10      jmmv      188:            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_RAGEGLPCI) ||
1.6       jmcneill  189:            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP))
1.1       macallan  190:                return 100;
                    191:        return (0);
                    192: }
                    193:
                    194: static void
                    195: r128fb_attach(device_t parent, device_t self, void *aux)
                    196: {
                    197:        struct r128fb_softc     *sc = device_private(self);
                    198:        struct pci_attach_args  *pa = aux;
                    199:        struct rasops_info      *ri;
1.14      macallan  200:        bus_space_tag_t         tag;
1.1       macallan  201:        struct wsemuldisplaydev_attach_args aa;
                    202:        prop_dictionary_t       dict;
                    203:        unsigned long           defattr;
1.39    ! macallan  204:        bool                    is_console = FALSE;
1.22      macallan  205:        int                     i, j;
                    206:        uint32_t                reg, flags;
1.33      macallan  207:        uint8_t                 cmap[768];
1.1       macallan  208:
                    209:        sc->sc_pc = pa->pa_pc;
                    210:        sc->sc_pcitag = pa->pa_tag;
                    211:        sc->sc_memt = pa->pa_memt;
                    212:        sc->sc_iot = pa->pa_iot;
                    213:        sc->sc_dev = self;
                    214:
1.28      drochner  215:        pci_aprint_devinfo(pa, NULL);
1.1       macallan  216:
                    217:        /* fill in parameters from properties */
                    218:        dict = device_properties(self);
                    219:        if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) {
                    220:                aprint_error("%s: no width property\n", device_xname(self));
                    221:                return;
                    222:        }
                    223:        if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) {
                    224:                aprint_error("%s: no height property\n", device_xname(self));
                    225:                return;
                    226:        }
1.34      macallan  227:
                    228: #ifdef GLYPHCACHE_DEBUG
                    229:        /* leave some visible VRAM unused so we can see the glyph cache */
1.36      macallan  230:        sc->sc_height -= 200;
1.34      macallan  231: #endif
                    232:
1.1       macallan  233:        if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) {
                    234:                aprint_error("%s: no depth property\n", device_xname(self));
                    235:                return;
                    236:        }
                    237:        if (!prop_dictionary_get_uint32(dict, "linebytes", &sc->sc_stride)) {
                    238:                aprint_error("%s: no linebytes property\n",
                    239:                    device_xname(self));
                    240:                return;
                    241:        }
                    242:
                    243:        prop_dictionary_get_bool(dict, "is_console", &is_console);
                    244:
1.13      macallan  245:        if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x10, PCI_MAPREG_TYPE_MEM,
                    246:            &sc->sc_fb, &sc->sc_fbsize, &flags)) {
1.1       macallan  247:                aprint_error("%s: failed to map the frame buffer.\n",
                    248:                    device_xname(sc->sc_dev));
                    249:        }
                    250:
                    251:        if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_MEM, 0,
1.14      macallan  252:            &tag, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) {
1.1       macallan  253:                aprint_error("%s: failed to map registers.\n",
                    254:                    device_xname(sc->sc_dev));
                    255:        }
                    256:
                    257:        aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self),
1.2       macallan  258:            (int)(sc->sc_fbsize >> 20), (uint32_t)sc->sc_fb);
1.1       macallan  259:
                    260:        sc->sc_defaultscreen_descr = (struct wsscreen_descr){
                    261:                "default",
                    262:                0, 0,
                    263:                NULL,
                    264:                8, 16,
                    265:                WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
                    266:                NULL
                    267:        };
                    268:        sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
                    269:        sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
                    270:        sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
                    271:        sc->sc_locked = 0;
                    272:
                    273:        vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
                    274:            &r128fb_accessops);
                    275:        sc->vd.init_screen = r128fb_init_screen;
                    276:
                    277:        /* init engine here */
                    278:        r128fb_init(sc);
                    279:
                    280:        ri = &sc->sc_console_screen.scr_ri;
                    281:
1.29      macallan  282:        sc->sc_gc.gc_bitblt = r128fb_bitblt;
                    283:        sc->sc_gc.gc_blitcookie = sc;
                    284:        sc->sc_gc.gc_rop = R128_ROP3_S;
1.1       macallan  285:        if (is_console) {
                    286:                vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
                    287:                    &defattr);
                    288:                sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
                    289:
1.9       macallan  290:                r128fb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
                    291:                    ri->ri_devcmap[(defattr >> 16) & 0xff]);
1.1       macallan  292:                sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
                    293:                sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
                    294:                sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
                    295:                sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
1.31      macallan  296:                glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
1.34      macallan  297:                                (0x800000 / sc->sc_stride) - sc->sc_height - 5,
1.29      macallan  298:                                sc->sc_width,
                    299:                                ri->ri_font->fontwidth,
                    300:                                ri->ri_font->fontheight,
                    301:                                defattr);
1.1       macallan  302:                wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
                    303:                    defattr);
1.9       macallan  304:                vcons_replay_msgbuf(&sc->sc_console_screen);
1.1       macallan  305:        } else {
                    306:                /*
                    307:                 * since we're not the console we can postpone the rest
                    308:                 * until someone actually allocates a screen for us
                    309:                 */
1.35      macallan  310:                if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
                    311:                        /* do some minimal setup to avoid weirdnesses later */
                    312:                        vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
                    313:                            &defattr);
1.37      macallan  314:                } else
                    315:                        (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
1.34      macallan  316:                glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
                    317:                                (0x800000 / sc->sc_stride) - sc->sc_height - 5,
1.29      macallan  318:                                sc->sc_width,
                    319:                                ri->ri_font->fontwidth,
                    320:                                ri->ri_font->fontheight,
                    321:                                defattr);
1.1       macallan  322:        }
                    323:
1.33      macallan  324:        j = 0;
                    325:        rasops_get_cmap(ri, cmap, sizeof(cmap));
                    326:        for (i = 0; i < 256; i++) {
                    327:                sc->sc_cmap_red[i] = cmap[j];
                    328:                sc->sc_cmap_green[i] = cmap[j + 1];
                    329:                sc->sc_cmap_blue[i] = cmap[j + 2];
                    330:                r128fb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]);
                    331:                j += 3;
                    332:        }
                    333:
1.11      macallan  334:        /* no suspend/resume support yet */
                    335:        pmf_device_register(sc->sc_dev, NULL, NULL);
1.16      macallan  336:
1.11      macallan  337:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL);
1.16      macallan  338:        DPRINTF("R128_LVDS_GEN_CNTL: %08x\n", reg);
1.11      macallan  339:        if (reg & R128_LVDS_ON) {
                    340:                sc->sc_have_backlight = 1;
1.14      macallan  341:                sc->sc_bl_on = 1;
1.11      macallan  342:                sc->sc_bl_level = 255 -
                    343:                    ((reg & R128_LEVEL_MASK) >> R128_LEVEL_SHIFT);
                    344:                pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_UP,
                    345:                    r128fb_brightness_up, TRUE);
                    346:                pmf_event_register(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_DOWN,
                    347:                    r128fb_brightness_down, TRUE);
1.12      macallan  348:                aprint_verbose("%s: LVDS output is active, enabling backlight"
                    349:                               " control\n", device_xname(self));
1.11      macallan  350:        } else
                    351:                sc->sc_have_backlight = 0;
1.12      macallan  352:
                    353:        aa.console = is_console;
                    354:        aa.scrdata = &sc->sc_screenlist;
                    355:        aa.accessops = &r128fb_accessops;
                    356:        aa.accesscookie = &sc->vd;
                    357:
                    358:        config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
1.1       macallan  359: }
                    360:
                    361: static int
                    362: r128fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
                    363:        struct lwp *l)
                    364: {
                    365:        struct vcons_data *vd = v;
                    366:        struct r128fb_softc *sc = vd->cookie;
                    367:        struct wsdisplay_fbinfo *wdf;
                    368:        struct vcons_screen *ms = vd->active;
1.12      macallan  369:        struct wsdisplay_param  *param;
1.1       macallan  370:
                    371:        switch (cmd) {
1.17      cegger    372:        case WSDISPLAYIO_GTYPE:
                    373:                *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
                    374:                return 0;
1.1       macallan  375:
1.17      cegger    376:        /* PCI config read/write passthrough. */
                    377:        case PCI_IOC_CFGREAD:
                    378:        case PCI_IOC_CFGWRITE:
1.20      cegger    379:                return pci_devioctl(sc->sc_pc, sc->sc_pcitag,
                    380:                    cmd, data, flag, l);
                    381:
                    382:        case WSDISPLAYIO_GET_BUSID:
1.36      macallan  383:                return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc,
                    384:                    sc->sc_pcitag, data);
1.17      cegger    385:
                    386:        case WSDISPLAYIO_GINFO:
                    387:                if (ms == NULL)
                    388:                        return ENODEV;
                    389:                wdf = (void *)data;
                    390:                wdf->height = ms->scr_ri.ri_height;
                    391:                wdf->width = ms->scr_ri.ri_width;
                    392:                wdf->depth = ms->scr_ri.ri_depth;
                    393:                wdf->cmsize = 256;
                    394:                return 0;
1.1       macallan  395:
1.17      cegger    396:        case WSDISPLAYIO_GETCMAP:
                    397:                return r128fb_getcmap(sc,
                    398:                    (struct wsdisplay_cmap *)data);
                    399:
                    400:        case WSDISPLAYIO_PUTCMAP:
                    401:                return r128fb_putcmap(sc,
                    402:                    (struct wsdisplay_cmap *)data);
1.1       macallan  403:
1.17      cegger    404:        case WSDISPLAYIO_LINEBYTES:
                    405:                *(u_int *)data = sc->sc_stride;
                    406:                return 0;
1.1       macallan  407:
1.17      cegger    408:        case WSDISPLAYIO_SMODE: {
                    409:                int new_mode = *(int*)data;
                    410:                if (new_mode != sc->sc_mode) {
                    411:                        sc->sc_mode = new_mode;
                    412:                        if(new_mode == WSDISPLAYIO_MODE_EMUL) {
                    413:                                r128fb_init(sc);
                    414:                                r128fb_restore_palette(sc);
1.29      macallan  415:                                glyphcache_wipe(&sc->sc_gc);
1.19      macallan  416:                                r128fb_rectfill(sc, 0, 0, sc->sc_width,
                    417:                                    sc->sc_height, ms->scr_ri.ri_devcmap[
                    418:                                    (ms->scr_defattr >> 16) & 0xff]);
1.17      cegger    419:                                vcons_redraw_screen(ms);
1.1       macallan  420:                        }
1.17      cegger    421:                }
                    422:                }
                    423:                return 0;
1.12      macallan  424:
1.17      cegger    425:        case WSDISPLAYIO_GETPARAM:
                    426:                param = (struct wsdisplay_param *)data;
                    427:                if (sc->sc_have_backlight == 0)
1.13      macallan  428:                        return EPASSTHROUGH;
1.17      cegger    429:                switch (param->param) {
                    430:                case WSDISPLAYIO_PARAM_BRIGHTNESS:
                    431:                        param->min = 0;
                    432:                        param->max = 255;
                    433:                        param->curval = sc->sc_bl_level;
                    434:                        return 0;
                    435:                case WSDISPLAYIO_PARAM_BACKLIGHT:
                    436:                        param->min = 0;
                    437:                        param->max = 1;
                    438:                        param->curval = sc->sc_bl_on;
                    439:                        return 0;
                    440:                }
                    441:                return EPASSTHROUGH;
1.12      macallan  442:
1.17      cegger    443:        case WSDISPLAYIO_SETPARAM:
                    444:                param = (struct wsdisplay_param *)data;
                    445:                if (sc->sc_have_backlight == 0)
1.13      macallan  446:                        return EPASSTHROUGH;
1.17      cegger    447:                switch (param->param) {
                    448:                case WSDISPLAYIO_PARAM_BRIGHTNESS:
                    449:                        r128fb_set_backlight(sc, param->curval);
                    450:                        return 0;
                    451:                case WSDISPLAYIO_PARAM_BACKLIGHT:
                    452:                        r128fb_switch_backlight(sc,  param->curval);
                    453:                        return 0;
                    454:                }
                    455:                return EPASSTHROUGH;
1.38      macallan  456:
1.22      macallan  457:        case WSDISPLAYIO_GET_EDID: {
                    458:                struct wsdisplayio_edid_info *d = data;
                    459:                return wsdisplayio_get_edid(sc->sc_dev, d);
                    460:        }
1.38      macallan  461:
                    462:        case WSDISPLAYIO_GET_FBINFO: {
                    463:                struct wsdisplayio_fbinfo *fbi = data;
                    464:                return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
                    465:        }
1.1       macallan  466:        }
                    467:        return EPASSTHROUGH;
                    468: }
                    469:
                    470: static paddr_t
                    471: r128fb_mmap(void *v, void *vs, off_t offset, int prot)
                    472: {
                    473:        struct vcons_data *vd = v;
                    474:        struct r128fb_softc *sc = vd->cookie;
                    475:        paddr_t pa;
                    476:
                    477:        /* 'regular' framebuffer mmap()ing */
                    478:        if (offset < sc->sc_fbsize) {
                    479:                pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot,
                    480:                    BUS_SPACE_MAP_LINEAR);
                    481:                return pa;
                    482:        }
                    483:
                    484:        /*
                    485:         * restrict all other mappings to processes with superuser privileges
                    486:         * or the kernel itself
                    487:         */
1.32      elad      488:        if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM,
                    489:            NULL, NULL, NULL, NULL) != 0) {
1.8       elad      490:                aprint_normal("%s: mmap() rejected.\n",
                    491:                    device_xname(sc->sc_dev));
                    492:                return -1;
1.1       macallan  493:        }
                    494:
                    495:        if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) {
                    496:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    497:                    BUS_SPACE_MAP_LINEAR);
                    498:                return pa;
                    499:        }
                    500:
                    501:        if ((offset >= sc->sc_reg) &&
                    502:            (offset < (sc->sc_reg + sc->sc_regsize))) {
                    503:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    504:                    BUS_SPACE_MAP_LINEAR);
                    505:                return pa;
                    506:        }
                    507:
1.3       macallan  508: #ifdef PCI_MAGIC_IO_RANGE
1.1       macallan  509:        /* allow mapping of IO space */
1.3       macallan  510:        if ((offset >= PCI_MAGIC_IO_RANGE) &&
                    511:            (offset < PCI_MAGIC_IO_RANGE + 0x10000)) {
                    512:                pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE,
                    513:                    0, prot, BUS_SPACE_MAP_LINEAR);
1.1       macallan  514:                return pa;
                    515:        }
                    516: #endif
                    517:
                    518: #ifdef OFB_ALLOW_OTHERS
                    519:        if (offset >= 0x80000000) {
                    520:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    521:                    BUS_SPACE_MAP_LINEAR);
                    522:                return pa;
                    523:        }
                    524: #endif
                    525:        return -1;
                    526: }
                    527:
                    528: static void
                    529: r128fb_init_screen(void *cookie, struct vcons_screen *scr,
                    530:     int existing, long *defattr)
                    531: {
                    532:        struct r128fb_softc *sc = cookie;
                    533:        struct rasops_info *ri = &scr->scr_ri;
                    534:
                    535:        ri->ri_depth = sc->sc_depth;
                    536:        ri->ri_width = sc->sc_width;
                    537:        ri->ri_height = sc->sc_height;
                    538:        ri->ri_stride = sc->sc_stride;
1.13      macallan  539:        ri->ri_flg = RI_CENTER;
1.23      macallan  540:        if (sc->sc_depth == 8)
                    541:                ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA;
1.1       macallan  542:
1.27      macallan  543:        rasops_init(ri, 0, 0);
1.1       macallan  544:        ri->ri_caps = WSSCREEN_WSCOLORS;
1.22      macallan  545: #ifdef VCONS_DRAW_INTR
                    546:        scr->scr_flags |= VCONS_DONT_READ;
                    547: #endif
1.1       macallan  548:
                    549:        rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
                    550:                    sc->sc_width / ri->ri_font->fontwidth);
                    551:
                    552:        ri->ri_hw = scr;
                    553:        ri->ri_ops.copyrows = r128fb_copyrows;
                    554:        ri->ri_ops.copycols = r128fb_copycols;
                    555:        ri->ri_ops.eraserows = r128fb_eraserows;
                    556:        ri->ri_ops.erasecols = r128fb_erasecols;
                    557:        ri->ri_ops.cursor = r128fb_cursor;
1.24      macallan  558:        if (FONT_IS_ALPHA(ri->ri_font)) {
                    559:                ri->ri_ops.putchar = r128fb_putchar_aa;
                    560:        } else
                    561:                ri->ri_ops.putchar = r128fb_putchar;
1.1       macallan  562: }
                    563:
                    564: static int
                    565: r128fb_putcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
                    566: {
                    567:        u_char *r, *g, *b;
                    568:        u_int index = cm->index;
                    569:        u_int count = cm->count;
                    570:        int i, error;
                    571:        u_char rbuf[256], gbuf[256], bbuf[256];
                    572:
                    573: #ifdef R128FB_DEBUG
                    574:        aprint_debug("putcmap: %d %d\n",index, count);
                    575: #endif
                    576:        if (cm->index >= 256 || cm->count > 256 ||
                    577:            (cm->index + cm->count) > 256)
                    578:                return EINVAL;
                    579:        error = copyin(cm->red, &rbuf[index], count);
                    580:        if (error)
                    581:                return error;
                    582:        error = copyin(cm->green, &gbuf[index], count);
                    583:        if (error)
                    584:                return error;
                    585:        error = copyin(cm->blue, &bbuf[index], count);
                    586:        if (error)
                    587:                return error;
                    588:
                    589:        memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
                    590:        memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
                    591:        memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
                    592:
                    593:        r = &sc->sc_cmap_red[index];
                    594:        g = &sc->sc_cmap_green[index];
                    595:        b = &sc->sc_cmap_blue[index];
                    596:
                    597:        for (i = 0; i < count; i++) {
                    598:                r128fb_putpalreg(sc, index, *r, *g, *b);
                    599:                index++;
                    600:                r++, g++, b++;
                    601:        }
                    602:        return 0;
                    603: }
                    604:
                    605: static int
                    606: r128fb_getcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
                    607: {
                    608:        u_int index = cm->index;
                    609:        u_int count = cm->count;
                    610:        int error;
                    611:
                    612:        if (index >= 255 || count > 256 || index + count > 256)
                    613:                return EINVAL;
                    614:
                    615:        error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
                    616:        if (error)
                    617:                return error;
                    618:        error = copyout(&sc->sc_cmap_green[index], cm->green, count);
                    619:        if (error)
                    620:                return error;
                    621:        error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
                    622:        if (error)
                    623:                return error;
                    624:
                    625:        return 0;
                    626: }
                    627:
                    628: static void
                    629: r128fb_restore_palette(struct r128fb_softc *sc)
                    630: {
                    631:        int i;
                    632:
                    633:        for (i = 0; i < (1 << sc->sc_depth); i++) {
                    634:                r128fb_putpalreg(sc, i, sc->sc_cmap_red[i],
                    635:                    sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
                    636:        }
                    637: }
                    638:
                    639: static int
                    640: r128fb_putpalreg(struct r128fb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
                    641:     uint8_t b)
                    642: {
                    643:        uint32_t reg;
                    644:
                    645:        /* whack the DAC */
                    646:        reg = (r << 16) | (g << 8) | b;
                    647:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_INDEX, idx);
                    648:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_DATA, reg);
                    649:        return 0;
                    650: }
                    651:
                    652: static void
                    653: r128fb_init(struct r128fb_softc *sc)
                    654: {
1.24      macallan  655:        uint32_t datatype, d, reg;
1.1       macallan  656:
                    657:        r128fb_flush_engine(sc);
                    658:
1.13      macallan  659:        r128fb_wait(sc, 9);
1.1       macallan  660:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_OFFSET, 0);
                    661:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_OFFSET, 0);
1.24      macallan  662:        /* pitch is in units of 8 pixels */
1.1       macallan  663:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_PITCH,
1.24      macallan  664:            sc->sc_width >> 3);
1.1       macallan  665:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_AUX_SC_CNTL, 0);
                    666:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    667:            R128_DEFAULT_SC_BOTTOM_RIGHT,
                    668:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
                    669:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_TOP_LEFT, 0);
                    670:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_BOTTOM_RIGHT,
                    671:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
1.13      macallan  672:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    673:            R128_DEFAULT_SC_BOTTOM_RIGHT,
                    674:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
                    675:
1.24      macallan  676: #if 0
1.13      macallan  677: #if BYTE_ORDER == BIG_ENDIAN
1.1       macallan  678:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_DATATYPE,
                    679:            R128_HOST_BIG_ENDIAN_EN);
1.13      macallan  680: #else
1.18      macallan  681:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_DATATYPE, 0);
1.13      macallan  682: #endif
1.24      macallan  683: #endif
                    684:        r128fb_wait(sc, 7);
1.1       macallan  685:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_PITCH,
1.24      macallan  686:            sc->sc_width >> 3);
1.1       macallan  687:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_PITCH,
1.24      macallan  688:            sc->sc_width >> 3);
1.1       macallan  689:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_OFFSET, 0);
                    690:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_OFFSET, 0);
                    691:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_WRITE_MASK,
                    692:            0xffffffff);
                    693:
                    694:        switch (sc->sc_depth) {
                    695:                case 8:
                    696:                        datatype = R128_GMC_DST_8BPP_CI;
1.24      macallan  697:                        d = R128_CRTC_COLOR_8BIT;
1.1       macallan  698:                        break;
                    699:                case 15:
                    700:                        datatype = R128_GMC_DST_15BPP;
1.24      macallan  701:                        d = R128_CRTC_COLOR_15BIT;
1.1       macallan  702:                        break;
                    703:                case 16:
                    704:                        datatype = R128_GMC_DST_16BPP;
1.24      macallan  705:                        d = R128_CRTC_COLOR_16BIT;
1.1       macallan  706:                        break;
                    707:                case 24:
                    708:                        datatype = R128_GMC_DST_24BPP;
1.24      macallan  709:                        d = R128_CRTC_COLOR_24BIT;
1.1       macallan  710:                        break;
                    711:                case 32:
                    712:                        datatype = R128_GMC_DST_32BPP;
1.24      macallan  713:                        d = R128_CRTC_COLOR_32BIT;
1.1       macallan  714:                        break;
                    715:                default:
                    716:                        aprint_error("%s: unsupported depth %d\n",
                    717:                            device_xname(sc->sc_dev), sc->sc_depth);
                    718:                        return;
                    719:        }
                    720:        sc->sc_master_cntl = R128_GMC_CLR_CMP_CNTL_DIS |
                    721:            R128_GMC_AUX_CLIP_DIS | datatype;
1.24      macallan  722:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_CRTC_GEN_CNTL);
                    723:        DPRINTF("depth: %d\n", reg & R128_CRTC_PIX_WIDTH);
                    724:        reg &= ~R128_CRTC_PIX_WIDTH;
                    725:        reg |= d;
                    726:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_GEN_CNTL, reg);
                    727:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_PITCH, sc->sc_width >> 3);
1.1       macallan  728:        r128fb_flush_engine(sc);
                    729: }
                    730:
                    731: static void
                    732: r128fb_rectfill(struct r128fb_softc *sc, int x, int y, int wi, int he,
                    733:      uint32_t colour)
                    734: {
                    735:
1.13      macallan  736:        r128fb_wait(sc, 5);
1.1       macallan  737:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
                    738:            R128_GMC_BRUSH_SOLID_COLOR |
                    739:            R128_GMC_SRC_DATATYPE_COLOR |
                    740:            R128_ROP3_P |
                    741:            sc->sc_master_cntl);
                    742:
                    743:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_BRUSH_FRGD_CLR,
                    744:            colour);
                    745:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL,
                    746:            R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
                    747:        /* now feed it coordinates */
                    748:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    749:            (x << 16) | y);
                    750:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    751:            (wi << 16) | he);
                    752: }
                    753:
                    754: static void
1.29      macallan  755: r128fb_bitblt(void *cookie, int xs, int ys, int xd, int yd,
1.1       macallan  756:     int wi, int he, int rop)
                    757: {
1.29      macallan  758:        struct r128fb_softc *sc = cookie;
1.1       macallan  759:        uint32_t dp_cntl = 0;
                    760:
                    761:        r128fb_wait(sc, 5);
                    762:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
                    763:            R128_GMC_BRUSH_SOLID_COLOR |
                    764:            R128_GMC_SRC_DATATYPE_COLOR |
                    765:            rop |
                    766:            R128_DP_SRC_SOURCE_MEMORY |
                    767:            sc->sc_master_cntl);
                    768:
                    769:        if (yd <= ys) {
                    770:                dp_cntl = R128_DST_Y_TOP_TO_BOTTOM;
                    771:        } else {
                    772:                ys += he - 1;
                    773:                yd += he - 1;
                    774:        }
                    775:        if (xd <= xs) {
                    776:                dp_cntl |= R128_DST_X_LEFT_TO_RIGHT;
                    777:        } else {
                    778:                xs += wi - 1;
                    779:                xd += wi - 1;
                    780:        }
                    781:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL, dp_cntl);
                    782:
                    783:        /* now feed it coordinates */
                    784:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y,
                    785:            (xs << 16) | ys);
                    786:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    787:            (xd << 16) | yd);
                    788:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    789:            (wi << 16) | he);
                    790: }
                    791:
                    792: static void
                    793: r128fb_cursor(void *cookie, int on, int row, int col)
                    794: {
                    795:        struct rasops_info *ri = cookie;
                    796:        struct vcons_screen *scr = ri->ri_hw;
                    797:        struct r128fb_softc *sc = scr->scr_cookie;
                    798:        int x, y, wi, he;
                    799:
                    800:        wi = ri->ri_font->fontwidth;
                    801:        he = ri->ri_font->fontheight;
                    802:
                    803:        if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
                    804:                x = ri->ri_ccol * wi + ri->ri_xorigin;
                    805:                y = ri->ri_crow * he + ri->ri_yorigin;
                    806:                if (ri->ri_flg & RI_CURSOR) {
                    807:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
                    808:                        ri->ri_flg &= ~RI_CURSOR;
                    809:                }
                    810:                ri->ri_crow = row;
                    811:                ri->ri_ccol = col;
                    812:                if (on) {
                    813:                        x = ri->ri_ccol * wi + ri->ri_xorigin;
                    814:                        y = ri->ri_crow * he + ri->ri_yorigin;
                    815:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
1.7       yamt      816:                        ri->ri_flg |= RI_CURSOR;
1.1       macallan  817:                }
                    818:        } else {
                    819:                scr->scr_ri.ri_crow = row;
                    820:                scr->scr_ri.ri_ccol = col;
                    821:                scr->scr_ri.ri_flg &= ~RI_CURSOR;
                    822:        }
                    823:
                    824: }
                    825:
                    826: static void
                    827: r128fb_putchar(void *cookie, int row, int col, u_int c, long attr)
                    828: {
1.13      macallan  829:        struct rasops_info *ri = cookie;
                    830:        struct wsdisplay_font *font = PICK_FONT(ri, c);
                    831:        struct vcons_screen *scr = ri->ri_hw;
                    832:        struct r128fb_softc *sc = scr->scr_cookie;
1.23      macallan  833:        void *data;
                    834:        uint32_t fg, bg;
1.26      macallan  835:        int i, x, y, wi, he, offset;
1.23      macallan  836:
                    837:        if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
                    838:                return;
1.13      macallan  839:
1.23      macallan  840:        if (!CHAR_IN_FONT(c, font))
                    841:                return;
                    842:
                    843:        wi = font->fontwidth;
                    844:        he = font->fontheight;
                    845:
                    846:        bg = ri->ri_devcmap[(attr >> 16) & 0xf];
                    847:        fg = ri->ri_devcmap[(attr >> 24) & 0xf];
                    848:        x = ri->ri_xorigin + col * wi;
                    849:        y = ri->ri_yorigin + row * he;
1.24      macallan  850:
1.23      macallan  851:        if (c == 0x20) {
                    852:                r128fb_rectfill(sc, x, y, wi, he, bg);
                    853:                return;
                    854:        }
1.13      macallan  855:
1.26      macallan  856:        data = WSFONT_GLYPH(c, font);
1.23      macallan  857:
1.24      macallan  858:        r128fb_wait(sc, 8);
                    859:
                    860:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    861:            R128_DP_GUI_MASTER_CNTL,
                    862:            R128_GMC_BRUSH_SOLID_COLOR |
                    863:            R128_GMC_SRC_DATATYPE_MONO_FG_BG |
                    864:            R128_ROP3_S |
                    865:            R128_DP_SRC_SOURCE_HOST_DATA |
                    866:            R128_GMC_DST_CLIPPING |
                    867:            sc->sc_master_cntl);
                    868:
                    869:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    870:            R128_DP_CNTL,
                    871:            R128_DST_Y_TOP_TO_BOTTOM |
                    872:            R128_DST_X_LEFT_TO_RIGHT);
                    873:
                    874:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    875:            R128_DP_SRC_FRGD_CLR, fg);
                    876:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    877:            R128_DP_SRC_BKGD_CLR, bg);
                    878:
                    879:        /*
                    880:         * The Rage 128 doesn't have anything to skip pixels
                    881:         * when colour expanding but all coordinates
                    882:         * are signed so we just clip the leading bytes and
                    883:         * trailing bits away
                    884:         */
                    885:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    886:            R128_SC_RIGHT, x + wi - 1);
                    887:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    888:            R128_SC_LEFT, x);
                    889:
                    890:        /* needed? */
                    891:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y, 0);
1.23      macallan  892:
1.24      macallan  893:        offset = 32 - (font->stride << 3);
                    894:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    895:            ((x - offset) << 16) | y);
                    896:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    897:            R128_DST_WIDTH_HEIGHT, (32 << 16) | he);
1.13      macallan  898:
1.24      macallan  899:        r128fb_wait(sc, he);
                    900:        switch (font->stride) {
                    901:                case 1: {
                    902:                        uint8_t *data8 = data;
                    903:                        uint32_t reg;
                    904:                        for (i = 0; i < he; i++) {
                    905:                                reg = *data8;
                    906:                                bus_space_write_stream_4(sc->sc_memt,
                    907:                                    sc->sc_regh, R128_HOST_DATA0, reg);
                    908:                                data8++;
1.13      macallan  909:                        }
1.24      macallan  910:                        break;
                    911:                }
                    912:                case 2: {
                    913:                        uint16_t *data16 = data;
                    914:                        uint32_t reg;
                    915:                        for (i = 0; i < he; i++) {
                    916:                                reg = *data16;
                    917:                                bus_space_write_stream_4(sc->sc_memt,
                    918:                                    sc->sc_regh, R128_HOST_DATA0, reg);
                    919:                                data16++;
1.13      macallan  920:                        }
1.24      macallan  921:                        break;
1.23      macallan  922:                }
1.24      macallan  923:        }
                    924: }
                    925:
                    926: static void
                    927: r128fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr)
                    928: {
                    929:        struct rasops_info *ri = cookie;
                    930:        struct wsdisplay_font *font = PICK_FONT(ri, c);
                    931:        struct vcons_screen *scr = ri->ri_hw;
                    932:        struct r128fb_softc *sc = scr->scr_cookie;
                    933:        uint32_t bg, latch = 0, bg8, fg8, pixel;
1.26      macallan  934:        int i, x, y, wi, he, r, g, b, aval;
1.24      macallan  935:        int r1, g1, b1, r0, g0, b0, fgo, bgo;
                    936:        uint8_t *data8;
1.31      macallan  937:        int rv, cnt = 0;
1.24      macallan  938:
                    939:        if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
                    940:                return;
                    941:
                    942:        if (!CHAR_IN_FONT(c, font))
                    943:                return;
                    944:
                    945:        wi = font->fontwidth;
                    946:        he = font->fontheight;
                    947:
                    948:        bg = ri->ri_devcmap[(attr >> 16) & 0xf];
                    949:        x = ri->ri_xorigin + col * wi;
                    950:        y = ri->ri_yorigin + row * he;
                    951:        if (c == 0x20) {
                    952:                r128fb_rectfill(sc, x, y, wi, he, bg);
                    953:                return;
                    954:        }
                    955:
1.29      macallan  956:        rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
                    957:        if (rv == GC_OK)
                    958:                return;
                    959:
1.26      macallan  960:        data8 = WSFONT_GLYPH(c, font);
1.24      macallan  961:
                    962:        r128fb_wait(sc, 5);
                    963:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    964:            R128_DP_GUI_MASTER_CNTL,
                    965:            R128_GMC_BRUSH_SOLID_COLOR |
                    966:            R128_GMC_SRC_DATATYPE_COLOR |
                    967:            R128_ROP3_S |
                    968:            R128_DP_SRC_SOURCE_HOST_DATA |
                    969:            sc->sc_master_cntl);
                    970:
                    971:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    972:            R128_DP_CNTL,
                    973:            R128_DST_Y_TOP_TO_BOTTOM |
                    974:            R128_DST_X_LEFT_TO_RIGHT);
                    975:
                    976:        /* needed? */
                    977:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y, 0);
                    978:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    979:            (x << 16) | y);
                    980:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    981:            (wi << 16) | he);
1.23      macallan  982:
1.24      macallan  983:        /*
                    984:         * we need the RGB colours here, so get offsets into rasops_cmap
                    985:         */
                    986:        fgo = ((attr >> 24) & 0xf) * 3;
                    987:        bgo = ((attr >> 16) & 0xf) * 3;
1.23      macallan  988:
1.24      macallan  989:        r0 = rasops_cmap[bgo];
                    990:        r1 = rasops_cmap[fgo];
                    991:        g0 = rasops_cmap[bgo + 1];
                    992:        g1 = rasops_cmap[fgo + 1];
                    993:        b0 = rasops_cmap[bgo + 2];
                    994:        b1 = rasops_cmap[fgo + 2];
1.23      macallan  995: #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6))
1.24      macallan  996:        bg8 = R3G3B2(r0, g0, b0);
                    997:        fg8 = R3G3B2(r1, g1, b1);
1.31      macallan  998:
                    999:        r128fb_wait(sc, 16);
                   1000:
1.24      macallan 1001:        for (i = 0; i < ri->ri_fontscale; i++) {
                   1002:                aval = *data8;
                   1003:                if (aval == 0) {
                   1004:                        pixel = bg8;
                   1005:                } else if (aval == 255) {
                   1006:                        pixel = fg8;
                   1007:                } else {
                   1008:                        r = aval * r1 + (255 - aval) * r0;
                   1009:                        g = aval * g1 + (255 - aval) * g0;
                   1010:                        b = aval * b1 + (255 - aval) * b0;
                   1011:                        pixel = ((r & 0xe000) >> 8) |
                   1012:                                ((g & 0xe000) >> 11) |
                   1013:                                ((b & 0xc000) >> 14);
1.23      macallan 1014:                }
1.24      macallan 1015:                latch = (latch << 8) | pixel;
                   1016:                /* write in 32bit chunks */
                   1017:                if ((i & 3) == 3) {
1.23      macallan 1018:                        bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
1.24      macallan 1019:                            R128_HOST_DATA0, latch);
                   1020:                        /*
                   1021:                         * not strictly necessary, old data should be shifted
                   1022:                         * out
                   1023:                         */
                   1024:                        latch = 0;
1.31      macallan 1025:                        cnt++;
                   1026:                        if (cnt > 15) {
                   1027:                                r128fb_wait(sc, 16);
                   1028:                                cnt = 0;
                   1029:                        }
1.13      macallan 1030:                }
1.24      macallan 1031:                data8++;
                   1032:        }
                   1033:        /* if we have pixels left in latch write them out */
                   1034:        if ((i & 3) != 0) {
                   1035:                latch = latch << ((4 - (i & 3)) << 3);
                   1036:                bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
                   1037:                                    R128_HOST_DATA0, latch);
1.13      macallan 1038:        }
1.29      macallan 1039:        if (rv == GC_ADD) {
                   1040:                glyphcache_add(&sc->sc_gc, c, x, y);
                   1041:        }
1.1       macallan 1042: }
                   1043:
                   1044: static void
                   1045: r128fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
                   1046: {
                   1047:        struct rasops_info *ri = cookie;
                   1048:        struct vcons_screen *scr = ri->ri_hw;
                   1049:        struct r128fb_softc *sc = scr->scr_cookie;
                   1050:        int32_t xs, xd, y, width, height;
                   1051:
                   1052:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1053:                xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
                   1054:                xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
                   1055:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1056:                width = ri->ri_font->fontwidth * ncols;
                   1057:                height = ri->ri_font->fontheight;
                   1058:                r128fb_bitblt(sc, xs, y, xd, y, width, height, R128_ROP3_S);
                   1059:        }
                   1060: }
                   1061:
                   1062: static void
                   1063: r128fb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
                   1064: {
                   1065:        struct rasops_info *ri = cookie;
                   1066:        struct vcons_screen *scr = ri->ri_hw;
                   1067:        struct r128fb_softc *sc = scr->scr_cookie;
                   1068:        int32_t x, y, width, height, fg, bg, ul;
                   1069:
                   1070:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1071:                x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
                   1072:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1073:                width = ri->ri_font->fontwidth * ncols;
                   1074:                height = ri->ri_font->fontheight;
                   1075:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
                   1076:
                   1077:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
                   1078:        }
                   1079: }
                   1080:
                   1081: static void
                   1082: r128fb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
                   1083: {
                   1084:        struct rasops_info *ri = cookie;
                   1085:        struct vcons_screen *scr = ri->ri_hw;
                   1086:        struct r128fb_softc *sc = scr->scr_cookie;
                   1087:        int32_t x, ys, yd, width, height;
                   1088:
                   1089:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1090:                x = ri->ri_xorigin;
                   1091:                ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
                   1092:                yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
                   1093:                width = ri->ri_emuwidth;
1.13      macallan 1094:                height = ri->ri_font->fontheight * nrows;
1.1       macallan 1095:                r128fb_bitblt(sc, x, ys, x, yd, width, height, R128_ROP3_S);
                   1096:        }
                   1097: }
                   1098:
                   1099: static void
                   1100: r128fb_eraserows(void *cookie, int row, int nrows, long fillattr)
                   1101: {
                   1102:        struct rasops_info *ri = cookie;
                   1103:        struct vcons_screen *scr = ri->ri_hw;
                   1104:        struct r128fb_softc *sc = scr->scr_cookie;
                   1105:        int32_t x, y, width, height, fg, bg, ul;
                   1106:
                   1107:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1108:                x = ri->ri_xorigin;
                   1109:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1110:                width = ri->ri_emuwidth;
                   1111:                height = ri->ri_font->fontheight * nrows;
                   1112:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
                   1113:
                   1114:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
                   1115:        }
                   1116: }
                   1117:
1.11      macallan 1118: static void
                   1119: r128fb_set_backlight(struct r128fb_softc *sc, int level)
                   1120: {
                   1121:        uint32_t reg;
                   1122:
1.14      macallan 1123:        /*
                   1124:         * should we do nothing when backlight is off, should we just store the
                   1125:         * level and use it when turning back on or should we just flip sc_bl_on
                   1126:         * and turn the backlight on?
                   1127:         * For now turn it on so a crashed screensaver can't get the user stuck
                   1128:         * with a dark screen as long as hotkeys work
                   1129:         */
1.11      macallan 1130:        if (level > 255) level = 255;
                   1131:        if (level < 0) level = 0;
                   1132:        if (level == sc->sc_bl_level)
                   1133:                return;
                   1134:        sc->sc_bl_level = level;
1.14      macallan 1135:        if (sc->sc_bl_on == 0)
                   1136:                sc->sc_bl_on = 1;
1.11      macallan 1137:        level = 255 - level;
                   1138:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL);
                   1139:        reg &= ~R128_LEVEL_MASK;
1.21      macallan 1140:        reg |= (level << R128_LEVEL_SHIFT);
1.11      macallan 1141:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL, reg);
1.14      macallan 1142:        DPRINTF("backlight level: %d reg %08x\n", level, reg);
                   1143: }
                   1144:
                   1145: static void
                   1146: r128fb_switch_backlight(struct r128fb_softc *sc, int on)
                   1147: {
                   1148:        uint32_t reg;
                   1149:        int level;
                   1150:
                   1151:        if (on == sc->sc_bl_on)
                   1152:                return;
                   1153:        sc->sc_bl_on = on;
                   1154:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL);
                   1155:        reg &= ~R128_LEVEL_MASK;
                   1156:        level = on ? 255 - sc->sc_bl_level : 255;
                   1157:        reg |= level << R128_LEVEL_SHIFT;
                   1158:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL, reg);
                   1159:        DPRINTF("backlight state: %d reg %08x\n", on, reg);
1.11      macallan 1160: }
                   1161:
                   1162:
                   1163: static void
                   1164: r128fb_brightness_up(device_t dev)
                   1165: {
                   1166:        struct r128fb_softc *sc = device_private(dev);
                   1167:
                   1168:        r128fb_set_backlight(sc, sc->sc_bl_level + 8);
                   1169: }
                   1170:
                   1171: static void
                   1172: r128fb_brightness_down(device_t dev)
                   1173: {
                   1174:        struct r128fb_softc *sc = device_private(dev);
                   1175:
                   1176:        r128fb_set_backlight(sc, sc->sc_bl_level - 8);
                   1177: }

CVSweb <webmaster@jp.NetBSD.org>