This syncs the imx-hdmi driver with Linux 4.2-rc1 where it makes sense. This
makes it easier to compare the driver with the kernel. This also adds
hdmi_av_composer which is mandatory. Somehow the driver worked without it in
lower resolutions, but now it also works for higher resolutions.

Signed-off-by: Sascha Hauer <[email protected]>
---
 drivers/video/imx-ipu-v3/imx-hdmi.c | 380 ++++++++++++++++++++++--------------
 drivers/video/imx-ipu-v3/imx-hdmi.h |   3 +-
 2 files changed, 235 insertions(+), 148 deletions(-)

diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c 
b/drivers/video/imx-ipu-v3/imx-hdmi.c
index f5a2e3c..fa55b19 100644
--- a/drivers/video/imx-ipu-v3/imx-hdmi.c
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -6,8 +6,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
- * for SLISHDMI13T and SLIPHDMIT IP cores
+ * Designware High-Definition Multimedia Interface (HDMI) driver
  *
  * Copyright (C) 2010, Guennadi Liakhovetski <[email protected]>
  */
@@ -60,7 +59,7 @@ enum hdmi_datamap {
        YCbCr422_12B = 0x12,
 };
 
-enum imx_hdmi_devtype {
+enum dw_hdmi_devtype {
        IMX6Q_HDMI,
        IMX6DL_HDMI,
 };
@@ -117,8 +116,8 @@ struct hdmi_data_info {
        struct hdmi_vmode video_mode;
 };
 
-struct imx_hdmi {
-       enum imx_hdmi_devtype dev_type;
+struct dw_hdmi {
+       enum dw_hdmi_devtype dev_type;
        struct device_d *dev;
        struct clk *isfr_clk;
        struct clk *iahb_clk;
@@ -140,10 +139,12 @@ struct imx_hdmi {
        unsigned int sample_rate;
        int ratio;
 
+       struct fb_videomode *mode;
+
        struct vpl vpl;
 };
 
-static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
+static void dw_hdmi_set_ipu_di_mux(struct dw_hdmi *hdmi, int ipu_di)
 {
        void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
        uint32_t val;
@@ -156,49 +157,47 @@ static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi 
*hdmi, int ipu_di)
        writel(val, gpr3);
 }
 
-static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
+static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
 {
        writeb(val, hdmi->regs + offset);
 }
 
-static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
+static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
 {
        return readb(hdmi->regs + offset);
 }
 
-static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
 {
        u8 val = hdmi_readb(hdmi, reg) & ~mask;
+
        val |= data & mask;
        hdmi_writeb(hdmi, val, reg);
 }
 
-static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
-                     u8 shift, u8 mask)
+static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
+                            u8 shift, u8 mask)
 {
        hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
-static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
-                                        unsigned int value)
+static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
+                          unsigned int n)
 {
-       hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
-       hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
-       hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
+       /* Must be set/cleared first */
+       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
        /* nshift factor = 0 */
        hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
-}
-
-static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
-{
-       /* Must be set/cleared first */
-       hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
 
-       hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
-       hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
        hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
                    HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+       hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+       hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+
+       hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
+       hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
+       hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
 }
 
 static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
@@ -334,12 +333,11 @@ static unsigned int hdmi_compute_cts(unsigned int freq, 
unsigned long pixel_clk,
        }
        if (ratio == 100)
                return cts;
-       else
-               return (cts * ratio) / 100;
+       return (cts * ratio) / 100;
 }
 
-static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
-       unsigned long pixel_clk)
+static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
+                                    unsigned long pixel_clk)
 {
        unsigned int clk_n, clk_cts;
 
@@ -350,7 +348,7 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
 
        if (!clk_cts) {
                dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-                        __func__, pixel_clk);
+                       __func__, pixel_clk);
                return;
        }
 
@@ -358,11 +356,10 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi 
*hdmi,
                __func__, hdmi->sample_rate, hdmi->ratio,
                pixel_clk, clk_n, clk_cts);
 
-       hdmi_set_clock_regenerator_n(hdmi, clk_n);
-       hdmi_regenerate_cts(hdmi, clk_cts);
+       hdmi_set_cts_n(hdmi, clk_cts, clk_n);
 }
 
-static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
+static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
 {
        hdmi_set_clk_regenerator(hdmi, 74250000);
 }
@@ -374,7 +371,7 @@ static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
  *                     pin{31~24} <==> G[7:0]
  *                     pin{15~8}  <==> B[7:0]
  */
-static void hdmi_video_sample(struct imx_hdmi *hdmi)
+static void hdmi_video_sample(struct dw_hdmi *hdmi)
 {
        int color_format = 0;
        u8 val;
@@ -430,27 +427,32 @@ static void hdmi_video_sample(struct imx_hdmi *hdmi)
        hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
 }
 
-static int is_color_space_conversion(struct imx_hdmi *hdmi)
+static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-       return (hdmi->hdmi_data.enc_in_format !=
-               hdmi->hdmi_data.enc_out_format);
+       return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
 }
 
-static int is_color_space_decimation(struct imx_hdmi *hdmi)
+static int is_color_space_decimation(struct dw_hdmi *hdmi)
 {
-       return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
-               (hdmi->hdmi_data.enc_in_format == RGB ||
-               hdmi->hdmi_data.enc_in_format == YCBCR444));
+       if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
+               return 0;
+       if (hdmi->hdmi_data.enc_in_format == RGB ||
+           hdmi->hdmi_data.enc_in_format == YCBCR444)
+               return 1;
+       return 0;
 }
 
-static int is_color_space_interpolation(struct imx_hdmi *hdmi)
+static int is_color_space_interpolation(struct dw_hdmi *hdmi)
 {
-       return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
-               (hdmi->hdmi_data.enc_out_format == RGB ||
-               hdmi->hdmi_data.enc_out_format == YCBCR444));
+       if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
+               return 0;
+       if (hdmi->hdmi_data.enc_out_format == RGB ||
+           hdmi->hdmi_data.enc_out_format == YCBCR444)
+               return 1;
+       return 0;
 }
 
-static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
+static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 {
        const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
        unsigned i;
@@ -458,12 +460,14 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi 
*hdmi)
 
        if (is_color_space_conversion(hdmi)) {
                if (hdmi->hdmi_data.enc_out_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry == 
HDMI_COLORIMETRY_ITU_601)
+                       if (hdmi->hdmi_data.colorimetry ==
+                                       HDMI_COLORIMETRY_ITU_601)
                                csc_coeff = &csc_coeff_rgb_out_eitu601;
                        else
                                csc_coeff = &csc_coeff_rgb_out_eitu709;
                } else if (hdmi->hdmi_data.enc_in_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry == 
HDMI_COLORIMETRY_ITU_601)
+                       if (hdmi->hdmi_data.colorimetry ==
+                                       HDMI_COLORIMETRY_ITU_601)
                                csc_coeff = &csc_coeff_rgb_in_eitu601;
                        else
                                csc_coeff = &csc_coeff_rgb_in_eitu709;
@@ -489,7 +493,7 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi 
*hdmi)
                  HDMI_CSC_SCALE);
 }
 
-static void hdmi_video_csc(struct imx_hdmi *hdmi)
+static void hdmi_video_csc(struct dw_hdmi *hdmi)
 {
        int color_depth = 0;
        int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
@@ -517,7 +521,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
        hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
                  HDMI_CSC_SCALE);
 
-       imx_hdmi_update_csc_coeffs(hdmi);
+       dw_hdmi_update_csc_coeffs(hdmi);
 }
 
 /*
@@ -525,7 +529,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
  * for example, if input is YCC422 mode or repeater is used,
  * data should be repacked this module can be bypassed.
  */
-static void hdmi_video_packetize(struct imx_hdmi *hdmi)
+static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 {
        unsigned int color_depth = 0;
        unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
@@ -533,21 +537,22 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
        struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
        u8 val, vp_conf;
 
-       if (hdmi_data->enc_out_format == RGB
-               || hdmi_data->enc_out_format == YCBCR444) {
-               if (!hdmi_data->enc_color_depth)
+       if (hdmi_data->enc_out_format == RGB ||
+           hdmi_data->enc_out_format == YCBCR444) {
+               if (!hdmi_data->enc_color_depth) {
                        output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-               else if (hdmi_data->enc_color_depth == 8) {
+               } else if (hdmi_data->enc_color_depth == 8) {
                        color_depth = 4;
                        output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-               } else if (hdmi_data->enc_color_depth == 10)
+               } else if (hdmi_data->enc_color_depth == 10) {
                        color_depth = 5;
-               else if (hdmi_data->enc_color_depth == 12)
+               } else if (hdmi_data->enc_color_depth == 12) {
                        color_depth = 6;
-               else if (hdmi_data->enc_color_depth == 16)
+               } else if (hdmi_data->enc_color_depth == 16) {
                        color_depth = 7;
-               else
+               } else {
                        return;
+               }
        } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
                if (!hdmi_data->enc_color_depth ||
                    hdmi_data->enc_color_depth == 8)
@@ -559,8 +564,9 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
                else
                        return;
                output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
-       } else
+       } else {
                return;
+       }
 
        /* set the packetizer registers */
        val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
@@ -620,109 +626,110 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
                  HDMI_VP_CONF);
 }
 
-static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
-                                               unsigned char bit)
+static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
+                                      unsigned char bit)
 {
        hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
                  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
-static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
-                                               unsigned char bit)
+static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
+                                       unsigned char bit)
 {
        hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
                  HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
 }
 
-static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
-                                               unsigned char bit)
+static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
+                                      unsigned char bit)
 {
        hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
                  HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
 }
 
-static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
-                                               unsigned char bit)
+static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
+                                    unsigned char bit)
 {
        hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
 }
 
-static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi,
-                                               unsigned char bit)
+static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
+                                     unsigned char bit)
 {
        hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
 }
 
-static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec)
+static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
 {
-       unsigned char val = 0;
-       val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
-       while (!val) {
-               udelay(1000);
+       u32 val;
+
+       while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
                if (msec-- == 0)
                        return false;
-               val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
+               udelay(1000);
        }
+       hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
+
        return true;
 }
 
-static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
-                             unsigned char addr)
+static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+                                unsigned char addr)
 {
        hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
        hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
        hdmi_writeb(hdmi, (unsigned char)(data >> 8),
-               HDMI_PHY_I2CM_DATAO_1_ADDR);
+                   HDMI_PHY_I2CM_DATAO_1_ADDR);
        hdmi_writeb(hdmi, (unsigned char)(data >> 0),
-               HDMI_PHY_I2CM_DATAO_0_ADDR);
+                   HDMI_PHY_I2CM_DATAO_0_ADDR);
        hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
-               HDMI_PHY_I2CM_OPERATION_ADDR);
+                   HDMI_PHY_I2CM_OPERATION_ADDR);
        hdmi_phy_wait_i2c_done(hdmi, 1000);
 }
 
-static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
-                                    unsigned char addr)
+static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+                             unsigned char addr)
 {
        __hdmi_phy_i2c_write(hdmi, data, addr);
        return 0;
 }
 
-static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable)
+static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_PDZ_OFFSET,
                         HDMI_PHY_CONF0_PDZ_MASK);
 }
 
-static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable)
+static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_ENTMDS_OFFSET,
                         HDMI_PHY_CONF0_ENTMDS_MASK);
 }
 
-static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable)
+static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
                         HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
 }
 
-static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable)
+static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
                         HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
 }
 
-static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable)
+static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
                         HDMI_PHY_CONF0_SELDATAENPOL_MASK);
 }
 
-static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 
enable)
+static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 {
        hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
                         HDMI_PHY_CONF0_SELDIPIF_OFFSET,
@@ -730,10 +737,10 @@ static void imx_hdmi_phy_sel_interface_control(struct 
imx_hdmi *hdmi, u8 enable)
 }
 
 enum {
-       RES_8,
-       RES_10,
-       RES_12,
-       RES_MAX,
+       DW_HDMI_RES_8,
+       DW_HDMI_RES_10,
+       DW_HDMI_RES_12,
+       DW_HDMI_RES_MAX,
 };
 
 struct mpll_config {
@@ -741,7 +748,7 @@ struct mpll_config {
        struct {
                u16 cpce;
                u16 gmp;
-       } res[RES_MAX];
+       } res[DW_HDMI_RES_MAX];
 };
 
 static const struct mpll_config mpll_config[] = {
@@ -774,7 +781,7 @@ static const struct mpll_config mpll_config[] = {
 
 struct curr_ctrl {
        unsigned long mpixelclock;
-       u16 curr[RES_MAX];
+       u16 curr[DW_HDMI_RES_MAX];
 };
 
 static const struct curr_ctrl curr_ctrl[] = {
@@ -794,7 +801,7 @@ static const struct curr_ctrl curr_ctrl[] = {
        }
 };
 
-static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
+static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
                              unsigned char res, int cscon)
 {
        unsigned res_idx, i;
@@ -806,13 +813,13 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
        switch (res) {
        case 0: /* color resolution 0 is 8 bit colour depth */
        case 8:
-               res_idx = RES_8;
+               res_idx = DW_HDMI_RES_8;
                break;
        case 10:
-               res_idx = RES_10;
+               res_idx = DW_HDMI_RES_10;
                break;
        case 12:
-               res_idx = RES_12;
+               res_idx = DW_HDMI_RES_12;
                break;
        default:
                return -EINVAL;
@@ -827,10 +834,10 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
        hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
 
        /* gen2 tx power off */
-       imx_hdmi_phy_gen2_txpwron(hdmi, 0);
+       dw_hdmi_phy_gen2_txpwron(hdmi, 0);
 
        /* gen2 pddq */
-       imx_hdmi_phy_gen2_pddq(hdmi, 1);
+       dw_hdmi_phy_gen2_pddq(hdmi, 1);
 
        /* PHY reset */
        hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
@@ -840,7 +847,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
 
        hdmi_phy_test_clear(hdmi, 1);
        hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
-                       HDMI_PHY_I2CM_SLAVE_ADDR);
+                   HDMI_PHY_I2CM_SLAVE_ADDR);
        hdmi_phy_test_clear(hdmi, 0);
 
        /* PLL/MPLL Cfg - always match on final entry */
@@ -878,15 +885,15 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
        /* REMOVE CLK TERM */
        hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */
 
-       imx_hdmi_phy_enable_power(hdmi, 1);
+       dw_hdmi_phy_enable_power(hdmi, 1);
 
        /* toggle TMDS enable */
-       imx_hdmi_phy_enable_tmds(hdmi, 0);
-       imx_hdmi_phy_enable_tmds(hdmi, 1);
+       dw_hdmi_phy_enable_tmds(hdmi, 0);
+       dw_hdmi_phy_enable_tmds(hdmi, 1);
 
        /* gen2 tx power on */
-       imx_hdmi_phy_gen2_txpwron(hdmi, 1);
-       imx_hdmi_phy_gen2_pddq(hdmi, 0);
+       dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+       dw_hdmi_phy_gen2_pddq(hdmi, 0);
 
        /*Wait for PHY PLL lock */
        msec = 5;
@@ -907,7 +914,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
        return 0;
 }
 
-static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 {
        int i, ret;
        bool cscon = false;
@@ -918,10 +925,10 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
 
        /* HDMI Phy spec says to do the phy initialization sequence twice */
        for (i = 0; i < 2; i++) {
-               imx_hdmi_phy_sel_data_en_pol(hdmi, 1);
-               imx_hdmi_phy_sel_interface_control(hdmi, 0);
-               imx_hdmi_phy_enable_tmds(hdmi, 0);
-               imx_hdmi_phy_enable_power(hdmi, 0);
+               dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
+               dw_hdmi_phy_sel_interface_control(hdmi, 0);
+               dw_hdmi_phy_enable_tmds(hdmi, 0);
+               dw_hdmi_phy_enable_power(hdmi, 0);
 
                /* Enable CSC */
                ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
@@ -933,7 +940,7 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
        return 0;
 }
 
-static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
+static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 {
        u8 de;
 
@@ -952,19 +959,99 @@ static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
                  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
-static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi)
+static void hdmi_av_composer(struct dw_hdmi *hdmi)
+{
+       u8 inv_val;
+       struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
+       int hblank, vblank;
+       struct fb_videomode *mode = hdmi->mode;
+
+       vmode->mhsyncpolarity = !!(mode->sync & FB_SYNC_HOR_HIGH_ACT);
+       vmode->mvsyncpolarity = !!(mode->sync & FB_SYNC_VERT_HIGH_ACT);
+       vmode->minterlaced = !!(mode->vmode & FB_VMODE_INTERLACED);
+       vmode->mpixelclock = PICOS2KHZ(mode->pixclock) * 1000;
+
+       dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
+
+       /* Set up HDMI_FC_INVIDCONF */
+       inv_val = (hdmi->hdmi_data.hdcp_enable ?
+               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
+               HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
+
+       inv_val |= (vmode->mvsyncpolarity ?
+               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
+
+       inv_val |= (vmode->mhsyncpolarity ?
+               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
+
+       inv_val |= (vmode->mdataenablepolarity ?
+               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
+               HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
+
+       if (hdmi->vic == 39)
+               inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
+       else
+               inv_val |= (vmode->minterlaced ?
+                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
+                       HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
+
+       inv_val |= (vmode->minterlaced ?
+               HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
+               HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
+
+       inv_val |= (vmode->mdvi ?
+               HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
+               HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
+
+       hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
+
+       /* Set up horizontal active pixel width */
+       hdmi_writeb(hdmi, mode->xres >> 8, HDMI_FC_INHACTV1);
+       hdmi_writeb(hdmi, mode->xres, HDMI_FC_INHACTV0);
+
+       /* Set up vertical active lines */
+       hdmi_writeb(hdmi, mode->yres >> 8, HDMI_FC_INVACTV1);
+       hdmi_writeb(hdmi, mode->yres, HDMI_FC_INVACTV0);
+
+       /* Set up horizontal blanking pixel region width */
+       hblank = mode->left_margin + mode->right_margin + mode->hsync_len;
+       hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
+       hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
+
+       /* Set up vertical blanking pixel region width */
+       vblank = mode->upper_margin + mode->lower_margin + mode->vsync_len;
+       hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
+
+       /* Set up HSYNC active edge delay width (in pixel clks) */
+       hdmi_writeb(hdmi, mode->right_margin >> 8, HDMI_FC_HSYNCINDELAY1);
+       hdmi_writeb(hdmi, mode->right_margin, HDMI_FC_HSYNCINDELAY0);
+
+       /* Set up VSYNC active edge delay (in lines) */
+       hdmi_writeb(hdmi, mode->lower_margin, HDMI_FC_VSYNCINDELAY);
+
+       /* Set up HSYNC active pulse width (in pixel clks) */
+       hdmi_writeb(hdmi, mode->hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
+       hdmi_writeb(hdmi, mode->hsync_len, HDMI_FC_HSYNCINWIDTH0);
+
+       /* Set up VSYNC active edge delay (in lines) */
+       hdmi_writeb(hdmi, mode->vsync_len, HDMI_FC_VSYNCINWIDTH);
+}
+
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 {
        if (!hdmi->phy_enabled)
                return;
 
-       imx_hdmi_phy_enable_tmds(hdmi, 0);
-       imx_hdmi_phy_enable_power(hdmi, 0);
+       dw_hdmi_phy_enable_tmds(hdmi, 0);
+       dw_hdmi_phy_enable_power(hdmi, 0);
 
        hdmi->phy_enabled = false;
 }
 
 /* HDMI Initialization Step B.4 */
-static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
+static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
        u8 clkdis;
 
@@ -994,7 +1081,7 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi 
*hdmi)
 }
 
 /* Workaround to clear the overflow condition */
-static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
+static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
 {
        int count;
        u8 val;
@@ -1012,12 +1099,10 @@ static void imx_hdmi_clear_overflow(struct imx_hdmi 
*hdmi)
                hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
 }
 
-static int imx_hdmi_setup(struct imx_hdmi *hdmi)
+static int dw_hdmi_setup(struct dw_hdmi *hdmi)
 {
        int ret;
 
-       hdmi->vic = 0;
-
        dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
        hdmi->hdmi_data.video_mode.mdvi = true;
 
@@ -1035,28 +1120,28 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi)
        hdmi->hdmi_data.hdcp_enable = 0;
        hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
 
+       /* HDMI Initialization Step B.1 */
+       hdmi_av_composer(hdmi);
+
        /* HDMI Initializateion Step B.2 */
-       ret = imx_hdmi_phy_init(hdmi);
+       ret = dw_hdmi_phy_init(hdmi);
        if (ret)
                return ret;
 
        /* HDMI Initialization Step B.3 */
-       imx_hdmi_enable_video_path(hdmi);
-
-       /* not for DVI mode */
-       dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
+       dw_hdmi_enable_video_path(hdmi);
 
        hdmi_video_packetize(hdmi);
        hdmi_video_csc(hdmi);
        hdmi_video_sample(hdmi);
        hdmi_tx_hdcp_config(hdmi);
 
-       imx_hdmi_clear_overflow(hdmi);
+       dw_hdmi_clear_overflow(hdmi);
 
        return 0;
 }
 
-static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi)
+static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
 {
        u8 ih_mute;
 
@@ -1108,22 +1193,22 @@ static void initialize_hdmi_ih_mutes(struct imx_hdmi 
*hdmi)
        hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
 }
 
-struct imx_hdmi_data {
+struct dw_hdmi_data {
        unsigned ipu_mask;
-       enum imx_hdmi_devtype devtype;
+       enum dw_hdmi_devtype devtype;
 };
 
-static struct imx_hdmi_data imx6q_hdmi_data = {
+static struct dw_hdmi_data imx6q_hdmi_data = {
        .ipu_mask = 0xf,
        .devtype = IMX6Q_HDMI,
 };
 
-static struct imx_hdmi_data imx6dl_hdmi_data = {
+static struct dw_hdmi_data imx6dl_hdmi_data = {
        .ipu_mask = 0x3,
        .devtype = IMX6DL_HDMI,
 };
 
-static struct of_device_id imx_hdmi_dt_ids[] = {
+static struct of_device_id dw_hdmi_dt_ids[] = {
        {
                .compatible = "fsl,imx6q-hdmi",
                .data = &imx6q_hdmi_data,
@@ -1135,7 +1220,7 @@ static struct of_device_id imx_hdmi_dt_ids[] = {
        }
 };
 
-static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, struct display_timings 
*timings)
+static int dw_hdmi_get_modes(struct dw_hdmi *hdmi, struct display_timings 
*timings)
 {
        int ret = -ENOENT;
 
@@ -1155,23 +1240,24 @@ static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, 
struct display_timings *tim
        return ret;
 }
 
-static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int port,
+static int dw_hdmi_ioctl(struct vpl *vpl, unsigned int port,
                unsigned int cmd, void *data)
 {
-       struct imx_hdmi *hdmi = container_of(vpl, struct imx_hdmi, vpl);
+       struct dw_hdmi *hdmi = container_of(vpl, struct dw_hdmi, vpl);
        struct ipu_di_mode *mode;
 
        switch (cmd) {
        case VPL_ENABLE:
-               return imx_hdmi_setup(hdmi);
+               return dw_hdmi_setup(hdmi);
        case VPL_DISABLE:
-               imx_hdmi_phy_disable(hdmi);
+               dw_hdmi_phy_disable(hdmi);
                return 0;
        case VPL_PREPARE:
-               imx_hdmi_set_ipu_di_mux(hdmi, port);
+               hdmi->mode = data;
+               dw_hdmi_set_ipu_di_mux(hdmi, port);
                return 0;
        case VPL_GET_VIDEOMODES:
-               return imx_hdmi_get_modes(hdmi, data);
+               return dw_hdmi_get_modes(hdmi, data);
        case IMX_IPU_VPL_DI_MODE:
                mode = data;
 
@@ -1184,12 +1270,12 @@ static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int 
port,
        return 0;
 }
 
-static int imx_hdmi_probe(struct device_d *dev)
+static int dw_hdmi_probe(struct device_d *dev)
 {
        struct device_node *np = dev->device_node;
-       struct imx_hdmi *hdmi;
+       struct dw_hdmi *hdmi;
        int ret;
-       const struct imx_hdmi_data *devtype;
+       const struct dw_hdmi_data *devtype;
 
        ret = dev_get_drvdata(dev, (const void **)&devtype);
        if (ret)
@@ -1275,7 +1361,7 @@ static int imx_hdmi_probe(struct device_d *dev)
        hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
        hdmi->vpl.node = np;
-       hdmi->vpl.ioctl = imx_hdmi_ioctl;
+       hdmi->vpl.ioctl = dw_hdmi_ioctl;
        ret = vpl_register(&hdmi->vpl);
        if (ret)
                return ret;
@@ -1288,12 +1374,12 @@ err_isfr:
        return ret;
 }
 
-static struct driver_d imx_hdmi_driver = {
-       .probe          = imx_hdmi_probe,
-       .of_compatible  = imx_hdmi_dt_ids,
+static struct driver_d dw_hdmi_driver = {
+       .probe          = dw_hdmi_probe,
+       .of_compatible  = dw_hdmi_dt_ids,
        .name           = "imx-hdmi",
 };
-device_platform_driver(imx_hdmi_driver);
+device_platform_driver(dw_hdmi_driver);
 
 MODULE_AUTHOR("Sascha Hauer <[email protected]>");
 MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver");
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.h 
b/drivers/video/imx-ipu-v3/imx-hdmi.h
index 39b6776..b3e1442 100644
--- a/drivers/video/imx-ipu-v3/imx-hdmi.h
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.h
@@ -837,7 +837,8 @@ enum {
        HDMI_PHY_CONF0_PDZ_OFFSET = 7,
        HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
        HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
-       HDMI_PHY_CONF0_SPARECTRL = 0x20,
+       HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20,
+       HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5,
        HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
        HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
        HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
-- 
2.4.6


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to