[BACK]Return to drmfb.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / external / bsd / drm2 / drm

Annotation of src/sys/external/bsd/drm2/drm/drmfb.c, Revision 1.9

1.9     ! riastrad    1: /*     $NetBSD: drmfb.c,v 1.8 2020/06/27 13:41:44 jmcneill Exp $       */
1.1       riastrad    2:
                      3: /*-
                      4:  * Copyright (c) 2014 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Taylor R. Campbell.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * drmfb: wsdisplay support, via genfb, for any drm device.  Use this
                     34:  * if you're too lazy to write a hardware-accelerated framebuffer using
                     35:  * wsdisplay directly.
                     36:  *
                     37:  * This doesn't actually do anything interesting -- just hooks up
                     38:  * drmkms crap and genfb crap.
                     39:  */
                     40:
                     41: #include <sys/cdefs.h>
1.9     ! riastrad   42: __KERNEL_RCSID(0, "$NetBSD: drmfb.c,v 1.8 2020/06/27 13:41:44 jmcneill Exp $");
1.1       riastrad   43:
                     44: #ifdef _KERNEL_OPT
                     45: #include "vga.h"
                     46: #endif
                     47:
                     48: #include <sys/types.h>
                     49: #include <sys/param.h>
                     50: #include <sys/bus.h>
                     51: #include <sys/device.h>
                     52: #include <sys/kauth.h>
                     53:
                     54: #if NVGA > 0
                     55: /*
                     56:  * XXX All we really need is vga_is_console from vgavar.h, but the
                     57:  * header files are missing their own dependencies, so we need to
                     58:  * explicitly drag in the other crap.
                     59:  */
                     60: #include <dev/ic/mc6845reg.h>
                     61: #include <dev/ic/pcdisplayvar.h>
                     62: #include <dev/ic/vgareg.h>
                     63: #include <dev/ic/vgavar.h>
                     64: #endif
                     65:
                     66: #include <dev/wsfb/genfbvar.h>
                     67:
                     68: #include <drm/drmP.h>
                     69: #include <drm/drm_fb_helper.h>
                     70: #include <drm/drmfb.h>
                     71:
                     72: static int     drmfb_genfb_ioctl(void *, void *, unsigned long, void *, int,
                     73:                    struct lwp *);
                     74: static paddr_t drmfb_genfb_mmap(void *, void *, off_t, int);
                     75: static int     drmfb_genfb_enable_polling(void *);
                     76: static int     drmfb_genfb_disable_polling(void *);
                     77: static bool    drmfb_genfb_setmode(struct genfb_softc *, int);
                     78:
                     79: static const struct genfb_mode_callback drmfb_genfb_mode_callback = {
                     80:        .gmc_setmode = drmfb_genfb_setmode,
                     81: };
                     82:
                     83: int
                     84: drmfb_attach(struct drmfb_softc *sc, const struct drmfb_attach_args *da)
                     85: {
                     86:        const struct drm_fb_helper_surface_size *const sizes = da->da_fb_sizes;
1.9     ! riastrad   87:        struct drm_connector_list_iter conn_iter;
        !            88:        struct drm_connector *connector;
1.1       riastrad   89:        const prop_dictionary_t dict = device_properties(da->da_dev);
                     90: #if NVGA > 0
                     91:        struct drm_device *const dev = da->da_fb_helper->dev;
                     92: #endif
                     93:        static const struct genfb_ops zero_genfb_ops;
                     94:        struct genfb_ops genfb_ops = zero_genfb_ops;
                     95:        enum { CONS_VGA, CONS_GENFB, CONS_NONE } what_was_cons;
1.2       jmcneill   96:        bool is_console;
1.9     ! riastrad   97:        int error;
1.1       riastrad   98:
                     99:        /* genfb requires this.  */
                    100:        KASSERTMSG((void *)&sc->sc_genfb == device_private(da->da_dev),
                    101:            "drmfb_softc must be first member of device softc");
                    102:
                    103:        sc->sc_da = *da;
                    104:
                    105:        prop_dictionary_set_uint32(dict, "width", sizes->surface_width);
                    106:        prop_dictionary_set_uint32(dict, "height", sizes->surface_height);
                    107:        prop_dictionary_set_uint8(dict, "depth", sizes->surface_bpp);
1.3       maya      108:        prop_dictionary_set_uint16(dict, "linebytes", da->da_fb_linebytes);
1.1       riastrad  109:        prop_dictionary_set_uint32(dict, "address", 0); /* XXX >32-bit */
                    110:        CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
                    111:        prop_dictionary_set_uint64(dict, "virtual_address",
                    112:            (uint64_t)(uintptr_t)da->da_fb_vaddr);
                    113:
                    114:        prop_dictionary_set_uint64(dict, "mode_callback",
                    115:            (uint64_t)(uintptr_t)&drmfb_genfb_mode_callback);
                    116:
1.2       jmcneill  117:        if (!prop_dictionary_get_bool(dict, "is_console", &is_console)) {
                    118:                /* XXX Whattakludge!  */
1.1       riastrad  119: #if NVGA > 0
1.2       jmcneill  120:                if ((da->da_params->dp_is_vga_console != NULL) &&
                    121:                    (*da->da_params->dp_is_vga_console)(dev)) {
                    122:                        what_was_cons = CONS_VGA;
                    123:                        prop_dictionary_set_bool(dict, "is_console", true);
                    124:                        vga_cndetach();
                    125:                        if (da->da_params->dp_disable_vga)
                    126:                                (*da->da_params->dp_disable_vga)(dev);
                    127:                } else
1.1       riastrad  128: #endif
1.2       jmcneill  129:                if (genfb_is_console() && genfb_is_enabled()) {
                    130:                        what_was_cons = CONS_GENFB;
                    131:                        prop_dictionary_set_bool(dict, "is_console", true);
                    132:                } else {
                    133:                        what_was_cons = CONS_NONE;
                    134:                        prop_dictionary_set_bool(dict, "is_console", false);
                    135:                }
1.1       riastrad  136:        } else {
                    137:                what_was_cons = CONS_NONE;
                    138:        }
                    139:
1.5       jmcneill  140:        /* Make the first EDID we find available to wsfb */
1.9     ! riastrad  141:        drm_connector_list_iter_begin(da->da_fb_helper->dev, &conn_iter);
        !           142:        drm_client_for_each_connector_iter(connector, &conn_iter) {
1.5       jmcneill  143:                struct drm_property_blob *edid = connector->edid_blob_ptr;
1.7       jmcneill  144:                if (edid && edid->length) {
1.8       jmcneill  145:                        prop_dictionary_set_data(dict, "EDID", edid->data,
                    146:                            edid->length);
1.5       jmcneill  147:                        break;
                    148:                }
                    149:        }
1.9     ! riastrad  150:        drm_connector_list_iter_end(&conn_iter);
1.5       jmcneill  151:
1.1       riastrad  152:        sc->sc_genfb.sc_dev = sc->sc_da.da_dev;
                    153:        genfb_init(&sc->sc_genfb);
                    154:        genfb_ops.genfb_ioctl = drmfb_genfb_ioctl;
                    155:        genfb_ops.genfb_mmap = drmfb_genfb_mmap;
                    156:        genfb_ops.genfb_enable_polling = drmfb_genfb_enable_polling;
                    157:        genfb_ops.genfb_disable_polling = drmfb_genfb_disable_polling;
                    158:
                    159:        error = genfb_attach(&sc->sc_genfb, &genfb_ops);
                    160:        if (error) {
                    161:                aprint_error_dev(sc->sc_da.da_dev,
                    162:                    "failed to attach genfb: %d\n", error);
                    163:                goto fail0;
                    164:        }
                    165:
                    166:        /* Success!  */
                    167:        return 0;
                    168:
                    169: fail0: KASSERT(error);
                    170:        /* XXX Restore console...  */
                    171:        switch (what_was_cons) {
                    172:        case CONS_VGA:
                    173:                break;
                    174:        case CONS_GENFB:
                    175:                break;
                    176:        case CONS_NONE:
                    177:                break;
                    178:        default:
                    179:                break;
                    180:        }
                    181:        return error;
                    182: }
                    183:
                    184: int
                    185: drmfb_detach(struct drmfb_softc *sc, int flags)
                    186: {
                    187:
                    188:        /* XXX genfb detach?  */
                    189:        return 0;
                    190: }
                    191:
                    192: static int
                    193: drmfb_genfb_ioctl(void *v, void *vs, unsigned long cmd, void *data, int flag,
                    194:     struct lwp *l)
                    195: {
                    196:        struct genfb_softc *const genfb = v;
                    197:        struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
                    198:            sc_genfb);
1.9     ! riastrad  199:        struct drm_connector_list_iter conn_iter;
        !           200:        struct drm_connector *connector;
1.1       riastrad  201:        int error;
                    202:
                    203:        if (sc->sc_da.da_params->dp_ioctl) {
                    204:                error = (*sc->sc_da.da_params->dp_ioctl)(sc, cmd, data, flag,
                    205:                    l);
                    206:                if (error != EPASSTHROUGH)
                    207:                        return error;
                    208:        }
                    209:
                    210:        switch (cmd) {
                    211:        /*
                    212:         * Screen blanking ioctls.  Not to be confused with backlight
                    213:         * (can be disabled while stuff is still drawn on the screen),
                    214:         * brightness, or contrast (which we don't support).  Backlight
                    215:         * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM.
                    216:         * This toggles between DPMS ON and DPMS OFF; backlight toggles
                    217:         * between DPMS ON and DPMS SUSPEND.
                    218:         */
                    219:        case WSDISPLAYIO_GVIDEO: {
                    220:                int *onp = (int *)data;
                    221:
                    222:                /* XXX Can't really determine a single answer here.  */
                    223:                *onp = 1;
                    224:                return 0;
                    225:        }
                    226:        case WSDISPLAYIO_SVIDEO: {
                    227:                const int on = *(const int *)data;
                    228:                const int dpms_mode = on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
                    229:                struct drm_fb_helper *const fb_helper = sc->sc_da.da_fb_helper;
                    230:                struct drm_device *const dev = fb_helper->dev;
                    231:
                    232:                drm_modeset_lock_all(dev);
1.9     ! riastrad  233:                drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
        !           234:                drm_client_for_each_connector_iter(connector, &conn_iter) {
1.1       riastrad  235:                        (*connector->funcs->dpms)(connector, dpms_mode);
                    236:                        drm_object_property_set_value(&connector->base,
                    237:                            dev->mode_config.dpms_property, dpms_mode);
                    238:                }
1.9     ! riastrad  239:                drm_connector_list_iter_end(&conn_iter);
1.1       riastrad  240:                drm_modeset_unlock_all(dev);
                    241:
                    242:                return 0;
                    243:        }
                    244:        default:
                    245:                return EPASSTHROUGH;
                    246:        }
                    247: }
                    248:
                    249: static paddr_t
                    250: drmfb_genfb_mmap(void *v, void *vs, off_t offset, int prot)
                    251: {
                    252:        struct genfb_softc *const genfb = v;
                    253:        struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
                    254:            sc_genfb);
                    255:
                    256:        KASSERT(0 <= offset);
                    257:
                    258:        if (offset < genfb->sc_fbsize) {
                    259:                if (sc->sc_da.da_params->dp_mmapfb == NULL)
                    260:                        return -1;
                    261:                return (*sc->sc_da.da_params->dp_mmapfb)(sc, offset, prot);
                    262:        } else {
                    263:                if (kauth_authorize_machdep(kauth_cred_get(),
                    264:                        KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL)
                    265:                    != 0)
                    266:                        return -1;
                    267:                if (sc->sc_da.da_params->dp_mmap == NULL)
                    268:                        return -1;
                    269:                return (*sc->sc_da.da_params->dp_mmap)(sc, offset, prot);
                    270:        }
                    271: }
                    272:
                    273: static int
                    274: drmfb_genfb_enable_polling(void *cookie)
                    275: {
                    276:        struct genfb_softc *const genfb = cookie;
                    277:        struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
                    278:            sc_genfb);
                    279:
                    280:        return drm_fb_helper_debug_enter_fb(sc->sc_da.da_fb_helper);
                    281: }
                    282:
                    283: static int
                    284: drmfb_genfb_disable_polling(void *cookie)
                    285: {
                    286:        struct genfb_softc *const genfb = cookie;
                    287:        struct drmfb_softc *const sc = container_of(genfb, struct drmfb_softc,
                    288:            sc_genfb);
                    289:
                    290:        return drm_fb_helper_debug_leave_fb(sc->sc_da.da_fb_helper);
                    291: }
                    292:
                    293: static bool
                    294: drmfb_genfb_setmode(struct genfb_softc *genfb, int mode)
                    295: {
                    296:        struct drmfb_softc *sc = container_of(genfb, struct drmfb_softc,
                    297:            sc_genfb);
1.4       riastrad  298:        struct drm_fb_helper *fb_helper = sc->sc_da.da_fb_helper;
1.1       riastrad  299:
                    300:        if (mode == WSDISPLAYIO_MODE_EMUL)
1.4       riastrad  301:                drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
1.1       riastrad  302:
                    303:        return true;
                    304: }
                    305:
                    306: bool
                    307: drmfb_shutdown(struct drmfb_softc *sc, int flags __unused)
                    308: {
                    309:
                    310:        genfb_enable_polling(sc->sc_da.da_dev);
                    311:        return true;
                    312: }

CVSweb <webmaster@jp.NetBSD.org>