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