[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.37

1.37    ! macallan    1: /*     $NetBSD: r128fb.c,v 1.36 2012/10/04 10:22:45 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.37    ! macallan   34: __KERNEL_RCSID(0, "$NetBSD: r128fb.c,v 1.36 2012/10/04 10:22:45 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;
                    204:        bool                    is_console;
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.22      macallan  456:        case WSDISPLAYIO_GET_EDID: {
                    457:                struct wsdisplayio_edid_info *d = data;
                    458:                return wsdisplayio_get_edid(sc->sc_dev, d);
                    459:        }
1.1       macallan  460:        }
                    461:        return EPASSTHROUGH;
                    462: }
                    463:
                    464: static paddr_t
                    465: r128fb_mmap(void *v, void *vs, off_t offset, int prot)
                    466: {
                    467:        struct vcons_data *vd = v;
                    468:        struct r128fb_softc *sc = vd->cookie;
                    469:        paddr_t pa;
                    470:
                    471:        /* 'regular' framebuffer mmap()ing */
                    472:        if (offset < sc->sc_fbsize) {
                    473:                pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot,
                    474:                    BUS_SPACE_MAP_LINEAR);
                    475:                return pa;
                    476:        }
                    477:
                    478:        /*
                    479:         * restrict all other mappings to processes with superuser privileges
                    480:         * or the kernel itself
                    481:         */
1.32      elad      482:        if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM,
                    483:            NULL, NULL, NULL, NULL) != 0) {
1.8       elad      484:                aprint_normal("%s: mmap() rejected.\n",
                    485:                    device_xname(sc->sc_dev));
                    486:                return -1;
1.1       macallan  487:        }
                    488:
                    489:        if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) {
                    490:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    491:                    BUS_SPACE_MAP_LINEAR);
                    492:                return pa;
                    493:        }
                    494:
                    495:        if ((offset >= sc->sc_reg) &&
                    496:            (offset < (sc->sc_reg + sc->sc_regsize))) {
                    497:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    498:                    BUS_SPACE_MAP_LINEAR);
                    499:                return pa;
                    500:        }
                    501:
1.3       macallan  502: #ifdef PCI_MAGIC_IO_RANGE
1.1       macallan  503:        /* allow mapping of IO space */
1.3       macallan  504:        if ((offset >= PCI_MAGIC_IO_RANGE) &&
                    505:            (offset < PCI_MAGIC_IO_RANGE + 0x10000)) {
                    506:                pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE,
                    507:                    0, prot, BUS_SPACE_MAP_LINEAR);
1.1       macallan  508:                return pa;
                    509:        }
                    510: #endif
                    511:
                    512: #ifdef OFB_ALLOW_OTHERS
                    513:        if (offset >= 0x80000000) {
                    514:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
                    515:                    BUS_SPACE_MAP_LINEAR);
                    516:                return pa;
                    517:        }
                    518: #endif
                    519:        return -1;
                    520: }
                    521:
                    522: static void
                    523: r128fb_init_screen(void *cookie, struct vcons_screen *scr,
                    524:     int existing, long *defattr)
                    525: {
                    526:        struct r128fb_softc *sc = cookie;
                    527:        struct rasops_info *ri = &scr->scr_ri;
                    528:
                    529:        ri->ri_depth = sc->sc_depth;
                    530:        ri->ri_width = sc->sc_width;
                    531:        ri->ri_height = sc->sc_height;
                    532:        ri->ri_stride = sc->sc_stride;
1.13      macallan  533:        ri->ri_flg = RI_CENTER;
1.23      macallan  534:        if (sc->sc_depth == 8)
                    535:                ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA;
1.1       macallan  536:
1.27      macallan  537:        rasops_init(ri, 0, 0);
1.1       macallan  538:        ri->ri_caps = WSSCREEN_WSCOLORS;
1.22      macallan  539: #ifdef VCONS_DRAW_INTR
                    540:        scr->scr_flags |= VCONS_DONT_READ;
                    541: #endif
1.1       macallan  542:
                    543:        rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
                    544:                    sc->sc_width / ri->ri_font->fontwidth);
                    545:
                    546:        ri->ri_hw = scr;
                    547:        ri->ri_ops.copyrows = r128fb_copyrows;
                    548:        ri->ri_ops.copycols = r128fb_copycols;
                    549:        ri->ri_ops.eraserows = r128fb_eraserows;
                    550:        ri->ri_ops.erasecols = r128fb_erasecols;
                    551:        ri->ri_ops.cursor = r128fb_cursor;
1.24      macallan  552:        if (FONT_IS_ALPHA(ri->ri_font)) {
                    553:                ri->ri_ops.putchar = r128fb_putchar_aa;
                    554:        } else
                    555:                ri->ri_ops.putchar = r128fb_putchar;
1.1       macallan  556: }
                    557:
                    558: static int
                    559: r128fb_putcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
                    560: {
                    561:        u_char *r, *g, *b;
                    562:        u_int index = cm->index;
                    563:        u_int count = cm->count;
                    564:        int i, error;
                    565:        u_char rbuf[256], gbuf[256], bbuf[256];
                    566:
                    567: #ifdef R128FB_DEBUG
                    568:        aprint_debug("putcmap: %d %d\n",index, count);
                    569: #endif
                    570:        if (cm->index >= 256 || cm->count > 256 ||
                    571:            (cm->index + cm->count) > 256)
                    572:                return EINVAL;
                    573:        error = copyin(cm->red, &rbuf[index], count);
                    574:        if (error)
                    575:                return error;
                    576:        error = copyin(cm->green, &gbuf[index], count);
                    577:        if (error)
                    578:                return error;
                    579:        error = copyin(cm->blue, &bbuf[index], count);
                    580:        if (error)
                    581:                return error;
                    582:
                    583:        memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
                    584:        memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
                    585:        memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
                    586:
                    587:        r = &sc->sc_cmap_red[index];
                    588:        g = &sc->sc_cmap_green[index];
                    589:        b = &sc->sc_cmap_blue[index];
                    590:
                    591:        for (i = 0; i < count; i++) {
                    592:                r128fb_putpalreg(sc, index, *r, *g, *b);
                    593:                index++;
                    594:                r++, g++, b++;
                    595:        }
                    596:        return 0;
                    597: }
                    598:
                    599: static int
                    600: r128fb_getcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
                    601: {
                    602:        u_int index = cm->index;
                    603:        u_int count = cm->count;
                    604:        int error;
                    605:
                    606:        if (index >= 255 || count > 256 || index + count > 256)
                    607:                return EINVAL;
                    608:
                    609:        error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
                    610:        if (error)
                    611:                return error;
                    612:        error = copyout(&sc->sc_cmap_green[index], cm->green, count);
                    613:        if (error)
                    614:                return error;
                    615:        error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
                    616:        if (error)
                    617:                return error;
                    618:
                    619:        return 0;
                    620: }
                    621:
                    622: static void
                    623: r128fb_restore_palette(struct r128fb_softc *sc)
                    624: {
                    625:        int i;
                    626:
                    627:        for (i = 0; i < (1 << sc->sc_depth); i++) {
                    628:                r128fb_putpalreg(sc, i, sc->sc_cmap_red[i],
                    629:                    sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
                    630:        }
                    631: }
                    632:
                    633: static int
                    634: r128fb_putpalreg(struct r128fb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
                    635:     uint8_t b)
                    636: {
                    637:        uint32_t reg;
                    638:
                    639:        /* whack the DAC */
                    640:        reg = (r << 16) | (g << 8) | b;
                    641:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_INDEX, idx);
                    642:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_DATA, reg);
                    643:        return 0;
                    644: }
                    645:
                    646: static void
                    647: r128fb_init(struct r128fb_softc *sc)
                    648: {
1.24      macallan  649:        uint32_t datatype, d, reg;
1.1       macallan  650:
                    651:        r128fb_flush_engine(sc);
                    652:
1.13      macallan  653:        r128fb_wait(sc, 9);
1.1       macallan  654:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_OFFSET, 0);
                    655:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_OFFSET, 0);
1.24      macallan  656:        /* pitch is in units of 8 pixels */
1.1       macallan  657:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_PITCH,
1.24      macallan  658:            sc->sc_width >> 3);
1.1       macallan  659:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_AUX_SC_CNTL, 0);
                    660:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    661:            R128_DEFAULT_SC_BOTTOM_RIGHT,
                    662:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
                    663:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_TOP_LEFT, 0);
                    664:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_BOTTOM_RIGHT,
                    665:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
1.13      macallan  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:
1.24      macallan  670: #if 0
1.13      macallan  671: #if BYTE_ORDER == BIG_ENDIAN
1.1       macallan  672:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_DATATYPE,
                    673:            R128_HOST_BIG_ENDIAN_EN);
1.13      macallan  674: #else
1.18      macallan  675:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_DATATYPE, 0);
1.13      macallan  676: #endif
1.24      macallan  677: #endif
                    678:        r128fb_wait(sc, 7);
1.1       macallan  679:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_PITCH,
1.24      macallan  680:            sc->sc_width >> 3);
1.1       macallan  681:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_PITCH,
1.24      macallan  682:            sc->sc_width >> 3);
1.1       macallan  683:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_OFFSET, 0);
                    684:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_OFFSET, 0);
                    685:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_WRITE_MASK,
                    686:            0xffffffff);
                    687:
                    688:        switch (sc->sc_depth) {
                    689:                case 8:
                    690:                        datatype = R128_GMC_DST_8BPP_CI;
1.24      macallan  691:                        d = R128_CRTC_COLOR_8BIT;
1.1       macallan  692:                        break;
                    693:                case 15:
                    694:                        datatype = R128_GMC_DST_15BPP;
1.24      macallan  695:                        d = R128_CRTC_COLOR_15BIT;
1.1       macallan  696:                        break;
                    697:                case 16:
                    698:                        datatype = R128_GMC_DST_16BPP;
1.24      macallan  699:                        d = R128_CRTC_COLOR_16BIT;
1.1       macallan  700:                        break;
                    701:                case 24:
                    702:                        datatype = R128_GMC_DST_24BPP;
1.24      macallan  703:                        d = R128_CRTC_COLOR_24BIT;
1.1       macallan  704:                        break;
                    705:                case 32:
                    706:                        datatype = R128_GMC_DST_32BPP;
1.24      macallan  707:                        d = R128_CRTC_COLOR_32BIT;
1.1       macallan  708:                        break;
                    709:                default:
                    710:                        aprint_error("%s: unsupported depth %d\n",
                    711:                            device_xname(sc->sc_dev), sc->sc_depth);
                    712:                        return;
                    713:        }
                    714:        sc->sc_master_cntl = R128_GMC_CLR_CMP_CNTL_DIS |
                    715:            R128_GMC_AUX_CLIP_DIS | datatype;
1.24      macallan  716:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_CRTC_GEN_CNTL);
                    717:        DPRINTF("depth: %d\n", reg & R128_CRTC_PIX_WIDTH);
                    718:        reg &= ~R128_CRTC_PIX_WIDTH;
                    719:        reg |= d;
                    720:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_GEN_CNTL, reg);
                    721:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_PITCH, sc->sc_width >> 3);
1.1       macallan  722:        r128fb_flush_engine(sc);
                    723: }
                    724:
                    725: static void
                    726: r128fb_rectfill(struct r128fb_softc *sc, int x, int y, int wi, int he,
                    727:      uint32_t colour)
                    728: {
                    729:
1.13      macallan  730:        r128fb_wait(sc, 5);
1.1       macallan  731:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
                    732:            R128_GMC_BRUSH_SOLID_COLOR |
                    733:            R128_GMC_SRC_DATATYPE_COLOR |
                    734:            R128_ROP3_P |
                    735:            sc->sc_master_cntl);
                    736:
                    737:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_BRUSH_FRGD_CLR,
                    738:            colour);
                    739:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL,
                    740:            R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
                    741:        /* now feed it coordinates */
                    742:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    743:            (x << 16) | y);
                    744:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    745:            (wi << 16) | he);
                    746: }
                    747:
                    748: static void
1.29      macallan  749: r128fb_bitblt(void *cookie, int xs, int ys, int xd, int yd,
1.1       macallan  750:     int wi, int he, int rop)
                    751: {
1.29      macallan  752:        struct r128fb_softc *sc = cookie;
1.1       macallan  753:        uint32_t dp_cntl = 0;
                    754:
                    755:        r128fb_wait(sc, 5);
                    756:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
                    757:            R128_GMC_BRUSH_SOLID_COLOR |
                    758:            R128_GMC_SRC_DATATYPE_COLOR |
                    759:            rop |
                    760:            R128_DP_SRC_SOURCE_MEMORY |
                    761:            sc->sc_master_cntl);
                    762:
                    763:        if (yd <= ys) {
                    764:                dp_cntl = R128_DST_Y_TOP_TO_BOTTOM;
                    765:        } else {
                    766:                ys += he - 1;
                    767:                yd += he - 1;
                    768:        }
                    769:        if (xd <= xs) {
                    770:                dp_cntl |= R128_DST_X_LEFT_TO_RIGHT;
                    771:        } else {
                    772:                xs += wi - 1;
                    773:                xd += wi - 1;
                    774:        }
                    775:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL, dp_cntl);
                    776:
                    777:        /* now feed it coordinates */
                    778:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y,
                    779:            (xs << 16) | ys);
                    780:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    781:            (xd << 16) | yd);
                    782:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    783:            (wi << 16) | he);
                    784: }
                    785:
                    786: static void
                    787: r128fb_cursor(void *cookie, int on, int row, int col)
                    788: {
                    789:        struct rasops_info *ri = cookie;
                    790:        struct vcons_screen *scr = ri->ri_hw;
                    791:        struct r128fb_softc *sc = scr->scr_cookie;
                    792:        int x, y, wi, he;
                    793:
                    794:        wi = ri->ri_font->fontwidth;
                    795:        he = ri->ri_font->fontheight;
                    796:
                    797:        if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
                    798:                x = ri->ri_ccol * wi + ri->ri_xorigin;
                    799:                y = ri->ri_crow * he + ri->ri_yorigin;
                    800:                if (ri->ri_flg & RI_CURSOR) {
                    801:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
                    802:                        ri->ri_flg &= ~RI_CURSOR;
                    803:                }
                    804:                ri->ri_crow = row;
                    805:                ri->ri_ccol = col;
                    806:                if (on) {
                    807:                        x = ri->ri_ccol * wi + ri->ri_xorigin;
                    808:                        y = ri->ri_crow * he + ri->ri_yorigin;
                    809:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
1.7       yamt      810:                        ri->ri_flg |= RI_CURSOR;
1.1       macallan  811:                }
                    812:        } else {
                    813:                scr->scr_ri.ri_crow = row;
                    814:                scr->scr_ri.ri_ccol = col;
                    815:                scr->scr_ri.ri_flg &= ~RI_CURSOR;
                    816:        }
                    817:
                    818: }
                    819:
                    820: static void
                    821: r128fb_putchar(void *cookie, int row, int col, u_int c, long attr)
                    822: {
1.13      macallan  823:        struct rasops_info *ri = cookie;
                    824:        struct wsdisplay_font *font = PICK_FONT(ri, c);
                    825:        struct vcons_screen *scr = ri->ri_hw;
                    826:        struct r128fb_softc *sc = scr->scr_cookie;
1.23      macallan  827:        void *data;
                    828:        uint32_t fg, bg;
1.26      macallan  829:        int i, x, y, wi, he, offset;
1.23      macallan  830:
                    831:        if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
                    832:                return;
1.13      macallan  833:
1.23      macallan  834:        if (!CHAR_IN_FONT(c, font))
                    835:                return;
                    836:
                    837:        wi = font->fontwidth;
                    838:        he = font->fontheight;
                    839:
                    840:        bg = ri->ri_devcmap[(attr >> 16) & 0xf];
                    841:        fg = ri->ri_devcmap[(attr >> 24) & 0xf];
                    842:        x = ri->ri_xorigin + col * wi;
                    843:        y = ri->ri_yorigin + row * he;
1.24      macallan  844:
1.23      macallan  845:        if (c == 0x20) {
                    846:                r128fb_rectfill(sc, x, y, wi, he, bg);
                    847:                return;
                    848:        }
1.13      macallan  849:
1.26      macallan  850:        data = WSFONT_GLYPH(c, font);
1.23      macallan  851:
1.24      macallan  852:        r128fb_wait(sc, 8);
                    853:
                    854:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    855:            R128_DP_GUI_MASTER_CNTL,
                    856:            R128_GMC_BRUSH_SOLID_COLOR |
                    857:            R128_GMC_SRC_DATATYPE_MONO_FG_BG |
                    858:            R128_ROP3_S |
                    859:            R128_DP_SRC_SOURCE_HOST_DATA |
                    860:            R128_GMC_DST_CLIPPING |
                    861:            sc->sc_master_cntl);
                    862:
                    863:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    864:            R128_DP_CNTL,
                    865:            R128_DST_Y_TOP_TO_BOTTOM |
                    866:            R128_DST_X_LEFT_TO_RIGHT);
                    867:
                    868:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    869:            R128_DP_SRC_FRGD_CLR, fg);
                    870:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    871:            R128_DP_SRC_BKGD_CLR, bg);
                    872:
                    873:        /*
                    874:         * The Rage 128 doesn't have anything to skip pixels
                    875:         * when colour expanding but all coordinates
                    876:         * are signed so we just clip the leading bytes and
                    877:         * trailing bits away
                    878:         */
                    879:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    880:            R128_SC_RIGHT, x + wi - 1);
                    881:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    882:            R128_SC_LEFT, x);
                    883:
                    884:        /* needed? */
                    885:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y, 0);
1.23      macallan  886:
1.24      macallan  887:        offset = 32 - (font->stride << 3);
                    888:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    889:            ((x - offset) << 16) | y);
                    890:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    891:            R128_DST_WIDTH_HEIGHT, (32 << 16) | he);
1.13      macallan  892:
1.24      macallan  893:        r128fb_wait(sc, he);
                    894:        switch (font->stride) {
                    895:                case 1: {
                    896:                        uint8_t *data8 = data;
                    897:                        uint32_t reg;
                    898:                        for (i = 0; i < he; i++) {
                    899:                                reg = *data8;
                    900:                                bus_space_write_stream_4(sc->sc_memt,
                    901:                                    sc->sc_regh, R128_HOST_DATA0, reg);
                    902:                                data8++;
1.13      macallan  903:                        }
1.24      macallan  904:                        break;
                    905:                }
                    906:                case 2: {
                    907:                        uint16_t *data16 = data;
                    908:                        uint32_t reg;
                    909:                        for (i = 0; i < he; i++) {
                    910:                                reg = *data16;
                    911:                                bus_space_write_stream_4(sc->sc_memt,
                    912:                                    sc->sc_regh, R128_HOST_DATA0, reg);
                    913:                                data16++;
1.13      macallan  914:                        }
1.24      macallan  915:                        break;
1.23      macallan  916:                }
1.24      macallan  917:        }
                    918: }
                    919:
                    920: static void
                    921: r128fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr)
                    922: {
                    923:        struct rasops_info *ri = cookie;
                    924:        struct wsdisplay_font *font = PICK_FONT(ri, c);
                    925:        struct vcons_screen *scr = ri->ri_hw;
                    926:        struct r128fb_softc *sc = scr->scr_cookie;
                    927:        uint32_t bg, latch = 0, bg8, fg8, pixel;
1.26      macallan  928:        int i, x, y, wi, he, r, g, b, aval;
1.24      macallan  929:        int r1, g1, b1, r0, g0, b0, fgo, bgo;
                    930:        uint8_t *data8;
1.31      macallan  931:        int rv, cnt = 0;
1.24      macallan  932:
                    933:        if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
                    934:                return;
                    935:
                    936:        if (!CHAR_IN_FONT(c, font))
                    937:                return;
                    938:
                    939:        wi = font->fontwidth;
                    940:        he = font->fontheight;
                    941:
                    942:        bg = ri->ri_devcmap[(attr >> 16) & 0xf];
                    943:        x = ri->ri_xorigin + col * wi;
                    944:        y = ri->ri_yorigin + row * he;
                    945:        if (c == 0x20) {
                    946:                r128fb_rectfill(sc, x, y, wi, he, bg);
                    947:                return;
                    948:        }
                    949:
1.29      macallan  950:        rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
                    951:        if (rv == GC_OK)
                    952:                return;
                    953:
1.26      macallan  954:        data8 = WSFONT_GLYPH(c, font);
1.24      macallan  955:
                    956:        r128fb_wait(sc, 5);
                    957:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    958:            R128_DP_GUI_MASTER_CNTL,
                    959:            R128_GMC_BRUSH_SOLID_COLOR |
                    960:            R128_GMC_SRC_DATATYPE_COLOR |
                    961:            R128_ROP3_S |
                    962:            R128_DP_SRC_SOURCE_HOST_DATA |
                    963:            sc->sc_master_cntl);
                    964:
                    965:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
                    966:            R128_DP_CNTL,
                    967:            R128_DST_Y_TOP_TO_BOTTOM |
                    968:            R128_DST_X_LEFT_TO_RIGHT);
                    969:
                    970:        /* needed? */
                    971:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y, 0);
                    972:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
                    973:            (x << 16) | y);
                    974:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
                    975:            (wi << 16) | he);
1.23      macallan  976:
1.24      macallan  977:        /*
                    978:         * we need the RGB colours here, so get offsets into rasops_cmap
                    979:         */
                    980:        fgo = ((attr >> 24) & 0xf) * 3;
                    981:        bgo = ((attr >> 16) & 0xf) * 3;
1.23      macallan  982:
1.24      macallan  983:        r0 = rasops_cmap[bgo];
                    984:        r1 = rasops_cmap[fgo];
                    985:        g0 = rasops_cmap[bgo + 1];
                    986:        g1 = rasops_cmap[fgo + 1];
                    987:        b0 = rasops_cmap[bgo + 2];
                    988:        b1 = rasops_cmap[fgo + 2];
1.23      macallan  989: #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6))
1.24      macallan  990:        bg8 = R3G3B2(r0, g0, b0);
                    991:        fg8 = R3G3B2(r1, g1, b1);
1.31      macallan  992:
                    993:        r128fb_wait(sc, 16);
                    994:
1.24      macallan  995:        for (i = 0; i < ri->ri_fontscale; i++) {
                    996:                aval = *data8;
                    997:                if (aval == 0) {
                    998:                        pixel = bg8;
                    999:                } else if (aval == 255) {
                   1000:                        pixel = fg8;
                   1001:                } else {
                   1002:                        r = aval * r1 + (255 - aval) * r0;
                   1003:                        g = aval * g1 + (255 - aval) * g0;
                   1004:                        b = aval * b1 + (255 - aval) * b0;
                   1005:                        pixel = ((r & 0xe000) >> 8) |
                   1006:                                ((g & 0xe000) >> 11) |
                   1007:                                ((b & 0xc000) >> 14);
1.23      macallan 1008:                }
1.24      macallan 1009:                latch = (latch << 8) | pixel;
                   1010:                /* write in 32bit chunks */
                   1011:                if ((i & 3) == 3) {
1.23      macallan 1012:                        bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
1.24      macallan 1013:                            R128_HOST_DATA0, latch);
                   1014:                        /*
                   1015:                         * not strictly necessary, old data should be shifted
                   1016:                         * out
                   1017:                         */
                   1018:                        latch = 0;
1.31      macallan 1019:                        cnt++;
                   1020:                        if (cnt > 15) {
                   1021:                                r128fb_wait(sc, 16);
                   1022:                                cnt = 0;
                   1023:                        }
1.13      macallan 1024:                }
1.24      macallan 1025:                data8++;
                   1026:        }
                   1027:        /* if we have pixels left in latch write them out */
                   1028:        if ((i & 3) != 0) {
                   1029:                latch = latch << ((4 - (i & 3)) << 3);
                   1030:                bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
                   1031:                                    R128_HOST_DATA0, latch);
1.13      macallan 1032:        }
1.29      macallan 1033:        if (rv == GC_ADD) {
                   1034:                glyphcache_add(&sc->sc_gc, c, x, y);
                   1035:        }
1.1       macallan 1036: }
                   1037:
                   1038: static void
                   1039: r128fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
                   1040: {
                   1041:        struct rasops_info *ri = cookie;
                   1042:        struct vcons_screen *scr = ri->ri_hw;
                   1043:        struct r128fb_softc *sc = scr->scr_cookie;
                   1044:        int32_t xs, xd, y, width, height;
                   1045:
                   1046:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1047:                xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
                   1048:                xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
                   1049:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1050:                width = ri->ri_font->fontwidth * ncols;
                   1051:                height = ri->ri_font->fontheight;
                   1052:                r128fb_bitblt(sc, xs, y, xd, y, width, height, R128_ROP3_S);
                   1053:        }
                   1054: }
                   1055:
                   1056: static void
                   1057: r128fb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
                   1058: {
                   1059:        struct rasops_info *ri = cookie;
                   1060:        struct vcons_screen *scr = ri->ri_hw;
                   1061:        struct r128fb_softc *sc = scr->scr_cookie;
                   1062:        int32_t x, y, width, height, fg, bg, ul;
                   1063:
                   1064:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1065:                x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
                   1066:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1067:                width = ri->ri_font->fontwidth * ncols;
                   1068:                height = ri->ri_font->fontheight;
                   1069:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
                   1070:
                   1071:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
                   1072:        }
                   1073: }
                   1074:
                   1075: static void
                   1076: r128fb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
                   1077: {
                   1078:        struct rasops_info *ri = cookie;
                   1079:        struct vcons_screen *scr = ri->ri_hw;
                   1080:        struct r128fb_softc *sc = scr->scr_cookie;
                   1081:        int32_t x, ys, yd, width, height;
                   1082:
                   1083:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1084:                x = ri->ri_xorigin;
                   1085:                ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
                   1086:                yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
                   1087:                width = ri->ri_emuwidth;
1.13      macallan 1088:                height = ri->ri_font->fontheight * nrows;
1.1       macallan 1089:                r128fb_bitblt(sc, x, ys, x, yd, width, height, R128_ROP3_S);
                   1090:        }
                   1091: }
                   1092:
                   1093: static void
                   1094: r128fb_eraserows(void *cookie, int row, int nrows, long fillattr)
                   1095: {
                   1096:        struct rasops_info *ri = cookie;
                   1097:        struct vcons_screen *scr = ri->ri_hw;
                   1098:        struct r128fb_softc *sc = scr->scr_cookie;
                   1099:        int32_t x, y, width, height, fg, bg, ul;
                   1100:
                   1101:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
                   1102:                x = ri->ri_xorigin;
                   1103:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
                   1104:                width = ri->ri_emuwidth;
                   1105:                height = ri->ri_font->fontheight * nrows;
                   1106:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
                   1107:
                   1108:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
                   1109:        }
                   1110: }
                   1111:
1.11      macallan 1112: static void
                   1113: r128fb_set_backlight(struct r128fb_softc *sc, int level)
                   1114: {
                   1115:        uint32_t reg;
                   1116:
1.14      macallan 1117:        /*
                   1118:         * should we do nothing when backlight is off, should we just store the
                   1119:         * level and use it when turning back on or should we just flip sc_bl_on
                   1120:         * and turn the backlight on?
                   1121:         * For now turn it on so a crashed screensaver can't get the user stuck
                   1122:         * with a dark screen as long as hotkeys work
                   1123:         */
1.11      macallan 1124:        if (level > 255) level = 255;
                   1125:        if (level < 0) level = 0;
                   1126:        if (level == sc->sc_bl_level)
                   1127:                return;
                   1128:        sc->sc_bl_level = level;
1.14      macallan 1129:        if (sc->sc_bl_on == 0)
                   1130:                sc->sc_bl_on = 1;
1.11      macallan 1131:        level = 255 - level;
                   1132:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL);
                   1133:        reg &= ~R128_LEVEL_MASK;
1.21      macallan 1134:        reg |= (level << R128_LEVEL_SHIFT);
1.11      macallan 1135:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL, reg);
1.14      macallan 1136:        DPRINTF("backlight level: %d reg %08x\n", level, reg);
                   1137: }
                   1138:
                   1139: static void
                   1140: r128fb_switch_backlight(struct r128fb_softc *sc, int on)
                   1141: {
                   1142:        uint32_t reg;
                   1143:        int level;
                   1144:
                   1145:        if (on == sc->sc_bl_on)
                   1146:                return;
                   1147:        sc->sc_bl_on = on;
                   1148:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL);
                   1149:        reg &= ~R128_LEVEL_MASK;
                   1150:        level = on ? 255 - sc->sc_bl_level : 255;
                   1151:        reg |= level << R128_LEVEL_SHIFT;
                   1152:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_LVDS_GEN_CNTL, reg);
                   1153:        DPRINTF("backlight state: %d reg %08x\n", on, reg);
1.11      macallan 1154: }
                   1155:
                   1156:
                   1157: static void
                   1158: r128fb_brightness_up(device_t dev)
                   1159: {
                   1160:        struct r128fb_softc *sc = device_private(dev);
                   1161:
                   1162:        r128fb_set_backlight(sc, sc->sc_bl_level + 8);
                   1163: }
                   1164:
                   1165: static void
                   1166: r128fb_brightness_down(device_t dev)
                   1167: {
                   1168:        struct r128fb_softc *sc = device_private(dev);
                   1169:
                   1170:        r128fb_set_backlight(sc, sc->sc_bl_level - 8);
                   1171: }

CVSweb <webmaster@jp.NetBSD.org>