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 add Rockchip (RK3399) glue for Analogi...
details: https://anonhg.NetBSD.org/src/rev/a6a9beee4e42
branches: trunk
changeset: 1005740:a6a9beee4e42
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Thu Dec 19 00:25:58 2019 +0000
description:
add Rockchip (RK3399) glue for Analogix DisplayPort core
diffstat:
sys/arch/arm/rockchip/files.rockchip | 6 +-
sys/arch/arm/rockchip/rk_anxdp.c | 296 +++++++++++++++++++++++++++++++++++
2 files changed, 301 insertions(+), 1 deletions(-)
diffs (truncated from 320 to 300 lines):
diff -r 9ad69d92cbf8 -r a6a9beee4e42 sys/arch/arm/rockchip/files.rockchip
--- a/sys/arch/arm/rockchip/files.rockchip Thu Dec 19 00:23:57 2019 +0000
+++ b/sys/arch/arm/rockchip/files.rockchip Thu Dec 19 00:25:58 2019 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.rockchip,v 1.22 2019/11/16 13:24:03 jmcneill Exp $
+# $NetBSD: files.rockchip,v 1.23 2019/12/19 00:25:58 jakllsch Exp $
#
# Configuration info for Rockchip family SoCs
#
@@ -103,6 +103,10 @@
attach dwhdmi at fdt with rk_dwhdmi
file arch/arm/rockchip/rk_dwhdmi.c rk_dwhdmi
+# DP/eDP (Analogix-based)
+attach anxdp at fdt with rk_anxdp
+file arch/arm/rockchip/rk_anxdp.c rk_anxdp
+
# I2S/PCM controller
device rki2s
attach rki2s at fdt with rk_i2s
diff -r 9ad69d92cbf8 -r a6a9beee4e42 sys/arch/arm/rockchip/rk_anxdp.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/rockchip/rk_anxdp.c Thu Dec 19 00:25:58 2019 +0000
@@ -0,0 +1,296 @@
+/* $NetBSD: rk_anxdp.c,v 1.1 2019/12/19 00:25:59 jakllsch Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jonathan A. Kollasch <jakllsch%kollasch.net@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_anxdp.c,v 1.1 2019/12/19 00:25:59 jakllsch 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 <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+#include <dev/fdt/fdtvar.h>
+#include <dev/fdt/fdt_port.h>
+#include <dev/fdt/syscon.h>
+
+#include <dev/ic/anx_dp.h>
+
+#define RK3399_GRF_SOC_CON20 0x6250
+#define EDP_LCDC_SEL __BIT(5)
+
+enum {
+ ANXDP_PORT_INPUT = 0,
+ ANXDP_PORT_OUTPUT = 1,
+};
+
+static const char * const compatible[] = {
+ "rockchip,rk3399-edp",
+ NULL
+};
+
+struct rk_anxdp_softc {
+ struct anxdp_softc sc_base;
+ int sc_phandle;
+
+ struct fdt_device_ports sc_ports;
+ struct drm_encoder sc_encoder;
+ struct drm_display_mode sc_curmode;
+ struct syscon *sc_grf;
+
+ bool sc_activated;
+};
+
+#define to_rk_anxdp_softc(x) container_of(x, struct rk_anxdp_softc, sc_base)
+#define to_rk_anxdp_encoder(x) container_of(x, struct rk_anxdp_softc, sc_encoder)
+
+static void
+rk_anxdp_select_input(struct rk_anxdp_softc *sc, u_int crtc_index)
+{
+ const uint32_t write_mask = EDP_LCDC_SEL << 16;
+ const uint32_t write_val = crtc_index == 0 ? EDP_LCDC_SEL : 0;
+
+ syscon_lock(sc->sc_grf);
+ syscon_write_4(sc->sc_grf, RK3399_GRF_SOC_CON20, write_mask | write_val);
+ syscon_unlock(sc->sc_grf);
+}
+
+static bool
+rk_anxdp_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static void
+rk_anxdp_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode, struct drm_display_mode *adjusted)
+{
+}
+
+static void
+rk_anxdp_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+static void
+rk_anxdp_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void
+rk_anxdp_encoder_prepare(struct drm_encoder *encoder)
+{
+ struct rk_anxdp_softc * const sc = to_rk_anxdp_encoder(encoder);
+ const u_int crtc_index = drm_crtc_index(encoder->crtc);
+
+ rk_anxdp_select_input(sc, crtc_index);
+}
+
+static void
+rk_anxdp_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static const struct drm_encoder_funcs rk_anxdp_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_encoder_helper_funcs rk_anxdp_encoder_helper_funcs = {
+ .prepare = rk_anxdp_encoder_prepare,
+ .mode_fixup = rk_anxdp_encoder_mode_fixup,
+ .mode_set = rk_anxdp_encoder_mode_set,
+ .enable = rk_anxdp_encoder_enable,
+ .disable = rk_anxdp_encoder_disable,
+ .commit = rk_anxdp_encoder_commit,
+};
+
+static int
+rk_anxdp_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate)
+{
+ struct rk_anxdp_softc * const sc = device_private(dev);
+ struct fdt_endpoint *in_ep = fdt_endpoint_remote(ep);
+ struct fdt_endpoint *out_ep, *out_rep;
+ struct drm_crtc *crtc;
+ int error;
+
+ if (sc->sc_activated != false) {
+ return 0;
+ }
+
+ if (!activate)
+ return EINVAL;
+
+ if (fdt_endpoint_port_index(ep) != ANXDP_PORT_INPUT)
+ return EINVAL;
+
+ switch (fdt_endpoint_type(in_ep)) {
+ case EP_DRM_CRTC:
+ crtc = fdt_endpoint_get_data(in_ep);
+ break;
+ default:
+ return EINVAL;
+ break;
+ }
+
+ sc->sc_encoder.possible_crtcs = 0x3; /* XXX */
+ drm_encoder_init(crtc->dev, &sc->sc_encoder, &rk_anxdp_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(&sc->sc_encoder, &rk_anxdp_encoder_helper_funcs);
+
+ out_ep = fdt_endpoint_get_from_index(&sc->sc_ports, ANXDP_PORT_OUTPUT, 0);
+ if (out_ep != NULL) {
+ out_rep = fdt_endpoint_remote(out_ep);
+ if (out_rep != NULL && fdt_endpoint_type(out_rep) == EP_DRM_PANEL)
+ sc->sc_base.sc_panel = fdt_endpoint_get_data(out_rep);
+ }
+
+ sc->sc_base.sc_connector.base.connector_type = DRM_MODE_CONNECTOR_eDP;
+ error = anxdp_bind(&sc->sc_base, &sc->sc_encoder);
+ if (error != 0)
+ return error;
+ sc->sc_activated = true;
+
+ if (out_ep != NULL) {
+ /* Ignore downstream connectors, we have our own. */
+ if (out_rep != NULL && fdt_endpoint_type(out_rep) == EP_DRM_CONNECTOR)
+ return 0;
+ error = fdt_endpoint_activate(out_ep, activate);
+ if (error != 0)
+ return error;
+ }
+
+ return 0;
+}
+
+static void *
+rk_anxdp_ep_get_data(device_t dev, struct fdt_endpoint *ep)
+{
+ struct rk_anxdp_softc * const sc = device_private(dev);
+
+ return &sc->sc_encoder;
+}
+
+#if ANXDP_AUDIO
+static audio_dai_tag_t
+rk_anxdp_dai_get_tag(device_t dev, const void *data, size_t len)
+{
+ struct rk_anxdp_softc * const sc = device_private(dev);
+
+ if (len != 4)
+ return NULL;
+
+ return &sc->sc_base.sc_dai;
+}
+
+static struct fdtbus_dai_controller_func rk_anxdp_dai_funcs = {
+ .get_tag = rk_anxdp_dai_get_tag
+};
+#endif
+
+static int
+rk_anxdp_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_anxdp_attach(device_t parent, device_t self, void *aux)
+{
+ struct rk_anxdp_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t addr;
+ bus_size_t size;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ /* Required */
+ if (fdtbus_clock_enable(phandle, "pclk", true) != 0) {
+ aprint_error(": couldn't enable pclk clock\n");
+ return;
+ }
+
+ /* Required */
+ if (fdtbus_clock_enable(phandle, "dp", true) != 0) {
+ aprint_error(": couldn't enable dp clock\n");
+ return;
+ }
+
+ /* Optional */
+ if (fdtbus_clock_enable(phandle, "grf", false) != 0) {
+ aprint_error(": couldn't enable grf clock\n");
+ return;
+ }
+
+ /* TODO: Optional phy */
+
+ sc->sc_base.sc_dev = self;
+ sc->sc_base.sc_bst = faa->faa_bst;
+ if (bus_space_map(sc->sc_base.sc_bst, addr, size, 0, &sc->sc_base.sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+ sc->sc_phandle = faa->faa_phandle;
+ sc->sc_grf = fdtbus_syscon_acquire(phandle, "rockchip,grf");
+ if (sc->sc_grf == NULL) {
+ aprint_error(": couldn't get grf syscon\n");
+ return;
+ }
+
+ aprint_naive("\n");
Home |
Main Index |
Thread Index |
Old Index