Module Name: src
Committed By: snj
Date: Tue Nov 18 18:19:10 UTC 2014
Modified Files:
src/sys/arch/arm/allwinner [netbsd-7]: awin_hdmi.c awin_hdmiaudio.c
awin_var.h
src/sys/arch/evbarm/awin [netbsd-7]: awin_machdep.c
src/sys/dev/i2c [netbsd-7]: ddc.c ddcvar.h
src/sys/dev/videomode [netbsd-7]: edid.c edidreg.h edidvar.h
Log Message:
Pull up following revision(s) (requested by jmcneill in ticket #244):
sys/arch/arm/allwinner/awin_hdmi.c: revision 1.13-1.15
sys/arch/arm/allwinner/awin_hdmiaudio.c: revision 1.4
sys/arch/arm/allwinner/awin_var.h: revision 1.25
sys/arch/evbarm/awin/awin_machdep.c: revision 1.29
sys/dev/i2c/ddc.c: revision 1.4
sys/dev/i2c/ddcvar.h: revision 1.2
sys/dev/videomode/edid.c: revision 1.13
sys/dev/videomode/edidreg.h: revision 1.4
sys/dev/videomode/edidvar.h: revision 1.3
Parse the extension block count field, and make it available in struct edid_info
--
add ddc_read_edid_block, which is the same as ddc_read_edid but takes an
additional block number argument
--
Add support for DVI displays. Detect HDMI vs DVI mode by looking for a
CEA-861-D extension block in the EDID, and then searching this block for
an HDMI vendor-specific data block (HDMI VSDB).
--
Allow for overriding DVI/HDMI detection with a kernel boot arg. Set
hdmi.forcemode=dvi or hdmi.forcemode=hdmi to disable auto-detection.
--
report hotplug status for AUDIO_GETDEV fields, only allow playback if a capable
display is connected
--
clear repeater sel bits before setting -- would cause an issue if we ever
switched away from a pixel doubling mode
To generate a diff of this commit:
cvs rdiff -u -r1.4.2.4 -r1.4.2.5 src/sys/arch/arm/allwinner/awin_hdmi.c
cvs rdiff -u -r1.3.2.2 -r1.3.2.3 src/sys/arch/arm/allwinner/awin_hdmiaudio.c
cvs rdiff -u -r1.10.2.4 -r1.10.2.5 src/sys/arch/arm/allwinner/awin_var.h
cvs rdiff -u -r1.8.2.7 -r1.8.2.8 src/sys/arch/evbarm/awin/awin_machdep.c
cvs rdiff -u -r1.3 -r1.3.62.1 src/sys/dev/i2c/ddc.c
cvs rdiff -u -r1.1 -r1.1.138.1 src/sys/dev/i2c/ddcvar.h
cvs rdiff -u -r1.12 -r1.12.12.1 src/sys/dev/videomode/edid.c
cvs rdiff -u -r1.3 -r1.3.30.1 src/sys/dev/videomode/edidreg.h
cvs rdiff -u -r1.2 -r1.2.138.1 src/sys/dev/videomode/edidvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/allwinner/awin_hdmi.c
diff -u src/sys/arch/arm/allwinner/awin_hdmi.c:1.4.2.4 src/sys/arch/arm/allwinner/awin_hdmi.c:1.4.2.5
--- src/sys/arch/arm/allwinner/awin_hdmi.c:1.4.2.4 Fri Nov 14 13:37:39 2014
+++ src/sys/arch/arm/allwinner/awin_hdmi.c Tue Nov 18 18:19:09 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_hdmi.c,v 1.4.2.4 2014/11/14 13:37:39 martin Exp $ */
+/* $NetBSD: awin_hdmi.c,v 1.4.2.5 2014/11/18 18:19:09 snj Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -32,7 +32,7 @@
#define AWIN_HDMI_PLL 3 /* PLL7 or PLL3 */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.4.2.4 2014/11/14 13:37:39 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_hdmi.c,v 1.4.2.5 2014/11/18 18:19:09 snj Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -64,6 +64,14 @@ struct awin_hdmi_softc {
kmutex_t sc_ic_lock;
bool sc_connected;
+ char sc_display_vendor[16];
+ char sc_display_product[16];
+
+ u_int sc_display_mode;
+ u_int sc_current_display_mode;
+#define DISPLAY_MODE_AUTO 0
+#define DISPLAY_MODE_HDMI 1
+#define DISPLAY_MODE_DVI 2
uint32_t sc_ver;
unsigned int sc_i2c_blklen;
@@ -85,17 +93,19 @@ static int awin_hdmi_i2c_acquire_bus(voi
static void awin_hdmi_i2c_release_bus(void *, int);
static int awin_hdmi_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
size_t, void *, size_t, int);
-static int awin_hdmi_i2c_xfer(void *, i2c_addr_t, uint8_t,
+static int awin_hdmi_i2c_xfer(void *, i2c_addr_t, uint8_t, uint8_t,
size_t, int, int);
static int awin_hdmi_i2c_reset(struct awin_hdmi_softc *, int);
static void awin_hdmi_enable(struct awin_hdmi_softc *);
static void awin_hdmi_read_edid(struct awin_hdmi_softc *);
+static u_int awin_hdmi_get_display_mode(struct awin_hdmi_softc *,
+ const struct edid_info *);
static void awin_hdmi_video_enable(struct awin_hdmi_softc *, bool);
static void awin_hdmi_set_videomode(struct awin_hdmi_softc *,
- const struct videomode *);
+ const struct videomode *, u_int);
static void awin_hdmi_set_audiomode(struct awin_hdmi_softc *,
- const struct videomode *);
+ const struct videomode *, u_int);
static void awin_hdmi_hpd(struct awin_hdmi_softc *);
static void awin_hdmi_thread(void *);
#if 0
@@ -127,6 +137,7 @@ awin_hdmi_attach(device_t parent, device
struct awin_hdmi_softc *sc = device_private(self);
struct awinio_attach_args * const aio = aux;
const struct awin_locators * const loc = &aio->aio_loc;
+ prop_dictionary_t cfg = device_properties(self);
uint32_t ver, clk;
sc->sc_dev = self;
@@ -172,6 +183,15 @@ awin_hdmi_attach(device_t parent, device
sc->sc_ver = ver;
sc->sc_i2c_blklen = 16;
+ const char *display_mode = NULL;
+ prop_dictionary_get_cstring_nocopy(cfg, "display-mode", &display_mode);
+ if (display_mode) {
+ if (strcasecmp(display_mode, "hdmi") == 0)
+ sc->sc_display_mode = DISPLAY_MODE_HDMI;
+ else if (strcasecmp(display_mode, "dvi") == 0)
+ sc->sc_display_mode = DISPLAY_MODE_DVI;
+ }
+
#if 0
sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL,
awin_hdmi_intr, sc);
@@ -237,6 +257,7 @@ awin_hdmi_i2c_exec(void *priv, i2c_op_t
{
struct awin_hdmi_softc *sc = priv;
uint8_t *pbuf;
+ uint8_t block;
int resid;
off_t off;
int err;
@@ -251,14 +272,15 @@ awin_hdmi_i2c_exec(void *priv, i2c_op_t
if (err)
goto done;
- off = *(const uint8_t *)cmdbuf;
+ block = *(const uint8_t *)cmdbuf;
+ off = (block & 1) ? 128 : 0;
pbuf = buf;
resid = len;
while (resid > 0) {
size_t blklen = min(resid, sc->sc_i2c_blklen);
- err = awin_hdmi_i2c_xfer(sc, addr, off, blklen,
+ err = awin_hdmi_i2c_xfer(sc, addr, block >> 1, off, blklen,
AWIN_HDMI_DDC_COMMAND_ACCESS_CMD_EOREAD, flags);
if (err)
goto done;
@@ -288,7 +310,7 @@ done:
}
static int
-awin_hdmi_i2c_xfer_1_3(void *priv, i2c_addr_t addr, uint8_t reg,
+awin_hdmi_i2c_xfer_1_3(void *priv, i2c_addr_t addr, uint8_t block, uint8_t reg,
size_t len, int type, int flags)
{
struct awin_hdmi_softc *sc = priv;
@@ -299,7 +321,8 @@ awin_hdmi_i2c_xfer_1_3(void *priv, i2c_a
val &= ~AWIN_HDMI_DDC_CTRL_FIFO_DIR;
HDMI_WRITE(sc, AWIN_HDMI_DDC_CTRL_REG, val);
- val = __SHIFTIN(0x60, AWIN_HDMI_DDC_SLAVE_ADDR_1);
+ val |= __SHIFTIN(block, AWIN_HDMI_DDC_SLAVE_ADDR_0);
+ val |= __SHIFTIN(0x60, AWIN_HDMI_DDC_SLAVE_ADDR_1);
val |= __SHIFTIN(reg, AWIN_HDMI_DDC_SLAVE_ADDR_2);
val |= __SHIFTIN(addr, AWIN_HDMI_DDC_SLAVE_ADDR_3);
HDMI_WRITE(sc, AWIN_HDMI_DDC_SLAVE_ADDR_REG, val);
@@ -336,7 +359,7 @@ awin_hdmi_i2c_xfer_1_3(void *priv, i2c_a
}
static int
-awin_hdmi_i2c_xfer_1_4(void *priv, i2c_addr_t addr, uint8_t reg,
+awin_hdmi_i2c_xfer_1_4(void *priv, i2c_addr_t addr, uint8_t block, uint8_t reg,
size_t len, int type, int flags)
{
struct awin_hdmi_softc *sc = priv;
@@ -347,7 +370,7 @@ awin_hdmi_i2c_xfer_1_4(void *priv, i2c_a
val |= AWIN_A31_HDMI_DDC_FIFO_CTRL_RST;
HDMI_WRITE(sc, AWIN_A31_HDMI_DDC_FIFO_CTRL_REG, val);
- val = __SHIFTIN(0, AWIN_A31_HDMI_DDC_SLAVE_ADDR_SEG_PTR);
+ val = __SHIFTIN(block, AWIN_A31_HDMI_DDC_SLAVE_ADDR_SEG_PTR);
val |= __SHIFTIN(0x60, AWIN_A31_HDMI_DDC_SLAVE_ADDR_DDC_CMD);
val |= __SHIFTIN(reg, AWIN_A31_HDMI_DDC_SLAVE_ADDR_OFF_ADR);
val |= __SHIFTIN(addr, AWIN_A31_HDMI_DDC_SLAVE_ADDR_DEV_ADR);
@@ -378,16 +401,18 @@ awin_hdmi_i2c_xfer_1_4(void *priv, i2c_a
}
static int
-awin_hdmi_i2c_xfer(void *priv, i2c_addr_t addr, uint8_t reg,
+awin_hdmi_i2c_xfer(void *priv, i2c_addr_t addr, uint8_t block, uint8_t reg,
size_t len, int type, int flags)
{
struct awin_hdmi_softc *sc = priv;
int rv;
if (HDMI_1_3_P(sc)) {
- rv = awin_hdmi_i2c_xfer_1_3(priv, addr, reg, len, type, flags);
+ rv = awin_hdmi_i2c_xfer_1_3(priv, addr, block, reg, len,
+ type, flags);
} else {
- rv = awin_hdmi_i2c_xfer_1_4(priv, addr, reg, len, type, flags);
+ rv = awin_hdmi_i2c_xfer_1_4(priv, addr, block, reg, len,
+ type, flags);
}
return rv;
@@ -468,12 +493,13 @@ awin_hdmi_read_edid(struct awin_hdmi_sof
char edid[128];
struct edid_info ei;
int retry = 4;
+ u_int display_mode;
memset(edid, 0, sizeof(edid));
memset(&ei, 0, sizeof(ei));
while (--retry > 0) {
- if (ddc_read_edid(&sc->sc_ic, edid, sizeof(edid)) == 0)
+ if (!ddc_read_edid_block(&sc->sc_ic, edid, sizeof(edid), 0))
break;
}
if (retry == 0) {
@@ -489,6 +515,22 @@ awin_hdmi_read_edid(struct awin_hdmi_sof
#endif
}
+ if (sc->sc_display_mode == DISPLAY_MODE_AUTO)
+ display_mode = awin_hdmi_get_display_mode(sc, &ei);
+ else
+ display_mode = sc->sc_display_mode;
+
+ const char *forced = sc->sc_display_mode == DISPLAY_MODE_AUTO ?
+ "auto-detected" : "forced";
+ device_printf(sc->sc_dev, "%s mode (%s)\n",
+ display_mode == DISPLAY_MODE_HDMI ? "HDMI" : "DVI", forced);
+
+ strlcpy(sc->sc_display_vendor, ei.edid_vendorname,
+ sizeof(sc->sc_display_vendor));
+ strlcpy(sc->sc_display_product, ei.edid_productname,
+ sizeof(sc->sc_display_product));
+ sc->sc_current_display_mode = display_mode;
+
mode = ei.edid_preferred_mode;
if (mode == NULL)
mode = pick_mode_by_ref(640, 480, 60);
@@ -500,8 +542,8 @@ awin_hdmi_read_edid(struct awin_hdmi_sof
awin_debe_set_videomode(mode);
awin_tcon_set_videomode(mode);
- awin_hdmi_set_videomode(sc, mode);
- awin_hdmi_set_audiomode(sc, mode);
+ awin_hdmi_set_videomode(sc, mode, display_mode);
+ awin_hdmi_set_audiomode(sc, mode, display_mode);
awin_debe_enable(true);
delay(20000);
awin_tcon_enable(true);
@@ -510,6 +552,90 @@ awin_hdmi_read_edid(struct awin_hdmi_sof
}
}
+static u_int
+awin_hdmi_get_display_mode(struct awin_hdmi_softc *sc,
+ const struct edid_info *ei)
+{
+ char edid[128];
+ bool found_hdmi = false;
+ unsigned int n, p;
+
+ /*
+ * Scan through extension blocks, looking for a CEA-861-D v3
+ * block. If an HDMI Vendor-Specific Data Block (HDMI VSDB) is
+ * found in that, assume HDMI mode.
+ */
+ for (n = 1; n <= MIN(ei->edid_ext_block_count, 4); n++) {
+ if (ddc_read_edid_block(&sc->sc_ic, edid, sizeof(edid), n)) {
+#ifdef AWIN_HDMI_DEBUG
+ device_printf(sc->sc_dev,
+ "Failed to read EDID block %d\n", n);
+#endif
+ break;
+ }
+
+#ifdef AWIN_HDMI_DEBUG
+ device_printf(sc->sc_dev, "EDID block #%d:\n", n);
+#endif
+
+ const uint8_t tag = edid[0];
+ const uint8_t rev = edid[1];
+ const uint8_t off = edid[2];
+
+#ifdef AWIN_HDMI_DEBUG
+ device_printf(sc->sc_dev, " Tag %d, Revision %d, Offset %d\n",
+ tag, rev, off);
+ device_printf(sc->sc_dev, " Flags: 0x%02x\n", edid[3]);
+#endif
+
+ /* We are looking for a CEA-861-D tag (02h) with revision 3 */
+ if (tag != 0x02 || rev != 3)
+ continue;
+ /*
+ * CEA data block collection starts at byte 4, so the
+ * DTD blocks must start after it.
+ */
+ if (off <= 4)
+ continue;
+
+ /* Parse the CEA data blocks */
+ for (p = 4; p < off;) {
+ const uint8_t btag = (edid[p] >> 5) & 0x7;
+ const uint8_t blen = edid[p] & 0x1f;
+
+#ifdef AWIN_HDMI_DEBUG
+ device_printf(sc->sc_dev, " CEA data block @ %d\n", p);
+ device_printf(sc->sc_dev, " Tag %d, Length %d\n",
+ btag, blen);
+#endif
+
+ /* Make sure the length is sane */
+ if (p + blen + 1 > off)
+ break;
+ /* Looking for a VSDB tag */
+ if (btag != 3)
+ goto next_block;
+ /* HDMI VSDB is at least 5 bytes long */
+ if (blen < 5)
+ goto next_block;
+
+#ifdef AWIN_HDMI_DEBUG
+ device_printf(sc->sc_dev, " ID: %02x%02x%02x\n",
+ edid[p + 1], edid[p + 2], edid[p + 3]);
+#endif
+
+ /* HDMI 24-bit IEEE registration ID is 0x000C03 */
+ if (memcmp(&edid[p + 1], "\x03\x0c\x00", 3) == 0)
+ found_hdmi = true;
+
+next_block:
+ p += (1 + blen);
+ }
+ }
+
+ return found_hdmi ? DISPLAY_MODE_HDMI : DISPLAY_MODE_DVI;
+}
+
static void
awin_hdmi_video_enable(struct awin_hdmi_softc *sc, bool enable)
{
@@ -538,7 +664,7 @@ awin_hdmi_video_enable(struct awin_hdmi_
static void
awin_hdmi_set_videomode(struct awin_hdmi_softc *sc,
- const struct videomode *mode)
+ const struct videomode *mode, u_int display_mode)
{
uint32_t val;
const u_int dblscan_p = !!(mode->flags & VID_DBLSCAN);
@@ -603,13 +729,20 @@ awin_hdmi_set_videomode(struct awin_hdmi
#endif
val = HDMI_READ(sc, AWIN_HDMI_VID_CTRL_REG);
- val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_HDMI_MODE_HDMI,
- AWIN_HDMI_VID_CTRL_HDMI_MODE);
- val &= ~AWIN_HDMI_VID_CTRL_OUTPUT_FMT;
+ val &= ~AWIN_HDMI_VID_CTRL_HDMI_MODE;
+ if (display_mode == DISPLAY_MODE_DVI) {
+ val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_HDMI_MODE_DVI,
+ AWIN_HDMI_VID_CTRL_HDMI_MODE);
+ } else {
+ val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_HDMI_MODE_HDMI,
+ AWIN_HDMI_VID_CTRL_HDMI_MODE);
+ }
+ val &= ~AWIN_HDMI_VID_CTRL_REPEATER_SEL;
if (dblscan_p) {
val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_REPEATER_SEL_2X,
AWIN_HDMI_VID_CTRL_REPEATER_SEL);
}
+ val &= ~AWIN_HDMI_VID_CTRL_OUTPUT_FMT;
if (interlace_p) {
val |= __SHIFTIN(AWIN_HDMI_VID_CTRL_OUTPUT_FMT_INTERLACE,
AWIN_HDMI_VID_CTRL_OUTPUT_FMT);
@@ -658,7 +791,7 @@ awin_hdmi_set_videomode(struct awin_hdmi
static void
awin_hdmi_set_audiomode(struct awin_hdmi_softc *sc,
- const struct videomode *mode)
+ const struct videomode *mode, u_int display_mode)
{
uint32_t cts, n, val;
@@ -675,6 +808,11 @@ awin_hdmi_set_audiomode(struct awin_hdmi
val = HDMI_READ(sc, AWIN_HDMI_AUD_CTRL_REG);
} while (val & AWIN_HDMI_AUD_CTRL_RST);
+ /* No audio support in DVI mode */
+ if (display_mode != DISPLAY_MODE_HDMI) {
+ return;
+ }
+
/* DMA & FIFO control */
val = HDMI_READ(sc, AWIN_HDMI_ADMA_CTRL_REG);
if (awin_chip_id() == AWIN_CHIP_ID_A31) {
@@ -740,7 +878,6 @@ awin_hdmi_hpd(struct awin_hdmi_softc *sc
if (sc->sc_connected == con)
return;
- sc->sc_connected = con;
if (con) {
device_printf(sc->sc_dev, "display connected\n");
awin_hdmi_read_edid(sc);
@@ -748,6 +885,8 @@ awin_hdmi_hpd(struct awin_hdmi_softc *sc
device_printf(sc->sc_dev, "display disconnected\n");
awin_tcon_set_videomode(NULL);
}
+
+ sc->sc_connected = con;
}
static void
@@ -780,6 +919,32 @@ awin_hdmi_intr(void *priv)
}
#endif
+void
+awin_hdmi_get_info(struct awin_hdmi_info *info)
+{
+ struct awin_hdmi_softc *sc;
+ device_t dev;
+
+ memset(info, 0, sizeof(*info));
+
+ dev = device_find_by_driver_unit("awinhdmi", 0);
+ if (dev == NULL) {
+ info->display_connected = false;
+ return;
+ }
+ sc = device_private(dev);
+
+ info->display_connected = sc->sc_connected;
+ if (info->display_connected) {
+ strlcpy(info->display_vendor, sc->sc_display_vendor,
+ sizeof(info->display_vendor));
+ strlcpy(info->display_product, sc->sc_display_product,
+ sizeof(info->display_product));
+ info->display_hdmimode =
+ sc->sc_current_display_mode == DISPLAY_MODE_HDMI;
+ }
+}
+
#if defined(DDB)
void
awin_hdmi_dump_regs(void)
Index: src/sys/arch/arm/allwinner/awin_hdmiaudio.c
diff -u src/sys/arch/arm/allwinner/awin_hdmiaudio.c:1.3.2.2 src/sys/arch/arm/allwinner/awin_hdmiaudio.c:1.3.2.3
--- src/sys/arch/arm/allwinner/awin_hdmiaudio.c:1.3.2.2 Fri Nov 14 13:37:39 2014
+++ src/sys/arch/arm/allwinner/awin_hdmiaudio.c Tue Nov 18 18:19:09 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_hdmiaudio.c,v 1.3.2.2 2014/11/14 13:37:39 martin Exp $ */
+/* $NetBSD: awin_hdmiaudio.c,v 1.3.2.3 2014/11/18 18:19:09 snj Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_hdmiaudio.c,v 1.3.2.2 2014/11/14 13:37:39 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_hdmiaudio.c,v 1.3.2.3 2014/11/18 18:19:09 snj Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -538,14 +538,35 @@ static int
awin_hdmiaudio_getdev(void *priv, struct audio_device *audiodev)
{
struct awin_hdmiaudio_softc *sc = priv;
+ struct awin_hdmi_info info;
+ const char *vendor = NULL, *product = NULL;
const int vmaj = __SHIFTOUT(sc->sc_ver, AWIN_HDMI_VERSION_ID_H);
const int vmin = __SHIFTOUT(sc->sc_ver, AWIN_HDMI_VERSION_ID_L);
- snprintf(audiodev->name, sizeof(audiodev->name), "Allwinner");
- snprintf(audiodev->version, sizeof(audiodev->version),
+ awin_hdmi_get_info(&info);
+
+ if (info.display_connected && info.display_hdmimode) {
+ if (strlen(info.display_vendor) > 0 &&
+ strlen(info.display_product) > 0) {
+ vendor = info.display_vendor;
+ product = info.display_product;
+ } else {
+ vendor = "HDMI";
+ product = "";
+ }
+ } else if (info.display_connected) {
+ vendor = "DVI";
+ product = "(unsupported)";
+ } else {
+ vendor = "HDMI";
+ product = "(disconnected)";
+ }
+
+ strlcpy(audiodev->name, vendor, sizeof(audiodev->name));
+ strlcpy(audiodev->version, product, sizeof(audiodev->version));
+ snprintf(audiodev->config, sizeof(audiodev->config),
"HDMI %d.%d", vmaj, vmin);
- snprintf(audiodev->config, sizeof(audiodev->config), "awin_hdmiaudio");
return 0;
}
@@ -574,11 +595,16 @@ awin_hdmiaudio_trigger_output(void *priv
{
struct awin_hdmiaudio_softc *sc = priv;
struct awin_hdmiaudio_dma *dma;
+ struct awin_hdmi_info info;
bus_addr_t pstart;
bus_size_t psize;
uint32_t dmacfg;
int error;
+ awin_hdmi_get_info(&info);
+ if (info.display_connected == false || info.display_hdmimode == false)
+ return ENXIO;
+
pstart = 0;
psize = (uintptr_t)end - (uintptr_t)start;
Index: src/sys/arch/arm/allwinner/awin_var.h
diff -u src/sys/arch/arm/allwinner/awin_var.h:1.10.2.4 src/sys/arch/arm/allwinner/awin_var.h:1.10.2.5
--- src/sys/arch/arm/allwinner/awin_var.h:1.10.2.4 Sat Nov 15 11:31:40 2014
+++ src/sys/arch/arm/allwinner/awin_var.h Tue Nov 18 18:19:09 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_var.h,v 1.10.2.4 2014/11/15 11:31:40 martin Exp $ */
+/* $NetBSD: awin_var.h,v 1.10.2.5 2014/11/18 18:19:09 snj Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -132,6 +132,15 @@ void awin_tcon_enable(bool);
void awin_debe_set_videomode(const struct videomode *);
void awin_debe_enable(bool);
int awin_debe_ioctl(device_t, u_long, void *);
+
+struct awin_hdmi_info {
+ bool display_connected;
+ char display_vendor[16];
+ char display_product[16];
+ bool display_hdmimode;
+};
+void awin_hdmi_get_info(struct awin_hdmi_info *);
+
void awin_fb_set_videomode(device_t, u_int, u_int);
void awin_fb_ddb_trap_callback(int);
Index: src/sys/arch/evbarm/awin/awin_machdep.c
diff -u src/sys/arch/evbarm/awin/awin_machdep.c:1.8.2.7 src/sys/arch/evbarm/awin/awin_machdep.c:1.8.2.8
--- src/sys/arch/evbarm/awin/awin_machdep.c:1.8.2.7 Fri Nov 14 22:23:28 2014
+++ src/sys/arch/evbarm/awin/awin_machdep.c Tue Nov 18 18:19:09 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_machdep.c,v 1.8.2.7 2014/11/14 22:23:28 martin Exp $ */
+/* $NetBSD: awin_machdep.c,v 1.8.2.8 2014/11/18 18:19:09 snj Exp $ */
/*
* Machine dependent functions for kernel setup for TI OSK5912 board.
@@ -125,7 +125,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.8.2.7 2014/11/14 22:23:28 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.8.2.8 2014/11/18 18:19:09 snj Exp $");
#include "opt_machdep.h"
#include "opt_ddb.h"
@@ -769,6 +769,20 @@ awin_device_register(device_t self, void
}
}
+ if (device_is_a(self, "awinhdmi")) {
+ char *display_mode;
+ if (get_bootconf_option(boot_args, "hdmi.forcemode",
+ BOOTOPT_TYPE_STRING, &display_mode)) {
+ if (strcasecmp(display_mode, "hdmi") == 0) {
+ prop_dictionary_set_cstring(dict,
+ "display-mode", "hdmi");
+ } else if (strcasecmp(display_mode, "dvi") == 0) {
+ prop_dictionary_set_cstring(dict,
+ "display-mode", "dvi");
+ }
+ }
+ }
+
#if NGENFB > 0
if (device_is_a(self, "genfb")) {
#ifdef DDB
Index: src/sys/dev/i2c/ddc.c
diff -u src/sys/dev/i2c/ddc.c:1.3 src/sys/dev/i2c/ddc.c:1.3.62.1
--- src/sys/dev/i2c/ddc.c:1.3 Sun May 4 15:26:29 2008
+++ src/sys/dev/i2c/ddc.c Tue Nov 18 18:19:10 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: ddc.c,v 1.3 2008/05/04 15:26:29 xtraeme Exp $ */
+/* $NetBSD: ddc.c,v 1.3.62.1 2014/11/18 18:19:10 snj Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ddc.c,v 1.3 2008/05/04 15:26:29 xtraeme Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ddc.c,v 1.3.62.1 2014/11/18 18:19:10 snj Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -91,12 +91,18 @@ ddc_attach(device_t parent, device_t sel
int
ddc_read_edid(i2c_tag_t tag, uint8_t *dest, size_t len)
{
+ return ddc_read_edid_block(tag, dest, len, DDC_EDID_START);
+}
+
+int
+ddc_read_edid_block(i2c_tag_t tag, uint8_t *dest, size_t len, uint8_t block)
+{
uint8_t wbuf[2];
if (iic_acquire_bus(tag, I2C_F_POLL) != 0)
return -1;
- wbuf[0] = DDC_EDID_START; /* start address */
+ wbuf[0] = block; /* start address */
if (iic_exec(tag, I2C_OP_READ_WITH_STOP, DDC_ADDR, wbuf, 1, dest,
len, I2C_F_POLL)) {
Index: src/sys/dev/i2c/ddcvar.h
diff -u src/sys/dev/i2c/ddcvar.h:1.1 src/sys/dev/i2c/ddcvar.h:1.1.138.1
--- src/sys/dev/i2c/ddcvar.h:1.1 Tue Apr 25 21:18:16 2006
+++ src/sys/dev/i2c/ddcvar.h Tue Nov 18 18:19:10 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: ddcvar.h,v 1.1 2006/04/25 21:18:16 gdamore Exp $ */
+/* $NetBSD: ddcvar.h,v 1.1.138.1 2014/11/18 18:19:10 snj Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -40,5 +40,6 @@
* autoconfiguration framework.
*/
int ddc_read_edid(i2c_tag_t, u_int8_t *, size_t);
+int ddc_read_edid_block(i2c_tag_t, u_int8_t *, size_t, uint8_t);
#endif /* _DEV_I2C_DDCVAR_H_ */
Index: src/sys/dev/videomode/edid.c
diff -u src/sys/dev/videomode/edid.c:1.12 src/sys/dev/videomode/edid.c:1.12.12.1
--- src/sys/dev/videomode/edid.c:1.12 Fri Feb 8 16:35:10 2013
+++ src/sys/dev/videomode/edid.c Tue Nov 18 18:19:10 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: edid.c,v 1.12 2013/02/08 16:35:10 skrll Exp $ */
+/* $NetBSD: edid.c,v 1.12.12.1 2014/11/18 18:19:10 snj Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: edid.c,v 1.12 2013/02/08 16:35:10 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: edid.c,v 1.12.12.1 2014/11/18 18:19:10 snj Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -286,6 +286,8 @@ edid_print(struct edid_info *edid)
DIVIDE(DIVIDE(edid->edid_preferred_mode->dot_clock * 1000,
edid->edid_preferred_mode->htotal),
edid->edid_preferred_mode->vtotal));
+
+ printf("Number of extension blocks: %d\n", edid->edid_ext_block_count);
}
static const struct videomode *
@@ -569,6 +571,8 @@ edid_parse(uint8_t *data, struct edid_in
edid->edid_chroma.ec_whitex = EDID_CHROMA_WHITEX(data);
edid->edid_chroma.ec_whitey = EDID_CHROMA_WHITEY(data);
+ edid->edid_ext_block_count = EDID_EXT_BLOCK_COUNT(data);
+
/* lookup established modes */
edid->edid_nmodes = 0;
edid->edid_preferred_mode = NULL;
Index: src/sys/dev/videomode/edidreg.h
diff -u src/sys/dev/videomode/edidreg.h:1.3 src/sys/dev/videomode/edidreg.h:1.3.30.1
--- src/sys/dev/videomode/edidreg.h:1.3 Wed Mar 30 18:49:56 2011
+++ src/sys/dev/videomode/edidreg.h Tue Nov 18 18:19:10 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: edidreg.h,v 1.3 2011/03/30 18:49:56 jdc Exp $ */
+/* $NetBSD: edidreg.h,v 1.3.30.1 2014/11/18 18:19:10 snj Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -250,4 +250,6 @@
#define EDID_DESC_STD_TIMING_START 5
#define EDID_DESC_STD_TIMING_COUNT 6
+#define EDID_EXT_BLOCK_COUNT(ptr) ((ptr)[126])
+
#endif /* _DEV_VIDEOMODE_EDIDREG_H */
Index: src/sys/dev/videomode/edidvar.h
diff -u src/sys/dev/videomode/edidvar.h:1.2 src/sys/dev/videomode/edidvar.h:1.2.138.1
--- src/sys/dev/videomode/edidvar.h:1.2 Thu May 11 19:05:41 2006
+++ src/sys/dev/videomode/edidvar.h Tue Nov 18 18:19:10 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: edidvar.h,v 1.2 2006/05/11 19:05:41 gdamore Exp $ */
+/* $NetBSD: edidvar.h,v 1.2.138.1 2014/11/18 18:19:10 snj Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -75,6 +75,7 @@ struct edid_info {
uint8_t edid_max_vsize; /* in cm */
uint8_t edid_gamma;
uint8_t edid_features;
+ uint8_t edid_ext_block_count;
int edid_have_range;
struct edid_range edid_range;