Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105800422
D4168.id10207.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
88 KB
Referenced Files
None
Subscribers
None
D4168.id10207.diff
View Options
Index: sys/arm/conf/IMX6
===================================================================
--- sys/arm/conf/IMX6
+++ sys/arm/conf/IMX6
@@ -129,6 +129,12 @@
#options SC_DFLT_FONT # compile font in
#makeoptions SC_DFLT_FONT=cp437
+device vt
+device kbdmux
+device ukbd
+device videomode
+device hdmi
+
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
makeoptions MODULES_EXTRA=dtb/imx6
Index: sys/arm/freescale/imx/files.imx6
===================================================================
--- sys/arm/freescale/imx/files.imx6
+++ sys/arm/freescale/imx/files.imx6
@@ -29,6 +29,11 @@
arm/freescale/imx/imx6_audmux.c optional sound
arm/freescale/imx/imx6_ssi.c optional sound
+arm/freescale/imx/imx6_ipu.c optional vt
+
+arm/arm/hdmi_if.m optional hdmi
+arm/freescale/imx/imx6_hdmi.c optional hdmi
+
#
# Optional devices.
#
Index: sys/arm/freescale/imx/imx6_ccm.c
===================================================================
--- sys/arm/freescale/imx/imx6_ccm.c
+++ sys/arm/freescale/imx/imx6_ccm.c
@@ -348,6 +348,43 @@
return (132000000);
}
+void
+imx_ccm_ipu_enable(int ipu)
+{
+ struct ccm_softc *sc;
+ uint32_t reg;
+
+ sc = ccm_sc;
+ reg = RD4(sc, CCM_CCGR3);
+ if (ipu == 1)
+ reg |= CCGR3_IPU1_IPU | CCGR3_IPU1_DI0;
+ else
+ reg |= CCGR3_IPU2_IPU | CCGR3_IPU2_DI0;
+ WR4(sc, CCM_CCGR3, reg);
+}
+
+void
+imx_ccm_hdmi_enable()
+{
+ struct ccm_softc *sc;
+ uint32_t reg;
+
+ sc = ccm_sc;
+ reg = RD4(sc, CCM_CCGR2);
+ reg |= CCGR2_HDMI_TX | CCGR2_HDMI_TX_ISFR;
+ WR4(sc, CCM_CCGR2, reg);
+
+ /* Set HDMI clock to 280MHz */
+ reg = RD4(sc, CCM_CHSCCDR);
+ reg &= ~(CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
+ CHSCCDR_IPU1_DI0_PODF_MASK | CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+ reg |= (CHSCCDR_PODF_DIVIDE_BY_3 << CHSCCDR_IPU1_DI0_PODF_SHIFT);
+ reg |= (CHSCCDR_IPU_PRE_CLK_540M_PFD << CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT);
+ WR4(sc, CCM_CHSCCDR, reg);
+ reg |= (CHSCCDR_CLK_SEL_LDB_DI0 << CHSCCDR_IPU1_DI0_CLK_SEL_SHIFT);
+ WR4(sc, CCM_CHSCCDR, reg);
+}
+
uint32_t
imx_ccm_get_cacrr(void)
{
Index: sys/arm/freescale/imx/imx6_ccmreg.h
===================================================================
--- sys/arm/freescale/imx/imx6_ccmreg.h
+++ sys/arm/freescale/imx/imx6_ccmreg.h
@@ -30,6 +30,9 @@
#define IMX6_CCMREG_H
#define CCM_CACCR 0x010
+#define CCM_CBCDR 0x014
+#define CBCDR_MMDC_CH1_AXI_PODF_SHIFT 3
+#define CBCDR_MMDC_CH1_AXI_PODF_MASK (7 << 3)
#define CCM_CSCMR1 0x01C
#define SSI1_CLK_SEL_S 10
#define SSI2_CLK_SEL_S 12
@@ -39,6 +42,7 @@
#define SSI_CLK_SEL_454_PFD 1
#define SSI_CLK_SEL_PLL4 2
#define CCM_CSCMR2 0x020
+#define CSCMR2_LDB_DI0_IPU_DIV_SHIFT 10
#define CCM_CS1CDR 0x028
#define SSI1_CLK_PODF_SHIFT 0
#define SSI1_CLK_PRED_SHIFT 6
@@ -49,6 +53,18 @@
#define CCM_CS2CDR 0x02C
#define SSI2_CLK_PODF_SHIFT 0
#define SSI2_CLK_PRED_SHIFT 6
+#define LDB_DI0_CLK_SEL_SHIFT 9
+#define LDB_DI0_CLK_SEL_MASK (3 << LDB_DI0_CLK_SEL_SHIFT)
+#define CCM_CHSCCDR 0x034
+#define CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
+#define CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT 6
+#define CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3)
+#define CHSCCDR_IPU1_DI0_PODF_SHIFT 3
+#define CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7)
+#define CHSCCDR_IPU1_DI0_CLK_SEL_SHIFT 0
+#define CHSCCDR_CLK_SEL_LDB_DI0 3
+#define CHSCCDR_PODF_DIVIDE_BY_3 2
+#define CHSCCDR_IPU_PRE_CLK_540M_PFD 5
#define CCM_CSCDR2 0x038
#define CCM_CLPCR 0x054
#define CCM_CLPCR_LPM_MASK 0x03
Index: sys/arm/freescale/imx/imx6_hdmi.c
===================================================================
--- /dev/null
+++ sys/arm/freescale/imx/imx6_hdmi.c
@@ -0,0 +1,777 @@
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * HDMI core module
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_iomuxvar.h>
+#include <arm/freescale/imx/imx6_hdmi_regs.h>
+
+#include "hdmi_if.h"
+
+#define I2C_DDC_ADDR (0x50 << 1)
+#define EDID_LENGTH 0x80
+
+struct imx_hdmi_softc {
+ device_t sc_dev;
+ struct resource *sc_mem_res;
+ int sc_mem_rid;
+ struct resource *sc_irq_res;
+ int sc_irq_rid;
+ void *sc_intr_hl;
+ struct intr_config_hook sc_mode_hook;
+ struct videomode sc_mode;
+ uint8_t *sc_edid;
+ uint8_t sc_edid_len;
+ phandle_t sc_i2c_xref;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6dl-hdmi", 1},
+ {"fsl,imx6q-hdmi", 1},
+ {NULL, 0}
+};
+
+static struct imx_hdmi_softc *imx_hdmi_sc;
+
+static inline uint8_t
+RD1(struct imx_hdmi_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_1(sc->sc_mem_res, off));
+}
+
+static inline void
+WR1(struct imx_hdmi_softc *sc, bus_size_t off, uint8_t val)
+{
+
+ bus_write_1(sc->sc_mem_res, off, val);
+}
+
+static uint8_t
+imx_hdmi_read_1(bus_size_t off)
+{
+
+ return RD1(imx_hdmi_sc, off);
+}
+
+static void
+imx_hdmi_write_1(bus_size_t off, uint8_t val)
+{
+
+ WR1(imx_hdmi_sc, off, val);
+}
+
+static void
+imx_hdmi_phy_wait_i2c_done(struct imx_hdmi_softc *sc, int msec)
+{
+ unsigned char val = 0;
+ val = imx_hdmi_read_1(HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ while (val == 0) {
+ DELAY(1000);
+ if (msec-- == 0)
+ return;
+ val = imx_hdmi_read_1(HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ }
+}
+
+static void imx_hdmi_phy_i2c_write(struct imx_hdmi_softc *sc, unsigned short data,
+ unsigned char addr)
+{
+ imx_hdmi_write_1(HDMI_IH_I2CMPHY_STAT0, 0xFF);
+ imx_hdmi_write_1(HDMI_PHY_I2CM_ADDRESS_ADDR, addr);
+ imx_hdmi_write_1(HDMI_PHY_I2CM_DATAO_1_ADDR, (unsigned char)(data >> 8));
+ imx_hdmi_write_1(HDMI_PHY_I2CM_DATAO_0_ADDR, (unsigned char)(data >> 0));
+ imx_hdmi_write_1(HDMI_PHY_I2CM_OPERATION_ADDR, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE);
+ imx_hdmi_phy_wait_i2c_done(sc, 1000);
+}
+
+static void
+imx_hdmi_disable_overflow_interrupts(struct imx_hdmi_softc *sc)
+{
+ imx_hdmi_write_1(HDMI_IH_MUTE_FC_STAT2, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK);
+ imx_hdmi_write_1(HDMI_FC_MASK2, 0xff);
+}
+
+static void
+imx_hdmi_av_composer(struct imx_hdmi_softc *sc)
+{
+ uint8_t inv_val;
+ int hblank, vblank, hsync_len, hbp, vbp;
+
+ /* Set up HDMI_FC_INVIDCONF */
+ inv_val = ((sc->sc_mode.flags & VID_NVSYNC) ?
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW :
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH);
+
+ inv_val |= ((sc->sc_mode.flags & VID_NHSYNC) ?
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW :
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH);
+
+ inv_val |= HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH;
+
+ inv_val |= ((sc->sc_mode.flags & VID_INTERLACE) ?
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
+
+ inv_val |= ((sc->sc_mode.flags & VID_INTERLACE) ?
+ HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
+ HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
+
+ inv_val |= (1 /*DVI*/ ?
+ HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
+ HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
+
+ imx_hdmi_write_1(HDMI_FC_INVIDCONF, inv_val);
+
+ /* Set up horizontal active pixel region width */
+ imx_hdmi_write_1(HDMI_FC_INHACTV1, sc->sc_mode.hdisplay >> 8);
+ imx_hdmi_write_1(HDMI_FC_INHACTV0, sc->sc_mode.hdisplay);
+
+ /* Set up vertical blanking pixel region width */
+ imx_hdmi_write_1(HDMI_FC_INVACTV1, sc->sc_mode.vdisplay >> 8);
+ imx_hdmi_write_1(HDMI_FC_INVACTV0, sc->sc_mode.vdisplay);
+
+ /* Set up horizontal blanking pixel region width */
+ hblank = sc->sc_mode.htotal - sc->sc_mode.hdisplay;
+ imx_hdmi_write_1(HDMI_FC_INHBLANK1, hblank >> 8);
+ imx_hdmi_write_1(HDMI_FC_INHBLANK0, hblank);
+
+ /* Set up vertical blanking pixel region width */
+ vblank = sc->sc_mode.vtotal - sc->sc_mode.vdisplay;
+ imx_hdmi_write_1(HDMI_FC_INVBLANK, vblank);
+
+ /* Set up HSYNC active edge delay width (in pixel clks) */
+ hbp = sc->sc_mode.htotal - sc->sc_mode.hsync_end;
+ imx_hdmi_write_1(HDMI_FC_HSYNCINDELAY1, hbp >> 8);
+ imx_hdmi_write_1(HDMI_FC_HSYNCINDELAY0, hbp);
+
+ /* Set up VSYNC active edge delay (in pixel clks) */
+ vbp = sc->sc_mode.vtotal - sc->sc_mode.vsync_end;
+ imx_hdmi_write_1(HDMI_FC_VSYNCINDELAY, vbp);
+
+ hsync_len = (sc->sc_mode.hsync_end - sc->sc_mode.hsync_start);
+ /* Set up HSYNC active pulse width (in pixel clks) */
+ imx_hdmi_write_1(HDMI_FC_HSYNCINWIDTH1, hsync_len >> 8);
+ imx_hdmi_write_1(HDMI_FC_HSYNCINWIDTH0, hsync_len);
+
+ /* Set up VSYNC active edge delay (in pixel clks) */
+ imx_hdmi_write_1(HDMI_FC_VSYNCINWIDTH, (sc->sc_mode.vsync_end - sc->sc_mode.vsync_start));
+}
+
+static void
+imx_hdmi_phy_enable_power(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_PDZ_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_PDZ_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static void
+imx_hdmi_phy_enable_tmds(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_ENTMDS_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static void
+imx_hdmi_phy_gen2_pddq(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static void
+imx_hdmi_phy_gen2_txpwron(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static void
+imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_SELDATAENPOL_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static void
+imx_hdmi_phy_sel_interface_control(struct imx_hdmi_softc *sc, uint8_t enable)
+{
+ uint8_t reg;
+
+ reg = imx_hdmi_read_1(HDMI_PHY_CONF0);
+ reg &= ~HDMI_PHY_CONF0_SELDIPIF_MASK;
+ reg |= (enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
+ imx_hdmi_write_1(HDMI_PHY_CONF0, reg);
+}
+
+static inline void
+imx_hdmi_phy_test_clear(struct imx_hdmi_softc *sc, unsigned char bit)
+{
+ uint8_t val;
+
+ val = imx_hdmi_read_1(HDMI_PHY_TST0);
+ val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
+ val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
+ HDMI_PHY_TST0_TSTCLR_MASK;
+ imx_hdmi_write_1(HDMI_PHY_TST0, val);
+}
+
+static void imx_hdmi_clear_overflow(struct imx_hdmi_softc *sc)
+{
+ int count;
+ uint8_t val;
+
+ /* TMDS software reset */
+ imx_hdmi_write_1(HDMI_MC_SWRSTZ, (uint8_t)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ);
+
+ val = imx_hdmi_read_1(HDMI_FC_INVIDCONF);
+
+ for (count = 0 ; count < 5 ; count++)
+ imx_hdmi_write_1(HDMI_FC_INVIDCONF, val);
+}
+
+static int imx_hdmi_phy_configure(struct imx_hdmi_softc *sc)
+{
+ uint8_t val;
+ uint8_t msec;
+
+ imx_hdmi_write_1(HDMI_MC_FLOWCTRL, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS);
+
+ /* gen2 tx power off */
+ imx_hdmi_phy_gen2_txpwron(sc, 0);
+
+ /* gen2 pddq */
+ imx_hdmi_phy_gen2_pddq(sc, 1);
+
+ /* PHY reset */
+ imx_hdmi_write_1(HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_DEASSERT);
+ imx_hdmi_write_1(HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_ASSERT);
+
+ imx_hdmi_write_1(HDMI_MC_HEACPHY_RST, HDMI_MC_HEACPHY_RST_ASSERT);
+
+ imx_hdmi_phy_test_clear(sc, 1);
+ imx_hdmi_write_1(HDMI_PHY_I2CM_SLAVE_ADDR, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2);
+ imx_hdmi_phy_test_clear(sc, 0);
+
+ if (sc->sc_mode.dot_clock*1000 <= 45250000) {
+ /* PLL/MPLL Cfg */
+ imx_hdmi_phy_i2c_write(sc, 0x01e0, 0x06);
+ imx_hdmi_phy_i2c_write(sc, 0x0000, 0x15); /* GMPCTRL */
+ } else if (sc->sc_mode.dot_clock*1000 <= 92500000) {
+ imx_hdmi_phy_i2c_write(sc, 0x0140, 0x06);
+ imx_hdmi_phy_i2c_write(sc, 0x0005, 0x15);
+ } else if (sc->sc_mode.dot_clock*1000 <= 148500000) {
+ imx_hdmi_phy_i2c_write(sc, 0x00a0, 0x06);
+ imx_hdmi_phy_i2c_write(sc, 0x000a, 0x15);
+ } else {
+ imx_hdmi_phy_i2c_write(sc, 0x00a0, 0x06);
+ imx_hdmi_phy_i2c_write(sc, 0x000a, 0x15);
+ }
+
+ if (sc->sc_mode.dot_clock*1000 <= 54000000) {
+ imx_hdmi_phy_i2c_write(sc, 0x091c, 0x10); /* CURRCTRL */
+ } else if (sc->sc_mode.dot_clock*1000 <= 58400000) {
+ imx_hdmi_phy_i2c_write(sc, 0x091c, 0x10);
+ } else if (sc->sc_mode.dot_clock*1000 <= 72000000) {
+ imx_hdmi_phy_i2c_write(sc, 0x06dc, 0x10);
+ } else if (sc->sc_mode.dot_clock*1000 <= 74250000) {
+ imx_hdmi_phy_i2c_write(sc, 0x06dc, 0x10);
+ } else if (sc->sc_mode.dot_clock*1000 <= 118800000) {
+ imx_hdmi_phy_i2c_write(sc, 0x091c, 0x10);
+ } else if (sc->sc_mode.dot_clock*1000 <= 216000000) {
+ imx_hdmi_phy_i2c_write(sc, 0x06dc, 0x10);
+ } else {
+ panic("Unsupported mode\n");
+ }
+
+ imx_hdmi_phy_i2c_write(sc, 0x0000, 0x13); /* PLLPHBYCTRL */
+ imx_hdmi_phy_i2c_write(sc, 0x0006, 0x17);
+ /* RESISTANCE TERM 133Ohm Cfg */
+ imx_hdmi_phy_i2c_write(sc, 0x0005, 0x19); /* TXTERM */
+ /* PREEMP Cgf 0.00 */
+ imx_hdmi_phy_i2c_write(sc, 0x800d, 0x09); /* CKSYMTXCTRL */
+ /* TX/CK LVL 10 */
+ imx_hdmi_phy_i2c_write(sc, 0x01ad, 0x0E); /* VLEVCTRL */
+
+ /* REMOVE CLK TERM */
+ imx_hdmi_phy_i2c_write(sc, 0x8000, 0x05); /* CKCALCTRL */
+
+ if (sc->sc_mode.dot_clock*1000 > 148500000) {
+ imx_hdmi_phy_i2c_write(sc, 0x800b, 0x09);
+ imx_hdmi_phy_i2c_write(sc, 0x0129, 0x0E);
+ }
+
+ imx_hdmi_phy_enable_power(sc, 1);
+
+ /* toggle TMDS enable */
+ imx_hdmi_phy_enable_tmds(sc, 0);
+ imx_hdmi_phy_enable_tmds(sc, 1);
+
+ /* gen2 tx power on */
+ imx_hdmi_phy_gen2_txpwron(sc, 1);
+ imx_hdmi_phy_gen2_pddq(sc, 0);
+
+ /*Wait for PHY PLL lock */
+ msec = 4;
+ val = imx_hdmi_read_1(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+ while (val == 0) {
+ DELAY(1000);
+ if (msec-- == 0) {
+ device_printf(sc->sc_dev, "PHY PLL not locked\n");
+ return (-1);
+ }
+ val = imx_hdmi_read_1(HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+ }
+
+ return true;
+}
+
+static void imx_hdmi_phy_init(struct imx_hdmi_softc *sc)
+{
+ int i;
+
+ /* HDMI Phy spec says to do the phy initialization sequence twice */
+ for (i = 0 ; i < 2 ; i++) {
+ imx_hdmi_phy_sel_data_en_pol(sc, 1);
+ imx_hdmi_phy_sel_interface_control(sc, 0);
+ imx_hdmi_phy_enable_tmds(sc, 0);
+ imx_hdmi_phy_enable_power(sc, 0);
+
+ /* Enable CSC */
+ imx_hdmi_phy_configure(sc);
+ }
+}
+
+static void imx_hdmi_enable_video_path(struct imx_hdmi_softc *sc)
+{
+ uint8_t clkdis;
+
+ /* control period minimum duration */
+ imx_hdmi_write_1(HDMI_FC_CTRLDUR, 12);
+ imx_hdmi_write_1(HDMI_FC_EXCTRLDUR, 32);
+ imx_hdmi_write_1(HDMI_FC_EXCTRLSPAC, 1);
+
+ /* Set to fill TMDS data channels */
+ imx_hdmi_write_1(HDMI_FC_CH0PREAM, 0x0B);
+ imx_hdmi_write_1(HDMI_FC_CH1PREAM, 0x16);
+ imx_hdmi_write_1(HDMI_FC_CH2PREAM, 0x21);
+
+ /* Save CEC clock */
+ clkdis = imx_hdmi_read_1(HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
+
+ /* Enable pixel clock and tmds data path */
+ clkdis = 0x7F & clkdis;
+ clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+ imx_hdmi_write_1(HDMI_MC_CLKDIS, clkdis);
+
+ clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+ imx_hdmi_write_1(HDMI_MC_CLKDIS, clkdis);
+}
+
+static void imx_hdmi_video_packetize(struct imx_hdmi_softc *sc)
+{
+ unsigned int color_depth = 0;
+ unsigned int remap_size = HDMI_VP_REMAP_YCC422_16BIT;
+ unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
+ uint8_t val;
+
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+ color_depth = 0;
+
+ /* set the packetizer registers */
+ val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+ HDMI_VP_PR_CD_COLOR_DEPTH_MASK);
+ imx_hdmi_write_1(HDMI_VP_PR_CD, val);
+
+ val = imx_hdmi_read_1(HDMI_VP_STUFF);
+ val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
+ val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
+ imx_hdmi_write_1(HDMI_VP_STUFF, val);
+
+ val = imx_hdmi_read_1(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_PR_EN_MASK |
+ HDMI_VP_CONF_BYPASS_SELECT_MASK);
+ val |= HDMI_VP_CONF_PR_EN_DISABLE |
+ HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+ imx_hdmi_write_1(HDMI_VP_CONF, val);
+
+ val = imx_hdmi_read_1(HDMI_VP_STUFF);
+ val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
+ val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
+ imx_hdmi_write_1(HDMI_VP_STUFF, val);
+
+ imx_hdmi_write_1(HDMI_VP_REMAP, remap_size);
+
+ if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
+ val = imx_hdmi_read_1(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_ENABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ imx_hdmi_write_1(HDMI_VP_CONF, val);
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
+ val = imx_hdmi_read_1(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_ENABLE;
+ imx_hdmi_write_1(HDMI_VP_CONF, val);
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
+ val = imx_hdmi_read_1(HDMI_VP_CONF);
+ val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
+ HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK);
+ val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ imx_hdmi_write_1(HDMI_VP_CONF, val);
+ } else {
+ return;
+ }
+
+ val = imx_hdmi_read_1(HDMI_VP_STUFF);
+ val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
+ HDMI_VP_STUFF_YCC422_STUFFING_MASK);
+ val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+ HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
+ imx_hdmi_write_1(HDMI_VP_STUFF, val);
+
+ val = imx_hdmi_read_1(HDMI_VP_CONF);
+ val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
+ val |= output_select;
+ imx_hdmi_write_1(HDMI_VP_CONF, val);
+}
+
+static void imx_hdmi_video_sample(struct imx_hdmi_softc *sc)
+{
+ int color_format;
+ uint8_t val;
+
+ color_format = 0x01;
+ val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+ ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+ HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+ imx_hdmi_write_1(HDMI_TX_INVID0, val);
+
+ /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
+ val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
+ imx_hdmi_write_1(HDMI_TX_INSTUFFING, val);
+ imx_hdmi_write_1(HDMI_TX_GYDATA0, 0x0);
+ imx_hdmi_write_1(HDMI_TX_GYDATA1, 0x0);
+ imx_hdmi_write_1(HDMI_TX_RCRDATA0, 0x0);
+ imx_hdmi_write_1(HDMI_TX_RCRDATA1, 0x0);
+ imx_hdmi_write_1(HDMI_TX_BCBDATA0, 0x0);
+ imx_hdmi_write_1(HDMI_TX_BCBDATA1, 0x0);
+}
+
+static int
+imx_hdmi_set_mode(struct imx_hdmi_softc *sc)
+{
+ imx_hdmi_disable_overflow_interrupts(sc);
+ imx_hdmi_av_composer(sc);
+ imx_hdmi_phy_init(sc);
+ imx_hdmi_enable_video_path(sc);
+ /* TODO: AVI infoframes */
+ imx_hdmi_video_packetize(sc);
+ /* TODO: imx_hdmi_video_csc(sc); */
+ imx_hdmi_video_sample(sc);
+ imx_hdmi_clear_overflow(sc);
+
+ return (0);
+}
+
+static int
+hdmi_edid_read(struct imx_hdmi_softc *sc, uint8_t **edid, uint32_t *edid_len)
+{
+ device_t i2c_dev;
+ int result;
+ uint8_t addr = 0;
+ struct iic_msg msg[] = {
+ { 0, IIC_M_WR, 1, &addr },
+ { 0, IIC_M_RD, EDID_LENGTH, NULL}
+ };
+
+ *edid = NULL;
+ *edid_len = 0;
+
+ if (sc->sc_i2c_xref == 0)
+ return (ENXIO);
+
+ i2c_dev = OF_device_from_xref(sc->sc_i2c_xref);
+ if (!i2c_dev) {
+ device_printf(sc->sc_dev,
+ "no actual device for \"ddc-i2c-bus\" property (handle=%x)\n", sc->sc_i2c_xref);
+ return (ENXIO);
+ }
+
+ device_printf(sc->sc_dev, "reading EDID from %s, addr %02x\n",
+ device_get_nameunit(i2c_dev), I2C_DDC_ADDR/2);
+
+ msg[0].slave = I2C_DDC_ADDR;
+ msg[1].slave = I2C_DDC_ADDR;
+ msg[1].buf = sc->sc_edid;
+
+ result = iicbus_transfer(i2c_dev, msg, 2);
+ if (result) {
+ device_printf(sc->sc_dev, "i2c transfer failed: %d\n", result);
+ return (result);
+ }
+ else {
+ *edid_len = sc->sc_edid_len;
+ *edid = sc->sc_edid;
+ }
+
+ return (result);
+}
+
+static void
+imx_hdmi_detect_cable(void *arg)
+{
+ struct imx_hdmi_softc *sc;
+
+ sc = arg;
+ EVENTHANDLER_INVOKE(hdmi_event, sc->sc_dev, HDMI_EVENT_CONNECTED);
+ /* Finished with the interrupt hook */
+ config_intrhook_disestablish(&sc->sc_mode_hook);
+}
+
+imx_hdmi_intr(void *arg)
+{
+ /* Do nothing */
+}
+
+static int
+imx_hdmi_detach(device_t dev)
+{
+ struct imx_hdmi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->sc_mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ if (sc->sc_intr_hl)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hl);
+
+ if (sc->sc_irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, sc->sc_irq_res);
+
+ return (0);
+}
+
+static int
+imx_hdmi_attach(device_t dev)
+{
+ struct imx_hdmi_softc *sc;
+ int err;
+ uint32_t gpr3;
+ int ipu_id, disp_id;
+ phandle_t node, i2c_xref;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ err = 0;
+
+ /* Allocate memory resources. */
+ sc->sc_mem_rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mem_rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ /* Allocate bus_space resources. */
+ sc->sc_irq_rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irq_rid,
+ RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(dev, "No IRQ\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, imx_hdmi_intr, sc,
+ &sc->sc_intr_hl) != 0) {
+ device_printf(dev, "Unable to setup the irq handler.\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ sc->sc_mode_hook.ich_func = imx_hdmi_detect_cable;
+ sc->sc_mode_hook.ich_arg = sc;
+
+ if (config_intrhook_establish(&sc->sc_mode_hook) != 0) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "ddc-i2c-bus", &i2c_xref, sizeof(i2c_xref)) == -1)
+ sc->sc_i2c_xref = 0;
+ else
+ sc->sc_i2c_xref = i2c_xref;
+
+ err = 0;
+
+ sc->sc_edid = malloc(EDID_LENGTH, M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->sc_edid_len = EDID_LENGTH;
+
+ imx_ccm_hdmi_enable();
+
+ device_printf(sc->sc_dev, "HDMI controller %02x:%02x:%02x:%02x\n",
+ RD1(sc, HDMI_DESIGN_ID), RD1(sc, HDMI_REVISION_ID),
+ RD1(sc, HDMI_PRODUCT_ID0), RD1(sc, HDMI_PRODUCT_ID1));
+
+ ipu_id = 0;
+ disp_id = 0;
+
+ gpr3 = imx_iomux_gpr_get(12);
+ gpr3 &= ~0x0d;
+ gpr3 |= ((ipu_id << 1) | disp_id) << 2;
+ imx_iomux_gpr_set(12, gpr3);
+
+ WR1(sc, HDMI_PHY_POL0, HDMI_PHY_HPD);
+ WR1(sc, HDMI_IH_PHY_STAT0, HDMI_IH_PHY_STAT0_HPD);
+
+ imx_hdmi_sc = sc;
+out:
+
+ if (err != 0)
+ imx_hdmi_detach(dev);
+
+ return (err);
+}
+
+static int
+imx_hdmi_probe(device_t dev)
+{
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX6 HDMI core");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+imx_hdmi_get_edid(device_t dev, uint8_t **edid, uint32_t *edid_len)
+{
+ struct imx_hdmi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return hdmi_edid_read(sc, edid, edid_len);
+}
+
+static int
+imx_hdmi_set_videomode(device_t dev, const struct videomode *mode)
+{
+ struct imx_hdmi_softc *sc;
+
+ sc = device_get_softc(dev);
+ memcpy(&sc->sc_mode, mode, sizeof(*mode));
+ imx_hdmi_set_mode(sc);
+
+ return (0);
+}
+
+static device_method_t imx_hdmi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, imx_hdmi_probe),
+ DEVMETHOD(device_attach, imx_hdmi_attach),
+ DEVMETHOD(device_detach, imx_hdmi_detach),
+
+ /* HDMI methods */
+ DEVMETHOD(hdmi_get_edid, imx_hdmi_get_edid),
+ DEVMETHOD(hdmi_set_videomode, imx_hdmi_set_videomode),
+
+ DEVMETHOD_END
+};
+
+static driver_t imx_hdmi_driver = {
+ "hdmi",
+ imx_hdmi_methods,
+ sizeof(struct imx_hdmi_softc)
+};
+
+static devclass_t imx_hdmi_devclass;
+
+DRIVER_MODULE(hdmi, simplebus, imx_hdmi_driver, imx_hdmi_devclass, 0, 0);
Index: sys/arm/freescale/imx/imx6_hdmi_regs.h
===================================================================
--- /dev/null
+++ sys/arm/freescale/imx/imx6_hdmi_regs.h
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IMX6__HDMI_REGS_H__
+#define __IMX6__HDMI_REGS_H__
+#define HDMI_DESIGN_ID 0x0000
+#define HDMI_REVISION_ID 0x0001
+#define HDMI_PRODUCT_ID0 0x0002
+#define HDMI_PRODUCT_ID1 0x0003
+
+/* Interrupt Registers */
+#define HDMI_IH_FC_STAT0 0x0100
+#define HDMI_IH_FC_STAT1 0x0101
+#define HDMI_IH_FC_STAT2 0x0102
+#define HDMI_IH_AS_STAT0 0x0103
+#define HDMI_IH_PHY_STAT0 0x0104
+#define HDMI_IH_PHY_STAT0_HPD (1 << 0)
+#define HDMI_IH_I2CM_STAT0 0x0105
+#define HDMI_IH_CEC_STAT0 0x0106
+#define HDMI_IH_VP_STAT0 0x0107
+#define HDMI_IH_I2CMPHY_STAT0 0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0 0x0109
+
+#define HDMI_IH_MUTE_FC_STAT0 0x0180
+#define HDMI_IH_MUTE_FC_STAT1 0x0181
+#define HDMI_IH_MUTE_FC_STAT2 0x0182
+#define HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK (0x3)
+#define HDMI_IH_MUTE_AS_STAT0 0x0183
+#define HDMI_IH_MUTE_PHY_STAT0 0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0 0x0185
+#define HDMI_IH_MUTE_CEC_STAT0 0x0186
+#define HDMI_IH_MUTE_VP_STAT0 0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189
+#define HDMI_IH_MUTE 0x01FF
+#define HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT (1<<1)
+#define HDMI_IH_MUTE_MUTE_ALL_INTERRUPT (1<<0)
+
+/* Video Sample Registers */
+#define HDMI_TX_INVID0 0x0200
+#define HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK 0x80
+#define HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE 0x80
+#define HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE 0x00
+#define HDMI_TX_INVID0_VIDEO_MAPPING_MASK 0x1F
+#define HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET 0
+#define HDMI_TX_INSTUFFING 0x0201
+#define HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK 0x4
+#define HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE 0x4
+#define HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE 0x0
+#define HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK 0x2
+#define HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE 0x2
+#define HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE 0x0
+#define HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK 0x1
+#define HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE 0x1
+#define HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE 0x0
+#define HDMI_TX_GYDATA0 0x0202
+#define HDMI_TX_GYDATA1 0x0203
+#define HDMI_TX_RCRDATA0 0x0204
+#define HDMI_TX_RCRDATA1 0x0205
+#define HDMI_TX_BCBDATA0 0x0206
+#define HDMI_TX_BCBDATA1 0x0207
+
+/* Video Packetizer Registers */
+#define HDMI_VP_STATUS 0x0800
+#define HDMI_VP_PR_CD 0x0801
+#define HDMI_VP_PR_CD_COLOR_DEPTH_MASK 0xF0
+#define HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET 4
+#define HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK 0x0F
+#define HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET 0
+
+#define HDMI_VP_STUFF 0x0802
+#define HDMI_VP_STUFF_IDEFAULT_PHASE_MASK 0x20
+#define HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET 5
+#define HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK 0x10
+#define HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET 4
+#define HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK 0x8
+#define HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET 3
+#define HDMI_VP_STUFF_YCC422_STUFFING_MASK 0x4
+#define HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE 0x4
+#define HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE 0x0
+#define HDMI_VP_STUFF_PP_STUFFING_MASK 0x2
+#define HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE 0x2
+#define HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE 0x0
+#define HDMI_VP_STUFF_PR_STUFFING_MASK 0x1
+#define HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE 0x1
+#define HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE 0x0
+#define HDMI_VP_REMAP 0x0803
+#define HDMI_VP_REMAP_MASK 0x3
+#define HDMI_VP_REMAP_YCC422_24BIT 0x2
+#define HDMI_VP_REMAP_YCC422_20BIT 0x1
+#define HDMI_VP_REMAP_YCC422_16BIT 0x0
+#define HDMI_VP_CONF 0x0804
+#define HDMI_VP_CONF_BYPASS_EN_MASK 0x40
+#define HDMI_VP_CONF_BYPASS_EN_ENABLE 0x40
+#define HDMI_VP_CONF_BYPASS_EN_DISABLE 0x00
+#define HDMI_VP_CONF_PP_EN_ENMASK 0x20
+#define HDMI_VP_CONF_PP_EN_ENABLE 0x20
+#define HDMI_VP_CONF_PP_EN_DISABLE 0x00
+#define HDMI_VP_CONF_PR_EN_MASK 0x10
+#define HDMI_VP_CONF_PR_EN_ENABLE 0x10
+#define HDMI_VP_CONF_PR_EN_DISABLE 0x00
+#define HDMI_VP_CONF_YCC422_EN_MASK 0x8
+#define HDMI_VP_CONF_YCC422_EN_ENABLE 0x8
+#define HDMI_VP_CONF_YCC422_EN_DISABLE 0x0
+#define HDMI_VP_CONF_BYPASS_SELECT_MASK 0x4
+#define HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER 0x4
+#define HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER 0x0
+#define HDMI_VP_CONF_OUTPUT_SELECTOR_MASK 0x3
+#define HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS 0x3
+#define HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 0x1
+#define HDMI_VP_CONF_OUTPUT_SELECTOR_PP 0x0
+#define HDMI_VP_STAT 0x0805
+#define HDMI_VP_INT 0x0806
+#define HDMI_VP_MASK 0x0807
+#define HDMI_VP_POL 0x0808
+
+/* Frame Composer Registers */
+#define HDMI_FC_INVIDCONF 0x1000
+#define HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH 0x40
+#define HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW 0x00
+#define HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH 0x20
+#define HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW 0x00
+#define HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH 0x10
+#define HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW 0x00
+#define HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE 0x8
+#define HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE 0x0
+#define HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH 0x2
+#define HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW 0x0
+#define HDMI_FC_INVIDCONF_IN_I_P_INTERLACED 0x1
+#define HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE 0x0
+#define HDMI_FC_INHACTV0 0x1001
+#define HDMI_FC_INHACTV1 0x1002
+#define HDMI_FC_INHBLANK0 0x1003
+#define HDMI_FC_INHBLANK1 0x1004
+#define HDMI_FC_INVACTV0 0x1005
+#define HDMI_FC_INVACTV1 0x1006
+#define HDMI_FC_INVBLANK 0x1007
+#define HDMI_FC_HSYNCINDELAY0 0x1008
+#define HDMI_FC_HSYNCINDELAY1 0x1009
+#define HDMI_FC_HSYNCINWIDTH0 0x100A
+#define HDMI_FC_HSYNCINWIDTH1 0x100B
+#define HDMI_FC_VSYNCINDELAY 0x100C
+#define HDMI_FC_VSYNCINWIDTH 0x100D
+#define HDMI_FC_INFREQ0 0x100E
+#define HDMI_FC_INFREQ1 0x100F
+#define HDMI_FC_INFREQ2 0x1010
+#define HDMI_FC_CTRLDUR 0x1011
+#define HDMI_FC_EXCTRLDUR 0x1012
+#define HDMI_FC_EXCTRLSPAC 0x1013
+#define HDMI_FC_CH0PREAM 0x1014
+#define HDMI_FC_CH1PREAM 0x1015
+#define HDMI_FC_CH2PREAM 0x1016
+#define HDMI_FC_AVICONF3 0x1017
+#define HDMI_FC_GCP 0x1018
+#define HDMI_FC_AVICONF0 0x1019
+#define HDMI_FC_AVICONF1 0x101A
+#define HDMI_FC_AVICONF2 0x101B
+#define HDMI_FC_AVIVID 0x101C
+#define HDMI_FC_AVIETB0 0x101D
+#define HDMI_FC_AVIETB1 0x101E
+#define HDMI_FC_AVISBB0 0x101F
+#define HDMI_FC_AVISBB1 0x1020
+#define HDMI_FC_AVIELB0 0x1021
+#define HDMI_FC_AVIELB1 0x1022
+#define HDMI_FC_AVISRB0 0x1023
+#define HDMI_FC_AVISRB1 0x1024
+#define HDMI_FC_AUDICONF0 0x1025
+#define HDMI_FC_AUDICONF1 0x1026
+#define HDMI_FC_AUDICONF2 0x1027
+#define HDMI_FC_AUDICONF3 0x1028
+#define HDMI_FC_VSDIEEEID0 0x1029
+#define HDMI_FC_VSDSIZE 0x102A
+#define HDMI_FC_VSDIEEEID1 0x1030
+#define HDMI_FC_VSDIEEEID2 0x1031
+#define HDMI_FC_VSDPAYLOAD0 0x1032
+#define HDMI_FC_VSDPAYLOAD1 0x1033
+#define HDMI_FC_VSDPAYLOAD2 0x1034
+#define HDMI_FC_VSDPAYLOAD3 0x1035
+#define HDMI_FC_VSDPAYLOAD4 0x1036
+#define HDMI_FC_VSDPAYLOAD5 0x1037
+#define HDMI_FC_VSDPAYLOAD6 0x1038
+#define HDMI_FC_VSDPAYLOAD7 0x1039
+#define HDMI_FC_VSDPAYLOAD8 0x103A
+#define HDMI_FC_VSDPAYLOAD9 0x103B
+#define HDMI_FC_VSDPAYLOAD10 0x103C
+#define HDMI_FC_VSDPAYLOAD11 0x103D
+#define HDMI_FC_VSDPAYLOAD12 0x103E
+#define HDMI_FC_VSDPAYLOAD13 0x103F
+#define HDMI_FC_VSDPAYLOAD14 0x1040
+#define HDMI_FC_VSDPAYLOAD15 0x1041
+#define HDMI_FC_VSDPAYLOAD16 0x1042
+#define HDMI_FC_VSDPAYLOAD17 0x1043
+#define HDMI_FC_VSDPAYLOAD18 0x1044
+#define HDMI_FC_VSDPAYLOAD19 0x1045
+#define HDMI_FC_VSDPAYLOAD20 0x1046
+#define HDMI_FC_VSDPAYLOAD21 0x1047
+#define HDMI_FC_VSDPAYLOAD22 0x1048
+#define HDMI_FC_VSDPAYLOAD23 0x1049
+#define HDMI_FC_SPDVENDORNAME0 0x104A
+#define HDMI_FC_SPDVENDORNAME1 0x104B
+#define HDMI_FC_SPDVENDORNAME2 0x104C
+#define HDMI_FC_SPDVENDORNAME3 0x104D
+#define HDMI_FC_SPDVENDORNAME4 0x104E
+#define HDMI_FC_SPDVENDORNAME5 0x104F
+#define HDMI_FC_SPDVENDORNAME6 0x1050
+#define HDMI_FC_SPDVENDORNAME7 0x1051
+#define HDMI_FC_SDPPRODUCTNAME0 0x1052
+#define HDMI_FC_SDPPRODUCTNAME1 0x1053
+#define HDMI_FC_SDPPRODUCTNAME2 0x1054
+#define HDMI_FC_SDPPRODUCTNAME3 0x1055
+#define HDMI_FC_SDPPRODUCTNAME4 0x1056
+#define HDMI_FC_SDPPRODUCTNAME5 0x1057
+#define HDMI_FC_SDPPRODUCTNAME6 0x1058
+#define HDMI_FC_SDPPRODUCTNAME7 0x1059
+#define HDMI_FC_SDPPRODUCTNAME8 0x105A
+#define HDMI_FC_SDPPRODUCTNAME9 0x105B
+#define HDMI_FC_SDPPRODUCTNAME10 0x105C
+#define HDMI_FC_SDPPRODUCTNAME11 0x105D
+#define HDMI_FC_SDPPRODUCTNAME12 0x105E
+#define HDMI_FC_SDPPRODUCTNAME13 0x105F
+#define HDMI_FC_SDPPRODUCTNAME14 0x1060
+#define HDMI_FC_SPDPRODUCTNAME15 0x1061
+#define HDMI_FC_SPDDEVICEINF 0x1062
+#define HDMI_FC_AUDSCONF 0x1063
+#define HDMI_FC_AUDSSTAT 0x1064
+#define HDMI_FC_DATACH0FILL 0x1070
+#define HDMI_FC_DATACH1FILL 0x1071
+#define HDMI_FC_DATACH2FILL 0x1072
+#define HDMI_FC_CTRLQHIGH 0x1073
+#define HDMI_FC_CTRLQLOW 0x1074
+#define HDMI_FC_ACP0 0x1075
+#define HDMI_FC_ACP28 0x1076
+#define HDMI_FC_ACP27 0x1077
+#define HDMI_FC_ACP26 0x1078
+#define HDMI_FC_ACP25 0x1079
+#define HDMI_FC_ACP24 0x107A
+#define HDMI_FC_ACP23 0x107B
+#define HDMI_FC_ACP22 0x107C
+#define HDMI_FC_ACP21 0x107D
+#define HDMI_FC_ACP20 0x107E
+#define HDMI_FC_ACP19 0x107F
+#define HDMI_FC_ACP18 0x1080
+#define HDMI_FC_ACP17 0x1081
+#define HDMI_FC_ACP16 0x1082
+#define HDMI_FC_ACP15 0x1083
+#define HDMI_FC_ACP14 0x1084
+#define HDMI_FC_ACP13 0x1085
+#define HDMI_FC_ACP12 0x1086
+#define HDMI_FC_ACP11 0x1087
+#define HDMI_FC_ACP10 0x1088
+#define HDMI_FC_ACP9 0x1089
+#define HDMI_FC_ACP8 0x108A
+#define HDMI_FC_ACP7 0x108B
+#define HDMI_FC_ACP6 0x108C
+#define HDMI_FC_ACP5 0x108D
+#define HDMI_FC_ACP4 0x108E
+#define HDMI_FC_ACP3 0x108F
+#define HDMI_FC_ACP2 0x1090
+#define HDMI_FC_ACP1 0x1091
+#define HDMI_FC_ISCR1_0 0x1092
+#define HDMI_FC_ISCR1_16 0x1093
+#define HDMI_FC_ISCR1_15 0x1094
+#define HDMI_FC_ISCR1_14 0x1095
+#define HDMI_FC_ISCR1_13 0x1096
+#define HDMI_FC_ISCR1_12 0x1097
+#define HDMI_FC_ISCR1_11 0x1098
+#define HDMI_FC_ISCR1_10 0x1099
+#define HDMI_FC_ISCR1_9 0x109A
+#define HDMI_FC_ISCR1_8 0x109B
+#define HDMI_FC_ISCR1_7 0x109C
+#define HDMI_FC_ISCR1_6 0x109D
+#define HDMI_FC_ISCR1_5 0x109E
+#define HDMI_FC_ISCR1_4 0x109F
+#define HDMI_FC_ISCR1_3 0x10A0
+#define HDMI_FC_ISCR1_2 0x10A1
+#define HDMI_FC_ISCR1_1 0x10A2
+#define HDMI_FC_ISCR2_15 0x10A3
+#define HDMI_FC_ISCR2_14 0x10A4
+#define HDMI_FC_ISCR2_13 0x10A5
+#define HDMI_FC_ISCR2_12 0x10A6
+#define HDMI_FC_ISCR2_11 0x10A7
+#define HDMI_FC_ISCR2_10 0x10A8
+#define HDMI_FC_ISCR2_9 0x10A9
+#define HDMI_FC_ISCR2_8 0x10AA
+#define HDMI_FC_ISCR2_7 0x10AB
+#define HDMI_FC_ISCR2_6 0x10AC
+#define HDMI_FC_ISCR2_5 0x10AD
+#define HDMI_FC_ISCR2_4 0x10AE
+#define HDMI_FC_ISCR2_3 0x10AF
+#define HDMI_FC_ISCR2_2 0x10B0
+#define HDMI_FC_ISCR2_1 0x10B1
+#define HDMI_FC_ISCR2_0 0x10B2
+#define HDMI_FC_DATAUTO0 0x10B3
+#define HDMI_FC_DATAUTO1 0x10B4
+#define HDMI_FC_DATAUTO2 0x10B5
+#define HDMI_FC_DATMAN 0x10B6
+#define HDMI_FC_DATAUTO3 0x10B7
+#define HDMI_FC_RDRB0 0x10B8
+#define HDMI_FC_RDRB1 0x10B9
+#define HDMI_FC_RDRB2 0x10BA
+#define HDMI_FC_RDRB3 0x10BB
+#define HDMI_FC_RDRB4 0x10BC
+#define HDMI_FC_RDRB5 0x10BD
+#define HDMI_FC_RDRB6 0x10BE
+#define HDMI_FC_RDRB7 0x10BF
+#define HDMI_FC_STAT0 0x10D0
+#define HDMI_FC_INT0 0x10D1
+#define HDMI_FC_MASK0 0x10D2
+#define HDMI_FC_POL0 0x10D3
+#define HDMI_FC_STAT1 0x10D4
+#define HDMI_FC_INT1 0x10D5
+#define HDMI_FC_MASK1 0x10D6
+#define HDMI_FC_POL1 0x10D7
+#define HDMI_FC_STAT2 0x10D8
+#define HDMI_FC_INT2 0x10D9
+#define HDMI_FC_MASK2 0x10DA
+#define HDMI_FC_POL2 0x10DB
+#define HDMI_FC_PRCONF 0x10E0
+
+#define HDMI_FC_GMD_STAT 0x1100
+#define HDMI_FC_GMD_EN 0x1101
+#define HDMI_FC_GMD_UP 0x1102
+#define HDMI_FC_GMD_CONF 0x1103
+#define HDMI_FC_GMD_HB 0x1104
+#define HDMI_FC_GMD_PB0 0x1105
+#define HDMI_FC_GMD_PB1 0x1106
+#define HDMI_FC_GMD_PB2 0x1107
+#define HDMI_FC_GMD_PB3 0x1108
+#define HDMI_FC_GMD_PB4 0x1109
+#define HDMI_FC_GMD_PB5 0x110A
+#define HDMI_FC_GMD_PB6 0x110B
+#define HDMI_FC_GMD_PB7 0x110C
+#define HDMI_FC_GMD_PB8 0x110D
+#define HDMI_FC_GMD_PB9 0x110E
+#define HDMI_FC_GMD_PB10 0x110F
+#define HDMI_FC_GMD_PB11 0x1110
+#define HDMI_FC_GMD_PB12 0x1111
+#define HDMI_FC_GMD_PB13 0x1112
+#define HDMI_FC_GMD_PB14 0x1113
+#define HDMI_FC_GMD_PB15 0x1114
+#define HDMI_FC_GMD_PB16 0x1115
+#define HDMI_FC_GMD_PB17 0x1116
+#define HDMI_FC_GMD_PB18 0x1117
+#define HDMI_FC_GMD_PB19 0x1118
+#define HDMI_FC_GMD_PB20 0x1119
+#define HDMI_FC_GMD_PB21 0x111A
+#define HDMI_FC_GMD_PB22 0x111B
+#define HDMI_FC_GMD_PB23 0x111C
+#define HDMI_FC_GMD_PB24 0x111D
+#define HDMI_FC_GMD_PB25 0x111E
+#define HDMI_FC_GMD_PB26 0x111F
+#define HDMI_FC_GMD_PB27 0x1120
+
+#define HDMI_FC_DBGFORCE 0x1200
+#define HDMI_FC_DBGAUD0CH0 0x1201
+#define HDMI_FC_DBGAUD1CH0 0x1202
+#define HDMI_FC_DBGAUD2CH0 0x1203
+#define HDMI_FC_DBGAUD0CH1 0x1204
+#define HDMI_FC_DBGAUD1CH1 0x1205
+#define HDMI_FC_DBGAUD2CH1 0x1206
+#define HDMI_FC_DBGAUD0CH2 0x1207
+#define HDMI_FC_DBGAUD1CH2 0x1208
+#define HDMI_FC_DBGAUD2CH2 0x1209
+#define HDMI_FC_DBGAUD0CH3 0x120A
+#define HDMI_FC_DBGAUD1CH3 0x120B
+#define HDMI_FC_DBGAUD2CH3 0x120C
+#define HDMI_FC_DBGAUD0CH4 0x120D
+#define HDMI_FC_DBGAUD1CH4 0x120E
+#define HDMI_FC_DBGAUD2CH4 0x120F
+#define HDMI_FC_DBGAUD0CH5 0x1210
+#define HDMI_FC_DBGAUD1CH5 0x1211
+#define HDMI_FC_DBGAUD2CH5 0x1212
+#define HDMI_FC_DBGAUD0CH6 0x1213
+#define HDMI_FC_DBGAUD1CH6 0x1214
+#define HDMI_FC_DBGAUD2CH6 0x1215
+#define HDMI_FC_DBGAUD0CH7 0x1216
+#define HDMI_FC_DBGAUD1CH7 0x1217
+#define HDMI_FC_DBGAUD2CH7 0x1218
+#define HDMI_FC_DBGTMDS0 0x1219
+#define HDMI_FC_DBGTMDS1 0x121A
+#define HDMI_FC_DBGTMDS2 0x121B
+
+#define HDMI_PHY_CONF0 0x00003000
+#define HDMI_PHY_CONF0_PDZ_MASK 0x80
+#define HDMI_PHY_CONF0_PDZ_OFFSET 7
+#define HDMI_PHY_CONF0_ENTMDS_MASK 0x40
+#define HDMI_PHY_CONF0_ENTMDS_OFFSET 6
+#define HDMI_PHY_CONF0_SPARECTRL 0x20
+#define HDMI_PHY_CONF0_GEN2_PDDQ_MASK 0x10
+#define HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET 4
+#define HDMI_PHY_CONF0_GEN2_TXPWRON_MASK 0x8
+#define HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET 3
+#define HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK 0x4
+#define HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET 2
+#define HDMI_PHY_CONF0_SELDATAENPOL_MASK 0x2
+#define HDMI_PHY_CONF0_SELDATAENPOL_OFFSET 1
+#define HDMI_PHY_CONF0_SELDIPIF_MASK 0x1
+#define HDMI_PHY_CONF0_SELDIPIF_OFFSET 0
+#define HDMI_PHY_TST0 0x3001
+#define HDMI_PHY_TST0_TSTCLR_MASK 0x20
+#define HDMI_PHY_TST0_TSTCLR_OFFSET 5
+#define HDMI_PHY_TST0_TSTEN_MASK 0x10
+#define HDMI_PHY_TST0_TSTEN_OFFSET 4
+#define HDMI_PHY_TST0_TSTCLK_MASK 0x1
+#define HDMI_PHY_TST0_TSTCLK_OFFSET 0
+#define HDMI_PHY_TST1 0x3002
+#define HDMI_PHY_TST2 0x3003
+#define HDMI_PHY_STAT0 0x3004
+#define HDMI_PHY_TX_PHY_LOCK 0x01
+#define HDMI_PHY_INT0 0x3005
+#define HDMI_PHY_MASK0 0x3006
+#define HDMI_PHY_POL0 0x3007
+#define HDMI_PHY_HPD (1 << 1)
+
+/* HDMI Master PHY Registers */
+#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
+#define HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 0x69
+#define HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY 0x49
+#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
+#define HDMI_PHY_I2CM_INT_ADDR 0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR 0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
+
+/* Audio Sampler Registers */
+#define HDMI_AUD_CONF0 0x3100
+#define HDMI_AUD_CONF1 0x3101
+#define HDMI_AUD_INT 0x3102
+#define HDMI_AUD_CONF2 0x3103
+#define HDMI_AUD_N1 0x3200
+#define HDMI_AUD_N2 0x3201
+#define HDMI_AUD_N3 0x3202
+#define HDMI_AUD_CTS1 0x3203
+#define HDMI_AUD_CTS2 0x3204
+#define HDMI_AUD_CTS3 0x3205
+#define HDMI_AUD_INPUTCLKFS 0x3206
+#define HDMI_AUD_SPDIFINT 0x3302
+#define HDMI_AUD_CONF0_HBR 0x3400
+#define HDMI_AUD_HBR_STATUS 0x3401
+#define HDMI_AUD_HBR_INT 0x3402
+#define HDMI_AUD_HBR_POL 0x3403
+#define HDMI_AUD_HBR_MASK 0x3404
+
+/*
+ * Generic Parallel Audio Interface Registers
+ * Not used as GPAUD interface is not enabled in hw
+ */
+#define HDMI_GP_CONF0 0x3500
+#define HDMI_GP_CONF1 0x3501
+#define HDMI_GP_CONF2 0x3502
+#define HDMI_GP_STAT 0x3503
+#define HDMI_GP_INT 0x3504
+#define HDMI_GP_MASK 0x3505
+#define HDMI_GP_POL 0x3506
+
+/* Main Controller Registers */
+#define HDMI_MC_SFRDIV 0x4000
+#define HDMI_MC_CLKDIS 0x4001
+#define HDMI_MC_CLKDIS_HDCPCLK_DISABLE (1 << 6)
+#define HDMI_MC_CLKDIS_CECCLK_DISABLE (1 << 5)
+#define HDMI_MC_CLKDIS_CSCCLK_DISABLE (1 << 4)
+#define HDMI_MC_CLKDIS_AUDCLK_DISABLE (1 << 3)
+#define HDMI_MC_CLKDIS_PREPCLK_DISABLE (1 << 2)
+#define HDMI_MC_CLKDIS_TMDSCLK_DISABLE (1 << 1)
+#define HDMI_MC_CLKDIS_PIXELCLK_DISABLE (1 << 0)
+
+#define HDMI_MC_SWRSTZ 0x4002
+#define HDMI_MC_SWRSTZ_TMDSSWRST_REQ 0x02
+#define HDMI_MC_OPCTRL 0x4003
+#define HDMI_MC_FLOWCTRL 0x4004
+#define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK 0x1
+#define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH 0x1
+#define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS 0x0
+#define HDMI_MC_PHYRSTZ 0x4005
+#define HDMI_MC_PHYRSTZ_ASSERT 0x0
+#define HDMI_MC_PHYRSTZ_DEASSERT 0x1
+#define HDMI_MC_LOCKONCLOCK 0x4006
+#define HDMI_MC_HEACPHY_RST 0x4007
+#define HDMI_MC_HEACPHY_RST_ASSERT 0x1
+#define HDMI_MC_HEACPHY_RST_DEASSERT 0x0
+
+/* HDCP Encryption Engine Registers */
+#define HDMI_A_HDCPCFG0 0x5000
+#define HDMI_A_HDCPCFG1 0x5001
+#define HDMI_A_HDCPOBS0 0x5002
+#define HDMI_A_HDCPOBS1 0x5003
+#define HDMI_A_HDCPOBS2 0x5004
+#define HDMI_A_HDCPOBS3 0x5005
+#define HDMI_A_APIINTCLR 0x5006
+#define HDMI_A_APIINTSTAT 0x5007
+#define HDMI_A_APIINTMSK 0x5008
+#define HDMI_A_VIDPOLCFG 0x5009
+#define HDMI_A_OESSWCFG 0x500A
+#define HDMI_A_TIMER1SETUP0 0x500B
+#define HDMI_A_TIMER1SETUP1 0x500C
+#define HDMI_A_TIMER2SETUP0 0x500D
+#define HDMI_A_TIMER2SETUP1 0x500E
+#define HDMI_A_100MSCFG 0x500F
+#define HDMI_A_2SCFG0 0x5010
+#define HDMI_A_2SCFG1 0x5011
+#define HDMI_A_5SCFG0 0x5012
+#define HDMI_A_5SCFG1 0x5013
+#define HDMI_A_SRMVERLSB 0x5014
+#define HDMI_A_SRMVERMSB 0x5015
+#define HDMI_A_SRMCTRL 0x5016
+#define HDMI_A_SFRSETUP 0x5017
+#define HDMI_A_I2CHSETUP 0x5018
+#define HDMI_A_INTSETUP 0x5019
+#define HDMI_A_PRESETUP 0x501A
+#define HDMI_A_SRM_BASE 0x5020
+
+/* CEC Engine Registers */
+#define HDMI_CEC_CTRL 0x7D00
+#define HDMI_CEC_STAT 0x7D01
+#define HDMI_CEC_MASK 0x7D02
+#define HDMI_CEC_POLARITY 0x7D03
+#define HDMI_CEC_INT 0x7D04
+#define HDMI_CEC_ADDR_L 0x7D05
+#define HDMI_CEC_ADDR_H 0x7D06
+#define HDMI_CEC_TX_CNT 0x7D07
+#define HDMI_CEC_RX_CNT 0x7D08
+#define HDMI_CEC_TX_DATA0 0x7D10
+#define HDMI_CEC_TX_DATA1 0x7D11
+#define HDMI_CEC_TX_DATA2 0x7D12
+#define HDMI_CEC_TX_DATA3 0x7D13
+#define HDMI_CEC_TX_DATA4 0x7D14
+#define HDMI_CEC_TX_DATA5 0x7D15
+#define HDMI_CEC_TX_DATA6 0x7D16
+#define HDMI_CEC_TX_DATA7 0x7D17
+#define HDMI_CEC_TX_DATA8 0x7D18
+#define HDMI_CEC_TX_DATA9 0x7D19
+#define HDMI_CEC_TX_DATA10 0x7D1a
+#define HDMI_CEC_TX_DATA11 0x7D1b
+#define HDMI_CEC_TX_DATA12 0x7D1c
+#define HDMI_CEC_TX_DATA13 0x7D1d
+#define HDMI_CEC_TX_DATA14 0x7D1e
+#define HDMI_CEC_TX_DATA15 0x7D1f
+#define HDMI_CEC_RX_DATA0 0x7D20
+#define HDMI_CEC_RX_DATA1 0x7D21
+#define HDMI_CEC_RX_DATA2 0x7D22
+#define HDMI_CEC_RX_DATA3 0x7D23
+#define HDMI_CEC_RX_DATA4 0x7D24
+#define HDMI_CEC_RX_DATA5 0x7D25
+#define HDMI_CEC_RX_DATA6 0x7D26
+#define HDMI_CEC_RX_DATA7 0x7D27
+#define HDMI_CEC_RX_DATA8 0x7D28
+#define HDMI_CEC_RX_DATA9 0x7D29
+#define HDMI_CEC_RX_DATA10 0x7D2a
+#define HDMI_CEC_RX_DATA11 0x7D2b
+#define HDMI_CEC_RX_DATA12 0x7D2c
+#define HDMI_CEC_RX_DATA13 0x7D2d
+#define HDMI_CEC_RX_DATA14 0x7D2e
+#define HDMI_CEC_RX_DATA15 0x7D2f
+#define HDMI_CEC_LOCK 0x7D30
+#define HDMI_CEC_WKUPCTRL 0x7D31
+
+/* I2C Master Registers (E-DDC) */
+#define HDMI_I2CM_SLAVE 0x7E00
+#define HDMI_I2CMESS 0x7E01
+#define HDMI_I2CM_DATAO 0x7E02
+#define HDMI_I2CM_DATAI 0x7E03
+#define HDMI_I2CM_OPERATION 0x7E04
+#define HDMI_PHY_I2CM_OPERATION_ADDR_WRITE 0x10
+#define HDMI_PHY_I2CM_OPERATION_ADDR_READ 0x1
+#define HDMI_I2CM_INT 0x7E05
+#define HDMI_I2CM_CTLINT 0x7E06
+#define HDMI_I2CM_DIV 0x7E07
+#define HDMI_I2CM_SEGADDR 0x7E08
+#define HDMI_I2CM_SOFTRSTZ 0x7E09
+#define HDMI_I2CM_SEGPTR 0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
+
+#endif /* __IMX6__HDMI_REGS_H__ */
+
Index: sys/arm/freescale/imx/imx6_ipu.c
===================================================================
--- /dev/null
+++ sys/arm/freescale/imx/imx6_ipu.c
@@ -0,0 +1,1097 @@
+/*-
+ * Copyright 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/clock.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/vt/vt.h>
+
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+
+#include <arm/freescale/imx/imx6_src.h>
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+#include "fb_if.h"
+#include "hdmi_if.h"
+
+#undef EDID_DEBUG
+
+static int have_ipu = 0;
+
+#define LDB_CLOCK_RATE 280000000
+
+#define MODE_HBP(mode) ((mode)->htotal - (mode)->hsync_end)
+#define MODE_HFP(mode) ((mode)->hsync_start - (mode)->hdisplay)
+#define MODE_HSW(mode) ((mode)->hsync_end - (mode)->hsync_start)
+#define MODE_VBP(mode) ((mode)->vtotal - (mode)->vsync_end)
+#define MODE_VFP(mode) ((mode)->vsync_start - (mode)->vdisplay)
+#define MODE_VSW(mode) ((mode)->vsync_end - (mode)->vsync_start)
+
+#define MODE_BPP 16
+#define MODE_PIXEL_CLOCK_INVERT 1
+
+#define M(nm,hr,vr,clk,hs,he,ht,vs,ve,vt,f) \
+ { clk, hr, hs, he, ht, vr, vs, ve, vt, f, nm }
+
+static struct videomode mode1024x768 = M("1024x768x60",1024,768,65000,1048,1184,1344,771,777,806,VID_NHSYNC|VID_PHSYNC);
+
+#define DMA_CHANNEL 23
+#define DC_CHAN5 5
+#define DI_PORT 0
+
+#define IPU_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define IPU_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define IPU_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "ipu", MTX_DEF)
+#define IPU_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+
+#define IPU_READ4(_sc, reg) bus_read_4((_sc)->sc_mem_res, (reg))
+#define IPU_WRITE4(_sc, reg, value) \
+ bus_write_4((_sc)->sc_mem_res, (reg), (value))
+
+#define CPMEM_BASE 0x300000
+#define DC_TEMPL_BASE 0x380000
+
+#define IPU_CONF 0x200000
+#define IPU_DISP_GEN 0x2000C4
+#define DISP_GEN_DI1_CNTR_RELEASE (1 << 25)
+#define DISP_GEN_DI0_CNTR_RELEASE (1 << 24)
+#define DISP_GEN_MCU_MAX_BURST_STOP (1 << 22)
+#define DISP_GEN_MCU_T_SHIFT 18
+#define IPU_MEM_RST 0x2000DC
+#define IPU_CH_DB_MODE_SEL_0 0x200150
+#define IPU_CH_DB_MODE_SEL_1 0x200154
+#define IPU_CUR_BUF_0 0x20023C
+#define IPU_CUR_BUF_1 0x200240
+
+#define IPU_IDMAC_CH_EN_1 0x208004
+#define IPU_IDMAC_CH_EN_2 0x208008
+#define IPU_IDMAC_CH_PRI_1 0x208014
+#define IPU_IDMAC_CH_PRI_2 0x208018
+
+#define IPU_DI0_GENERAL 0x240000
+#define DI_GENERAL_POL_CLK (1 << 17)
+#define DI_GENERAL_POLARITY_3 (1 << 2)
+#define DI_GENERAL_POLARITY_2 (1 << 1)
+#define IPU_DI0_BS_CLKGEN0 0x240004
+#define IPU_DI0_BS_CLKGEN1 0x240008
+#define IPU_DI0_SW_GEN0_1 0x24000C
+#define IPU_DI0_SW_GEN1_1 0x240030
+#define IPU_DI0_SYNC_AS_GEN 0x240054
+#define IPU_DI0_DW_GEN_0 0x240058
+#define IPU_DI0_DW_SET3_0 0x240118
+#define IPU_DI0_STP_REP 0x240148
+#define IPU_DI0_POL 0x240164
+#define IPU_DI0_SCR_CONF 0x240170
+
+#define IPU_DI1_GENERAL 0x248000
+#define IPU_DI1_BS_CLKGEN0 0x248004
+#define IPU_DI1_BS_CLKGEN1 0x248008
+#define IPU_DI1_SW_GEN0_1 0x24800C
+#define IPU_DI1_SW_GEN1_1 0x248030
+#define IPU_DI1_SYNC_AS_GEN 0x248054
+#define IPU_DI1_DW_GEN_0 0x248058
+#define IPU_DI1_POL 0x248164
+#define IPU_DI1_DW_SET3_0 0x248118
+#define IPU_DI1_STP_REP 0x248148
+#define IPU_DI1_SCR_CONF 0x248170
+
+#define DI_COUNTER_INT_HSYNC 1
+#define DI_COUNTER_HSYNC 2
+#define DI_COUNTER_VSYNC 3
+#define DI_COUNTER_AD_0 4
+#define DI_COUNTER_AD_1 5
+
+#define DI_SYNC_NONE 0
+#define DI_SYNC_CLK 1
+#define DI_SYNC_COUNTER(c) ((c)+1)
+
+#define DMFC_RD_CHAN 0x260000
+#define DMFC_WR_CHAN 0x260004
+#define DMFC_WR_CHAN_DEF 0x260008
+#define DMFC_DP_CHAN 0x26000C
+#define DMFC_DP_CHAN_DEF 0x260010
+#define DMFC_GENERAL_1 0x260014
+#define DMFC_IC_CTRL 0x26001C
+
+#define DC_WRITE_CH_CONF_1 0x0025801C
+#define DC_WRITE_CH_ADDR_1 0x00258020
+#define DC_WRITE_CH_CONF_5 0x0025805C
+#define DC_WRITE_CH_ADDR_5 0x00258060
+#define DC_RL0_CH_5 0x00258064
+#define DC_GEN 0x002580D4
+#define DC_DISP_CONF2(di) (0x002580E8 + (di)*4)
+#define DC_MAP_CONF_0 0x00258108
+#define DC_MAP_CONF_15 0x00258144
+#define DC_MAP_CONF_VAL(map) (DC_MAP_CONF_15 + ((map)/2)*sizeof(uint32_t))
+#define DC_MAP_CONF_PTR(ptr) (DC_MAP_CONF_0 + ((ptr)/2)*sizeof(uint32_t))
+
+struct ipu_cpmem_word {
+ uint32_t data[5];
+ uint32_t padding[3];
+};
+
+struct ipu_cpmem_ch_param {
+ struct ipu_cpmem_word word[2];
+};
+
+#define CH_PARAM_RESET(param) memset(param, 0, sizeof(*param))
+#define IPU_READ_CH_PARAM(_sc, ch, param) bus_read_region_4( \
+ (_sc)->sc_mem_res, CPMEM_BASE + ch*(sizeof(*param)),\
+ (uint32_t*)param, sizeof(*param)/4)
+#define IPU_WRITE_CH_PARAM(_sc, ch, param) bus_write_region_4( \
+ (_sc)->sc_mem_res, CPMEM_BASE + ch*(sizeof(*param)),\
+ (uint32_t*)param, sizeof(*param)/4)
+
+#define CH_PARAM_SET_FW(param, v) ipu_ch_param_set_value((param), \
+ 0, 125, 13, (v))
+#define CH_PARAM_SET_FH(param, v) ipu_ch_param_set_value((param), \
+ 0, 138, 12, (v))
+#define CH_PARAM_SET_SLY(param, v) ipu_ch_param_set_value((param), \
+ 1, 102, 14, (v))
+#define CH_PARAM_SET_EBA0(param, v) ipu_ch_param_set_value((param), \
+ 1, 0, 29, (v))
+#define CH_PARAM_SET_EBA1(param, v) ipu_ch_param_set_value((param), \
+ 1, 29, 29, (v))
+#define CH_PARAM_SET_BPP(param, v) ipu_ch_param_set_value((param), \
+ 0, 107, 3, (v))
+#define CH_PARAM_SET_PFS(param, v) ipu_ch_param_set_value((param), \
+ 1, 85, 4, (v))
+#define CH_PARAM_SET_NPB(param, v) ipu_ch_param_set_value((param), \
+ 1, 78, 7, (v))
+#define CH_PARAM_SET_UBO(param, v) ipu_ch_param_set_value((param), \
+ 0, 46, 22, (v))
+#define CH_PARAM_SET_VBO(param, v) ipu_ch_param_set_value((param), \
+ 0, 68, 22, (v))
+
+#define CH_PARAM_SET_RED_WIDTH(param, v) ipu_ch_param_set_value((param), \
+ 1, 116, 3, (v))
+#define CH_PARAM_SET_RED_OFFSET(param, v) ipu_ch_param_set_value((param), \
+ 1, 128, 5, (v))
+
+#define CH_PARAM_SET_GREEN_WIDTH(param, v) ipu_ch_param_set_value((param), \
+ 1, 119, 3, (v))
+#define CH_PARAM_SET_GREEN_OFFSET(param, v) ipu_ch_param_set_value((param), \
+ 1, 133, 5, (v))
+
+#define CH_PARAM_SET_BLUE_WIDTH(param, v) ipu_ch_param_set_value((param), \
+ 1, 122, 3, (v))
+#define CH_PARAM_SET_BLUE_OFFSET(param, v) ipu_ch_param_set_value((param), \
+ 1, 138, 5, (v))
+
+#define CH_PARAM_SET_ALPHA_WIDTH(param, v) ipu_ch_param_set_value((param), \
+ 1, 125, 3, (v))
+#define CH_PARAM_SET_ALPHA_OFFSET(param, v) ipu_ch_param_set_value((param), \
+ 1, 143, 5, (v))
+
+#define CH_PARAM_GET_FW(param) ipu_ch_param_get_value((param), \
+ 0, 125, 13)
+#define CH_PARAM_GET_FH(param) ipu_ch_param_get_value((param), \
+ 0, 138, 12)
+#define CH_PARAM_GET_SLY(param) ipu_ch_param_get_value((param), \
+ 1, 102, 14)
+#define CH_PARAM_GET_EBA0(param) ipu_ch_param_get_value((param), \
+ 1, 0, 29)
+#define CH_PARAM_GET_EBA1(param) ipu_ch_param_get_value((param), \
+ 1, 29, 29)
+#define CH_PARAM_GET_BPP(param) ipu_ch_param_get_value((param), \
+ 0, 107, 3)
+#define CH_PARAM_GET_PFS(param) ipu_ch_param_get_value((param), \
+ 1, 85, 4)
+#define CH_PARAM_GET_NPB(param) ipu_ch_param_get_value((param), \
+ 1, 78, 7)
+#define CH_PARAM_GET_UBO(param) ipu_ch_param_get_value((param), \
+ 0, 46, 22)
+#define CH_PARAM_GET_VBO(param) ipu_ch_param_get_value((param), \
+ 0, 68, 22)
+
+#define CH_PARAM_GET_RED_WIDTH(param) ipu_ch_param_get_value((param), \
+ 1, 116, 3)
+#define CH_PARAM_GET_RED_OFFSET(param) ipu_ch_param_get_value((param), \
+ 1, 128, 5)
+
+#define CH_PARAM_GET_GREEN_WIDTH(param) ipu_ch_param_get_value((param), \
+ 1, 119, 3)
+#define CH_PARAM_GET_GREEN_OFFSET(param) ipu_ch_param_get_value((param), \
+ 1, 133, 5)
+
+#define CH_PARAM_GET_BLUE_WIDTH(param) ipu_ch_param_get_value((param), \
+ 1, 122, 3)
+#define CH_PARAM_GET_BLUE_OFFSET(param) ipu_ch_param_get_value((param), \
+ 1, 138, 5)
+
+#define CH_PARAM_GET_ALPHA_WIDTH(param) ipu_ch_param_get_value((param), \
+ 1, 125, 3)
+#define CH_PARAM_GET_ALPHA_OFFSET(param) ipu_ch_param_get_value((param), \
+ 1, 143, 5)
+
+#define IPU_PIX_FORMAT_RGB 7
+
+enum dc_event_t {
+ DC_EVENT_NF = 0,
+ DC_EVENT_NL,
+ DC_EVENT_EOF,
+ DC_EVENT_NFIELD,
+ DC_EVENT_EOL,
+ DC_EVENT_EOFIELD,
+ DC_EVENT_NEW_ADDR,
+ DC_EVENT_NEW_CHAN,
+ DC_EVENT_NEW_DATA
+};
+
+struct ipu_softc {
+ device_t sc_dev;
+ struct resource *sc_mem_res;
+ int sc_mem_rid;
+ struct resource *sc_irq_res;
+ int sc_irq_rid;
+ void *sc_intr_hl;
+ struct mtx sc_mtx;
+ struct fb_info sc_fb_info;
+ struct videomode *sc_mode;
+
+ /* Framebuffer */
+ bus_dma_tag_t sc_dma_tag;
+ bus_dmamap_t sc_dma_map;
+ size_t sc_fb_size;
+ bus_addr_t sc_fb_phys;
+ uint8_t *sc_fb_base;
+
+ /* HDMI */
+ eventhandler_tag sc_hdmi_evh;
+};
+
+static void
+ipu_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = segs[0].ds_addr;
+}
+
+static void
+ipu_ch_param_set_value(struct ipu_cpmem_ch_param *param,
+ int word, int offset, int len, uint32_t value)
+{
+ uint32_t datapos, bitpos, mask;
+ uint32_t data, data2;
+
+ datapos = offset / 32;
+ bitpos = offset % 32;
+ mask = (1 << len) - 1;
+
+ if (len > 32)
+ panic("%s: field len is more than 32",
+ __func__);
+
+ data = param->word[word].data[datapos];
+ data &= ~(mask << bitpos);
+ data |= (value << bitpos);
+ param->word[word].data[datapos] = data;
+
+ if ((bitpos + len) > 32) {
+ len = bitpos + len - 32;
+ mask = (1UL << len) - 1;
+ data2 = param->word[word].data[datapos+1];
+ data2 &= mask;
+ data2 |= (value >> (32 - bitpos));
+ param->word[word].data[datapos+1] = data2;
+ }
+}
+
+#ifdef DEBUG
+static uint32_t
+ipu_ch_param_get_value(struct ipu_cpmem_ch_param *param,
+ int word, int offset, int len)
+{
+ uint32_t datapos, bitpos, mask;
+ uint32_t data, data2;
+
+ datapos = offset / 32;
+ bitpos = offset % 32;
+ mask = (1UL << len) - 1;
+
+ if (len > 32)
+ panic("%s: field len is more than 32",
+ __func__);
+ data = param->word[word].data[datapos];
+ data = data >> bitpos;
+ data &= mask;
+ if ((bitpos + len) > 32) {
+ len = bitpos + len - 32;
+ mask = (1UL << len) - 1;
+ data2 = param->word[word].data[datapos+1];
+ data2 &= mask;
+ data |= (data2 << (32 - bitpos));
+ }
+
+ return (data);
+}
+
+static void
+ipu_print_channel(struct ipu_cpmem_ch_param *param)
+{
+ int offset0[] = {0, 10, 19, 32, 44, 45, 46, 68, 90, 94, 95, 113, 114, 117, 119, 120, 121, 122, 123, 124, 125, 138, 150, 151, -1};
+ int offset1[] = {0, 29, 58, 78, 85, 89, 90, 93, 95, 102, 116, 119, 122, 125, 128, 133, 138, 143, 148, 149, 150, -1};
+ printf("WORD0: %08x %08x %08x %08x %08x\n",
+ param->word[0].data[0], param->word[0].data[1],
+ param->word[0].data[2], param->word[0].data[3],
+ param->word[0].data[4]);
+ printf("WORD1: %08x %08x %08x %08x %08x\n",
+ param->word[1].data[0], param->word[1].data[1],
+ param->word[1].data[2], param->word[1].data[3],
+ param->word[1].data[4]);
+
+ for (int i = 0; offset0[i+1] != -1; i++) {
+ int len = offset0[i+1] - offset0[i];
+ printf("W0[%d:%d] = %d\n", offset0[i],
+ offset0[i] + len - 1,
+ ipu_ch_param_get_value(param, 0, offset0[i], len)
+ );
+ }
+
+ for (int i = 0; offset1[i+1] != -1; i++) {
+ int len = offset1[i+1] - offset1[i];
+ printf("W1[%d:%d] = %d\n", offset1[i],
+ offset1[i] + len - 1,
+ ipu_ch_param_get_value(param, 1, offset1[i], len)
+ );
+ }
+
+ printf("FW: %d\n", CH_PARAM_GET_FW(param));
+ printf("FH: %d\n", CH_PARAM_GET_FH(param));
+ printf("SLY: %d\n", CH_PARAM_GET_SLY(param));
+ printf("EBA0: 0x%08x\n", CH_PARAM_GET_EBA0(param));
+ printf("EBA1: 0x%08x\n", CH_PARAM_GET_EBA1(param));
+ printf("BPP: %d\n", CH_PARAM_GET_BPP(param));
+ printf("PFS: %d\n", CH_PARAM_GET_PFS(param));
+ printf("NPB: %d\n", CH_PARAM_GET_NPB(param));
+ printf("UBO: %d\n", CH_PARAM_GET_UBO(param));
+ printf("VBO: %d\n", CH_PARAM_GET_VBO(param));
+ printf("RED: %d bits @%d\n", CH_PARAM_GET_RED_WIDTH(param) + 1,
+ CH_PARAM_GET_RED_OFFSET(param));
+ printf("GREEN: %d bits @%d\n", CH_PARAM_GET_GREEN_WIDTH(param) + 1,
+ CH_PARAM_GET_GREEN_OFFSET(param));
+ printf("BLUE: %d bits @%d\n", CH_PARAM_GET_BLUE_WIDTH(param) + 1,
+ CH_PARAM_GET_BLUE_OFFSET(param));
+ printf("ALPHA: %d bits @%d\n", CH_PARAM_GET_ALPHA_WIDTH(param) + 1,
+ CH_PARAM_GET_ALPHA_OFFSET(param));
+}
+#endif
+
+static void
+ipu_di_enable(struct ipu_softc *sc, int di)
+{
+ uint32_t flag, reg;
+
+ flag = di ? DISP_GEN_DI1_CNTR_RELEASE : DISP_GEN_DI0_CNTR_RELEASE;
+ reg = IPU_READ4(sc, IPU_DISP_GEN);
+ reg |= flag;
+ IPU_WRITE4(sc, IPU_DISP_GEN, reg);
+}
+
+static void
+ipu_config_wave_gen_0(struct ipu_softc *sc, int di,
+ int wave_gen, int run_value, int run_res,
+ int offset_value, int offset_res)
+{
+ uint32_t addr, reg;
+
+ addr = (di ? IPU_DI1_SW_GEN0_1 : IPU_DI0_SW_GEN0_1)
+ + (wave_gen-1)*sizeof(uint32_t);
+ reg = IPU_READ4(sc, addr);
+ reg = (run_value << 19) | (run_res << 16) |
+ (offset_value << 3) | offset_res;
+ IPU_WRITE4(sc, addr, reg);
+}
+
+static void
+ipu_config_wave_gen_1(struct ipu_softc *sc, int di, int wave_gen,
+ int repeat_count, int cnt_clr_src,
+ int cnt_polarity_gen_en,
+ int cnt_polarity_clr_src,
+ int cnt_polarity_trigger_src,
+ int cnt_up, int cnt_down)
+{
+ uint32_t addr, reg;
+
+ addr = (di ? IPU_DI1_SW_GEN1_1 : IPU_DI0_SW_GEN1_1)
+ + (wave_gen-1)*sizeof(uint32_t);
+ reg = IPU_READ4(sc, addr);
+ reg = (cnt_polarity_gen_en << 29) | (cnt_clr_src << 25)
+ | (cnt_polarity_trigger_src << 12) | (cnt_polarity_clr_src << 9);
+ reg |= (cnt_down << 16) | cnt_up;
+ if (repeat_count == 0)
+ reg |= (1 << 28);
+ IPU_WRITE4(sc, addr, reg);
+
+ addr = (di ? IPU_DI1_STP_REP : IPU_DI0_STP_REP)
+ + (wave_gen-1)/2*sizeof(uint32_t);
+ reg = IPU_READ4(sc, addr);
+ if (wave_gen % 2) {
+ reg &= ~(0xffff);
+ reg |= repeat_count;
+ }
+ else {
+ reg &= ~(0xffff << 16);
+ reg |= (repeat_count << 16);
+ }
+ IPU_WRITE4(sc, addr, reg);
+}
+
+static void
+ipu_reset_wave_gen(struct ipu_softc *sc, int di,
+ int wave_gen)
+{
+ uint32_t addr, reg;
+
+ addr = (di ? IPU_DI1_SW_GEN0_1 : IPU_DI0_SW_GEN0_1)
+ + (wave_gen-1)*sizeof(uint32_t);
+ IPU_WRITE4(sc, addr, 0);
+
+ addr = (di ? IPU_DI1_SW_GEN1_1 : IPU_DI0_SW_GEN1_1)
+ + (wave_gen-1)*sizeof(uint32_t);
+ IPU_WRITE4(sc, addr, 0);
+
+ addr = (di ? IPU_DI1_STP_REP : IPU_DI0_STP_REP)
+ + (wave_gen-1)/2*sizeof(uint32_t);
+ reg = IPU_READ4(sc, addr);
+ if (wave_gen % 2)
+ reg &= ~(0xffff);
+ else
+ reg &= ~(0xffff << 16);
+ IPU_WRITE4(sc, addr, reg);
+}
+
+static void
+ipu_init_micorcode_template(struct ipu_softc *sc, int di, int map)
+{
+ uint32_t addr;
+ uint32_t w1, w2;
+ int i, word;
+ int glue;
+
+ word = di ? 2 : 5;
+
+ for (i = 0; i < 3; i++) {
+ if (i == 0)
+ glue = 8; /* keep asserted */
+ else if (i == 1)
+ glue = 4; /* keep negated */
+ else if (i == 2)
+ glue = 0;
+
+ w1 = 5; /* sync */
+ w1 |= (glue << 4); /* glue */
+ w1 |= (1 << 11); /* wave unit 0 */
+ w1 |= ((map+1) << 15);
+ /* operand is zero */
+
+ /* Write data to DI and Hold data in register */
+ w2 = 0x18 << 4; /* opcode: WROD 0x0 */
+ w2 |= (1 << 9); /* Stop */
+
+ addr = DC_TEMPL_BASE + (word+i)*2*sizeof(uint32_t);
+ IPU_WRITE4(sc, addr, w1);
+ IPU_WRITE4(sc, addr + sizeof(uint32_t), w2);
+ }
+}
+
+static void
+ipu_config_timing(struct ipu_softc *sc, int di)
+{
+ int div;
+ uint32_t di_scr_conf;
+ uint32_t gen_offset, gen;
+ uint32_t as_gen_offset, as_gen;
+ uint32_t dw_gen_offset, dw_gen;
+ uint32_t dw_set_offset, dw_set;
+ uint32_t bs_clkgen_offset;
+ int map;
+
+ /* TODO: check mode restrictions / fixup */
+ /* TODO: enable timers, get divisors */
+ div = 1;
+ map = 0;
+
+ bs_clkgen_offset = di ? IPU_DI1_BS_CLKGEN0 : IPU_DI0_BS_CLKGEN0;
+ IPU_WRITE4(sc, bs_clkgen_offset, (div * 16));
+ IPU_WRITE4(sc, bs_clkgen_offset + 4, (div << 16));
+
+ /*
+ * TODO: Configure LLDB clock by changing following fields
+ * in CCM fields:
+ * CS2CDR_LDB_DI0_CLK_SEL
+ * CSCMR2_LDB_DI0_IPU_DIV
+ * CBCDR_MMDC_CH1_AXI_PODF
+ */
+
+ /* Setup wave generator */
+ dw_gen_offset = di ? IPU_DI1_DW_GEN_0 : IPU_DI0_DW_GEN_0;
+ dw_gen = IPU_READ4(sc, dw_gen_offset);
+ dw_gen = ((div - 1) << 24) | ((div - 1) << 16);
+ dw_gen &= ~(3 << 8); /* pin15 */
+ dw_gen |= (3 << 8); /* pin15, set 3 */
+ IPU_WRITE4(sc, dw_gen_offset, dw_gen);
+
+ dw_set_offset = di ? IPU_DI1_DW_SET3_0 : IPU_DI0_DW_SET3_0;
+ dw_set = IPU_READ4(sc, dw_set_offset);
+ dw_set = (div*2 << 16) | 0;
+ IPU_WRITE4(sc, dw_set_offset, dw_set);
+
+ div = 0;
+
+ /* DI_COUNTER_INT_HSYNC */
+ ipu_config_wave_gen_0(sc, di, DI_COUNTER_INT_HSYNC,
+ sc->sc_mode->htotal - 1, DI_SYNC_CLK, 0, DI_SYNC_NONE);
+ ipu_config_wave_gen_1(sc, di, DI_COUNTER_INT_HSYNC,
+ 0, DI_SYNC_NONE, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
+
+ /* DI_COUNTER_HSYNC */
+ ipu_config_wave_gen_0(sc, di, DI_COUNTER_HSYNC,
+ sc->sc_mode->htotal - 1, DI_SYNC_CLK, 0, DI_SYNC_CLK);
+ ipu_config_wave_gen_1(sc, di, DI_COUNTER_HSYNC,
+ 0, DI_SYNC_NONE, 1, DI_SYNC_NONE, DI_SYNC_CLK,
+ 0, MODE_HSW(sc->sc_mode)*2);
+
+ /* DI_COUNTER_VSYNC */
+ ipu_config_wave_gen_0(sc, di, DI_COUNTER_VSYNC,
+ sc->sc_mode->vtotal - 1, DI_SYNC_COUNTER(DI_COUNTER_INT_HSYNC),
+ 0, DI_SYNC_NONE);
+ ipu_config_wave_gen_1(sc, di, DI_COUNTER_VSYNC,
+ 0, DI_SYNC_NONE, 1, DI_SYNC_NONE,
+ DI_SYNC_COUNTER(DI_COUNTER_INT_HSYNC),
+ 0, MODE_VSW(sc->sc_mode)*2);
+
+ di_scr_conf = di ? IPU_DI1_SCR_CONF : IPU_DI0_SCR_CONF;
+ IPU_WRITE4(sc, di_scr_conf, sc->sc_mode->vtotal - 1);
+
+ /* TODO: update DI_SCR_CONF */
+
+ /* Active Data 0 */
+ ipu_config_wave_gen_0(sc, di, DI_COUNTER_AD_0,
+ 0, DI_SYNC_COUNTER(DI_COUNTER_HSYNC),
+ MODE_VSW(sc->sc_mode) + MODE_VFP(sc->sc_mode), DI_SYNC_COUNTER(DI_COUNTER_HSYNC));
+ ipu_config_wave_gen_1(sc, di, DI_COUNTER_AD_0,
+ sc->sc_mode->vdisplay, DI_SYNC_COUNTER(DI_COUNTER_VSYNC),
+ 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
+
+ ipu_config_wave_gen_0(sc, di, DI_COUNTER_AD_1,
+ 0, DI_SYNC_CLK, MODE_HSW(sc->sc_mode) + MODE_HFP(sc->sc_mode), DI_SYNC_CLK);
+ ipu_config_wave_gen_1(sc, di, DI_COUNTER_AD_1,
+ sc->sc_mode->hdisplay, DI_SYNC_COUNTER(DI_COUNTER_AD_0),
+ 0, DI_SYNC_NONE, DI_SYNC_NONE, 0, 0);
+
+ ipu_reset_wave_gen(sc, di, 6);
+ ipu_reset_wave_gen(sc, di, 7);
+ ipu_reset_wave_gen(sc, di, 8);
+ ipu_reset_wave_gen(sc, di, 9);
+
+ ipu_init_micorcode_template(sc, di, map);
+
+ gen_offset = di ? IPU_DI1_GENERAL : IPU_DI0_GENERAL;
+ gen = IPU_READ4(sc, gen_offset);
+
+ if (sc->sc_mode->flags & VID_NHSYNC)
+ gen &= ~DI_GENERAL_POLARITY_2;
+ else /* active high */
+ gen |= DI_GENERAL_POLARITY_2;
+
+ if (sc->sc_mode->flags & VID_NVSYNC)
+ gen &= ~DI_GENERAL_POLARITY_3;
+ else /* active high */
+ gen |= DI_GENERAL_POLARITY_3;
+
+ if (MODE_PIXEL_CLOCK_INVERT)
+ gen &= ~DI_GENERAL_POL_CLK;
+ else
+ gen |= DI_GENERAL_POL_CLK;
+
+ /* User LDB clock to drive pixel clock */
+ gen |= 0x00100000;
+
+ IPU_WRITE4(sc, gen_offset, gen);
+
+ as_gen_offset = di ? IPU_DI1_SYNC_AS_GEN : IPU_DI0_SYNC_AS_GEN;
+ as_gen = IPU_READ4(sc, as_gen_offset);
+ as_gen = ((DI_COUNTER_VSYNC-1) << 13) | 2;
+ IPU_WRITE4(sc, as_gen_offset, as_gen);
+
+ IPU_WRITE4(sc, (di ? IPU_DI1_POL : IPU_DI0_POL), 0x10);
+
+ IPU_WRITE4(sc, DC_DISP_CONF2(di), sc->sc_mode->hdisplay);
+}
+
+static void
+ipu_dc_enable(struct ipu_softc *sc)
+{
+ uint32_t conf;
+
+ /* channel 1 uses DI1 */
+ IPU_WRITE4(sc, DC_WRITE_CH_CONF_1, 0x00000004);
+
+ conf = IPU_READ4(sc, DC_WRITE_CH_CONF_5);
+ conf &= ~(7 << 5); /* PROG_CHAN_TYP */
+ conf |= 4 << 5; /* ENABLED */
+ IPU_WRITE4(sc, DC_WRITE_CH_CONF_5, conf);
+
+ /* TODO: enable clock */
+}
+
+static void
+ipu_dc_link_event(struct ipu_softc *sc, int event, int addr, int priority)
+{
+ uint32_t reg;
+ int offset;
+ int shift;
+
+ if (event % 2)
+ shift = 16;
+ else
+ shift = 0;
+
+ offset = DC_RL0_CH_5 + (event/2)*sizeof(uint32_t);
+
+ reg = IPU_READ4(sc, offset);
+ reg &= ~(0xFFFF << shift);
+ reg |= ((addr << 8) | priority) << shift;
+ IPU_WRITE4(sc, offset, reg);
+}
+
+static void
+ipu_dc_setup_map(struct ipu_softc *sc, int map,
+ int byte, int offset, int mask)
+{
+ uint32_t reg, shift, ptr;
+
+ ptr = map*3 + byte;
+
+ reg = IPU_READ4(sc, DC_MAP_CONF_VAL(ptr));
+ if (ptr & 1)
+ shift = 16;
+ else
+ shift = 0;
+ reg &= ~(0xffff << shift);
+ reg |= ((offset << 8) | mask) << shift;
+ IPU_WRITE4(sc, DC_MAP_CONF_VAL(ptr), reg);
+
+ reg = IPU_READ4(sc, DC_MAP_CONF_PTR(map));
+ if (map & 1)
+ shift = 16 + 5*byte;
+ else
+ shift = 5*byte;
+ reg &= ~(0x1f << shift);
+ reg |= (ptr) << shift;
+ IPU_WRITE4(sc, DC_MAP_CONF_PTR(map), reg);
+}
+
+static void
+ipu_dc_reset_map(struct ipu_softc *sc, int map)
+{
+ uint32_t reg;
+ reg = IPU_READ4(sc, DC_MAP_CONF_PTR(map));
+ if (map & 1)
+ reg &= 0x0000ffff;
+ else
+ reg &= 0xffff0000;
+ IPU_WRITE4(sc, DC_MAP_CONF_PTR(map), reg);
+}
+
+static void
+ipu_dc_init(struct ipu_softc *sc)
+{
+ int addr;
+ uint32_t conf;
+
+ if (DI_PORT)
+ addr = 2;
+ else
+ addr = 5;
+
+ ipu_dc_link_event(sc, DC_EVENT_NL, addr, 3);
+ ipu_dc_link_event(sc, DC_EVENT_EOL, addr+1, 2);
+ ipu_dc_link_event(sc, DC_EVENT_NEW_DATA, addr+2, 1);
+ ipu_dc_link_event(sc, DC_EVENT_NF, 0, 0);
+ ipu_dc_link_event(sc, DC_EVENT_NFIELD, 0, 0);
+ ipu_dc_link_event(sc, DC_EVENT_EOF, 0, 0);
+ ipu_dc_link_event(sc, DC_EVENT_EOFIELD, 0, 0);
+ ipu_dc_link_event(sc, DC_EVENT_NEW_CHAN, 0, 0);
+ ipu_dc_link_event(sc, DC_EVENT_NEW_ADDR, 0, 0);
+
+ conf = 0x02; /* W_SIZE */
+ conf |= DI_PORT << 3; /* PROG_DISP_ID */
+ conf |= DI_PORT << 2; /* PROG_DI_ID */
+
+ IPU_WRITE4(sc, DC_WRITE_CH_CONF_5, conf);
+ IPU_WRITE4(sc, DC_WRITE_CH_ADDR_5, 0x00000000);
+ IPU_WRITE4(sc, DC_GEN, 0x84); /* High priority, sync */
+}
+
+static void
+ipu_init_buffer(struct ipu_softc *sc)
+{
+ struct ipu_cpmem_ch_param param;
+ uint32_t stride;
+ uint32_t reg, db_mode_sel, cur_buf;
+
+ stride = sc->sc_mode->hdisplay*MODE_BPP/8;
+
+ /* init channel paramters */
+ CH_PARAM_RESET(¶m);
+ /* XXX: interlaced modes are not supported yet */
+ CH_PARAM_SET_FW(¶m, sc->sc_mode->hdisplay - 1);
+ CH_PARAM_SET_FH(¶m, sc->sc_mode->vdisplay - 1);
+ CH_PARAM_SET_SLY(¶m, stride - 1);
+
+ CH_PARAM_SET_EBA0(¶m, (sc->sc_fb_phys >> 3));
+ CH_PARAM_SET_EBA1(¶m, (sc->sc_fb_phys >> 3));
+
+ CH_PARAM_SET_BPP(¶m, 3);
+ CH_PARAM_SET_PFS(¶m, IPU_PIX_FORMAT_RGB);
+ CH_PARAM_SET_NPB(¶m, 15);
+
+ CH_PARAM_SET_RED_OFFSET(¶m, 0);
+ CH_PARAM_SET_RED_WIDTH(¶m, 5 - 1);
+ CH_PARAM_SET_GREEN_OFFSET(¶m, 5);
+ CH_PARAM_SET_GREEN_WIDTH(¶m, 6 - 1);
+ CH_PARAM_SET_BLUE_OFFSET(¶m, 11);
+ CH_PARAM_SET_BLUE_WIDTH(¶m, 5 - 1);
+ CH_PARAM_SET_ALPHA_OFFSET(¶m, 16);
+ CH_PARAM_SET_ALPHA_WIDTH(¶m, 8 - 1);
+
+ CH_PARAM_SET_UBO(¶m, 0);
+ CH_PARAM_SET_VBO(¶m, 0);
+
+ IPU_WRITE_CH_PARAM(sc, DMA_CHANNEL, ¶m);
+#ifdef DEBUG
+ ipu_print_channel(¶m);
+#endif
+
+ /* init DMFC */
+ IPU_WRITE4(sc, DMFC_IC_CTRL, 0x2);
+ /* High resolution DP */
+ IPU_WRITE4(sc, DMFC_WR_CHAN, 0x00000090);
+ IPU_WRITE4(sc, DMFC_WR_CHAN_DEF, 0x202020F6);
+ IPU_WRITE4(sc, DMFC_DP_CHAN, 0x0000968a);
+ IPU_WRITE4(sc, DMFC_DP_CHAN_DEF, 0x2020F6F6);
+
+ reg = IPU_READ4(sc, DMFC_GENERAL_1);
+ reg &= ~(1UL << 20);
+ IPU_WRITE4(sc, DMFC_GENERAL_1, reg);
+
+ /* XXX: set priority? */
+
+ /* Set single buffer mode */
+ if (DMA_CHANNEL < 32) {
+ db_mode_sel = IPU_CH_DB_MODE_SEL_0;
+ cur_buf = IPU_CUR_BUF_0;
+ } else {
+ db_mode_sel = IPU_CH_DB_MODE_SEL_1;
+ cur_buf = IPU_CUR_BUF_1;
+ }
+
+ reg = IPU_READ4(sc, db_mode_sel);
+ reg |= (1UL << (DMA_CHANNEL & 0x1f));
+ IPU_WRITE4(sc, db_mode_sel, reg);
+
+ IPU_WRITE4(sc, cur_buf, (1UL << (DMA_CHANNEL & 0x1f)));
+}
+
+static int
+ipu_init(struct ipu_softc *sc)
+{
+ uint32_t reg, off;
+ int i, err;
+ size_t dma_size;
+
+ reg = IPU_READ4(sc, IPU_CONF);
+
+ IPU_WRITE4(sc, IPU_CONF, 0x00000040);
+
+ IPU_WRITE4(sc, IPU_MEM_RST, 0x807FFFFF);
+ i = 1000;
+ while (i-- > 0) {
+ if (!(IPU_READ4(sc, IPU_MEM_RST) & 0x80000000))
+ break;
+ DELAY(1);
+ }
+
+ if (i <= 0) {
+ err = ETIMEDOUT;
+ device_printf(sc->sc_dev, "timeout while resetting memory\n");
+ goto fail;
+ }
+
+ ipu_dc_reset_map(sc, 0);
+ ipu_dc_setup_map(sc, 0, 0, 7, 0xff);
+ ipu_dc_setup_map(sc, 0, 1, 15, 0xff);
+ ipu_dc_setup_map(sc, 0, 2, 23, 0xff);
+
+ dma_size = round_page(sc->sc_mode->hdisplay*sc->sc_mode->vdisplay*(MODE_BPP/8));
+
+ /*
+ * Now allocate framebuffer memory
+ */
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->sc_dev),
+ 4, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ dma_size, 1, /* maxsize, nsegments */
+ dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->sc_dma_tag);
+ if (err)
+ goto fail;
+
+ err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base,
+ BUS_DMA_COHERENT, &sc->sc_dma_map);
+
+ if (err) {
+ device_printf(sc->sc_dev, "cannot allocate framebuffer\n");
+ goto fail;
+ }
+
+ err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base,
+ dma_size, ipu_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT);
+
+ if (err) {
+ device_printf(sc->sc_dev, "cannot load DMA map\n");
+ goto fail;
+ }
+
+ /* Make sure it's blank */
+ memset(sc->sc_fb_base, 0x00, dma_size);
+
+ /* Calculate actual FB Size */
+ sc->sc_fb_size = sc->sc_mode->hdisplay*sc->sc_mode->vdisplay*MODE_BPP/8;
+
+ ipu_dc_init(sc);
+ IPU_WRITE4(sc, IPU_CONF, 0x00000660);
+
+ ipu_config_timing(sc, DI_PORT);
+ ipu_init_buffer(sc);
+ ipu_di_enable(sc, DI_PORT);
+
+ /* Enable DMA channel */
+ off = (DMA_CHANNEL > 31) ? IPU_IDMAC_CH_EN_2 : IPU_IDMAC_CH_EN_1;
+ reg = IPU_READ4(sc, off);
+ reg |= (1 << (DMA_CHANNEL & 0x1f));
+ IPU_WRITE4(sc, off, reg);
+
+ ipu_dc_enable(sc);
+
+ sc->sc_fb_info.fb_name = device_get_nameunit(sc->sc_dev);
+ sc->sc_fb_info.fb_vbase = (intptr_t)sc->sc_fb_base;
+ sc->sc_fb_info.fb_pbase = sc->sc_fb_phys;
+ sc->sc_fb_info.fb_size = sc->sc_fb_size;
+ sc->sc_fb_info.fb_bpp = sc->sc_fb_info.fb_depth = MODE_BPP;
+ sc->sc_fb_info.fb_stride = sc->sc_mode->hdisplay*MODE_BPP / 8;
+ sc->sc_fb_info.fb_width = sc->sc_mode->hdisplay;
+ sc->sc_fb_info.fb_height = sc->sc_mode->vdisplay;
+
+ device_t fbd = device_add_child(sc->sc_dev, "fbd",
+ device_get_unit(sc->sc_dev));
+ if (fbd == NULL) {
+ device_printf(sc->sc_dev, "Failed to add fbd child\n");
+ goto fail;
+ }
+ if (device_probe_and_attach(fbd) != 0) {
+ device_printf(sc->sc_dev, "Failed to attach fbd device\n");
+ goto fail;
+ }
+
+ return (0);
+fail:
+
+ return (err);
+}
+
+static void
+ipu_hdmi_event(void *arg, device_t hdmi_dev)
+{
+ struct ipu_softc *sc;
+ uint8_t *edid;
+ uint32_t edid_len;
+ struct edid_info ei;
+ const struct videomode *videomode;
+
+ sc = arg;
+
+ edid = NULL;
+ edid_len = 0;
+ if (HDMI_GET_EDID(hdmi_dev, &edid, &edid_len) != 0) {
+ device_printf(sc->sc_dev, "failed to get EDID info from HDMI framer\n");
+ }
+
+ videomode = NULL;
+
+#ifdef EDID_DEBUG
+ if ( edid && (edid_parse(edid, &ei) == 0)) {
+ edid_print(&ei);
+ } else
+ device_printf(sc->sc_dev, "failed to parse EDID\n");
+#endif
+
+ sc->sc_mode = &mode1024x768;
+ ipu_init(sc);
+
+ HDMI_SET_VIDEOMODE(hdmi_dev, sc->sc_mode);
+}
+
+static int
+ipu_probe(device_t dev)
+{
+
+ if (have_ipu)
+ return (ENXIO);
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ipu"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale IPU");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ipu_attach(device_t dev)
+{
+ struct ipu_softc *sc;
+
+ if (have_ipu)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ sc->sc_mem_rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->sc_mem_rid, RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_irq_rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->sc_irq_rid, RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->sc_mem_rid, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Enable IPU1 */
+ imx_ccm_ipu_enable(1);
+
+ if (src_reset_ipu() != 0) {
+ device_printf(dev, "failed to reset IPU\n");
+ return (ENXIO);
+ }
+
+ IPU_LOCK_INIT(sc);
+
+ sc->sc_hdmi_evh = EVENTHANDLER_REGISTER(hdmi_event,
+ ipu_hdmi_event, sc, 0);
+
+ have_ipu = 1;
+
+ return (0);
+}
+
+static int
+ipu_detach(device_t dev)
+{
+ /* Do not let unload driver */
+ return (EBUSY);
+}
+
+static struct fb_info *
+ipu_fb_getinfo(device_t dev)
+{
+ struct ipu_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (&sc->sc_fb_info);
+}
+
+static device_method_t ipu_methods[] = {
+ DEVMETHOD(device_probe, ipu_probe),
+ DEVMETHOD(device_attach, ipu_attach),
+ DEVMETHOD(device_detach, ipu_detach),
+
+ /* Framebuffer service methods */
+ DEVMETHOD(fb_getinfo, ipu_fb_getinfo),
+
+ DEVMETHOD_END
+};
+
+static driver_t ipu_driver = {
+ "fb",
+ ipu_methods,
+ sizeof(struct ipu_softc),
+};
+
+static devclass_t ipu_devclass;
+
+DRIVER_MODULE(ipu, simplebus, ipu_driver, ipu_devclass, 0, 0);
+MODULE_VERSION(ipu, 1);
+MODULE_DEPEND(ipu, simplebus, 1, 1, 1);
Index: sys/arm/freescale/imx/imx_ccmvar.h
===================================================================
--- sys/arm/freescale/imx/imx_ccmvar.h
+++ sys/arm/freescale/imx/imx_ccmvar.h
@@ -52,6 +52,8 @@
void imx_ccm_usb_enable(device_t _usbdev);
void imx_ccm_usbphy_enable(device_t _phydev);
void imx_ccm_ssi_configure(device_t _ssidev);
+void imx_ccm_hdmi_enable(void);
+void imx_ccm_ipu_enable(int ipu);
/* Routines to get and set the arm clock root divisor register. */
uint32_t imx_ccm_get_cacrr(void);
Index: sys/arm/freescale/imx/imx_i2c.c
===================================================================
--- sys/arm/freescale/imx/imx_i2c.c
+++ sys/arm/freescale/imx/imx_i2c.c
@@ -293,6 +293,8 @@
i2c_attach(device_t dev)
{
struct i2c_softc *sc;
+ phandle_t node;
+ device_t iic_dev;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -312,7 +314,13 @@
}
bus_generic_attach(dev);
- return (0);
+
+ /* register actual iic access device */
+ node = ofw_bus_get_node(dev);
+ iic_dev = device_find_child(sc->iicbus, "iic", -1);
+ OF_device_register_xref(OF_xref_from_node(node), iic_dev);
+
+ return (IIC_NOERR);
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 9:22 PM (19 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15547027
Default Alt Text
D4168.id10207.diff (88 KB)
Attached To
Mode
D4168: i.MX6 IPU drivers
Attached
Detach File
Event Timeline
Log In to Comment