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 Work in progress: convert sunx...



details:   https://anonhg.NetBSD.org/src/rev/9e32b892725d
branches:  bouyer-sunxi-drm
changeset: 371903:9e32b892725d
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Oct 16 14:56:04 2022 +0000

description:
Work in progress: convert sunxi_hdmi to drm

diffstat:

 sys/arch/arm/sunxi/sunxi_hdmi.c    |  667 ++++++++++++++++++++++++------------
 sys/arch/arm/sunxi/sunxi_hdmireg.h |    7 +-
 2 files changed, 448 insertions(+), 226 deletions(-)

diffs (truncated from 942 to 300 lines):

diff -r 46147024a685 -r 9e32b892725d sys/arch/arm/sunxi/sunxi_hdmi.c
--- a/sys/arch/arm/sunxi/sunxi_hdmi.c   Sun Oct 02 10:40:40 2022 +0000
+++ b/sys/arch/arm/sunxi/sunxi_hdmi.c   Sun Oct 16 14:56:04 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_hdmi.c,v 1.14.16.1 2022/10/02 10:37:12 bouyer Exp $ */
+/* $NetBSD: sunxi_hdmi.c,v 1.14.16.2 2022/10/16 14:56:04 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_ddb.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.14.16.1 2022/10/02 10:37:12 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.14.16.2 2022/10/16 14:56:04 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -52,6 +52,8 @@
 #include <arm/sunxi/sunxi_hdmireg.h>
 #include <arm/sunxi/sunxi_display.h>
 
+#include <arm/sunxi/sunxi_drm.h>
+
 #include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_drv.h>
@@ -62,6 +64,14 @@
        HDMI_A31,
 };
 
+struct sunxi_hdmi_softc;
+
+struct sunxi_hdmi_encoder {
+       struct drm_encoder      base;
+       struct sunxi_hdmi_softc *sc;
+       struct drm_display_mode curmode;
+};
+
 struct sunxi_hdmi_softc {
        device_t sc_dev;
        int sc_phandle;
@@ -75,16 +85,22 @@
        void *sc_ih;
        lwp_t *sc_thread;
 
-       struct i2c_controller sc_ic;
+       struct sunxi_hdmi_encoder sc_encoder;
+       struct drm_connector sc_connector;
+       struct i2c_adapter sc_i2c_adapt;
+
+       enum sc_display_mode {
+               DISPLAY_MODE_NONE = 0,
+               DISPLAY_MODE_DVI,
+               DISPLAY_MODE_HDMI
+       } sc_display_mode;
+
        kmutex_t sc_exec_lock;
 
-       bool sc_display_connected;
-
        kmutex_t sc_pwr_lock;
        int     sc_pwr_refcount; /* reference who needs HDMI */
 
        uint32_t sc_ver;
-       unsigned int sc_i2c_blklen;
 
        struct fdt_device_ports sc_ports;
        struct fdt_endpoint *sc_in_ep;
@@ -93,6 +109,56 @@
        struct drm_display_mode sc_curmode;
 };
 
+#define to_sunxi_hdmi_encoder(x)       container_of(x, struct sunxi_hdmi_encoder, base)
+
+#define connector_to_hdmi(x)           container_of(x, struct sunxi_hdmi_softc, sc_connector)
+
+static void
+sunxi_hdmi_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs sunxi_hdmi_enc_funcs = {
+       .destroy = sunxi_hdmi_destroy,
+};
+
+static int sunxi_hdmi_atomic_check(struct drm_encoder *,
+    struct drm_crtc_state *, struct drm_connector_state *);
+static void sunxi_hdmi_disable(struct drm_encoder *);
+static void sunxi_hdmi_enable(struct drm_encoder *);
+static void sunxi_hdmi_mode_set(struct drm_encoder *,
+    struct drm_display_mode *, struct drm_display_mode *);
+static void sunxi_hdmi_mode_valid(struct drm_encoder *,
+    struct drm_display_mode *);
+
+static const struct drm_encoder_helper_funcs sunxi_hdmi_enc_helper_funcs = {
+       .atomic_check   = sunxi_hdmi_atomic_check,
+       .disable        = sunxi_hdmi_disable,
+       .enable         = sunxi_hdmi_enable,
+       .mode_set       = sunxi_hdmi_mode_set,
+       .mode_valid     = sunxi_hdmi_mode_valid,
+};
+
+static enum drm_connector_status sunxi_hdmi_connector_detect(
+    struct drm_connector *, bool);
+
+static const struct drm_connector_funcs sunxi_hdmi_connector_funcs = {
+       .detect                 = sunxi_hdmi_connector_detect,
+       .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_hdmi_get_modes(struct drm_connector *);
+
+static const struct drm_connector_helper_funcs sunxi_hdmi_connector_helper_funcs
+ = {
+        .get_modes      = sunxi_hdmi_get_modes,
+};
+
 #define HDMI_READ(sc, reg)                     \
     bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
 #define HDMI_WRITE(sc, reg, val)               \
@@ -110,11 +176,11 @@
 static int     sunxi_hdmi_match(device_t, cfdata_t, void *);
 static void    sunxi_hdmi_attach(device_t, device_t, void *);
 static void    sunxi_hdmi_i2c_init(struct sunxi_hdmi_softc *);
-static int     sunxi_hdmi_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
-                                  size_t, void *, size_t, int);
-static int     sunxi_hdmi_i2c_xfer(void *, i2c_addr_t, uint8_t, uint8_t,
-                                  size_t, int, int);
-static int     sunxi_hdmi_i2c_reset(struct sunxi_hdmi_softc *, int);
+static int     sunxi_hdmi_i2c_drm_xfer(struct i2c_adapter *,
+                                  struct i2c_msg *, int);
+static int     sunxi_hdmi_i2c_xfer(struct sunxi_hdmi_softc *,
+                                       struct i2c_msg *);
+static int     sunxi_hdmi_i2c_reset(struct sunxi_hdmi_softc *);
 
 static int     sunxi_hdmi_ep_activate(device_t, struct fdt_endpoint *, bool);
 static int     sunxi_hdmi_ep_enable(device_t, struct fdt_endpoint *, bool);
@@ -127,11 +193,10 @@
                                           const struct edid_info *);
 #endif
 static void    sunxi_hdmi_video_enable(struct sunxi_hdmi_softc *, bool);
+static void    sunxi_hdmi_set_audiomode(struct sunxi_hdmi_softc *, int);
 #if 0
 static void    sunxi_hdmi_set_videomode(struct sunxi_hdmi_softc *,
                                        const struct videomode *, u_int);
-static void    sunxi_hdmi_set_audiomode(struct sunxi_hdmi_softc *,
-                                       const struct videomode *, u_int);
 static void    sunxi_hdmi_hpd(struct sunxi_hdmi_softc *);
 static void    sunxi_hdmi_thread(void *);
 #endif
@@ -168,6 +233,7 @@
        sc->sc_dev = self;
        sc->sc_phandle = phandle;
        sc->sc_bst = faa->faa_bst;
+       sc->sc_encoder.sc = sc;
 
        sc->sc_type =
            of_compatible_lookup(faa->faa_phandle, compat_data)->value;
@@ -209,7 +275,6 @@
        aprint_normal(": HDMI %d.%d\n", vmaj, vmin);
 
        sc->sc_ver = ver;
-       sc->sc_i2c_blklen = 16;
 
        sc->sc_ports.dp_ep_activate = sunxi_hdmi_ep_activate;
        sc->sc_ports.dp_ep_enable = sunxi_hdmi_ep_enable;
@@ -257,71 +322,83 @@
        }
 }
 
+static int
+sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
+    struct drm_crtc_state * crtc_state,
+    struct drm_connector_state *conn_state)
+{
+       if (crtc_state->mode.flags & DRM_MODE_FLAG_DBLCLK)
+               return -EINVAL;
+       return 0;
+}
+
+static void
+sunxi_hdmi_disable(struct drm_encoder *enc)
+{
+       struct sunxi_hdmi_encoder *hdmi_encoder = to_sunxi_hdmi_encoder(enc);
+       struct sunxi_hdmi_softc *sc = hdmi_encoder->sc;
+       sunxi_hdmi_video_enable(sc, false);
+}
+
+static void
+sunxi_hdmi_enable(struct drm_encoder *enc)
+{
+       struct sunxi_hdmi_encoder *hdmi_encoder = to_sunxi_hdmi_encoder(enc);
+       struct sunxi_hdmi_softc *sc = hdmi_encoder->sc;
+       struct drm_display_mode *mode = &enc->crtc->state->adjusted_mode;
+       sunxi_hdmi_video_enable(sc, true);
+}
+
+static uint32_t sunxi_hdmi_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm sunxi_hdmi_i2c_algorithm = {
+        .master_xfer    = sunxi_hdmi_i2c_drm_xfer,
+       .functionality  = sunxi_hdmi_i2c_func, 
+};      
+
 static void
 sunxi_hdmi_i2c_init(struct sunxi_hdmi_softc *sc)
 {
-       struct i2c_controller *ic = &sc->sc_ic;
-
        mutex_init(&sc->sc_exec_lock, MUTEX_DEFAULT, IPL_NONE);
 
-       iic_tag_init(ic);
-       ic->ic_cookie = sc;
-       ic->ic_exec = sunxi_hdmi_i2c_exec;
+       sc->sc_i2c_adapt.owner = THIS_MODULE;
+       sc->sc_i2c_adapt.class = I2C_CLASS_DDC;
+       sc->sc_i2c_adapt.algo = &sunxi_hdmi_i2c_algorithm;
+       strlcpy(sc->sc_i2c_adapt.name, "sunxi_hdmi_i2c",
+           sizeof(sc->sc_i2c_adapt.name));
 }
 
 static int
-sunxi_hdmi_i2c_exec(void *priv, i2c_op_t op, i2c_addr_t addr,
-    const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
-{
-       struct sunxi_hdmi_softc *sc = priv;
-       uint8_t *pbuf;
-       uint8_t block;
-       int resid;
-       off_t off;
-       int err;
+sunxi_hdmi_i2c_drm_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num){
+       struct sunxi_hdmi_softc *sc = i2c_get_adapdata(adap);
+       int i, err;
 
        mutex_enter(&sc->sc_exec_lock);
 
-       KASSERT(op == I2C_OP_READ_WITH_STOP);
-       KASSERT(addr == DDC_ADDR);
-       KASSERT(cmdlen > 0);
-       KASSERT(buf != NULL);
+       for (i = 0; i < num; i++) {
+               if (msg[i].len == 0 ||
+                   msg[i].len > SUNXI_HDMI_DDC_BYTE_COUNTER) 
+                       return -EINVAL;
+       }
 
-       err = sunxi_hdmi_i2c_reset(sc, flags);
+       err = sunxi_hdmi_i2c_reset(sc);
        if (err)
                goto done;
 
-       block = *(const uint8_t *)cmdbuf;
-       off = (block & 1) ? 128 : 0;
-
-       pbuf = buf;
-       resid = len;
-       while (resid > 0) {
-               size_t blklen = uimin(resid, sc->sc_i2c_blklen);
-
-               err = sunxi_hdmi_i2c_xfer(sc, addr, block >> 1, off, blklen,
-                     SUNXI_HDMI_DDC_COMMAND_ACCESS_CMD_EOREAD, flags);
+       for (i = 0; i < num; i++) {
+               err = sunxi_hdmi_i2c_xfer(sc, &msg[i]);
                if (err)
-                       goto done;
-
-               if (HDMI_1_3_P(sc)) {
-                       bus_space_read_multi_1(sc->sc_bst, sc->sc_bsh,
-                           SUNXI_HDMI_DDC_FIFO_ACCESS_REG, pbuf, blklen);
-               } else {
-                       bus_space_read_multi_1(sc->sc_bst, sc->sc_bsh,
-                           SUNXI_A31_HDMI_DDC_FIFO_ACCESS_REG, pbuf, blklen);
-               }
-
+                       break;
 #ifdef SUNXI_HDMI_DEBUG
-               printf("off=%d:", (int)off);
-               for (int i = 0; i < blklen; i++)
-                       printf(" %02x", pbuf[i]);
+               printf("msg %d:", i);
+               for (int j = 0; j < msg[i].len; j++)
+                       printf(" %02x", msg[i].buf[j]);
                printf("\n");
 #endif
-
-               pbuf += blklen;
-               off += blklen;
-               resid -= blklen;
        }



Home | Main Index | Thread Index | Old Index