Module Name:    src
Committed By:   jmcneill
Date:           Mon Nov  4 10:02:39 UTC 2019

Modified Files:
        src/sys/dev/i2c: tda19988.c

Log Message:
Speed up mode setting a bit and turn off the display while changing modes


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/i2c/tda19988.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/tda19988.c
diff -u src/sys/dev/i2c/tda19988.c:1.2 src/sys/dev/i2c/tda19988.c:1.3
--- src/sys/dev/i2c/tda19988.c:1.2	Sun Nov  3 23:28:59 2019
+++ src/sys/dev/i2c/tda19988.c	Mon Nov  4 10:02:39 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: tda19988.c,v 1.2 2019/11/03 23:28:59 jmcneill Exp $ */
+/* $NetBSD: tda19988.c,v 1.3 2019/11/04 10:02:39 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Oleksandr Tymoshenko <go...@freebsd.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tda19988.c,v 1.2 2019/11/03 23:28:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tda19988.c,v 1.3 2019/11/04 10:02:39 jmcneill Exp $");
 
 /*
 * NXP TDA19988 HDMI encoder 
@@ -257,6 +257,7 @@ struct tda19988_connector {
 
 struct tda19988_softc {
 	device_t		sc_dev;
+	int			sc_phandle;
 	i2c_tag_t		sc_i2c;
 	i2c_addr_t		sc_addr;
 	uint32_t		sc_cec_addr;
@@ -264,12 +265,14 @@ struct tda19988_softc {
 	int			sc_current_page;
 	uint8_t			*sc_edid;
 	uint32_t		sc_edid_len;
+	bool			sc_edid_valid;
 
 	struct drm_bridge	sc_bridge;
 	struct tda19988_connector sc_connector;
 
 	struct fdt_device_ports	sc_ports;
-	struct drm_display_mode	sc_curmode;
+
+	enum drm_connector_status sc_last_status;
 };
 
 #define	to_tda_connector(x)	container_of(x, struct tda19988_connector, base)
@@ -280,7 +283,8 @@ tda19988_set_page(struct tda19988_softc 
 	uint8_t buf[2] = { TDA_CURPAGE_ADDR, page };
 	int result;
 
-	result = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, buf, 2, NULL, 0, I2C_F_POLL);
+	result = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, buf, 2, NULL, 0,
+	    cold ? I2C_F_POLL : 0);
 	if (result == 0)
 		sc->sc_current_page = page;
 
@@ -290,7 +294,8 @@ tda19988_set_page(struct tda19988_softc 
 static int
 tda19988_cec_read(struct tda19988_softc *sc, uint8_t addr, uint8_t *data)
 {
-	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_cec_addr, &addr, 1, data, 1, I2C_F_POLL);
+	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_cec_addr, &addr, 1, data, 1,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static int 
@@ -298,7 +303,8 @@ tda19988_cec_write(struct tda19988_softc
 {
 	uint8_t buf[2] = { addr, data };
 
-	return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_cec_addr, buf, 2, NULL, 0, I2C_F_POLL);
+	return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_cec_addr, buf, 2, NULL, 0,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static int
@@ -311,19 +317,8 @@ tda19988_block_read(struct tda19988_soft
 	if (sc->sc_current_page != REGPAGE(addr))
 		tda19988_set_page(sc, REGPAGE(addr));
 
-#if notyet
-	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, data, len, I2C_F_POLL);
-#else
-	int error, i;
-	for (i = 0; i < len; i++) {
-		error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, &data[i], 1, I2C_F_POLL);
-		if (error != 0)
-			return error;
-		reg++;
-	}
-
-	return 0;
-#endif
+	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, data, len,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static int
@@ -336,7 +331,8 @@ tda19988_reg_read(struct tda19988_softc 
 	if (sc->sc_current_page != REGPAGE(addr))
 		tda19988_set_page(sc, REGPAGE(addr));
 
-	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, data, 1, I2C_F_POLL);
+	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, data, 1,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static int
@@ -347,7 +343,8 @@ tda19988_reg_write(struct tda19988_softc
 	if (sc->sc_current_page != REGPAGE(addr))
 		tda19988_set_page(sc, REGPAGE(addr));
 
-	return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, buf, 2, NULL, 0, I2C_F_POLL);
+	return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, buf, 2, NULL, 0,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static int
@@ -362,7 +359,8 @@ tda19988_reg_write2(struct tda19988_soft
 	if (sc->sc_current_page != REGPAGE(address))
 		tda19988_set_page(sc, REGPAGE(address));
 
-	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, buf, 3, NULL, 0, I2C_F_POLL);
+	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, buf, 3, NULL, 0,
+	    cold ? I2C_F_POLL : 0);
 }
 
 static void
@@ -686,13 +684,6 @@ tda19988_start(struct tda19988_softc *sc
     	tda19988_cec_write(sc, TDA_CEC_FRO_IM_CLK_CTRL,
             CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
 
-#if 0
-	if (tda19988_read_edid(sc) < 0) {
-		device_printf(dev, "failed to read EDID\n");
-		return;
-	}
-#endif
-
 	/* Default values for RGB 4:4:4 mapping */
 	tda19988_reg_write(sc, TDA_VIP_CNTRL_0, 0x23);
 	tda19988_reg_write(sc, TDA_VIP_CNTRL_1, 0x01);
@@ -704,15 +695,25 @@ tda19988_connector_detect(struct drm_con
 {
 	struct tda19988_connector *tda_connector = to_tda_connector(connector);
 	struct tda19988_softc * const sc = tda_connector->sc;
+	enum drm_connector_status status;
 	uint8_t data = 0;
 
-	iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+	iic_acquire_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
 	tda19988_cec_read(sc, TDA_CEC_RXSHPDLEV, &data);
-	iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+	iic_release_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
 
-	return (data & RXSHPDLEV_HPD) ?
+	status = (data & RXSHPDLEV_HPD) ?
 	    connector_status_connected :
 	    connector_status_disconnected;
+
+	/* On connect, invalidate the last EDID */
+	if (status == connector_status_connected &&
+	    sc->sc_last_status != connector_status_connected)
+		sc->sc_edid_valid = false;
+
+	sc->sc_last_status = status;
+
+	return status;
 }
 
 static void
@@ -737,10 +738,15 @@ tda19988_connector_get_modes(struct drm_
 	struct edid *pedid = NULL;
 	int error;
 
-	iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
-	if (tda19988_read_edid(sc) == 0)
+	if (sc->sc_edid_valid) {
 		pedid = (struct edid *)sc->sc_edid;
-	iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+	} else {
+		iic_acquire_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
+		if (tda19988_read_edid(sc) == 0)
+			pedid = (struct edid *)sc->sc_edid;
+		iic_release_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
+		sc->sc_edid_valid = true;
+	}
 
 	drm_mode_connector_update_edid_property(connector, pedid);
 	if (pedid == NULL)
@@ -805,9 +811,7 @@ tda19988_bridge_enable(struct drm_bridge
 {
 	struct tda19988_softc * const sc = bridge->driver_private;
 
-	iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
-	tda19988_init_encoder(sc, &sc->sc_curmode);
-	iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+	fdtbus_pinctrl_set_config(sc->sc_phandle, "default");
 }
 
 static void
@@ -818,6 +822,9 @@ tda19988_bridge_pre_enable(struct drm_br
 static void
 tda19988_bridge_disable(struct drm_bridge *bridge)
 {
+	struct tda19988_softc * const sc = bridge->driver_private;
+
+	fdtbus_pinctrl_set_config(sc->sc_phandle, "off");
 }
 
 static void
@@ -831,7 +838,9 @@ tda19988_bridge_mode_set(struct drm_brid
 {
 	struct tda19988_softc * const sc = bridge->driver_private;
 
-	sc->sc_curmode = *adjusted_mode;
+	iic_acquire_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
+	tda19988_init_encoder(sc, adjusted_mode);
+	iic_release_bus(sc->sc_i2c, cold ? I2C_F_POLL : 0);
 }
 
 static bool
@@ -905,18 +914,19 @@ tda19988_attach(device_t parent, device_
 	const int phandle = ia->ia_cookie;
 
 	sc->sc_dev = self;
+	sc->sc_phandle = phandle;
 	sc->sc_i2c = ia->ia_tag;
 	sc->sc_addr = ia->ia_addr;
 	sc->sc_cec_addr = 0x34; /* hardcoded */
 	sc->sc_current_page = 0xff;
 	sc->sc_edid = kmem_zalloc(EDID_LENGTH, KM_SLEEP);
 	sc->sc_edid_len = EDID_LENGTH;
+	sc->sc_edid_valid = false;
+	sc->sc_last_status = connector_status_unknown;
 
 	aprint_naive("\n");
 	aprint_normal(": NXP TDA19988 HDMI transmitter\n");
 
-	fdtbus_pinctrl_set_config(phandle, "default");
-
 	iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
 	tda19988_start(sc);
 	iic_release_bus(sc->sc_i2c, I2C_F_POLL);

Reply via email to