Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/rockchip WIP display driver for Rockchip RK3399



details:   https://anonhg.NetBSD.org/src/rev/99fb70acf132
branches:  trunk
changeset: 460911:99fb70acf132
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Nov 09 23:30:14 2019 +0000

description:
WIP display driver for Rockchip RK3399

diffstat:

 sys/arch/arm/rockchip/files.rockchip |   22 +-
 sys/arch/arm/rockchip/rk_drm.c       |  514 +++++++++++++++++++++++++++
 sys/arch/arm/rockchip/rk_drm.h       |   99 +++++
 sys/arch/arm/rockchip/rk_dwhdmi.c    |  293 +++++++++++++++
 sys/arch/arm/rockchip/rk_fb.c        |  160 ++++++++
 sys/arch/arm/rockchip/rk_vop.c       |  659 +++++++++++++++++++++++++++++++++++
 6 files changed, 1746 insertions(+), 1 deletions(-)

diffs (truncated from 1781 to 300 lines):

diff -r 54f73024a0d0 -r 99fb70acf132 sys/arch/arm/rockchip/files.rockchip
--- a/sys/arch/arm/rockchip/files.rockchip      Sat Nov 09 23:29:48 2019 +0000
+++ b/sys/arch/arm/rockchip/files.rockchip      Sat Nov 09 23:30:14 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.rockchip,v 1.20 2019/08/05 15:22:59 tnn Exp $
+#      $NetBSD: files.rockchip,v 1.21 2019/11/09 23:30:14 jmcneill Exp $
 #
 # Configuration info for Rockchip family SoCs
 #
@@ -83,6 +83,26 @@
 attach rkpwm at fdt with rk_pwm
 file   arch/arm/rockchip/rk_pwm.c              rk_pwm
 
+# DRM master
+define rkfbbus { }
+device rkdrm: drmkms, ddc_read_edid, rkfbbus
+attach rkdrm at fdt with rk_drm
+file   arch/arm/rockchip/rk_drm.c              rk_drm
+
+# DRM framebuffer console
+device rkfb: rkfbbus, drmfb, wsemuldisplaydev
+attach rkfb at rkfbbus with rk_fb
+file   arch/arm/rockchip/rk_fb.c               rk_fb
+
+# Visual Output Processor
+device rkvop: drmkms
+attach rkvop at fdt with rk_vop
+file   arch/arm/rockchip/rk_vop.c              rk_vop
+
+# HDMI TX (Designware based)
+attach dwhdmi at fdt with rk_dwhdmi
+file   arch/arm/rockchip/rk_dwhdmi.c           rk_dwhdmi
+
 # SOC parameters
 defflag        opt_soc.h                       SOC_ROCKCHIP
 defflag        opt_soc.h                       SOC_RK3328: SOC_ROCKCHIP
diff -r 54f73024a0d0 -r 99fb70acf132 sys/arch/arm/rockchip/rk_drm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/rockchip/rk_drm.c    Sat Nov 09 23:30:14 2019 +0000
@@ -0,0 +1,514 @@
+/* $NetBSD: rk_drm.c,v 1.1 2019/11/09 23:30:14 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rk_drm.c,v 1.1 2019/11/09 23:30:14 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.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 <dev/fdt/fdtvar.h>
+#include <dev/fdt/fdt_port.h>
+
+#include <arm/rockchip/rk_drm.h>
+
+#define        RK_DRM_MAX_WIDTH        3840
+#define        RK_DRM_MAX_HEIGHT       2160
+
+static TAILQ_HEAD(, rk_drm_ports) rk_drm_ports =
+    TAILQ_HEAD_INITIALIZER(rk_drm_ports);
+
+static const char * const compatible[] = {
+       "rockchip,display-subsystem",
+       NULL
+};
+
+static const char * fb_compatible[] = {
+       "simple-framebuffer",
+       NULL
+};
+
+static int     rk_drm_match(device_t, cfdata_t, void *);
+static void    rk_drm_attach(device_t, device_t, void *);
+
+static void    rk_drm_init(device_t);
+static vmem_t  *rk_drm_alloc_cma_pool(struct drm_device *, size_t);
+
+static int     rk_drm_set_busid(struct drm_device *, struct drm_master *);
+
+static uint32_t        rk_drm_get_vblank_counter(struct drm_device *, unsigned int);
+static int     rk_drm_enable_vblank(struct drm_device *, unsigned int);
+static void    rk_drm_disable_vblank(struct drm_device *, unsigned int);
+
+static int     rk_drm_load(struct drm_device *, unsigned long);
+static int     rk_drm_unload(struct drm_device *);
+
+static struct drm_driver rk_drm_driver = {
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+       .dev_priv_size = 0,
+       .load = rk_drm_load,
+       .unload = rk_drm_unload,
+
+       .gem_free_object = drm_gem_cma_free_object,
+       .mmap_object = drm_gem_or_legacy_mmap_object,
+       .gem_uvm_ops = &drm_gem_cma_uvm_ops,
+
+       .dumb_create = drm_gem_cma_dumb_create,
+       .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+       .dumb_destroy = drm_gem_dumb_destroy,
+
+       .get_vblank_counter = rk_drm_get_vblank_counter,
+       .enable_vblank = rk_drm_enable_vblank,
+       .disable_vblank = rk_drm_disable_vblank,
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+
+       .set_busid = rk_drm_set_busid,
+};
+
+CFATTACH_DECL_NEW(rk_drm, sizeof(struct rk_drm_softc),
+       rk_drm_match, rk_drm_attach, NULL, NULL);
+
+static int
+rk_drm_match(device_t parent, cfdata_t cf, void *aux)
+{
+       struct fdt_attach_args * const faa = aux;
+
+       return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+rk_drm_attach(device_t parent, device_t self, void *aux)
+{
+       struct rk_drm_softc * const sc = device_private(self);
+       struct fdt_attach_args * const faa = aux;
+       struct drm_driver * const driver = &rk_drm_driver;
+       prop_dictionary_t dict = device_properties(self);
+       bool is_disabled;
+
+       sc->sc_dev = self;
+       sc->sc_dmat = faa->faa_dmat;
+       sc->sc_bst = faa->faa_bst;
+       sc->sc_phandle = faa->faa_phandle;
+
+       drm_debug = 0xff;
+
+       aprint_naive("\n");
+
+       if (prop_dictionary_get_bool(dict, "disabled", &is_disabled) && is_disabled) {
+               aprint_normal(": (disabled)\n");
+               return;
+       }
+
+       aprint_normal("\n");
+
+       sc->sc_ddev = drm_dev_alloc(driver, sc->sc_dev);
+       if (sc->sc_ddev == NULL) {
+               aprint_error_dev(self, "couldn't allocate DRM device\n");
+               return;
+       }
+       sc->sc_ddev->dev_private = sc;
+       sc->sc_ddev->bst = sc->sc_bst;
+       sc->sc_ddev->bus_dmat = sc->sc_dmat;
+       sc->sc_ddev->dmat = sc->sc_ddev->bus_dmat;
+       sc->sc_ddev->dmat_subregion_p = false;
+
+       fdt_remove_bycompat(fb_compatible);
+
+       config_defer(self, rk_drm_init);
+}
+
+static void
+rk_drm_init(device_t dev)
+{
+       struct rk_drm_softc * const sc = device_private(dev);
+       struct drm_driver * const driver = &rk_drm_driver;
+       int error;
+
+       error = -drm_dev_register(sc->sc_ddev, 0);
+       if (error) {
+               drm_dev_unref(sc->sc_ddev);
+               aprint_error_dev(dev, "couldn't register DRM device: %d\n",
+                   error);
+               return;
+       }
+
+       aprint_normal_dev(dev, "initialized %s %d.%d.%d %s on minor %d\n",
+           driver->name, driver->major, driver->minor, driver->patchlevel,
+           driver->date, sc->sc_ddev->primary->index);
+}
+
+static vmem_t *
+rk_drm_alloc_cma_pool(struct drm_device *ddev, size_t cma_size)
+{
+       struct rk_drm_softc * const sc = rk_drm_private(ddev);
+       bus_dma_segment_t segs[1];
+       int nsegs;
+       int error;
+
+       error = bus_dmamem_alloc(sc->sc_dmat, cma_size, PAGE_SIZE, 0,
+           segs, 1, &nsegs, BUS_DMA_NOWAIT);
+       if (error) {
+               aprint_error_dev(sc->sc_dev, "couldn't allocate CMA pool\n");
+               return NULL;
+       }
+
+       return vmem_create("rkdrm", segs[0].ds_addr, segs[0].ds_len,
+           PAGE_SIZE, NULL, NULL, NULL, 0, VM_SLEEP, IPL_NONE);
+}
+
+static int
+rk_drm_set_busid(struct drm_device *ddev, struct drm_master *master)
+{
+       struct rk_drm_softc * const sc = rk_drm_private(ddev);
+       char id[32];
+
+       snprintf(id, sizeof(id), "platform:rk:%u", device_unit(sc->sc_dev));
+
+       master->unique = kzalloc(strlen(id) + 1, GFP_KERNEL);
+       if (master->unique == NULL)
+               return -ENOMEM;
+       strcpy(master->unique, id);
+       master->unique_len = strlen(master->unique);
+
+       return 0;
+}
+
+static int
+rk_drm_fb_create_handle(struct drm_framebuffer *fb,
+    struct drm_file *file, unsigned int *handle)
+{
+       struct rk_drm_framebuffer *sfb = to_rk_drm_framebuffer(fb);
+
+       return drm_gem_handle_create(file, &sfb->obj->base, handle);
+}
+
+static void
+rk_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+       struct rk_drm_framebuffer *sfb = to_rk_drm_framebuffer(fb);
+
+       drm_framebuffer_cleanup(fb);
+       drm_gem_object_unreference_unlocked(&sfb->obj->base);
+       kmem_free(sfb, sizeof(*sfb));
+}
+
+static const struct drm_framebuffer_funcs rk_drm_framebuffer_funcs = {
+       .create_handle = rk_drm_fb_create_handle,
+       .destroy = rk_drm_fb_destroy,
+};
+
+static struct drm_framebuffer *
+rk_drm_fb_create(struct drm_device *ddev, struct drm_file *file,
+    struct drm_mode_fb_cmd2 *cmd)
+{
+       struct rk_drm_framebuffer *fb;
+       struct drm_gem_object *gem_obj;
+       int error;
+
+       if (cmd->flags)
+               return NULL;
+
+       gem_obj = drm_gem_object_lookup(ddev, file, cmd->handles[0]);
+       if (gem_obj == NULL)
+               return NULL;
+
+       fb = kmem_zalloc(sizeof(*fb), KM_SLEEP);
+       fb->obj = to_drm_gem_cma_obj(gem_obj);



Home | Main Index | Thread Index | Old Index