[PATCH v12 03/11] staging: imx-drm: imx-hdmi: convert imx-hdmi to drm_bridge mode

2014-11-17 Thread Andy Yan
IMX6 and Rockchip RK3288 and JZ4780 (Ingenic Xburst/MIPS)
use the interface compatible Designware HDMI IP, but they
also have some lightly differences, such as phy pll configuration,
register width, 4K support, clk useage, and the crtc mux configuration
is also platform specific.

To reuse the imx hdmi driver, convert it to drm_bridge

Signed-off-by: Andy Yan 
Signed-off-by: Yakir Yang 

---

Changes in v12:
- squash patch 

Changes in v11:
- squash patch  

Changes in v10:
- split generic dw_hdmi.c improvements from patch#11 (add rk3288 support)

Changes in v9: None
Changes in v8: None
Changes in v7:
- remove unused variables from structure dw_hdmi
- remove a wrong modification
- add copyrights for dw_hdmi-imx.c

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/staging/imx-drm/imx-hdmi.c | 498 +++--
 1 file changed, 314 insertions(+), 184 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index 8029a07..c42da29 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -111,16 +112,24 @@ struct hdmi_data_info {
struct hdmi_vmode video_mode;
 };
 
+struct imx_hdmi_plat_data {
+   const struct mpll_config *mpll_cfg;
+   const struct curr_ctrl *cur_ctr;
+   const struct sym_term *sym_term;
+   enum imx_hdmi_devtype dev_type;
+};
+
 struct imx_hdmi {
struct drm_connector connector;
-   struct drm_encoder encoder;
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
 
enum imx_hdmi_devtype dev_type;
struct device *dev;
-   struct clk *isfr_clk;
-   struct clk *iahb_clk;
 
struct hdmi_data_info hdmi_data;
+   const struct imx_hdmi_plat_data *plat_data;
+   void *priv;
int vic;
 
u8 edid[HDMI_EDID_LEN];
@@ -137,12 +146,13 @@ struct imx_hdmi {
int ratio;
 };
 
-static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
-{
-   regmap_update_bits(hdmi->regmap, IOMUXC_GPR3,
-  IMX6Q_GPR3_HDMI_MUX_CTL_MASK,
-  ipu_di << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
-}
+struct imx_hdmi_priv {
+   struct device *dev;
+   struct clk *isfr_clk;
+   struct clk *iahb_clk;
+   struct regmap *regmap;
+   struct drm_encoder encoder;
+};
 
 static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
 {
@@ -743,7 +753,7 @@ struct mpll_config {
} res[RES_MAX];
 };
 
-static const struct mpll_config mpll_config[] = {
+static const struct mpll_config imx_mpll_cfg[] = {
{
4525, {
{ 0x01e0, 0x },
@@ -776,7 +786,7 @@ struct curr_ctrl {
u16 curr[RES_MAX];
 };
 
-static const struct curr_ctrl curr_ctrl[] = {
+static const struct curr_ctrl imx_cur_ctr[] = {
/*  pixelclk bpp8bpp10   bpp12 */
{
 5400, { 0x091c, 0x091c, 0x06dc },
@@ -793,11 +803,26 @@ static const struct curr_ctrl curr_ctrl[] = {
}
 };
 
+struct sym_term {
+   unsigned long mpixelclock;
+   u16 sym_ctr;/*clock symbol and transmitter control*/
+   u16 term;   /*transmission termination value*/
+};
+
+static const struct sym_term imx_sym_term[] = {
+   /*pixelclk   symbol   term*/
+   { 14850, 0x800d, 0x0005 },
+   { ~0UL,  0x, 0x }
+};
+
 static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
  unsigned char res, int cscon)
 {
unsigned res_idx, i;
u8 val, msec;
+   const struct mpll_config *mpll_cfg = hdmi->plat_data->mpll_cfg;
+   const struct curr_ctrl   *curr_ctr = hdmi->plat_data->cur_ctr;
+   const struct sym_term *sym_term =  hdmi->plat_data->sym_term;
 
if (prep)
return -EINVAL;
@@ -843,34 +868,41 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
hdmi_phy_test_clear(hdmi, 0);
 
/* PLL/MPLL Cfg - always match on final entry */
-   for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+   for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++)
if (hdmi->hdmi_data.video_mode.mpixelclock <=
-   mpll_config[i].mpixelclock)
+   mpll_cfg[i].mpixelclock)
break;
 
-   hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
-   hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+   hdmi_phy_i2c_write(hdmi, mpll_cfg[i].res[res_idx].cpce, 0x06);
+   hdmi_phy_i2c_write(hdmi, mpll_cfg[i].res[res_idx].gmp, 0x15);
 
-   for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+   for (i = 0; curr_ctr[i].mpixelclock != (~0UL); i++)
if (hdmi->hdmi_data.video_mode.mpixelclock <=
-   

[PATCH v12 03/11] staging: imx-drm: imx-hdmi: convert imx-hdmi to drm_bridge mode

2014-11-17 Thread Andy Yan
IMX6 and Rockchip RK3288 and JZ4780 (Ingenic Xburst/MIPS)
use the interface compatible Designware HDMI IP, but they
also have some lightly differences, such as phy pll configuration,
register width, 4K support, clk useage, and the crtc mux configuration
is also platform specific.

To reuse the imx hdmi driver, convert it to drm_bridge

Signed-off-by: Andy Yan andy@rock-chips.com
Signed-off-by: Yakir Yang y...@rock-chips.com

---

Changes in v12:
- squash patch convert dw_hdmi to drm_bridge

Changes in v11:
- squash patch  split some phy configuration to platform driver

Changes in v10:
- split generic dw_hdmi.c improvements from patch#11 (add rk3288 support)

Changes in v9: None
Changes in v8: None
Changes in v7:
- remove unused variables from structure dw_hdmi
- remove a wrong modification
- add copyrights for dw_hdmi-imx.c

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/staging/imx-drm/imx-hdmi.c | 498 +++--
 1 file changed, 314 insertions(+), 184 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index 8029a07..c42da29 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -23,6 +23,7 @@
 #include linux/mfd/syscon/imx6q-iomuxc-gpr.h
 #include linux/of_device.h
 
+#include drm/drm_of.h
 #include drm/drmP.h
 #include drm/drm_crtc_helper.h
 #include drm/drm_edid.h
@@ -111,16 +112,24 @@ struct hdmi_data_info {
struct hdmi_vmode video_mode;
 };
 
+struct imx_hdmi_plat_data {
+   const struct mpll_config *mpll_cfg;
+   const struct curr_ctrl *cur_ctr;
+   const struct sym_term *sym_term;
+   enum imx_hdmi_devtype dev_type;
+};
+
 struct imx_hdmi {
struct drm_connector connector;
-   struct drm_encoder encoder;
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
 
enum imx_hdmi_devtype dev_type;
struct device *dev;
-   struct clk *isfr_clk;
-   struct clk *iahb_clk;
 
struct hdmi_data_info hdmi_data;
+   const struct imx_hdmi_plat_data *plat_data;
+   void *priv;
int vic;
 
u8 edid[HDMI_EDID_LEN];
@@ -137,12 +146,13 @@ struct imx_hdmi {
int ratio;
 };
 
-static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
-{
-   regmap_update_bits(hdmi-regmap, IOMUXC_GPR3,
-  IMX6Q_GPR3_HDMI_MUX_CTL_MASK,
-  ipu_di  IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
-}
+struct imx_hdmi_priv {
+   struct device *dev;
+   struct clk *isfr_clk;
+   struct clk *iahb_clk;
+   struct regmap *regmap;
+   struct drm_encoder encoder;
+};
 
 static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
 {
@@ -743,7 +753,7 @@ struct mpll_config {
} res[RES_MAX];
 };
 
-static const struct mpll_config mpll_config[] = {
+static const struct mpll_config imx_mpll_cfg[] = {
{
4525, {
{ 0x01e0, 0x },
@@ -776,7 +786,7 @@ struct curr_ctrl {
u16 curr[RES_MAX];
 };
 
-static const struct curr_ctrl curr_ctrl[] = {
+static const struct curr_ctrl imx_cur_ctr[] = {
/*  pixelclk bpp8bpp10   bpp12 */
{
 5400, { 0x091c, 0x091c, 0x06dc },
@@ -793,11 +803,26 @@ static const struct curr_ctrl curr_ctrl[] = {
}
 };
 
+struct sym_term {
+   unsigned long mpixelclock;
+   u16 sym_ctr;/*clock symbol and transmitter control*/
+   u16 term;   /*transmission termination value*/
+};
+
+static const struct sym_term imx_sym_term[] = {
+   /*pixelclk   symbol   term*/
+   { 14850, 0x800d, 0x0005 },
+   { ~0UL,  0x, 0x }
+};
+
 static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
  unsigned char res, int cscon)
 {
unsigned res_idx, i;
u8 val, msec;
+   const struct mpll_config *mpll_cfg = hdmi-plat_data-mpll_cfg;
+   const struct curr_ctrl   *curr_ctr = hdmi-plat_data-cur_ctr;
+   const struct sym_term *sym_term =  hdmi-plat_data-sym_term;
 
if (prep)
return -EINVAL;
@@ -843,34 +868,41 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, 
unsigned char prep,
hdmi_phy_test_clear(hdmi, 0);
 
/* PLL/MPLL Cfg - always match on final entry */
-   for (i = 0; i  ARRAY_SIZE(mpll_config) - 1; i++)
+   for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++)
if (hdmi-hdmi_data.video_mode.mpixelclock =
-   mpll_config[i].mpixelclock)
+   mpll_cfg[i].mpixelclock)
break;
 
-   hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
-   hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+   hdmi_phy_i2c_write(hdmi, mpll_cfg[i].res[res_idx].cpce, 0x06);
+   hdmi_phy_i2c_write(hdmi,