summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-02-21 15:44:55 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-02-21 15:44:55 +0000
commit415e399e115014b583101785db2dbf3d5ef8059d (patch)
tree7f4ee6c046b9a37631e7334d57756210447be346
parent4a7a957f092524a8350887d5faa71d4b73933cda (diff)
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@
-rw-r--r--sys/dev/fdt/files.fdt7
-rw-r--r--sys/dev/fdt/rkdrm.c552
-rw-r--r--sys/dev/fdt/rkdrm.h109
3 files changed, 667 insertions, 1 deletions
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 <jmcneill@invisible.ca>
+ * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se>
+ * 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 <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_gpio.h>
+#include <dev/ofw/ofw_misc.h>
+#include <dev/ofw/fdt.h>
+
+#include <uvm/uvm_extern.h>
+#include <uvm/uvm_object.h>
+#include <uvm/uvm_device.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+
+#include <dev/fdt/rkdrm.h>
+
+#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 <jmcneill@invisible.ca>
+ * 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 <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#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 */