From 415e399e115014b583101785db2dbf3d5ef8059d Mon Sep 17 00:00:00 2001 From: Patrick Wildt Date: Fri, 21 Feb 2020 15:44:55 +0000 Subject: Add rkdrm(4), a driver which combines all the separate components and lets drm(4) attach to it. Taken from NetBSD and adjusted to our layers. ok kettenis@ --- sys/dev/fdt/files.fdt | 7 +- sys/dev/fdt/rkdrm.c | 552 ++++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/fdt/rkdrm.h | 109 ++++++++++ 3 files changed, 667 insertions(+), 1 deletion(-) create mode 100644 sys/dev/fdt/rkdrm.c create mode 100644 sys/dev/fdt/rkdrm.h diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index c0c81c03807..2c35deae1eb 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,4 +1,4 @@ -# $OpenBSD: files.fdt,v 1.109 2020/01/26 06:20:30 patrick Exp $ +# $OpenBSD: files.fdt,v 1.110 2020/02/21 15:44:54 patrick Exp $ # # Config file and device description for machine-independent FDT code. # Included by ports that need it. @@ -228,6 +228,11 @@ device rkclock attach rkclock at fdt file dev/fdt/rkclock.c rkclock +device rkdrm: drmbase, wsemuldisplaydev, rasops15, rasops16, rasops24, rasops32 +attach rkdrm at fdt +file dev/fdt/rkdrm.c rkdrm +file dev/pci/drm/drm_gem_cma_helper.c rkdrm + device rkdwusb: fdt attach rkdwusb at fdt file dev/fdt/rkdwusb.c rkdwusb diff --git a/sys/dev/fdt/rkdrm.c b/sys/dev/fdt/rkdrm.c new file mode 100644 index 00000000000..ec8c1b1c678 --- /dev/null +++ b/sys/dev/fdt/rkdrm.c @@ -0,0 +1,552 @@ +/* $OpenBSD: rkdrm.c,v 1.1 2020/02/21 15:44:54 patrick Exp $ */ +/* $NetBSD: rk_drm.c,v 1.3 2019/12/15 01:00:58 mrg Exp $ */ +/*- + * Copyright (c) 2019 Jared D. McNeill + * Copyright (c) 2020 Patrick Wildt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define RK_DRM_MAX_WIDTH 3840 +#define RK_DRM_MAX_HEIGHT 2160 + +TAILQ_HEAD(, rkdrm_ports) rkdrm_ports = + TAILQ_HEAD_INITIALIZER(rkdrm_ports); + +int rkdrm_match(struct device *, void *, void *); +void rkdrm_attach(struct device *, struct device *, void *); +void rkdrm_attachhook(struct device *); + +#ifdef notyet +vmem_t *rkdrm_alloc_cma_pool(struct drm_device *, size_t); +#endif + +uint32_t rkdrm_get_vblank_counter(struct drm_device *, unsigned int); +int rkdrm_enable_vblank(struct drm_device *, unsigned int); +void rkdrm_disable_vblank(struct drm_device *, unsigned int); + +int rkdrm_load(struct drm_device *, unsigned long); +int rkdrm_unload(struct drm_device *); + +struct drm_driver rkdrm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, + + .get_vblank_counter = rkdrm_get_vblank_counter, + .enable_vblank = rkdrm_enable_vblank, + .disable_vblank = rkdrm_disable_vblank, + + .dumb_create = drm_gem_cma_dumb_create, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + + /* XXX GEM stuff */ + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +struct cfattach rkdrm_ca = { + sizeof (struct rkdrm_softc), rkdrm_match, rkdrm_attach +}; + +struct cfdriver rkdrm_cd = { + NULL, "rkdrm", DV_DULL +}; + +int +rkdrm_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "rockchip,display-subsystem"); +} + +void +rkdrm_attach(struct device *parent, struct device *self, void *aux) +{ + struct rkdrm_softc *sc = (struct rkdrm_softc *)self; + struct fdt_attach_args *faa = aux; + + sc->sc_dmat = faa->fa_dmat; + sc->sc_iot = faa->fa_iot; + sc->sc_node = faa->fa_node; + + printf("\n"); + + config_mountroot(self, rkdrm_attachhook); +} + +int +rkdrm_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file, unsigned int *handle) +{ + struct rkdrm_framebuffer *sfb = to_rkdrm_framebuffer(fb); + + return drm_gem_handle_create(file, &sfb->obj->base, handle); +} + +void +rkdrm_fb_destroy(struct drm_framebuffer *fb) +{ + struct rkdrm_framebuffer *sfb = to_rkdrm_framebuffer(fb); + + drm_framebuffer_cleanup(fb); + drm_gem_object_unreference_unlocked(&sfb->obj->base); + free(sfb, M_DRM, sizeof(*sfb)); +} + +struct drm_framebuffer_funcs rkdrm_framebuffer_funcs = { + .create_handle = rkdrm_fb_create_handle, + .destroy = rkdrm_fb_destroy, +}; + +struct drm_framebuffer * +rkdrm_fb_create(struct drm_device *ddev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *cmd) +{ + struct rkdrm_framebuffer *fb; + struct drm_gem_object *gem_obj; + int error; + + if (cmd->flags) + return NULL; + + gem_obj = drm_gem_object_lookup(file, cmd->handles[0]); + if (gem_obj == NULL) + return NULL; + + fb = malloc(sizeof(*fb), M_DRM, M_ZERO | M_WAITOK); + drm_helper_mode_fill_fb_struct(ddev, &fb->base, cmd); + fb->base.format = drm_format_info(DRM_FORMAT_ARGB8888); + fb->obj = to_drm_gem_cma_obj(gem_obj); + + error = drm_framebuffer_init(ddev, &fb->base, &rkdrm_framebuffer_funcs); + if (error != 0) + goto dealloc; + + return &fb->base; + +dealloc: + drm_framebuffer_cleanup(&fb->base); + free(fb, M_DRM, sizeof(*fb)); + drm_gem_object_unreference_unlocked(gem_obj); + + return NULL; +} + +struct drm_mode_config_funcs rkdrm_mode_config_funcs = { + .fb_create = rkdrm_fb_create, +}; + +int rkdrm_fb_probe(struct drm_fb_helper *, struct drm_fb_helper_surface_size *); + +struct drm_fb_helper_funcs rkdrm_fb_helper_funcs = { + .fb_probe = rkdrm_fb_probe, +}; + +uint32_t +rkdrm_get_vblank_counter(struct drm_device *ddev, unsigned int crtc) +{ + struct rkdrm_softc *sc = rkdrm_private(ddev); + + if (crtc >= nitems(sc->sc_vbl)) + return 0; + + if (sc->sc_vbl[crtc].get_vblank_counter == NULL) + return 0; + + return sc->sc_vbl[crtc].get_vblank_counter(sc->sc_vbl[crtc].priv); +} + +int +rkdrm_enable_vblank(struct drm_device *ddev, unsigned int crtc) +{ + struct rkdrm_softc *sc = rkdrm_private(ddev); + + if (crtc >= nitems(sc->sc_vbl)) + return 0; + + if (sc->sc_vbl[crtc].enable_vblank == NULL) + return 0; + + sc->sc_vbl[crtc].enable_vblank(sc->sc_vbl[crtc].priv); + + return 0; +} + +void +rkdrm_disable_vblank(struct drm_device *ddev, unsigned int crtc) +{ + struct rkdrm_softc *sc = rkdrm_private(ddev); + + if (crtc >= nitems(sc->sc_vbl)) + return; + + if (sc->sc_vbl[crtc].disable_vblank == NULL) + return; + + sc->sc_vbl[crtc].disable_vblank(sc->sc_vbl[crtc].priv); +} + +int +rkdrm_unload(struct drm_device *ddev) +{ + drm_mode_config_cleanup(ddev); + + return 0; +} + +void rkdrm_burner(void *, u_int, u_int); +int rkdrm_wsioctl(void *, u_long, caddr_t, int, struct proc *); +paddr_t rkdrm_wsmmap(void *, off_t, int); +int rkdrm_alloc_screen(void *, const struct wsscreen_descr *, + void **, int *, int *, long *); +void rkdrm_free_screen(void *, void *); +int rkdrm_show_screen(void *, void *, int, + void (*)(void *, int, int), void *); +void rkdrm_doswitch(void *); +void rkdrm_enter_ddb(void *, void *); +int rkdrm_get_param(struct wsdisplay_param *); +int rkdrm_set_param(struct wsdisplay_param *); + +struct wsscreen_descr rkdrm_stdscreen = { + "std", + 0, 0, + 0, + 0, 0, + WSSCREEN_UNDERLINE | WSSCREEN_HILIT | + WSSCREEN_REVERSE | WSSCREEN_WSCOLORS +}; + +const struct wsscreen_descr *rkdrm_scrlist[] = { + &rkdrm_stdscreen, +}; + +struct wsscreen_list rkdrm_screenlist = { + nitems(rkdrm_scrlist), rkdrm_scrlist +}; + +struct wsdisplay_accessops rkdrm_accessops = { + .ioctl = rkdrm_wsioctl, + .mmap = rkdrm_wsmmap, + .alloc_screen = rkdrm_alloc_screen, + .free_screen = rkdrm_free_screen, + .show_screen = rkdrm_show_screen, + .enter_ddb = rkdrm_enter_ddb, + .getchar = rasops_getchar, + .load_font = rasops_load_font, + .list_font = rasops_list_font, + .scrollback = rasops_scrollback, +#ifdef notyet + .burn_screen = rkdrm_burner +#endif +}; + +int +rkdrm_wsioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct rasops_info *ri = v; + struct rkdrm_softc *sc = ri->ri_hw; + struct wsdisplay_param *dp = (struct wsdisplay_param *)data; + struct wsdisplay_fbinfo *wdf; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_EFIFB; + return 0; + case WSDISPLAYIO_GINFO: + wdf = (struct wsdisplay_fbinfo *)data; + wdf->width = ri->ri_width; + wdf->height = ri->ri_height; + wdf->depth = ri->ri_depth; + wdf->cmsize = 0; + return 0; + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = ri->ri_stride; + return 0; + } + + return (-1); +} + +paddr_t +rkdrm_wsmmap(void *v, off_t off, int prot) +{ + struct rasops_info *ri = v; + struct rkdrm_softc *sc = ri->ri_hw; + struct drm_fb_helper *helper = &sc->helper; + struct rkdrm_framebuffer *sfb = to_rkdrm_framebuffer(helper->fb); + uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr; + size_t size = sfb->obj->dmamap->dm_segs[0].ds_len; + + if (off < 0 || off >= size) + return -1; + + return ((paddr + off) | PMAP_NOCACHE); +} + +int +rkdrm_alloc_screen(void *v, const struct wsscreen_descr *type, + void **cookiep, int *curxp, int *curyp, long *attrp) +{ + return rasops_alloc_screen(v, cookiep, curxp, curyp, attrp); +} + +void +rkdrm_free_screen(void *v, void *cookie) +{ + return rasops_free_screen(v, cookie); +} + +int +rkdrm_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + struct rasops_info *ri = v; + struct rkdrm_softc *sc = ri->ri_hw; + + if (cookie == ri->ri_active) + return (0); + + sc->switchcb = cb; + sc->switchcbarg = cbarg; + sc->switchcookie = cookie; + if (cb) { + task_add(systq, &sc->switchtask); + return (EAGAIN); + } + + rkdrm_doswitch(v); + + return (0); +} + +void +rkdrm_doswitch(void *v) +{ + struct rasops_info *ri = v; + struct rkdrm_softc *sc = ri->ri_hw; + struct rkdrm_crtc *rkdrm_crtc; + int i, crtc; + + rasops_show_screen(ri, sc->switchcookie, 0, NULL, NULL); + drm_fb_helper_restore_fbdev_mode_unlocked(&sc->helper); + + if (sc->switchcb) + (sc->switchcb)(sc->switchcbarg, 0, 0); +} + +void +rkdrm_enter_ddb(void *v, void *cookie) +{ + struct rasops_info *ri = v; + struct rkdrm_softc *sc = ri->ri_hw; + struct drm_fb_helper *fb_helper = &sc->helper; + + if (cookie == ri->ri_active) + return; + + rasops_show_screen(ri, cookie, 0, NULL, NULL); + drm_fb_helper_debug_enter(fb_helper->fbdev); +} + +void +rkdrm_attachhook(struct device *dev) +{ + struct rkdrm_softc *sc = (struct rkdrm_softc *)dev; + struct wsemuldisplaydev_attach_args aa; + struct drm_fb_helper *helper = &sc->helper; + struct rasops_info *ri = &sc->ro; + struct rkdrm_framebuffer *sfb; + struct drm_device *ddev; + uint32_t *ports; + int i, portslen, nports; + + portslen = OF_getproplen(sc->sc_node, "ports"); + if (portslen < 0) { + printf("%s: no display interface ports specified\n", + sc->sc_dev.dv_xname); + return; + } + + sc->sc_ddev.driver = &rkdrm_driver; + sc->sc_ddev.dev_private = sc; + sc->sc_ddev.bst = sc->sc_iot; + sc->sc_ddev.dmat = sc->sc_dmat; + + drm_mode_config_init(&sc->sc_ddev); + sc->sc_ddev.mode_config.min_width = 0; + sc->sc_ddev.mode_config.min_height = 0; + sc->sc_ddev.mode_config.max_width = RK_DRM_MAX_WIDTH; + sc->sc_ddev.mode_config.max_height = RK_DRM_MAX_HEIGHT; + sc->sc_ddev.mode_config.funcs = &rkdrm_mode_config_funcs; + + nports = 0; + ports = malloc(portslen, M_TEMP, M_WAITOK); + OF_getpropintarray(sc->sc_node, "ports", ports, portslen); + for (i = 0; i < portslen / sizeof(uint32_t); i++) { + video_port_activate(ports[i], &sc->sc_ddev); + nports++; + } + free(ports, M_TEMP, portslen); + + if (nports == 0) { + printf("%s: no display interface ports configured\n", + sc->sc_dev.dv_xname); + drm_mode_config_cleanup(&sc->sc_ddev); + return; + } + + drm_fb_helper_prepare(&sc->sc_ddev, &sc->helper, &rkdrm_fb_helper_funcs); + if (drm_fb_helper_init(&sc->sc_ddev, &sc->helper, 1)) { + printf("%s: can't initialize framebuffer helper\n", + sc->sc_dev.dv_xname); + drm_mode_config_cleanup(&sc->sc_ddev); + return; + } + + sc->helper.fb = malloc(sizeof(struct rkdrm_framebuffer), + M_DRM, M_WAITOK | M_ZERO); + + drm_fb_helper_single_add_all_connectors(&sc->helper); + drm_helper_disable_unused_functions(&sc->sc_ddev); + drm_fb_helper_initial_config(&sc->helper, 32); + + /* XXX */ + sc->sc_ddev.irq_enabled = true; + drm_vblank_init(&sc->sc_ddev, 1); + + task_set(&sc->switchtask, rkdrm_doswitch, ri); + + drm_fb_helper_restore_fbdev_mode_unlocked(&sc->helper); + + sfb = to_rkdrm_framebuffer(helper->fb); + ri->ri_bits = sfb->obj->vaddr; + ri->ri_flg = RI_CENTER | RI_VCONS; + ri->ri_depth = helper->fb->format->depth; + ri->ri_width = helper->fb->width; + ri->ri_height = helper->fb->height; + ri->ri_stride = ri->ri_width * ri->ri_depth / 8; + rasops_init(ri, helper->fb->height, helper->fb->width); + ri->ri_hw = sc; + + rkdrm_stdscreen.capabilities = ri->ri_caps; + rkdrm_stdscreen.nrows = ri->ri_rows; + rkdrm_stdscreen.ncols = ri->ri_cols; + rkdrm_stdscreen.textops = &ri->ri_ops; + rkdrm_stdscreen.fontwidth = ri->ri_font->fontwidth; + rkdrm_stdscreen.fontheight = ri->ri_font->fontheight; + + memset(&aa, 0, sizeof(aa)); + aa.scrdata = &rkdrm_screenlist; + aa.accessops = &rkdrm_accessops; + aa.accesscookie = ri; + + printf("%s: %dx%d, %dbpp\n", sc->sc_dev.dv_xname, + ri->ri_width, ri->ri_height, ri->ri_depth); + + config_found_sm(&sc->sc_dev, &aa, wsemuldisplaydevprint, + wsemuldisplaydevsubmatch); + +#ifdef notyet + drm_dev_register(&sc->sc_ddev, 0); +#endif +} + +int +rkdrm_fb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) +{ + struct rkdrm_softc *sc = rkdrm_private(helper->dev); + struct drm_device *ddev = helper->dev; + struct rkdrm_framebuffer *sfb = to_rkdrm_framebuffer(helper->fb); + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct drm_framebuffer *fb = helper->fb; + struct wsemuldisplaydev_attach_args aa; + struct rasops_info *ri = &sc->ro; + struct rkdrmfb_attach_args sfa; + unsigned int bytes_per_pixel; + struct fb_info *info; + size_t size; + int error; + + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = roundup(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE); + + /* FIXME: CMA pool? */ + + sfb->obj = drm_gem_cma_create(ddev, size); + if (sfb->obj == NULL) { + DRM_ERROR("failed to allocate memory for framebuffer\n"); + return -ENOMEM; + } + + drm_helper_mode_fill_fb_struct(ddev, fb, &mode_cmd); + fb->format = drm_format_info(DRM_FORMAT_ARGB8888); + error = drm_framebuffer_init(ddev, fb, &rkdrm_framebuffer_funcs); + if (error != 0) { + DRM_ERROR("failed to initialize framebuffer\n"); + return error; + } + + info = drm_fb_helper_alloc_fbi(helper); + if (IS_ERR(info)) { + DRM_ERROR("Failed to allocate fb_info\n"); + return error; + } + info->par = helper; + return 0; +} diff --git a/sys/dev/fdt/rkdrm.h b/sys/dev/fdt/rkdrm.h new file mode 100644 index 00000000000..a84216b5013 --- /dev/null +++ b/sys/dev/fdt/rkdrm.h @@ -0,0 +1,109 @@ +/* $OpenBSD: rkdrm.h,v 1.1 2020/02/21 15:44:54 patrick Exp $ */ +/* $NetBSD: rk_drm.h,v 1.1 2019/11/09 23:30:14 jmcneill Exp $ */ +/*- + * Copyright (c) 2019 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARM_RK_DRM_H +#define _ARM_RK_DRM_H + +#include +#include +#include + +#include +#include + +#define DRIVER_AUTHOR "Jared McNeill" + +#define DRIVER_NAME "rk" +#define DRIVER_DESC "Rockchip Display Subsystem" +#define DRIVER_DATE "20191109" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +struct rk_framebuffer; + +#define RK_DRM_MAX_CRTC 2 + +struct rkdrm_vblank { + void *priv; + void (*enable_vblank)(void *); + void (*disable_vblank)(void *); + uint32_t (*get_vblank_counter)(void *); +}; + +struct rkdrm_softc { + struct device sc_dev; + struct drm_device sc_ddev; + + bus_space_tag_t sc_iot; + bus_dma_tag_t sc_dmat; + + int sc_node; + + struct rkdrm_vblank sc_vbl[RK_DRM_MAX_CRTC]; + + void (*switchcb)(void *, int, int); + void *switchcbarg; + void *switchcookie; + struct task switchtask; + struct rasops_info ro; + int console; + int primary; + + struct drm_fb_helper helper; +}; + +struct rkdrm_framebuffer { + struct drm_framebuffer base; + struct drm_gem_cma_object *obj; +}; + +struct rkdrm_ports { + int phandle; + struct drm_device *ddev; + TAILQ_ENTRY(rkdrm_ports) entries; +}; + +struct rkdrm_fbdev { + struct drm_fb_helper helper; +}; + +struct rkdrmfb_attach_args { + struct drm_device *sfa_drm_dev; + struct drm_fb_helper *sfa_fb_helper; + struct drm_fb_helper_surface_size sfa_fb_sizes; + bus_space_tag_t sfa_fb_iot; + bus_dma_tag_t sfa_fb_dmat; + uint32_t sfa_fb_linebytes; +}; + +#define rkdrm_private(ddev) (ddev)->dev_private +#define to_rkdrm_framebuffer(x) container_of(x, struct rkdrm_framebuffer, base) + +#endif /* _ARM_RK_DRM_H */ -- cgit v1.2.3