Source-Changes-HG archive

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

[src/bouyer-sunxi-drm]: src/sys/arch/arm/sunxi Abandon sunxi_lcdc for the A20...



details:   https://anonhg.NetBSD.org/src/rev/a50bc363f7e8
branches:  bouyer-sunxi-drm
changeset: 371910:a50bc363f7e8
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Oct 16 17:08:46 2022 +0000

description:
Abandon sunxi_lcdc for the A20, there's too much pieces missing.
Convert sunxi_tcon to drm. Actually it's connected to DRM only when
in LVDS mode; for HDMI sunxi_hdmi does the interface.

diffstat:

 sys/arch/arm/sunxi/sunxi_lcdc.c |    6 +-
 sys/arch/arm/sunxi/sunxi_tcon.c |  145 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 142 insertions(+), 9 deletions(-)

diffs (238 lines):

diff -r 9e32b892725d -r a50bc363f7e8 sys/arch/arm/sunxi/sunxi_lcdc.c
--- a/sys/arch/arm/sunxi/sunxi_lcdc.c   Sun Oct 16 14:56:04 2022 +0000
+++ b/sys/arch/arm/sunxi/sunxi_lcdc.c   Sun Oct 16 17:08:46 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_lcdc.c,v 1.15.2.1 2022/10/02 10:37:12 bouyer Exp $ */
+/* $NetBSD: sunxi_lcdc.c,v 1.15.2.2 2022/10/16 17:08:46 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_lcdc.c,v 1.15.2.1 2022/10/02 10:37:12 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_lcdc.c,v 1.15.2.2 2022/10/16 17:08:46 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -112,8 +112,6 @@
        { .compat = "allwinner,sun8i-v3s-tcon",         .value = TYPE_TCON0 },
        { .compat = "allwinner,sun50i-a64-tcon-lcd",    .value = TYPE_TCON0 },
        { .compat = "allwinner,sun50i-a64-tcon-tv",     .value = TYPE_TCON1 },
-       { .compat = "allwinner,sun7i-a20-tcon0",        .value = TYPE_TCON0 },
-       { .compat = "allwinner,sun7i-a20-tcon1",        .value = TYPE_TCON1 },
        DEVICE_COMPAT_EOL
 };
 
diff -r 9e32b892725d -r a50bc363f7e8 sys/arch/arm/sunxi/sunxi_tcon.c
--- a/sys/arch/arm/sunxi/sunxi_tcon.c   Sun Oct 16 14:56:04 2022 +0000
+++ b/sys/arch/arm/sunxi/sunxi_tcon.c   Sun Oct 16 17:08:46 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_tcon.c,v 1.13 2021/08/20 20:25:27 andvar Exp $ */
+/* $NetBSD: sunxi_tcon.c,v 1.13.2.1 2022/10/16 17:08:46 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2018 Manuel Bouyer <bouyer%antioche.eu.org@localhost>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.13 2021/08/20 20:25:27 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.13.2.1 2022/10/16 17:08:46 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,11 +45,14 @@
 #include <dev/fdt/fdt_port.h>
 #include <dev/fdt/panel_fdt.h>
 
-#include <dev/videomode/videomode.h>
-
 #include <arm/sunxi/sunxi_tconreg.h>
 #include <arm/sunxi/sunxi_display.h>
 
+#include <drm/drm_bridge.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modes.h>
+
 #define DIVIDE(x,y)     (((x) + ((y) / 2)) / (y))
 
 enum sunxi_tcon_type {
@@ -75,6 +78,8 @@
        struct fdt_endpoint *sc_in_ep;
        struct fdt_endpoint *sc_in_rep;
        struct fdt_endpoint *sc_out_ep;
+       struct drm_encoder sc_encoder;
+       struct drm_connector sc_connector;
 };
 
 static bus_space_handle_t tcon_mux_bsh;
@@ -88,6 +93,70 @@
 static int  sunxi_tcon1_enable(struct sunxi_tcon_softc *, bool);
 void sunxi_tcon_dump_regs(int);
 
+#define encoder_to_tcon(x)             container_of(x, struct sunxi_tcon_softc, sc_encoder)
+#define connector_to_tcon(x)           container_of(x, struct sunxi_tcon_softc, sc_connector)
+
+static void
+sunxi_tcon_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs sunxi_tcon_enc_funcs = {
+       .destroy = sunxi_tcon_destroy,
+};
+
+static int sunxi_tcon_atomic_check(struct drm_encoder *,
+    struct drm_crtc_state *, struct drm_connector_state *);
+static void sunxi_tcon_disable(struct drm_encoder *);
+static void sunxi_tcon_enable(struct drm_encoder *);
+static void sunxi_tcon_mode_set(struct drm_encoder *,
+    struct drm_display_mode *, struct drm_display_mode *);
+static void sunxi_tcon_mode_valid(struct drm_encoder *,
+    struct drm_display_mode *);
+
+static void
+sunxi_tcon_encoder_disable(struct drm_encoder *encoder)
+{
+       int ret;
+       struct sunxi_tcon_softc *sc = encoder_to_tcon(encoder);
+       ret = sunxi_tcon0_enable(sc, false);
+       if (ret)
+               device_printf(sc->sc_dev, "failed to disable tcon0: %d\n", ret);
+}
+static void
+sunci_tcon_encoder_enable(struct drm_encoder *encoder)
+{
+       int ret;
+       struct sunxi_tcon_softc *sc = encoder_to_tcon(encoder);
+       ret = sunxi_tcon0_enable(sc, true);
+       if (ret)
+               device_printf(sc->sc_dev, "failed to enable tcon0: %d\n", ret);
+}
+
+static const struct drm_encoder_helper_funcs sunxi_tcon_enc_helper_funcs = {
+       .disable        = sunxi_tcon_disable,
+       .enable         = sunxi_tcon_enable,
+};
+
+static enum drm_connector_status sunxi_tcon_connector_detect(
+    struct drm_connector *, bool);
+
+static const struct drm_connector_funcs sunxi_tcon_connector_funcs = {
+       .fill_modes             = drm_helper_probe_single_connector_modes,
+       .destroy                = drm_connector_cleanup,
+       .reset                  = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
+};
+
+static int sunxi_tcon_get_modes(struct drm_connector *);
+
+static const struct drm_connector_helper_funcs sunxi_tcon_connector_helper_funcs
+ = {
+        .get_modes      = sunxi_tcon_get_modes,
+};
+
 #define TCON_READ(sc, reg) \
     bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
 #define TCON_WRITE(sc, reg, val) \
@@ -96,6 +165,8 @@
 static const struct device_compatible_entry compat_data[] = {
        { .compat = "allwinner,sun4i-a10-tcon", .value = TCON_A10},
        { .compat = "allwinner,sun7i-a20-tcon", .value = TCON_A10},
+       { .compat = "allwinner,sun7i-a20-tcon0", .value = TCON_A10 },
+       { .compat = "allwinner,sun7i-a20-tcon1", .value = TCON_A10 },
        DEVICE_COMPAT_EOL
 };
 
@@ -320,6 +391,29 @@
        }
 }
 
+static int 
+sunxi_tcon0_drm_register(struct sunxi_tcon_softc *sc)
+{
+       struct drm_crtc *crtc = sunxi_tcon_get_crtc(sc->sc_dev);
+       KASSERT(crtc != NULL);
+       int error;
+
+       sc->sc_encoder.possible_crtcs = 1 << drm_crtc_index(crtc);
+       drm_encoder_helper_add(&sc->sc_encoder, sunxi_tcon_enc_helper_funcs);
+       error = drm_encoder_init(crtc->dev, &sc->sc_encoder,
+           sunxi_tcon_enc_funcs, DRM_MODE_ENCODER_LVDS, NULL);
+       if (error)
+               return -error;
+       drm_connector_helper_add(&sc->sc_connector,
+           &sunxi_tcon_connector_helper_funcs);
+       error = drm_connector_init(crtc->dev, &sc->sc_connector,
+           DRM_MODE_CONNECTOR_LVDS);
+       if (error)
+               return -error;
+       drm_connector_attach_encoder(&sc->sc_connector, &sc->sc_encoder.base);
+       return sunxi_tcon0_set_video(sc);
+}
+
 static int
 sunxi_tcon_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate)
 {
@@ -376,7 +470,7 @@
                            device_xname(fdt_endpoint_device(rep)));
                        sc->sc_out_ep = out_ep;
                        if (outi == 0)
-                               return sunxi_tcon0_set_video(sc);
+                               return sunxi_tcon0_drm_register(sc);
                        /* XXX should check VGA here */
                        sc->sc_output_type = OUTPUT_HDMI;
                        return 0;
@@ -878,6 +972,47 @@
        return is_console;
 }
 
+struct drm_crtc *
+sunxi_tcon_get_crtc(device_t dev)
+{
+       struct sunxi_tcon_softc *sc = device_private(dev);
+       return sunxi_debe_get_crtc(fdt_endpoint_device(sc->sc_in_rep));
+}
+
+static int
+sunxi_tcon_get_modes(struct drm_connector * conn)
+{
+       struct drm_display_mode *mode;
+       const struct fdt_panel * panel;
+
+       panel = fdt_endpoint_get_data(fdt_endpoint_remote(sc->sc_out_ep));
+       KASSERT(panel != NULL);
+       KASSERT(panel->panel_type == PANEL_DUAL_LVDS ||
+           panel->panel_type == PANEL_LVDS);
+       sc->sc_output_type = OUTPUT_LVDS;
+
+       mode = drm_mode_create(connector->dev);
+       if (mode == NULL)
+               return ENOMEM;
+
+       mode->hdisplay = panel->panel_timing.hactive;
+       mode->hsync_start = mode->hdisplay + panel->panel_timing.hfront_porch;
+       mode->hsync_end = mode->hsync_start + panel->panel_timing.hsync_len;
+       mode->htotal = mode->hsync_end + panel->panel_timing.back_porch;
+       mode->vdisplay = panel->panel_timing.vactive;
+       mode->vsync_start = mode->vdisplay + panel->panel_timing.vfront_porch;
+       mode->vsync_end = mode->vsync_start + panel->panel_timing.vsync_len;
+       mode->vtotal = mode->vsync_end + panel->panel_timing.vback_porch;
+
+       mode->clock = panel->panel_timing.clock_freq / 1000;
+
+       /* XXX */
+       mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       drm_mode_set_name(mode);
+       return 0;
+}
+
 #if defined(DDB) || defined(SUNXI_TCON_DEBUG)
 void
 sunxi_tcon_dump_regs(int u)



Home | Main Index | Thread Index | Old Index