All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support
@ 2017-03-03 17:19 ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

Hello,

This patch series refactors all the PHY handling code in order to allow
support of vendor PHYs and Synopsys DWC HDMI 2.0 TX PHYs.

The series starts with a few cleanups and small fixes. Patch 01/10 just
removes unused code, patch 02/10 moves the color converter code out of the PHY
configure function as it isn't PHY-dependent, and patch 03/10 enables color
conversion even for DVI as it is needed to output RGB when the input format is
YUV.

The next two patches fix the power down (04/10) and up (05/10) sequences to
comply with the HDMI TX PHY specifications. They are the biggest functional
changes in the whole set, and have been tested successfully (with the rest of
the series) on i.MX6Q, RK3288 and R-Car H3. The PLL PHY lock delay has been
measured to be between 300µs and 350µs on R-Car H3, between 400µs and 600µs on
i.MX6Q and between 150µs and 450µs on RK3288. The PHY power down delay has
been measured to be less than 50µs on all platforms, and was often close to
instant with power down reported in the first poll iteration. We should thus
be more than safe with a 5ms timeout.

Patch 06/10 breaks the PHY operations out. Glue code is then allowed to pass a
PHY operations structure to support vendor PHYs. The existing PHY support code
is turned into a default Synopsys PHYs implementation for those PHY
operations.

Patch 07/10 further refactors the Synopsys PHY configuration function to make
it modular, in order to support DWC HDMI 2.0 TX PHYs that have a very
different register layout compared to the currently supported PHYs. Glue code
is again allowed to provide a custom PHY configuration implementation, with
the existing PHY support code turned into the default implementation for all
currently supported Synopsys PHYs.

Patch 08/10 is a small cleanup that removes the now unneeded device type for
glue code platform data, and patch 09/10 follows by switching the driver to
regmap in order to support vendor-specific register access more easily.

Patch 10/10 is a v5 addition that moves the code to a new directory per Jose's
request. v5 also picked up review tags from the mailing list, and is rebased
on top of the latest drm-misc-next branch. The series is otherwise unchanged
compared to v4.

Archit, how would you like to proceed to get this merged ?

Kieran Bingham (2):
  drm: bridge: dw-hdmi: Add support for custom PHY configuration
  drm: bridge: dw-hdmi: Remove device type from platform data

Laurent Pinchart (6):
  drm: bridge: dw-hdmi: Remove unused functions
  drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
  drm: bridge: dw-hdmi: Fix the PHY power down sequence
  drm: bridge: dw-hdmi: Fix the PHY power up sequence
  drm: bridge: dw-hdmi: Create PHY operations
  drm: bridge: dw-hdmi: Move the driver to a separate directory.

Neil Armstrong (2):
  drm: bridge: dw-hdmi: Enable CSC even for DVI
  drm: bridge: dw-hdmi: Switch to regmap for register access

 drivers/gpu/drm/bridge/Kconfig                     |   2 +
 drivers/gpu/drm/bridge/Makefile                    |   4 +-
 drivers/gpu/drm/bridge/synopsys/Kconfig            |  23 +
 drivers/gpu/drm/bridge/synopsys/Makefile           |   5 +
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |   0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |   0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |   0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    | 467 ++++++++++++---------
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |   0
 drivers/gpu/drm/imx/dw_hdmi-imx.c                  |   2 -
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        |   1 -
 include/drm/bridge/dw_hdmi.h                       |  33 +-
 12 files changed, 335 insertions(+), 202 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (88%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support
@ 2017-03-03 17:19 ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

Hello,

This patch series refactors all the PHY handling code in order to allow
support of vendor PHYs and Synopsys DWC HDMI 2.0 TX PHYs.

The series starts with a few cleanups and small fixes. Patch 01/10 just
removes unused code, patch 02/10 moves the color converter code out of the PHY
configure function as it isn't PHY-dependent, and patch 03/10 enables color
conversion even for DVI as it is needed to output RGB when the input format is
YUV.

The next two patches fix the power down (04/10) and up (05/10) sequences to
comply with the HDMI TX PHY specifications. They are the biggest functional
changes in the whole set, and have been tested successfully (with the rest of
the series) on i.MX6Q, RK3288 and R-Car H3. The PLL PHY lock delay has been
measured to be between 300µs and 350µs on R-Car H3, between 400µs and 600µs on
i.MX6Q and between 150µs and 450µs on RK3288. The PHY power down delay has
been measured to be less than 50µs on all platforms, and was often close to
instant with power down reported in the first poll iteration. We should thus
be more than safe with a 5ms timeout.

Patch 06/10 breaks the PHY operations out. Glue code is then allowed to pass a
PHY operations structure to support vendor PHYs. The existing PHY support code
is turned into a default Synopsys PHYs implementation for those PHY
operations.

Patch 07/10 further refactors the Synopsys PHY configuration function to make
it modular, in order to support DWC HDMI 2.0 TX PHYs that have a very
different register layout compared to the currently supported PHYs. Glue code
is again allowed to provide a custom PHY configuration implementation, with
the existing PHY support code turned into the default implementation for all
currently supported Synopsys PHYs.

Patch 08/10 is a small cleanup that removes the now unneeded device type for
glue code platform data, and patch 09/10 follows by switching the driver to
regmap in order to support vendor-specific register access more easily.

Patch 10/10 is a v5 addition that moves the code to a new directory per Jose's
request. v5 also picked up review tags from the mailing list, and is rebased
on top of the latest drm-misc-next branch. The series is otherwise unchanged
compared to v4.

Archit, how would you like to proceed to get this merged ?

Kieran Bingham (2):
  drm: bridge: dw-hdmi: Add support for custom PHY configuration
  drm: bridge: dw-hdmi: Remove device type from platform data

Laurent Pinchart (6):
  drm: bridge: dw-hdmi: Remove unused functions
  drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
  drm: bridge: dw-hdmi: Fix the PHY power down sequence
  drm: bridge: dw-hdmi: Fix the PHY power up sequence
  drm: bridge: dw-hdmi: Create PHY operations
  drm: bridge: dw-hdmi: Move the driver to a separate directory.

Neil Armstrong (2):
  drm: bridge: dw-hdmi: Enable CSC even for DVI
  drm: bridge: dw-hdmi: Switch to regmap for register access

 drivers/gpu/drm/bridge/Kconfig                     |   2 +
 drivers/gpu/drm/bridge/Makefile                    |   4 +-
 drivers/gpu/drm/bridge/synopsys/Kconfig            |  23 +
 drivers/gpu/drm/bridge/synopsys/Makefile           |   5 +
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |   0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |   0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |   0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    | 467 ++++++++++++---------
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |   0
 drivers/gpu/drm/imx/dw_hdmi-imx.c                  |   2 -
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        |   1 -
 include/drm/bridge/dw_hdmi.h                       |  33 +-
 12 files changed, 335 insertions(+), 202 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (88%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v5 01/10] drm: bridge: dw-hdmi: Remove unused functions
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:19   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

Most of the hdmi_phy_test_*() functions are unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
Tested-by: Nickey Yang <nickey.yang@rock-chips.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 26 --------------------------
 1 file changed, 26 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 9a9ec27d9e28..ce7496399ccf 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -837,32 +837,6 @@ static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 		  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
-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 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 dw_hdmi *hdmi,
-				     unsigned char bit)
-{
-	hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
-}
-
-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 dw_hdmi *hdmi, int msec)
 {
 	u32 val;
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 01/10] drm: bridge: dw-hdmi: Remove unused functions
@ 2017-03-03 17:19   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

Most of the hdmi_phy_test_*() functions are unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
Tested-by: Nickey Yang <nickey.yang@rock-chips.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 26 --------------------------
 1 file changed, 26 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 9a9ec27d9e28..ce7496399ccf 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -837,32 +837,6 @@ static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 		  HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
 }
 
-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 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 dw_hdmi *hdmi,
-				     unsigned char bit)
-{
-	hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
-}
-
-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 dw_hdmi *hdmi, int msec)
 {
 	u32 val;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 02/10] drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:19   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

The color space converter isn't part of the PHY, move its configuration
out of PHY code.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index ce7496399ccf..906583beb08b 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -914,7 +914,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
@@ -946,14 +946,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
 		return -EINVAL;
 	}
 
-	/* Enable csc path */
-	if (cscon)
-		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
-	else
-		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
-
-	hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
-
 	/* gen2 tx power off */
 	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
 
@@ -1028,10 +1020,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 {
 	int i, ret;
-	bool cscon;
-
-	/*check csc whether needed activated in HDMI mode */
-	cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
 
 	/* HDMI Phy spec says to do the phy initialization sequence twice */
 	for (i = 0; i < 2; i++) {
@@ -1040,8 +1028,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 		dw_hdmi_phy_enable_tmds(hdmi, 0);
 		dw_hdmi_phy_enable_powerdown(hdmi, true);
 
-		/* Enable CSC */
-		ret = hdmi_phy_configure(hdmi, cscon);
+		ret = hdmi_phy_configure(hdmi);
 		if (ret)
 			return ret;
 	}
@@ -1303,6 +1290,14 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
 		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
 	}
+
+	/* Enable color space conversion if needed (for HDMI sinks only). */
+	if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
+		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
+			    HDMI_MC_FLOWCTRL);
+	else
+		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
+			    HDMI_MC_FLOWCTRL);
 }
 
 static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 02/10] drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
@ 2017-03-03 17:19   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:19 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

The color space converter isn't part of the PHY, move its configuration
out of PHY code.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index ce7496399ccf..906583beb08b 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -914,7 +914,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
-static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
@@ -946,14 +946,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
 		return -EINVAL;
 	}
 
-	/* Enable csc path */
-	if (cscon)
-		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
-	else
-		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
-
-	hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
-
 	/* gen2 tx power off */
 	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
 
@@ -1028,10 +1020,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 {
 	int i, ret;
-	bool cscon;
-
-	/*check csc whether needed activated in HDMI mode */
-	cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
 
 	/* HDMI Phy spec says to do the phy initialization sequence twice */
 	for (i = 0; i < 2; i++) {
@@ -1040,8 +1028,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 		dw_hdmi_phy_enable_tmds(hdmi, 0);
 		dw_hdmi_phy_enable_powerdown(hdmi, true);
 
-		/* Enable CSC */
-		ret = hdmi_phy_configure(hdmi, cscon);
+		ret = hdmi_phy_configure(hdmi);
 		if (ret)
 			return ret;
 	}
@@ -1303,6 +1290,14 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
 		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
 	}
+
+	/* Enable color space conversion if needed (for HDMI sinks only). */
+	if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
+		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
+			    HDMI_MC_FLOWCTRL);
+	else
+		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
+			    HDMI_MC_FLOWCTRL);
 }
 
 static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 03/10] drm: bridge: dw-hdmi: Enable CSC even for DVI
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

From: Neil Armstrong <narmstrong@baylibre.com>

If the input pixel format is not RGB, the CSC must be enabled in order to
provide valid pixel to DVI sinks.
This patch removes the hdmi only dependency on the CSC enabling.

Reviewed-by: Jose Abreu <joabreu@synopsys.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 906583beb08b..d863b3393aee 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1291,8 +1291,8 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
 	}
 
-	/* Enable color space conversion if needed (for HDMI sinks only). */
-	if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
+	/* Enable color space conversion if needed */
+	if (is_color_space_conversion(hdmi))
 		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
 			    HDMI_MC_FLOWCTRL);
 	else
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 03/10] drm: bridge: dw-hdmi: Enable CSC even for DVI
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

From: Neil Armstrong <narmstrong@baylibre.com>

If the input pixel format is not RGB, the CSC must be enabled in order to
provide valid pixel to DVI sinks.
This patch removes the hdmi only dependency on the CSC enabling.

Reviewed-by: Jose Abreu <joabreu@synopsys.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 906583beb08b..d863b3393aee 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1291,8 +1291,8 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
 	}
 
-	/* Enable color space conversion if needed (for HDMI sinks only). */
-	if (hdmi->sink_is_hdmi && is_color_space_conversion(hdmi))
+	/* Enable color space conversion if needed */
+	if (is_color_space_conversion(hdmi))
 		hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
 			    HDMI_MC_FLOWCTRL);
 	else
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

The PHY requires us to wait for the PHY to switch to low power mode
after deasserting TXPWRON and before asserting PDDQ in the power down
sequence, otherwise power down will fail.

The PHY power down can be monitored though the TX_READY bit, available
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
through the HDMI TX registers. As the two are equivalent, let's pick the
easier solution of polling the TX_PHY_LOCK bit.

The power down code is currently duplicated in multiple places. To avoid
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
refactor the power down code and group it all in a single function.

Tests showed that one poll iteration was enough for TX_PHY_LOCK to
become low, without requiring any additional delay. Retrying the read
five times with a 1ms to 2ms delay between each attempt should thus be
more than enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index d863b3393aee..85348ba6bb1c 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
 struct dw_hdmi_phy_data {
 	enum dw_hdmi_phy_type type;
 	const char *name;
+	unsigned int gen;
 	bool has_svsret;
 };
 
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	unsigned int i;
+	u16 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_powerdown(hdmi, true);
+		return;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+	/*
+	 * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
+	 * to low power mode.
+	 */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+		if (!(val & HDMI_PHY_TX_PHY_LOCK))
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (val & HDMI_PHY_TX_PHY_LOCK)
+		dev_warn(hdmi->dev, "PHY failed to power down\n");
+	else
+		dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
+
+	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		return -EINVAL;
 	}
 
-	/* gen2 tx power off */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-
-	/* gen2 pddq */
-	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
 	if (hdmi->phy->has_svsret)
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 	for (i = 0; i < 2; i++) {
 		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_powerdown(hdmi, true);
 
 		ret = hdmi_phy_configure(hdmi);
 		if (ret)
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 	if (!hdmi->phy_enabled)
 		return;
 
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_powerdown(hdmi, true);
+	dw_hdmi_phy_power_off(hdmi);
 
 	hdmi->phy_enabled = false;
 }
@@ -1827,23 +1855,29 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 	{
 		.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
 		.name = "DWC HDMI TX PHY",
+		.gen = 1,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
 		.name = "DWC MHL PHY + HEAC PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}
 };
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

The PHY requires us to wait for the PHY to switch to low power mode
after deasserting TXPWRON and before asserting PDDQ in the power down
sequence, otherwise power down will fail.

The PHY power down can be monitored though the TX_READY bit, available
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
through the HDMI TX registers. As the two are equivalent, let's pick the
easier solution of polling the TX_PHY_LOCK bit.

The power down code is currently duplicated in multiple places. To avoid
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
refactor the power down code and group it all in a single function.

Tests showed that one poll iteration was enough for TX_PHY_LOCK to
become low, without requiring any additional delay. Retrying the read
five times with a 1ms to 2ms delay between each attempt should thus be
more than enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index d863b3393aee..85348ba6bb1c 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
 struct dw_hdmi_phy_data {
 	enum dw_hdmi_phy_type type;
 	const char *name;
+	unsigned int gen;
 	bool has_svsret;
 };
 
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	unsigned int i;
+	u16 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_powerdown(hdmi, true);
+		return;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+	/*
+	 * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
+	 * to low power mode.
+	 */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+		if (!(val & HDMI_PHY_TX_PHY_LOCK))
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (val & HDMI_PHY_TX_PHY_LOCK)
+		dev_warn(hdmi->dev, "PHY failed to power down\n");
+	else
+		dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
+
+	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		return -EINVAL;
 	}
 
-	/* gen2 tx power off */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-
-	/* gen2 pddq */
-	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
 	if (hdmi->phy->has_svsret)
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 	for (i = 0; i < 2; i++) {
 		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_powerdown(hdmi, true);
 
 		ret = hdmi_phy_configure(hdmi);
 		if (ret)
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 	if (!hdmi->phy_enabled)
 		return;
 
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_powerdown(hdmi, true);
+	dw_hdmi_phy_power_off(hdmi);
 
 	hdmi->phy_enabled = false;
 }
@@ -1827,23 +1855,29 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 	{
 		.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
 		.name = "DWC HDMI TX PHY",
+		.gen = 1,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
 		.name = "DWC MHL PHY + HEAC PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}
 };
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

When powering the PHY up we need to wait for the PLL to lock. This is
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
(interrupt-based wait could be implemented as well but is likely
overkill). The bit is asserted when the PLL locks, but the current code
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
replace the udelay() with a sleep as the code never runs in
non-sleepable context.

To be consistent with the power down implementation move the poll loop
to the power off function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 85348ba6bb1c..0aa3ad404f77 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_gen2_pddq(hdmi, 1);
 }
 
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	unsigned int i;
+	u8 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_powerdown(hdmi, false);
+
+		/* Toggle TMDS enable. */
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_tmds(hdmi, 1);
+		return 0;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+	dw_hdmi_phy_gen2_pddq(hdmi, 0);
+
+	/* Wait for PHY PLL lock */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+		if (val)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (!val) {
+		dev_err(hdmi->dev, "PHY PLL failed to lock\n");
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
+	return 0;
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
-	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
 			   HDMI_3D_TX_PHY_CKCALCTRL);
 
-	dw_hdmi_phy_enable_powerdown(hdmi, false);
-
-	/* toggle TMDS enable */
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_tmds(hdmi, 1);
-
-	/* gen2 tx power on */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
-	dw_hdmi_phy_gen2_pddq(hdmi, 0);
-
-	/* Wait for PHY PLL lock */
-	msec = 5;
-	do {
-		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
-		if (!val)
-			break;
-
-		if (msec == 0) {
-			dev_err(hdmi->dev, "PHY PLL not locked\n");
-			return -ETIMEDOUT;
-		}
-
-		udelay(1000);
-		msec--;
-	} while (1);
-
-	return 0;
+	return dw_hdmi_phy_power_on(hdmi);
 }
 
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

When powering the PHY up we need to wait for the PLL to lock. This is
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
(interrupt-based wait could be implemented as well but is likely
overkill). The bit is asserted when the PLL locks, but the current code
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
replace the udelay() with a sleep as the code never runs in
non-sleepable context.

To be consistent with the power down implementation move the poll loop
to the power off function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 85348ba6bb1c..0aa3ad404f77 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_gen2_pddq(hdmi, 1);
 }
 
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	unsigned int i;
+	u8 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_powerdown(hdmi, false);
+
+		/* Toggle TMDS enable. */
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_tmds(hdmi, 1);
+		return 0;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+	dw_hdmi_phy_gen2_pddq(hdmi, 0);
+
+	/* Wait for PHY PLL lock */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+		if (val)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (!val) {
+		dev_err(hdmi->dev, "PHY PLL failed to lock\n");
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
+	return 0;
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
-	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
 			   HDMI_3D_TX_PHY_CKCALCTRL);
 
-	dw_hdmi_phy_enable_powerdown(hdmi, false);
-
-	/* toggle TMDS enable */
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_tmds(hdmi, 1);
-
-	/* gen2 tx power on */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
-	dw_hdmi_phy_gen2_pddq(hdmi, 0);
-
-	/* Wait for PHY PLL lock */
-	msec = 5;
-	do {
-		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
-		if (!val)
-			break;
-
-		if (msec == 0) {
-			dev_err(hdmi->dev, "PHY PLL not locked\n");
-			return -ETIMEDOUT;
-		}
-
-		udelay(1000);
-		msec--;
-	} while (1);
-
-	return 0;
+	return dw_hdmi_phy_power_on(hdmi);
 }
 
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 06/10] drm: bridge: dw-hdmi: Create PHY operations
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

The HDMI TX controller support different PHYs whose programming
interface can vary significantly, especially with vendor PHYs that are
not provided by Synopsys. To support them, create a PHY operation
structure that can be provided by the platform glue layer. The existing
PHY handling code (limited to Synopsys PHY support) is refactored into a
set of default PHY operations that are used automatically when the
platform glue doesn't provide its own operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 91 ++++++++++++++++++++++++++++------------
 include/drm/bridge/dw_hdmi.h     | 18 +++++++-
 2 files changed, 80 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 0aa3ad404f77..cb2703862be2 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -141,8 +141,12 @@ struct dw_hdmi {
 	u8 edid[HDMI_EDID_LEN];
 	bool cable_plugin;
 
-	const struct dw_hdmi_phy_data *phy;
-	bool phy_enabled;
+	struct {
+		const struct dw_hdmi_phy_ops *ops;
+		const char *name;
+		void *data;
+		bool enabled;
+	} phy;
 
 	struct drm_display_mode previous_mode;
 
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 		  HDMI_VP_CONF);
 }
 
+/* -----------------------------------------------------------------------------
+ * Synopsys PHY Handling
+ */
+
 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 				       unsigned char bit)
 {
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
-	if (hdmi->phy->has_svsret)
+	if (phy->has_svsret)
 		dw_hdmi_phy_enable_svsret(hdmi, 1);
 
 	/* PHY reset. The reset signal is active high on Gen2 PHYs. */
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	return dw_hdmi_phy_power_on(hdmi);
 }
 
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+			    struct drm_display_mode *mode)
 {
 	int i, ret;
 
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 			return ret;
 	}
 
-	hdmi->phy_enabled = true;
 	return 0;
 }
 
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+	dw_hdmi_phy_power_off(hdmi);
+}
+
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
+						      void *data)
+{
+	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+	.init = dw_hdmi_phy_init,
+	.disable = dw_hdmi_phy_disable,
+	.read_hpd = dw_hdmi_phy_read_hpd,
+};
+
+/* -----------------------------------------------------------------------------
+ * HDMI TX Setup
+ */
+
 static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 {
 	u8 de;
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
 }
 
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
-{
-	if (!hdmi->phy_enabled)
-		return;
-
-	dw_hdmi_phy_power_off(hdmi);
-
-	hdmi->phy_enabled = false;
-}
-
 /* HDMI Initialization Step B.4 */
 static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	hdmi_av_composer(hdmi, mode);
 
 	/* HDMI Initializateion Step B.2 */
-	ret = dw_hdmi_phy_init(hdmi);
+	ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
 	if (ret)
 		return ret;
+	hdmi->phy.enabled = true;
 
 	/* HDMI Initialization Step B.3 */
 	dw_hdmi_enable_video_path(hdmi);
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
 
 static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
 {
-	dw_hdmi_phy_disable(hdmi);
+	if (hdmi->phy.enabled) {
+		hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
+		hdmi->phy.enabled = false;
+	}
+
 	hdmi->bridge_is_on = false;
 }
 
@@ -1611,8 +1637,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	dw_hdmi_update_phy_mask(hdmi);
 	mutex_unlock(&hdmi->mutex);
 
-	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-		connector_status_connected : connector_status_disconnected;
+	return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 
 	phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
 
+	if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
+		/* Vendor PHYs require support from the glue layer. */
+		if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
+			dev_err(hdmi->dev,
+				"Vendor HDMI PHY not supported by glue layer\n");
+			return -ENODEV;
+		}
+
+		hdmi->phy.ops = hdmi->plat_data->phy_ops;
+		hdmi->phy.data = hdmi->plat_data->phy_data;
+		hdmi->phy.name = hdmi->plat_data->phy_name;
+		return 0;
+	}
+
+	/* Synopsys PHYs are handled internally. */
 	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
 		if (dw_hdmi_phys[i].type == phy_type) {
-			hdmi->phy = &dw_hdmi_phys[i];
+			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
+			hdmi->phy.name = dw_hdmi_phys[i].name;
+			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
 			return 0;
 		}
 	}
 
-	if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
-		dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
-	else
-		dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
-			phy_type);
-
+	dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
 	return -ENODEV;
 }
 
@@ -2031,7 +2068,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
 		 hdmi->version >> 12, hdmi->version & 0xfff,
 		 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
-		 hdmi->phy->name);
+		 hdmi->phy.name);
 
 	initialize_hdmi_ih_mutes(hdmi);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index b080a171a23f..0f583ca7e66e 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
 	u16 vlev_ctr;   /* voltage level control */
 };
 
+struct dw_hdmi_phy_ops {
+	int (*init)(struct dw_hdmi *hdmi, void *data,
+		    struct drm_display_mode *mode);
+	void (*disable)(struct dw_hdmi *hdmi, void *data);
+	enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
+};
+
 struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
+	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+					   struct drm_display_mode *mode);
+
+	/* Vendor PHY support */
+	const struct dw_hdmi_phy_ops *phy_ops;
+	const char *phy_name;
+	void *phy_data;
+
+	/* Synopsys PHY support */
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
-	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-					   struct drm_display_mode *mode);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 06/10] drm: bridge: dw-hdmi: Create PHY operations
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

The HDMI TX controller support different PHYs whose programming
interface can vary significantly, especially with vendor PHYs that are
not provided by Synopsys. To support them, create a PHY operation
structure that can be provided by the platform glue layer. The existing
PHY handling code (limited to Synopsys PHY support) is refactored into a
set of default PHY operations that are used automatically when the
platform glue doesn't provide its own operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 91 ++++++++++++++++++++++++++++------------
 include/drm/bridge/dw_hdmi.h     | 18 +++++++-
 2 files changed, 80 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 0aa3ad404f77..cb2703862be2 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -141,8 +141,12 @@ struct dw_hdmi {
 	u8 edid[HDMI_EDID_LEN];
 	bool cable_plugin;
 
-	const struct dw_hdmi_phy_data *phy;
-	bool phy_enabled;
+	struct {
+		const struct dw_hdmi_phy_ops *ops;
+		const char *name;
+		void *data;
+		bool enabled;
+	} phy;
 
 	struct drm_display_mode previous_mode;
 
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 		  HDMI_VP_CONF);
 }
 
+/* -----------------------------------------------------------------------------
+ * Synopsys PHY Handling
+ */
+
 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 				       unsigned char bit)
 {
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
-	if (hdmi->phy->has_svsret)
+	if (phy->has_svsret)
 		dw_hdmi_phy_enable_svsret(hdmi, 1);
 
 	/* PHY reset. The reset signal is active high on Gen2 PHYs. */
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	return dw_hdmi_phy_power_on(hdmi);
 }
 
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+			    struct drm_display_mode *mode)
 {
 	int i, ret;
 
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 			return ret;
 	}
 
-	hdmi->phy_enabled = true;
 	return 0;
 }
 
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+	dw_hdmi_phy_power_off(hdmi);
+}
+
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
+						      void *data)
+{
+	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+	.init = dw_hdmi_phy_init,
+	.disable = dw_hdmi_phy_disable,
+	.read_hpd = dw_hdmi_phy_read_hpd,
+};
+
+/* -----------------------------------------------------------------------------
+ * HDMI TX Setup
+ */
+
 static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 {
 	u8 de;
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
 }
 
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
-{
-	if (!hdmi->phy_enabled)
-		return;
-
-	dw_hdmi_phy_power_off(hdmi);
-
-	hdmi->phy_enabled = false;
-}
-
 /* HDMI Initialization Step B.4 */
 static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	hdmi_av_composer(hdmi, mode);
 
 	/* HDMI Initializateion Step B.2 */
-	ret = dw_hdmi_phy_init(hdmi);
+	ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
 	if (ret)
 		return ret;
+	hdmi->phy.enabled = true;
 
 	/* HDMI Initialization Step B.3 */
 	dw_hdmi_enable_video_path(hdmi);
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
 
 static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
 {
-	dw_hdmi_phy_disable(hdmi);
+	if (hdmi->phy.enabled) {
+		hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
+		hdmi->phy.enabled = false;
+	}
+
 	hdmi->bridge_is_on = false;
 }
 
@@ -1611,8 +1637,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	dw_hdmi_update_phy_mask(hdmi);
 	mutex_unlock(&hdmi->mutex);
 
-	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-		connector_status_connected : connector_status_disconnected;
+	return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 
 	phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
 
+	if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
+		/* Vendor PHYs require support from the glue layer. */
+		if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
+			dev_err(hdmi->dev,
+				"Vendor HDMI PHY not supported by glue layer\n");
+			return -ENODEV;
+		}
+
+		hdmi->phy.ops = hdmi->plat_data->phy_ops;
+		hdmi->phy.data = hdmi->plat_data->phy_data;
+		hdmi->phy.name = hdmi->plat_data->phy_name;
+		return 0;
+	}
+
+	/* Synopsys PHYs are handled internally. */
 	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
 		if (dw_hdmi_phys[i].type == phy_type) {
-			hdmi->phy = &dw_hdmi_phys[i];
+			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
+			hdmi->phy.name = dw_hdmi_phys[i].name;
+			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
 			return 0;
 		}
 	}
 
-	if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
-		dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
-	else
-		dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
-			phy_type);
-
+	dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
 	return -ENODEV;
 }
 
@@ -2031,7 +2068,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
 		 hdmi->version >> 12, hdmi->version & 0xfff,
 		 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
-		 hdmi->phy->name);
+		 hdmi->phy.name);
 
 	initialize_hdmi_ih_mutes(hdmi);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index b080a171a23f..0f583ca7e66e 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
 	u16 vlev_ctr;   /* voltage level control */
 };
 
+struct dw_hdmi_phy_ops {
+	int (*init)(struct dw_hdmi *hdmi, void *data,
+		    struct drm_display_mode *mode);
+	void (*disable)(struct dw_hdmi *hdmi, void *data);
+	enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
+};
+
 struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
+	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+					   struct drm_display_mode *mode);
+
+	/* Vendor PHY support */
+	const struct dw_hdmi_phy_ops *phy_ops;
+	const char *phy_name;
+	void *phy_data;
+
+	/* Synopsys PHY support */
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
-	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-					   struct drm_display_mode *mode);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc, Kieran Bingham

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The DWC HDMI TX controller interfaces with a companion PHY. While
Synopsys provides multiple standard PHYs, SoC vendors can also integrate
a custom PHY.

Modularize PHY configuration to support vendor PHYs through platform
data. The existing PHY configuration code was originally written to
support the DWC HDMI 3D TX PHY, and seems to be compatible with the DWC
MLP PHY. The HDMI 2.0 PHY will require a separate configuration
function.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
---
Changes since v1:

- Check pdata->phy_configure in hdmi_phy_configure() to avoid
  dereferencing NULL pointer.
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 109 ++++++++++++++++++++++++++-------------
 include/drm/bridge/dw_hdmi.h     |   7 +++
 2 files changed, 81 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index cb2703862be2..b835d81bb471 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
 	const char *name;
 	unsigned int gen;
 	bool has_svsret;
+	int (*configure)(struct dw_hdmi *hdmi,
+			 const struct dw_hdmi_plat_data *pdata,
+			 unsigned long mpixelclock);
 };
 
 struct dw_hdmi {
@@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
 	return true;
 }
 
-static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
-				 unsigned char addr)
+void dw_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);
@@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
 		    HDMI_PHY_I2CM_OPERATION_ADDR);
 	hdmi_phy_wait_i2c_done(hdmi, 1000);
 }
+EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
 
 static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
 {
@@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 	return 0;
 }
 
-static int hdmi_phy_configure(struct dw_hdmi *hdmi)
+/*
+ * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
+ * information the DWC MHL PHY has the same register layout and is thus also
+ * supported by this function.
+ */
+static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
+		const struct dw_hdmi_plat_data *pdata,
+		unsigned long mpixelclock)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
-	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
 
 	/* PLL/MPLL Cfg - always match on final entry */
 	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    mpll_config->mpixelclock)
+		if (mpixelclock <= mpll_config->mpixelclock)
 			break;
 
 	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    curr_ctrl->mpixelclock)
+		if (mpixelclock <= curr_ctrl->mpixelclock)
 			break;
 
 	for (; phy_config->mpixelclock != ~0UL; phy_config++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    phy_config->mpixelclock)
+		if (mpixelclock <= phy_config->mpixelclock)
 			break;
 
 	if (mpll_config->mpixelclock == ~0UL ||
 	    curr_ctrl->mpixelclock == ~0UL ||
-	    phy_config->mpixelclock == ~0UL) {
-		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
-			hdmi->hdmi_data.video_mode.mpixelclock);
+	    phy_config->mpixelclock == ~0UL)
 		return -EINVAL;
-	}
+
+	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
+			      HDMI_3D_TX_PHY_CPCE_CTRL);
+	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
+			      HDMI_3D_TX_PHY_GMPCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
+			      HDMI_3D_TX_PHY_CURRCTRL);
+
+	dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
+			      HDMI_3D_TX_PHY_MSM_CTRL);
+
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
+			      HDMI_3D_TX_PHY_CKSYMTXCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
+			      HDMI_3D_TX_PHY_VLEVCTRL);
+
+	/* Override and disable clock termination. */
+	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
+			      HDMI_3D_TX_PHY_CKCALCTRL);
+
+	return 0;
+}
+
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
+	unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
+	int ret;
 
 	dw_hdmi_phy_power_off(hdmi);
 
@@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		    HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
-			   HDMI_3D_TX_PHY_CPCE_CTRL);
-	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
-			   HDMI_3D_TX_PHY_GMPCTRL);
-	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
-			   HDMI_3D_TX_PHY_CURRCTRL);
-
-	hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
-	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
-			   HDMI_3D_TX_PHY_MSM_CTRL);
-
-	hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
-	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
-			   HDMI_3D_TX_PHY_CKSYMTXCTRL);
-	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
-			   HDMI_3D_TX_PHY_VLEVCTRL);
-
-	/* Override and disable clock termination. */
-	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
-			   HDMI_3D_TX_PHY_CKCALCTRL);
+	/* Write to the PHY as configured by the platform */
+	if (pdata->configure_phy)
+		ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
+	else
+		ret = phy->configure(hdmi, pdata, mpixelclock);
+	if (ret) {
+		dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
+			mpixelclock);
+		return ret;
+	}
 
 	return dw_hdmi_phy_power_on(hdmi);
 }
@@ -1895,24 +1919,31 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 		.name = "DWC MHL PHY + HEAC PHY",
 		.gen = 2,
 		.has_svsret = true,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
 		.gen = 2,
 		.has_svsret = true,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
 		.gen = 2,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
 		.gen = 2,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
 		.gen = 2,
 		.has_svsret = true,
+	}, {
+		.type = DW_HDMI_PHY_VENDOR_PHY,
+		.name = "Vendor PHY",
 	}
 };
 
@@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
 			hdmi->phy.name = dw_hdmi_phys[i].name;
 			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
+
+			if (!dw_hdmi_phys[i].configure &&
+			    !hdmi->plat_data->configure_phy) {
+				dev_err(hdmi->dev, "%s requires platform support\n",
+					hdmi->phy.name);
+				return -ENODEV;
+			}
+
 			return 0;
 		}
 	}
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 0f583ca7e66e..dd330259a3dc 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
+	int (*configure_phy)(struct dw_hdmi *hdmi,
+			     const struct dw_hdmi_plat_data *pdata,
+			     unsigned long mpixelclock);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
@@ -91,4 +94,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
 void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
 void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
 
+/* PHY configuration */
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+			   unsigned char addr);
+
 #endif /* __IMX_HDMI_H__ */
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Kieran Bingham, Russell King,
	Andy Yan, Vladimir Zapolskiy

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The DWC HDMI TX controller interfaces with a companion PHY. While
Synopsys provides multiple standard PHYs, SoC vendors can also integrate
a custom PHY.

Modularize PHY configuration to support vendor PHYs through platform
data. The existing PHY configuration code was originally written to
support the DWC HDMI 3D TX PHY, and seems to be compatible with the DWC
MLP PHY. The HDMI 2.0 PHY will require a separate configuration
function.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
---
Changes since v1:

- Check pdata->phy_configure in hdmi_phy_configure() to avoid
  dereferencing NULL pointer.
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 109 ++++++++++++++++++++++++++-------------
 include/drm/bridge/dw_hdmi.h     |   7 +++
 2 files changed, 81 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index cb2703862be2..b835d81bb471 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
 	const char *name;
 	unsigned int gen;
 	bool has_svsret;
+	int (*configure)(struct dw_hdmi *hdmi,
+			 const struct dw_hdmi_plat_data *pdata,
+			 unsigned long mpixelclock);
 };
 
 struct dw_hdmi {
@@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
 	return true;
 }
 
-static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
-				 unsigned char addr)
+void dw_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);
@@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
 		    HDMI_PHY_I2CM_OPERATION_ADDR);
 	hdmi_phy_wait_i2c_done(hdmi, 1000);
 }
+EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
 
 static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
 {
@@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 	return 0;
 }
 
-static int hdmi_phy_configure(struct dw_hdmi *hdmi)
+/*
+ * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
+ * information the DWC MHL PHY has the same register layout and is thus also
+ * supported by this function.
+ */
+static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
+		const struct dw_hdmi_plat_data *pdata,
+		unsigned long mpixelclock)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
-	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
 
 	/* PLL/MPLL Cfg - always match on final entry */
 	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    mpll_config->mpixelclock)
+		if (mpixelclock <= mpll_config->mpixelclock)
 			break;
 
 	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    curr_ctrl->mpixelclock)
+		if (mpixelclock <= curr_ctrl->mpixelclock)
 			break;
 
 	for (; phy_config->mpixelclock != ~0UL; phy_config++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    phy_config->mpixelclock)
+		if (mpixelclock <= phy_config->mpixelclock)
 			break;
 
 	if (mpll_config->mpixelclock == ~0UL ||
 	    curr_ctrl->mpixelclock == ~0UL ||
-	    phy_config->mpixelclock == ~0UL) {
-		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
-			hdmi->hdmi_data.video_mode.mpixelclock);
+	    phy_config->mpixelclock == ~0UL)
 		return -EINVAL;
-	}
+
+	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
+			      HDMI_3D_TX_PHY_CPCE_CTRL);
+	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
+			      HDMI_3D_TX_PHY_GMPCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
+			      HDMI_3D_TX_PHY_CURRCTRL);
+
+	dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
+			      HDMI_3D_TX_PHY_MSM_CTRL);
+
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
+			      HDMI_3D_TX_PHY_CKSYMTXCTRL);
+	dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
+			      HDMI_3D_TX_PHY_VLEVCTRL);
+
+	/* Override and disable clock termination. */
+	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
+			      HDMI_3D_TX_PHY_CKCALCTRL);
+
+	return 0;
+}
+
+static int hdmi_phy_configure(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
+	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
+	unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
+	int ret;
 
 	dw_hdmi_phy_power_off(hdmi);
 
@@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		    HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
-			   HDMI_3D_TX_PHY_CPCE_CTRL);
-	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
-			   HDMI_3D_TX_PHY_GMPCTRL);
-	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
-			   HDMI_3D_TX_PHY_CURRCTRL);
-
-	hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
-	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
-			   HDMI_3D_TX_PHY_MSM_CTRL);
-
-	hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
-	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
-			   HDMI_3D_TX_PHY_CKSYMTXCTRL);
-	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
-			   HDMI_3D_TX_PHY_VLEVCTRL);
-
-	/* Override and disable clock termination. */
-	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
-			   HDMI_3D_TX_PHY_CKCALCTRL);
+	/* Write to the PHY as configured by the platform */
+	if (pdata->configure_phy)
+		ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
+	else
+		ret = phy->configure(hdmi, pdata, mpixelclock);
+	if (ret) {
+		dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
+			mpixelclock);
+		return ret;
+	}
 
 	return dw_hdmi_phy_power_on(hdmi);
 }
@@ -1895,24 +1919,31 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 		.name = "DWC MHL PHY + HEAC PHY",
 		.gen = 2,
 		.has_svsret = true,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
 		.gen = 2,
 		.has_svsret = true,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
 		.gen = 2,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
 		.gen = 2,
+		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
 		.gen = 2,
 		.has_svsret = true,
+	}, {
+		.type = DW_HDMI_PHY_VENDOR_PHY,
+		.name = "Vendor PHY",
 	}
 };
 
@@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
 			hdmi->phy.name = dw_hdmi_phys[i].name;
 			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
+
+			if (!dw_hdmi_phys[i].configure &&
+			    !hdmi->plat_data->configure_phy) {
+				dev_err(hdmi->dev, "%s requires platform support\n",
+					hdmi->phy.name);
+				return -ENODEV;
+			}
+
 			return 0;
 		}
 	}
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 0f583ca7e66e..dd330259a3dc 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
+	int (*configure_phy)(struct dw_hdmi *hdmi,
+			     const struct dw_hdmi_plat_data *pdata,
+			     unsigned long mpixelclock);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
@@ -91,4 +94,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
 void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
 void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
 
+/* PHY configuration */
+void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
+			   unsigned char addr);
+
 #endif /* __IMX_HDMI_H__ */
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 08/10] drm: bridge: dw-hdmi: Remove device type from platform data
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc, Kieran Bingham

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The device type isn't used anymore now that workarounds and PHY-specific
operations are performed based on version information read at runtime.
Remove it.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c            | 2 --
 drivers/gpu/drm/imx/dw_hdmi-imx.c           | 2 --
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
 include/drm/bridge/dw_hdmi.h                | 7 -------
 4 files changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index b835d81bb471..132c00685796 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -127,7 +127,6 @@ struct dw_hdmi {
 	struct drm_connector connector;
 	struct drm_bridge bridge;
 
-	enum dw_hdmi_devtype dev_type;
 	unsigned int version;
 
 	struct platform_device *audio;
@@ -2014,7 +2013,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
 
 	hdmi->plat_data = plat_data;
 	hdmi->dev = dev;
-	hdmi->dev_type = plat_data->dev_type;
 	hdmi->sample_rate = 48000;
 	hdmi->disabled = true;
 	hdmi->rxsense = true;
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index f645275e6e63..f039641070ac 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -175,7 +175,6 @@ static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
 	.mpll_cfg   = imx_mpll_cfg,
 	.cur_ctr    = imx_cur_ctr,
 	.phy_config = imx_phy_config,
-	.dev_type   = IMX6Q_HDMI,
 	.mode_valid = imx6q_hdmi_mode_valid,
 };
 
@@ -183,7 +182,6 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
 	.mpll_cfg = imx_mpll_cfg,
 	.cur_ctr  = imx_cur_ctr,
 	.phy_config = imx_phy_config,
-	.dev_type = IMX6DL_HDMI,
 	.mode_valid = imx6dl_hdmi_mode_valid,
 };
 
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index a6d4a0236e8f..d53827413996 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -237,7 +237,6 @@ static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
 	.mpll_cfg   = rockchip_mpll_cfg,
 	.cur_ctr    = rockchip_cur_ctr,
 	.phy_config = rockchip_phy_config,
-	.dev_type   = RK3288_HDMI,
 };
 
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index dd330259a3dc..545f04fae3b6 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -21,12 +21,6 @@ enum {
 	DW_HDMI_RES_MAX,
 };
 
-enum dw_hdmi_devtype {
-	IMX6Q_HDMI,
-	IMX6DL_HDMI,
-	RK3288_HDMI,
-};
-
 enum dw_hdmi_phy_type {
 	DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
 	DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
@@ -65,7 +59,6 @@ struct dw_hdmi_phy_ops {
 };
 
 struct dw_hdmi_plat_data {
-	enum dw_hdmi_devtype dev_type;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
 
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 08/10] drm: bridge: dw-hdmi: Remove device type from platform data
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Kieran Bingham, Russell King,
	Andy Yan, Vladimir Zapolskiy

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The device type isn't used anymore now that workarounds and PHY-specific
operations are performed based on version information read at runtime.
Remove it.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c            | 2 --
 drivers/gpu/drm/imx/dw_hdmi-imx.c           | 2 --
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
 include/drm/bridge/dw_hdmi.h                | 7 -------
 4 files changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index b835d81bb471..132c00685796 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -127,7 +127,6 @@ struct dw_hdmi {
 	struct drm_connector connector;
 	struct drm_bridge bridge;
 
-	enum dw_hdmi_devtype dev_type;
 	unsigned int version;
 
 	struct platform_device *audio;
@@ -2014,7 +2013,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
 
 	hdmi->plat_data = plat_data;
 	hdmi->dev = dev;
-	hdmi->dev_type = plat_data->dev_type;
 	hdmi->sample_rate = 48000;
 	hdmi->disabled = true;
 	hdmi->rxsense = true;
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index f645275e6e63..f039641070ac 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -175,7 +175,6 @@ static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
 	.mpll_cfg   = imx_mpll_cfg,
 	.cur_ctr    = imx_cur_ctr,
 	.phy_config = imx_phy_config,
-	.dev_type   = IMX6Q_HDMI,
 	.mode_valid = imx6q_hdmi_mode_valid,
 };
 
@@ -183,7 +182,6 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
 	.mpll_cfg = imx_mpll_cfg,
 	.cur_ctr  = imx_cur_ctr,
 	.phy_config = imx_phy_config,
-	.dev_type = IMX6DL_HDMI,
 	.mode_valid = imx6dl_hdmi_mode_valid,
 };
 
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index a6d4a0236e8f..d53827413996 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -237,7 +237,6 @@ static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
 	.mpll_cfg   = rockchip_mpll_cfg,
 	.cur_ctr    = rockchip_cur_ctr,
 	.phy_config = rockchip_phy_config,
-	.dev_type   = RK3288_HDMI,
 };
 
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index dd330259a3dc..545f04fae3b6 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -21,12 +21,6 @@ enum {
 	DW_HDMI_RES_MAX,
 };
 
-enum dw_hdmi_devtype {
-	IMX6Q_HDMI,
-	IMX6DL_HDMI,
-	RK3288_HDMI,
-};
-
 enum dw_hdmi_phy_type {
 	DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00,
 	DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2,
@@ -65,7 +59,6 @@ struct dw_hdmi_phy_ops {
 };
 
 struct dw_hdmi_plat_data {
-	enum dw_hdmi_devtype dev_type;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 09/10] drm: bridge: dw-hdmi: Switch to regmap for register access
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

From: Neil Armstrong <narmstrong@baylibre.com>

The Synopsys Designware HDMI TX Controller does not enforce register
access on platforms instanciating it. The current driver supports two
different types of memory-mapped flat register access, but in order to
support the Amlogic Meson SoCs integration, and provide a more generic
way to handle all sorts of register mapping, switch the register access
to use the regmap infrastructure.

In the case of registers that are not flat memory-mapped or do not
conform to the current driver implementation, a regmap struct can be
given in the plat_data and be used at probe or bind.

Since the AHB audio driver is only available with direct memory access,
only allow the I2S audio driver to be registered is directly
memory-mapped.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 109 +++++++++++++++++++++------------------
 include/drm/bridge/dw_hdmi.h     |   1 +
 2 files changed, 59 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 132c00685796..026a0dce7661 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -19,6 +19,7 @@
 #include <linux/hdmi.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_of.h>
@@ -171,8 +172,8 @@ struct dw_hdmi {
 	unsigned int audio_n;
 	bool audio_enable;
 
-	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
-	u8 (*read)(struct dw_hdmi *hdmi, int offset);
+	unsigned int reg_shift;
+	struct regmap *regm;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -183,42 +184,23 @@ struct dw_hdmi {
 	(HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
 	 HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
 
-static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-	writel(val, hdmi->regs + (offset << 2));
-}
-
-static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
-{
-	return readl(hdmi->regs + (offset << 2));
-}
-
-static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-	writeb(val, hdmi->regs + offset);
-}
-
-static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
-{
-	return readb(hdmi->regs + offset);
-}
-
 static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
 {
-	hdmi->write(hdmi, val, offset);
+	regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
 }
 
 static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
 {
-	return hdmi->read(hdmi, offset);
+	unsigned int val = 0;
+
+	regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
+
+	return val;
 }
 
 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);
+	regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
 }
 
 static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
@@ -1989,6 +1971,20 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 	return -ENODEV;
 }
 
+static const struct regmap_config hdmi_regmap_8bit_config = {
+	.reg_bits	= 32,
+	.val_bits	= 8,
+	.reg_stride	= 1,
+	.max_register	= HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
+};
+
+static const struct regmap_config hdmi_regmap_32bit_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
+};
+
 static struct dw_hdmi *
 __dw_hdmi_probe(struct platform_device *pdev,
 		const struct dw_hdmi_plat_data *plat_data)
@@ -1998,7 +1994,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	struct platform_device_info pdevinfo;
 	struct device_node *ddc_node;
 	struct dw_hdmi *hdmi;
-	struct resource *iores;
+	struct resource *iores = NULL;
 	int irq;
 	int ret;
 	u32 val = 1;
@@ -2022,22 +2018,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	mutex_init(&hdmi->audio_mutex);
 	spin_lock_init(&hdmi->audio_lock);
 
-	of_property_read_u32(np, "reg-io-width", &val);
-
-	switch (val) {
-	case 4:
-		hdmi->write = dw_hdmi_writel;
-		hdmi->read = dw_hdmi_readl;
-		break;
-	case 1:
-		hdmi->write = dw_hdmi_writeb;
-		hdmi->read = dw_hdmi_readb;
-		break;
-	default:
-		dev_err(dev, "reg-io-width must be 1 or 4\n");
-		return ERR_PTR(-EINVAL);
-	}
-
 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 	if (ddc_node) {
 		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
@@ -2051,11 +2031,38 @@ __dw_hdmi_probe(struct platform_device *pdev,
 		dev_dbg(hdmi->dev, "no ddc property found\n");
 	}
 
-	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hdmi->regs = devm_ioremap_resource(dev, iores);
-	if (IS_ERR(hdmi->regs)) {
-		ret = PTR_ERR(hdmi->regs);
-		goto err_res;
+	if (!plat_data->regm) {
+		const struct regmap_config *reg_config;
+
+		of_property_read_u32(np, "reg-io-width", &val);
+		switch (val) {
+		case 4:
+			reg_config = &hdmi_regmap_32bit_config;
+			hdmi->reg_shift = 2;
+			break;
+		case 1:
+			reg_config = &hdmi_regmap_8bit_config;
+			break;
+		default:
+			dev_err(dev, "reg-io-width must be 1 or 4\n");
+			return ERR_PTR(-EINVAL);
+		}
+
+		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		hdmi->regs = devm_ioremap_resource(dev, iores);
+		if (IS_ERR(hdmi->regs)) {
+			ret = PTR_ERR(hdmi->regs);
+			goto err_res;
+		}
+
+		hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
+		if (IS_ERR(hdmi->regm)) {
+			dev_err(dev, "Failed to configure regmap\n");
+			ret = PTR_ERR(hdmi->regm);
+			goto err_res;
+		}
+	} else {
+		hdmi->regm = plat_data->regm;
 	}
 
 	hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
@@ -2165,7 +2172,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
 	config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
 
-	if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
+	if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
 		struct dw_hdmi_audio_data audio;
 
 		audio.phys = iores->start;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 545f04fae3b6..bcceee8114a4 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -59,6 +59,7 @@ struct dw_hdmi_phy_ops {
 };
 
 struct dw_hdmi_plat_data {
+	struct regmap *regm;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
 
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 09/10] drm: bridge: dw-hdmi: Switch to regmap for register access
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

From: Neil Armstrong <narmstrong@baylibre.com>

The Synopsys Designware HDMI TX Controller does not enforce register
access on platforms instanciating it. The current driver supports two
different types of memory-mapped flat register access, but in order to
support the Amlogic Meson SoCs integration, and provide a more generic
way to handle all sorts of register mapping, switch the register access
to use the regmap infrastructure.

In the case of registers that are not flat memory-mapped or do not
conform to the current driver implementation, a regmap struct can be
given in the plat_data and be used at probe or bind.

Since the AHB audio driver is only available with direct memory access,
only allow the I2S audio driver to be registered is directly
memory-mapped.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 109 +++++++++++++++++++++------------------
 include/drm/bridge/dw_hdmi.h     |   1 +
 2 files changed, 59 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 132c00685796..026a0dce7661 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -19,6 +19,7 @@
 #include <linux/hdmi.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_of.h>
@@ -171,8 +172,8 @@ struct dw_hdmi {
 	unsigned int audio_n;
 	bool audio_enable;
 
-	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
-	u8 (*read)(struct dw_hdmi *hdmi, int offset);
+	unsigned int reg_shift;
+	struct regmap *regm;
 };
 
 #define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -183,42 +184,23 @@ struct dw_hdmi {
 	(HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
 	 HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
 
-static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-	writel(val, hdmi->regs + (offset << 2));
-}
-
-static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
-{
-	return readl(hdmi->regs + (offset << 2));
-}
-
-static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
-{
-	writeb(val, hdmi->regs + offset);
-}
-
-static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
-{
-	return readb(hdmi->regs + offset);
-}
-
 static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
 {
-	hdmi->write(hdmi, val, offset);
+	regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
 }
 
 static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
 {
-	return hdmi->read(hdmi, offset);
+	unsigned int val = 0;
+
+	regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
+
+	return val;
 }
 
 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);
+	regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
 }
 
 static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
@@ -1989,6 +1971,20 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 	return -ENODEV;
 }
 
+static const struct regmap_config hdmi_regmap_8bit_config = {
+	.reg_bits	= 32,
+	.val_bits	= 8,
+	.reg_stride	= 1,
+	.max_register	= HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
+};
+
+static const struct regmap_config hdmi_regmap_32bit_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
+};
+
 static struct dw_hdmi *
 __dw_hdmi_probe(struct platform_device *pdev,
 		const struct dw_hdmi_plat_data *plat_data)
@@ -1998,7 +1994,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	struct platform_device_info pdevinfo;
 	struct device_node *ddc_node;
 	struct dw_hdmi *hdmi;
-	struct resource *iores;
+	struct resource *iores = NULL;
 	int irq;
 	int ret;
 	u32 val = 1;
@@ -2022,22 +2018,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	mutex_init(&hdmi->audio_mutex);
 	spin_lock_init(&hdmi->audio_lock);
 
-	of_property_read_u32(np, "reg-io-width", &val);
-
-	switch (val) {
-	case 4:
-		hdmi->write = dw_hdmi_writel;
-		hdmi->read = dw_hdmi_readl;
-		break;
-	case 1:
-		hdmi->write = dw_hdmi_writeb;
-		hdmi->read = dw_hdmi_readb;
-		break;
-	default:
-		dev_err(dev, "reg-io-width must be 1 or 4\n");
-		return ERR_PTR(-EINVAL);
-	}
-
 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 	if (ddc_node) {
 		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
@@ -2051,11 +2031,38 @@ __dw_hdmi_probe(struct platform_device *pdev,
 		dev_dbg(hdmi->dev, "no ddc property found\n");
 	}
 
-	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hdmi->regs = devm_ioremap_resource(dev, iores);
-	if (IS_ERR(hdmi->regs)) {
-		ret = PTR_ERR(hdmi->regs);
-		goto err_res;
+	if (!plat_data->regm) {
+		const struct regmap_config *reg_config;
+
+		of_property_read_u32(np, "reg-io-width", &val);
+		switch (val) {
+		case 4:
+			reg_config = &hdmi_regmap_32bit_config;
+			hdmi->reg_shift = 2;
+			break;
+		case 1:
+			reg_config = &hdmi_regmap_8bit_config;
+			break;
+		default:
+			dev_err(dev, "reg-io-width must be 1 or 4\n");
+			return ERR_PTR(-EINVAL);
+		}
+
+		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		hdmi->regs = devm_ioremap_resource(dev, iores);
+		if (IS_ERR(hdmi->regs)) {
+			ret = PTR_ERR(hdmi->regs);
+			goto err_res;
+		}
+
+		hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
+		if (IS_ERR(hdmi->regm)) {
+			dev_err(dev, "Failed to configure regmap\n");
+			ret = PTR_ERR(hdmi->regm);
+			goto err_res;
+		}
+	} else {
+		hdmi->regm = plat_data->regm;
 	}
 
 	hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
@@ -2165,7 +2172,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
 	config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
 
-	if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
+	if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
 		struct dw_hdmi_audio_data audio;
 
 		audio.phys = iores->start;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 545f04fae3b6..bcceee8114a4 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -59,6 +59,7 @@ struct dw_hdmi_phy_ops {
 };
 
 struct dw_hdmi_plat_data {
+	struct regmap *regm;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory.
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-03 17:20   ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Andy Yan, Archit Taneja, Fabio Estevam, Jose Abreu,
	Kieran Bingham, Neil Armstrong, Nickey Yang, Russell King,
	Vladimir Zapolskiy, linux-renesas-soc

The driver is already made of 5 separate source files. Move it to a
newly created directory named synopsys where more Synopsys bridge
drivers can be added later (for the DisplayPort controller for
instance).

Suggested-by: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
Changes since v4:

- Fixed typos in Kconfig
---
 drivers/gpu/drm/bridge/Kconfig                     |  2 ++
 drivers/gpu/drm/bridge/Makefile                    |  4 +---
 drivers/gpu/drm/bridge/synopsys/Kconfig            | 23 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/Makefile           |  5 +++++
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |  0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |  0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |  0
 9 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index eb8688ec6f18..68ceba083ca1 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -101,4 +101,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
 
+source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 2e83a7855399..103f82e63102 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,9 +2,6 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
-obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -13,3 +10,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
new file mode 100644
index 000000000000..40d2827a6d19
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -0,0 +1,23 @@
+config DRM_DW_HDMI
+	tristate
+	select DRM_KMS_HELPER
+
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsys Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_ELD
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsys
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsys Designware I2S Audio interface"
+	depends on SND_SOC
+	depends on DRM_DW_HDMI
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the I2S Audio interface which is part of the Synopsys
+	  Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
new file mode 100644
index 000000000000..17aa7a65b57e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -0,0 +1,5 @@
+#ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-audio.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory.
@ 2017-03-03 17:20   ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-03 17:20 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy

The driver is already made of 5 separate source files. Move it to a
newly created directory named synopsys where more Synopsys bridge
drivers can be added later (for the DisplayPort controller for
instance).

Suggested-by: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
Changes since v4:

- Fixed typos in Kconfig
---
 drivers/gpu/drm/bridge/Kconfig                     |  2 ++
 drivers/gpu/drm/bridge/Makefile                    |  4 +---
 drivers/gpu/drm/bridge/synopsys/Kconfig            | 23 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/Makefile           |  5 +++++
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |  0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |  0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |  0
 9 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index eb8688ec6f18..68ceba083ca1 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -101,4 +101,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
 
+source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 2e83a7855399..103f82e63102 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,9 +2,6 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
-obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -13,3 +10,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
new file mode 100644
index 000000000000..40d2827a6d19
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -0,0 +1,23 @@
+config DRM_DW_HDMI
+	tristate
+	select DRM_KMS_HELPER
+
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsys Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_ELD
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsys
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsys Designware I2S Audio interface"
+	depends on SND_SOC
+	depends on DRM_DW_HDMI
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the I2S Audio interface which is part of the Synopsys
+	  Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
new file mode 100644
index 000000000000..17aa7a65b57e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -0,0 +1,5 @@
+#ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-audio.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory.
  2017-03-03 17:19   ` Laurent Pinchart
@ 2017-03-04  1:11     ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-04  1:11 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy, Archit Taneja

The driver is already made of 5 separate source files. Move it to a
newly created directory named synopsys where more Synopsys bridge
drivers can be added later (for the DisplayPort controller for
instance).

Suggested-by: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
Changes since v5:

- Removed dw-hdmi Kconfig options from drivers/gpu/bridge/Kconfig

Changes since v4:

- Fixed typos in Kconfig
---
 drivers/gpu/drm/bridge/Kconfig                     | 26 ++--------------------
 drivers/gpu/drm/bridge/Makefile                    |  4 +---
 drivers/gpu/drm/bridge/synopsys/Kconfig            | 23 +++++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/Makefile           |  5 +++++
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |  0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |  0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |  0
 9 files changed, 31 insertions(+), 27 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index eb8688ec6f18..02e211cd8129 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -24,30 +24,6 @@ config DRM_DUMB_VGA_DAC
 	help
 	  Support for RGB to VGA DAC based bridges
 
-config DRM_DW_HDMI
-	tristate
-	select DRM_KMS_HELPER
-
-config DRM_DW_HDMI_AHB_AUDIO
-	tristate "Synopsis Designware AHB Audio interface"
-	depends on DRM_DW_HDMI && SND
-	select SND_PCM
-	select SND_PCM_ELD
-	select SND_PCM_IEC958
-	help
-	  Support the AHB Audio interface which is part of the Synopsis
-	  Designware HDMI block.  This is used in conjunction with
-	  the i.MX6 HDMI driver.
-
-config DRM_DW_HDMI_I2S_AUDIO
-	tristate "Synopsis Designware I2S Audio interface"
-	depends on SND_SOC
-	depends on DRM_DW_HDMI
-	select SND_SOC_HDMI_CODEC
-	help
-	  Support the I2S Audio interface which is part of the Synopsis
-	  Designware HDMI block.
-
 config DRM_NXP_PTN3460
 	tristate "NXP PTN3460 DP/LVDS bridge"
 	depends on OF
@@ -101,4 +77,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
 
+source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 2e83a7855399..103f82e63102 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,9 +2,6 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
-obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -13,3 +10,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
new file mode 100644
index 000000000000..40d2827a6d19
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -0,0 +1,23 @@
+config DRM_DW_HDMI
+	tristate
+	select DRM_KMS_HELPER
+
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsys Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_ELD
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsys
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsys Designware I2S Audio interface"
+	depends on SND_SOC
+	depends on DRM_DW_HDMI
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the I2S Audio interface which is part of the Synopsys
+	  Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
new file mode 100644
index 000000000000..17aa7a65b57e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -0,0 +1,5 @@
+#ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-audio.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory.
@ 2017-03-04  1:11     ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-04  1:11 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Andy Yan, Russell King,
	Vladimir Zapolskiy

The driver is already made of 5 separate source files. Move it to a
newly created directory named synopsys where more Synopsys bridge
drivers can be added later (for the DisplayPort controller for
instance).

Suggested-by: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
Changes since v5:

- Removed dw-hdmi Kconfig options from drivers/gpu/bridge/Kconfig

Changes since v4:

- Fixed typos in Kconfig
---
 drivers/gpu/drm/bridge/Kconfig                     | 26 ++--------------------
 drivers/gpu/drm/bridge/Makefile                    |  4 +---
 drivers/gpu/drm/bridge/synopsys/Kconfig            | 23 +++++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/Makefile           |  5 +++++
 .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |  0
 .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |  0
 .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    |  0
 drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |  0
 9 files changed, 31 insertions(+), 27 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (100%)
 rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index eb8688ec6f18..02e211cd8129 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -24,30 +24,6 @@ config DRM_DUMB_VGA_DAC
 	help
 	  Support for RGB to VGA DAC based bridges
 
-config DRM_DW_HDMI
-	tristate
-	select DRM_KMS_HELPER
-
-config DRM_DW_HDMI_AHB_AUDIO
-	tristate "Synopsis Designware AHB Audio interface"
-	depends on DRM_DW_HDMI && SND
-	select SND_PCM
-	select SND_PCM_ELD
-	select SND_PCM_IEC958
-	help
-	  Support the AHB Audio interface which is part of the Synopsis
-	  Designware HDMI block.  This is used in conjunction with
-	  the i.MX6 HDMI driver.
-
-config DRM_DW_HDMI_I2S_AUDIO
-	tristate "Synopsis Designware I2S Audio interface"
-	depends on SND_SOC
-	depends on DRM_DW_HDMI
-	select SND_SOC_HDMI_CODEC
-	help
-	  Support the I2S Audio interface which is part of the Synopsis
-	  Designware HDMI block.
-
 config DRM_NXP_PTN3460
 	tristate "NXP PTN3460 DP/LVDS bridge"
 	depends on OF
@@ -101,4 +77,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
 
+source "drivers/gpu/drm/bridge/synopsys/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 2e83a7855399..103f82e63102 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,9 +2,6 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
-obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
-obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
@@ -13,3 +10,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
new file mode 100644
index 000000000000..40d2827a6d19
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -0,0 +1,23 @@
+config DRM_DW_HDMI
+	tristate
+	select DRM_KMS_HELPER
+
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsys Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_ELD
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsys
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsys Designware I2S Audio interface"
+	depends on SND_SOC
+	depends on DRM_DW_HDMI
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the I2S Audio interface which is part of the Synopsys
+	  Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
new file mode 100644
index 000000000000..17aa7a65b57e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -0,0 +1,5 @@
+#ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-audio.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.c
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw-hdmi.h
rename to drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence
  2017-03-03 17:20   ` Laurent Pinchart
@ 2017-03-05 23:35     ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:35 UTC (permalink / raw)
  To: dri-devel
  Cc: Archit Taneja, Fabio Estevam, Jose Abreu, Neil Armstrong,
	Kieran Bingham, linux-renesas-soc, Nickey Yang, Russell King,
	Andy Yan, Vladimir Zapolskiy

The PHY requires us to wait for the PHY to switch to low power mode
after deasserting TXPWRON and before asserting PDDQ in the power down
sequence, otherwise power down will fail.

The PHY power down can be monitored though the TX_READY bit, available
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
through the HDMI TX registers. As the two are equivalent, let's pick the
easier solution of polling the TX_PHY_LOCK bit.

The power down code is currently duplicated in multiple places. To avoid
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
refactor the power down code and group it all in a single function.

Tests showed that one poll iteration was enough for TX_PHY_LOCK to
become low, without requiring any additional delay. Retrying the read
five times with a 1ms to 2ms delay between each attempt should thus be
more than enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 9 deletions(-)

Changes since v5:

- Fix compilation breakage due to reordering of the patches compared to v4

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index d863b3393aee..3a1cd4c7ac64 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
 struct dw_hdmi_phy_data {
 	enum dw_hdmi_phy_type type;
 	const char *name;
+	unsigned int gen;
 	bool has_svsret;
 };
 
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	unsigned int i;
+	u16 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_powerdown(hdmi, true);
+		return;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+	/*
+	 * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
+	 * to low power mode.
+	 */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+		if (!(val & HDMI_PHY_TX_PHY_LOCK))
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (val & HDMI_PHY_TX_PHY_LOCK)
+		dev_warn(hdmi->dev, "PHY failed to power down\n");
+	else
+		dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
+
+	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		return -EINVAL;
 	}
 
-	/* gen2 tx power off */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-
-	/* gen2 pddq */
-	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
 	if (hdmi->phy->has_svsret)
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 	for (i = 0; i < 2; i++) {
 		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_powerdown(hdmi, true);
 
 		ret = hdmi_phy_configure(hdmi);
 		if (ret)
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 	if (!hdmi->phy_enabled)
 		return;
 
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_powerdown(hdmi, true);
+	dw_hdmi_phy_power_off(hdmi);
 
 	hdmi->phy_enabled = false;
 }
@@ -1827,23 +1855,29 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 	{
 		.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
 		.name = "DWC HDMI TX PHY",
+		.gen = 1,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
 		.name = "DWC MHL PHY + HEAC PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}
 };
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence
@ 2017-03-05 23:35     ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:35 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Andy Yan, Russell King,
	Vladimir Zapolskiy

The PHY requires us to wait for the PHY to switch to low power mode
after deasserting TXPWRON and before asserting PDDQ in the power down
sequence, otherwise power down will fail.

The PHY power down can be monitored though the TX_READY bit, available
through I2C in the PHY registers, or the TX_PHY_LOCK bit, available
through the HDMI TX registers. As the two are equivalent, let's pick the
easier solution of polling the TX_PHY_LOCK bit.

The power down code is currently duplicated in multiple places. To avoid
spreading multiple calls to a TX_PHY_LOCK poll function, we have to
refactor the power down code and group it all in a single function.

Tests showed that one poll iteration was enough for TX_PHY_LOCK to
become low, without requiring any additional delay. Retrying the read
five times with a 1ms to 2ms delay between each attempt should thus be
more than enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 52 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 9 deletions(-)

Changes since v5:

- Fix compilation breakage due to reordering of the patches compared to v4

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index d863b3393aee..3a1cd4c7ac64 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -116,6 +116,7 @@ struct dw_hdmi_i2c {
 struct dw_hdmi_phy_data {
 	enum dw_hdmi_phy_type type;
 	const char *name;
+	unsigned int gen;
 	bool has_svsret;
 };
 
@@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 			 HDMI_PHY_CONF0_SELDIPIF_MASK);
 }
 
+static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	unsigned int i;
+	u16 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_powerdown(hdmi, true);
+		return;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+	/*
+	 * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went
+	 * to low power mode.
+	 */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0);
+		if (!(val & HDMI_PHY_TX_PHY_LOCK))
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (val & HDMI_PHY_TX_PHY_LOCK)
+		dev_warn(hdmi->dev, "PHY failed to power down\n");
+	else
+		dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i);
+
+	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
 	u8 val, msec;
@@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 		return -EINVAL;
 	}
 
-	/* gen2 tx power off */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-
-	/* gen2 pddq */
-	dw_hdmi_phy_gen2_pddq(hdmi, 1);
+	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
 	if (hdmi->phy->has_svsret)
@@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 	for (i = 0; i < 2; i++) {
 		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_powerdown(hdmi, true);
 
 		ret = hdmi_phy_configure(hdmi);
 		if (ret)
@@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
 	if (!hdmi->phy_enabled)
 		return;
 
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_powerdown(hdmi, true);
+	dw_hdmi_phy_power_off(hdmi);
 
 	hdmi->phy_enabled = false;
 }
@@ -1827,23 +1855,29 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
 	{
 		.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
 		.name = "DWC HDMI TX PHY",
+		.gen = 1,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC,
 		.name = "DWC MHL PHY + HEAC PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_MHL_PHY,
 		.name = "DWC MHL PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
 		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
 		.name = "DWC HDMI 3D TX PHY",
+		.gen = 2,
 	}, {
 		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
 		.name = "DWC HDMI 2.0 TX PHY",
+		.gen = 2,
 		.has_svsret = true,
 	}
 };
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence
  2017-03-03 17:20   ` Laurent Pinchart
@ 2017-03-05 23:35     ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:35 UTC (permalink / raw)
  To: dri-devel
  Cc: Archit Taneja, Fabio Estevam, Jose Abreu, Neil Armstrong,
	Kieran Bingham, linux-renesas-soc, Nickey Yang, Russell King,
	Andy Yan, Vladimir Zapolskiy

When powering the PHY up we need to wait for the PLL to lock. This is
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
(interrupt-based wait could be implemented as well but is likely
overkill). The bit is asserted when the PLL locks, but the current code
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
replace the udelay() with a sleep as the code never runs in
non-sleepable context.

To be consistent with the power down implementation move the poll loop
to the power off function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 28 deletions(-)

Changes since v5:

- Fix compilation breakage due to reordering of the patches compared to v4

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 3a1cd4c7ac64..c25eac8ba47b 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_gen2_pddq(hdmi, 1);
 }
 
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	unsigned int i;
+	u8 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_powerdown(hdmi, false);
+
+		/* Toggle TMDS enable. */
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_tmds(hdmi, 1);
+		return 0;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+	dw_hdmi_phy_gen2_pddq(hdmi, 0);
+
+	/* Wait for PHY PLL lock */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+		if (val)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (!val) {
+		dev_err(hdmi->dev, "PHY PLL failed to lock\n");
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
+	return 0;
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
-	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
 			   HDMI_3D_TX_PHY_CKCALCTRL);
 
-	dw_hdmi_phy_enable_powerdown(hdmi, false);
-
-	/* toggle TMDS enable */
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_tmds(hdmi, 1);
-
-	/* gen2 tx power on */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
-	dw_hdmi_phy_gen2_pddq(hdmi, 0);
-
-	/* Wait for PHY PLL lock */
-	msec = 5;
-	do {
-		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
-		if (!val)
-			break;
-
-		if (msec == 0) {
-			dev_err(hdmi->dev, "PHY PLL not locked\n");
-			return -ETIMEDOUT;
-		}
-
-		udelay(1000);
-		msec--;
-	} while (1);
-
-	return 0;
+	return dw_hdmi_phy_power_on(hdmi);
 }
 
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence
@ 2017-03-05 23:35     ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:35 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Andy Yan, Russell King,
	Vladimir Zapolskiy

When powering the PHY up we need to wait for the PLL to lock. This is
done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register
(interrupt-based wait could be implemented as well but is likely
overkill). The bit is asserted when the PLL locks, but the current code
incorrectly waits for the bit to be deasserted. Fix it, and while at it,
replace the udelay() with a sleep as the code never runs in
non-sleepable context.

To be consistent with the power down implementation move the poll loop
to the power off function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 28 deletions(-)

Changes since v5:

- Fix compilation breakage due to reordering of the patches compared to v4

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 3a1cd4c7ac64..c25eac8ba47b 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_gen2_pddq(hdmi, 1);
 }
 
+static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
+{
+	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	unsigned int i;
+	u8 val;
+
+	if (phy->gen == 1) {
+		dw_hdmi_phy_enable_powerdown(hdmi, false);
+
+		/* Toggle TMDS enable. */
+		dw_hdmi_phy_enable_tmds(hdmi, 0);
+		dw_hdmi_phy_enable_tmds(hdmi, 1);
+		return 0;
+	}
+
+	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
+	dw_hdmi_phy_gen2_pddq(hdmi, 0);
+
+	/* Wait for PHY PLL lock */
+	for (i = 0; i < 5; ++i) {
+		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+		if (val)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (!val) {
+		dev_err(hdmi->dev, "PHY PLL failed to lock\n");
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i);
+	return 0;
+}
+
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
-	u8 val, msec;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
 			   HDMI_3D_TX_PHY_CKCALCTRL);
 
-	dw_hdmi_phy_enable_powerdown(hdmi, false);
-
-	/* toggle TMDS enable */
-	dw_hdmi_phy_enable_tmds(hdmi, 0);
-	dw_hdmi_phy_enable_tmds(hdmi, 1);
-
-	/* gen2 tx power on */
-	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
-	dw_hdmi_phy_gen2_pddq(hdmi, 0);
-
-	/* Wait for PHY PLL lock */
-	msec = 5;
-	do {
-		val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
-		if (!val)
-			break;
-
-		if (msec == 0) {
-			dev_err(hdmi->dev, "PHY PLL not locked\n");
-			return -ETIMEDOUT;
-		}
-
-		udelay(1000);
-		msec--;
-	} while (1);
-
-	return 0;
+	return dw_hdmi_phy_power_on(hdmi);
 }
 
 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 06/10] drm: bridge: dw-hdmi: Create PHY operations
  2017-03-03 17:20   ` Laurent Pinchart
@ 2017-03-05 23:36     ` Laurent Pinchart
  -1 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:36 UTC (permalink / raw)
  To: dri-devel
  Cc: Archit Taneja, Fabio Estevam, Jose Abreu, Neil Armstrong,
	Kieran Bingham, linux-renesas-soc, Nickey Yang, Russell King,
	Andy Yan, Vladimir Zapolskiy

The HDMI TX controller support different PHYs whose programming
interface can vary significantly, especially with vendor PHYs that are
not provided by Synopsys. To support them, create a PHY operation
structure that can be provided by the platform glue layer. The existing
PHY handling code (limited to Synopsys PHY support) is refactored into a
set of default PHY operations that are used automatically when the
platform glue doesn't provide its own operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 95 ++++++++++++++++++++++++++++------------
 include/drm/bridge/dw_hdmi.h     | 18 +++++++-
 2 files changed, 82 insertions(+), 31 deletions(-)

Changes since v5:

- Undo changes from v5.1 04/10 and 05/10

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index c25eac8ba47b..cb2703862be2 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -141,8 +141,12 @@ struct dw_hdmi {
 	u8 edid[HDMI_EDID_LEN];
 	bool cable_plugin;
 
-	const struct dw_hdmi_phy_data *phy;
-	bool phy_enabled;
+	struct {
+		const struct dw_hdmi_phy_ops *ops;
+		const char *name;
+		void *data;
+		bool enabled;
+	} phy;
 
 	struct drm_display_mode previous_mode;
 
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 		  HDMI_VP_CONF);
 }
 
+/* -----------------------------------------------------------------------------
+ * Synopsys PHY Handling
+ */
+
 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 				       unsigned char bit)
 {
@@ -917,7 +925,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 
 static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	unsigned int i;
 	u16 val;
 
@@ -951,7 +959,7 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 
 static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	unsigned int i;
 	u8 val;
 
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
-	if (hdmi->phy->has_svsret)
+	if (phy->has_svsret)
 		dw_hdmi_phy_enable_svsret(hdmi, 1);
 
 	/* PHY reset. The reset signal is active high on Gen2 PHYs. */
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	return dw_hdmi_phy_power_on(hdmi);
 }
 
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+			    struct drm_display_mode *mode)
 {
 	int i, ret;
 
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 			return ret;
 	}
 
-	hdmi->phy_enabled = true;
 	return 0;
 }
 
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+	dw_hdmi_phy_power_off(hdmi);
+}
+
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
+						      void *data)
+{
+	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+	.init = dw_hdmi_phy_init,
+	.disable = dw_hdmi_phy_disable,
+	.read_hpd = dw_hdmi_phy_read_hpd,
+};
+
+/* -----------------------------------------------------------------------------
+ * HDMI TX Setup
+ */
+
 static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 {
 	u8 de;
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
 }
 
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
-{
-	if (!hdmi->phy_enabled)
-		return;
-
-	dw_hdmi_phy_power_off(hdmi);
-
-	hdmi->phy_enabled = false;
-}
-
 /* HDMI Initialization Step B.4 */
 static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	hdmi_av_composer(hdmi, mode);
 
 	/* HDMI Initializateion Step B.2 */
-	ret = dw_hdmi_phy_init(hdmi);
+	ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
 	if (ret)
 		return ret;
+	hdmi->phy.enabled = true;
 
 	/* HDMI Initialization Step B.3 */
 	dw_hdmi_enable_video_path(hdmi);
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
 
 static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
 {
-	dw_hdmi_phy_disable(hdmi);
+	if (hdmi->phy.enabled) {
+		hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
+		hdmi->phy.enabled = false;
+	}
+
 	hdmi->bridge_is_on = false;
 }
 
@@ -1611,8 +1637,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	dw_hdmi_update_phy_mask(hdmi);
 	mutex_unlock(&hdmi->mutex);
 
-	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-		connector_status_connected : connector_status_disconnected;
+	return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 
 	phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
 
+	if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
+		/* Vendor PHYs require support from the glue layer. */
+		if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
+			dev_err(hdmi->dev,
+				"Vendor HDMI PHY not supported by glue layer\n");
+			return -ENODEV;
+		}
+
+		hdmi->phy.ops = hdmi->plat_data->phy_ops;
+		hdmi->phy.data = hdmi->plat_data->phy_data;
+		hdmi->phy.name = hdmi->plat_data->phy_name;
+		return 0;
+	}
+
+	/* Synopsys PHYs are handled internally. */
 	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
 		if (dw_hdmi_phys[i].type == phy_type) {
-			hdmi->phy = &dw_hdmi_phys[i];
+			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
+			hdmi->phy.name = dw_hdmi_phys[i].name;
+			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
 			return 0;
 		}
 	}
 
-	if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
-		dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
-	else
-		dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
-			phy_type);
-
+	dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
 	return -ENODEV;
 }
 
@@ -2031,7 +2068,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
 		 hdmi->version >> 12, hdmi->version & 0xfff,
 		 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
-		 hdmi->phy->name);
+		 hdmi->phy.name);
 
 	initialize_hdmi_ih_mutes(hdmi);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index b080a171a23f..0f583ca7e66e 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
 	u16 vlev_ctr;   /* voltage level control */
 };
 
+struct dw_hdmi_phy_ops {
+	int (*init)(struct dw_hdmi *hdmi, void *data,
+		    struct drm_display_mode *mode);
+	void (*disable)(struct dw_hdmi *hdmi, void *data);
+	enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
+};
+
 struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
+	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+					   struct drm_display_mode *mode);
+
+	/* Vendor PHY support */
+	const struct dw_hdmi_phy_ops *phy_ops;
+	const char *phy_name;
+	void *phy_data;
+
+	/* Synopsys PHY support */
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
-	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-					   struct drm_display_mode *mode);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v5.1 06/10] drm: bridge: dw-hdmi: Create PHY operations
@ 2017-03-05 23:36     ` Laurent Pinchart
  0 siblings, 0 replies; 35+ messages in thread
From: Laurent Pinchart @ 2017-03-05 23:36 UTC (permalink / raw)
  To: dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Andy Yan, Russell King,
	Vladimir Zapolskiy

The HDMI TX controller support different PHYs whose programming
interface can vary significantly, especially with vendor PHYs that are
not provided by Synopsys. To support them, create a PHY operation
structure that can be provided by the platform glue layer. The existing
PHY handling code (limited to Synopsys PHY support) is refactored into a
set of default PHY operations that are used automatically when the
platform glue doesn't provide its own operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 95 ++++++++++++++++++++++++++++------------
 include/drm/bridge/dw_hdmi.h     | 18 +++++++-
 2 files changed, 82 insertions(+), 31 deletions(-)

Changes since v5:

- Undo changes from v5.1 04/10 and 05/10

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index c25eac8ba47b..cb2703862be2 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -141,8 +141,12 @@ struct dw_hdmi {
 	u8 edid[HDMI_EDID_LEN];
 	bool cable_plugin;
 
-	const struct dw_hdmi_phy_data *phy;
-	bool phy_enabled;
+	struct {
+		const struct dw_hdmi_phy_ops *ops;
+		const char *name;
+		void *data;
+		bool enabled;
+	} phy;
 
 	struct drm_display_mode previous_mode;
 
@@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 		  HDMI_VP_CONF);
 }
 
+/* -----------------------------------------------------------------------------
+ * Synopsys PHY Handling
+ */
+
 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
 				       unsigned char bit)
 {
@@ -917,7 +925,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 
 static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	unsigned int i;
 	u16 val;
 
@@ -951,7 +959,7 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
 
 static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 {
-	const struct dw_hdmi_phy_data *phy = hdmi->phy;
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	unsigned int i;
 	u8 val;
 
@@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
 
 static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 {
+	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
 	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
@@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	dw_hdmi_phy_power_off(hdmi);
 
 	/* Leave low power consumption mode by asserting SVSRET. */
-	if (hdmi->phy->has_svsret)
+	if (phy->has_svsret)
 		dw_hdmi_phy_enable_svsret(hdmi, 1);
 
 	/* PHY reset. The reset signal is active high on Gen2 PHYs. */
@@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
 	return dw_hdmi_phy_power_on(hdmi);
 }
 
-static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
+static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+			    struct drm_display_mode *mode)
 {
 	int i, ret;
 
@@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 			return ret;
 	}
 
-	hdmi->phy_enabled = true;
 	return 0;
 }
 
+static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+	dw_hdmi_phy_power_off(hdmi);
+}
+
+static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
+						      void *data)
+{
+	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+	.init = dw_hdmi_phy_init,
+	.disable = dw_hdmi_phy_disable,
+	.read_hpd = dw_hdmi_phy_read_hpd,
+};
+
+/* -----------------------------------------------------------------------------
+ * HDMI TX Setup
+ */
+
 static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 {
 	u8 de;
@@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
 }
 
-static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
-{
-	if (!hdmi->phy_enabled)
-		return;
-
-	dw_hdmi_phy_power_off(hdmi);
-
-	hdmi->phy_enabled = false;
-}
-
 /* HDMI Initialization Step B.4 */
 static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
 {
@@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	hdmi_av_composer(hdmi, mode);
 
 	/* HDMI Initializateion Step B.2 */
-	ret = dw_hdmi_phy_init(hdmi);
+	ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode);
 	if (ret)
 		return ret;
+	hdmi->phy.enabled = true;
 
 	/* HDMI Initialization Step B.3 */
 	dw_hdmi_enable_video_path(hdmi);
@@ -1548,7 +1570,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
 
 static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
 {
-	dw_hdmi_phy_disable(hdmi);
+	if (hdmi->phy.enabled) {
+		hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
+		hdmi->phy.enabled = false;
+	}
+
 	hdmi->bridge_is_on = false;
 }
 
@@ -1611,8 +1637,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	dw_hdmi_update_phy_mask(hdmi);
 	mutex_unlock(&hdmi->mutex);
 
-	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-		connector_status_connected : connector_status_disconnected;
+	return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
 }
 
 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -1898,19 +1923,31 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
 
 	phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
 
+	if (phy_type == DW_HDMI_PHY_VENDOR_PHY) {
+		/* Vendor PHYs require support from the glue layer. */
+		if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
+			dev_err(hdmi->dev,
+				"Vendor HDMI PHY not supported by glue layer\n");
+			return -ENODEV;
+		}
+
+		hdmi->phy.ops = hdmi->plat_data->phy_ops;
+		hdmi->phy.data = hdmi->plat_data->phy_data;
+		hdmi->phy.name = hdmi->plat_data->phy_name;
+		return 0;
+	}
+
+	/* Synopsys PHYs are handled internally. */
 	for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) {
 		if (dw_hdmi_phys[i].type == phy_type) {
-			hdmi->phy = &dw_hdmi_phys[i];
+			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
+			hdmi->phy.name = dw_hdmi_phys[i].name;
+			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
 			return 0;
 		}
 	}
 
-	if (phy_type == DW_HDMI_PHY_VENDOR_PHY)
-		dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n");
-	else
-		dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n",
-			phy_type);
-
+	dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type);
 	return -ENODEV;
 }
 
@@ -2031,7 +2068,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
 	dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
 		 hdmi->version >> 12, hdmi->version & 0xfff,
 		 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without",
-		 hdmi->phy->name);
+		 hdmi->phy.name);
 
 	initialize_hdmi_ih_mutes(hdmi);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index b080a171a23f..0f583ca7e66e 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -57,13 +57,27 @@ struct dw_hdmi_phy_config {
 	u16 vlev_ctr;   /* voltage level control */
 };
 
+struct dw_hdmi_phy_ops {
+	int (*init)(struct dw_hdmi *hdmi, void *data,
+		    struct drm_display_mode *mode);
+	void (*disable)(struct dw_hdmi *hdmi, void *data);
+	enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data);
+};
+
 struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
+	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+					   struct drm_display_mode *mode);
+
+	/* Vendor PHY support */
+	const struct dw_hdmi_phy_ops *phy_ops;
+	const char *phy_name;
+	void *phy_data;
+
+	/* Synopsys PHY support */
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config;
-	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-					   struct drm_display_mode *mode);
 };
 
 int dw_hdmi_probe(struct platform_device *pdev,
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support
  2017-03-03 17:19 ` Laurent Pinchart
@ 2017-03-10 11:10   ` Archit Taneja
  -1 siblings, 0 replies; 35+ messages in thread
From: Archit Taneja @ 2017-03-10 11:10 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Andy Yan, Fabio Estevam, Jose Abreu, Kieran Bingham,
	Neil Armstrong, Nickey Yang, Russell King, Vladimir Zapolskiy,
	linux-renesas-soc



On 3/3/2017 10:49 PM, Laurent Pinchart wrote:
> Hello,
>
> This patch series refactors all the PHY handling code in order to allow
> support of vendor PHYs and Synopsys DWC HDMI 2.0 TX PHYs.
>
> The series starts with a few cleanups and small fixes. Patch 01/10 just
> removes unused code, patch 02/10 moves the color converter code out of the PHY
> configure function as it isn't PHY-dependent, and patch 03/10 enables color
> conversion even for DVI as it is needed to output RGB when the input format is
> YUV.
>
> The next two patches fix the power down (04/10) and up (05/10) sequences to
> comply with the HDMI TX PHY specifications. They are the biggest functional
> changes in the whole set, and have been tested successfully (with the rest of
> the series) on i.MX6Q, RK3288 and R-Car H3. The PLL PHY lock delay has been
> measured to be between 300µs and 350µs on R-Car H3, between 400µs and 600µs on
> i.MX6Q and between 150µs and 450µs on RK3288. The PHY power down delay has
> been measured to be less than 50µs on all platforms, and was often close to
> instant with power down reported in the first poll iteration. We should thus
> be more than safe with a 5ms timeout.
>
> Patch 06/10 breaks the PHY operations out. Glue code is then allowed to pass a
> PHY operations structure to support vendor PHYs. The existing PHY support code
> is turned into a default Synopsys PHYs implementation for those PHY
> operations.
>
> Patch 07/10 further refactors the Synopsys PHY configuration function to make
> it modular, in order to support DWC HDMI 2.0 TX PHYs that have a very
> different register layout compared to the currently supported PHYs. Glue code
> is again allowed to provide a custom PHY configuration implementation, with
> the existing PHY support code turned into the default implementation for all
> currently supported Synopsys PHYs.
>
> Patch 08/10 is a small cleanup that removes the now unneeded device type for
> glue code platform data, and patch 09/10 follows by switching the driver to
> regmap in order to support vendor-specific register access more easily.
>
> Patch 10/10 is a v5 addition that moves the code to a new directory per Jose's
> request. v5 also picked up review tags from the mailing list, and is rebased
> on top of the latest drm-misc-next branch. The series is otherwise unchanged
> compared to v4.
>
> Archit, how would you like to proceed to get this merged ?

Queued to drm-misc-next. Picked up the v5.1s where applicable. Resolved
some minor Kconfig/Makefile conflicts that came up because the
Megachips driver got pulled in first.

Thanks,
Archit

>
> Kieran Bingham (2):
>   drm: bridge: dw-hdmi: Add support for custom PHY configuration
>   drm: bridge: dw-hdmi: Remove device type from platform data
>
> Laurent Pinchart (6):
>   drm: bridge: dw-hdmi: Remove unused functions
>   drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
>   drm: bridge: dw-hdmi: Fix the PHY power down sequence
>   drm: bridge: dw-hdmi: Fix the PHY power up sequence
>   drm: bridge: dw-hdmi: Create PHY operations
>   drm: bridge: dw-hdmi: Move the driver to a separate directory.
>
> Neil Armstrong (2):
>   drm: bridge: dw-hdmi: Enable CSC even for DVI
>   drm: bridge: dw-hdmi: Switch to regmap for register access
>
>  drivers/gpu/drm/bridge/Kconfig                     |   2 +
>  drivers/gpu/drm/bridge/Makefile                    |   4 +-
>  drivers/gpu/drm/bridge/synopsys/Kconfig            |  23 +
>  drivers/gpu/drm/bridge/synopsys/Makefile           |   5 +
>  .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |   0
>  .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |   0
>  .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |   0
>  drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    | 467 ++++++++++++---------
>  drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |   0
>  drivers/gpu/drm/imx/dw_hdmi-imx.c                  |   2 -
>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        |   1 -
>  include/drm/bridge/dw_hdmi.h                       |  33 +-
>  12 files changed, 335 insertions(+), 202 deletions(-)
>  create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
>  create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (88%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)
>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support
@ 2017-03-10 11:10   ` Archit Taneja
  0 siblings, 0 replies; 35+ messages in thread
From: Archit Taneja @ 2017-03-10 11:10 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Fabio Estevam, Jose Abreu, Neil Armstrong, Kieran Bingham,
	linux-renesas-soc, Nickey Yang, Russell King, Andy Yan,
	Vladimir Zapolskiy



On 3/3/2017 10:49 PM, Laurent Pinchart wrote:
> Hello,
>
> This patch series refactors all the PHY handling code in order to allow
> support of vendor PHYs and Synopsys DWC HDMI 2.0 TX PHYs.
>
> The series starts with a few cleanups and small fixes. Patch 01/10 just
> removes unused code, patch 02/10 moves the color converter code out of the PHY
> configure function as it isn't PHY-dependent, and patch 03/10 enables color
> conversion even for DVI as it is needed to output RGB when the input format is
> YUV.
>
> The next two patches fix the power down (04/10) and up (05/10) sequences to
> comply with the HDMI TX PHY specifications. They are the biggest functional
> changes in the whole set, and have been tested successfully (with the rest of
> the series) on i.MX6Q, RK3288 and R-Car H3. The PLL PHY lock delay has been
> measured to be between 300µs and 350µs on R-Car H3, between 400µs and 600µs on
> i.MX6Q and between 150µs and 450µs on RK3288. The PHY power down delay has
> been measured to be less than 50µs on all platforms, and was often close to
> instant with power down reported in the first poll iteration. We should thus
> be more than safe with a 5ms timeout.
>
> Patch 06/10 breaks the PHY operations out. Glue code is then allowed to pass a
> PHY operations structure to support vendor PHYs. The existing PHY support code
> is turned into a default Synopsys PHYs implementation for those PHY
> operations.
>
> Patch 07/10 further refactors the Synopsys PHY configuration function to make
> it modular, in order to support DWC HDMI 2.0 TX PHYs that have a very
> different register layout compared to the currently supported PHYs. Glue code
> is again allowed to provide a custom PHY configuration implementation, with
> the existing PHY support code turned into the default implementation for all
> currently supported Synopsys PHYs.
>
> Patch 08/10 is a small cleanup that removes the now unneeded device type for
> glue code platform data, and patch 09/10 follows by switching the driver to
> regmap in order to support vendor-specific register access more easily.
>
> Patch 10/10 is a v5 addition that moves the code to a new directory per Jose's
> request. v5 also picked up review tags from the mailing list, and is rebased
> on top of the latest drm-misc-next branch. The series is otherwise unchanged
> compared to v4.
>
> Archit, how would you like to proceed to get this merged ?

Queued to drm-misc-next. Picked up the v5.1s where applicable. Resolved
some minor Kconfig/Makefile conflicts that came up because the
Megachips driver got pulled in first.

Thanks,
Archit

>
> Kieran Bingham (2):
>   drm: bridge: dw-hdmi: Add support for custom PHY configuration
>   drm: bridge: dw-hdmi: Remove device type from platform data
>
> Laurent Pinchart (6):
>   drm: bridge: dw-hdmi: Remove unused functions
>   drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
>   drm: bridge: dw-hdmi: Fix the PHY power down sequence
>   drm: bridge: dw-hdmi: Fix the PHY power up sequence
>   drm: bridge: dw-hdmi: Create PHY operations
>   drm: bridge: dw-hdmi: Move the driver to a separate directory.
>
> Neil Armstrong (2):
>   drm: bridge: dw-hdmi: Enable CSC even for DVI
>   drm: bridge: dw-hdmi: Switch to regmap for register access
>
>  drivers/gpu/drm/bridge/Kconfig                     |   2 +
>  drivers/gpu/drm/bridge/Makefile                    |   4 +-
>  drivers/gpu/drm/bridge/synopsys/Kconfig            |  23 +
>  drivers/gpu/drm/bridge/synopsys/Makefile           |   5 +
>  .../drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c  |   0
>  .../gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h  |   0
>  .../drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c  |   0
>  drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c    | 467 ++++++++++++---------
>  drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h    |   0
>  drivers/gpu/drm/imx/dw_hdmi-imx.c                  |   2 -
>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        |   1 -
>  include/drm/bridge/dw_hdmi.h                       |  33 +-
>  12 files changed, 335 insertions(+), 202 deletions(-)
>  create mode 100644 drivers/gpu/drm/bridge/synopsys/Kconfig
>  create mode 100644 drivers/gpu/drm/bridge/synopsys/Makefile
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-ahb-audio.c (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-audio.h (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi-i2s-audio.c (100%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.c (88%)
>  rename drivers/gpu/drm/bridge/{ => synopsys}/dw-hdmi.h (100%)
>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration
  2017-03-03 17:20   ` Laurent Pinchart
  (?)
@ 2017-04-24  7:46   ` 郑阳
  2017-04-26 11:04     ` Jose Abreu
  -1 siblings, 1 reply; 35+ messages in thread
From: 郑阳 @ 2017-04-24  7:46 UTC (permalink / raw)
  To: dri-devel; +Cc: 杨悦书, 蔡枫, xhc

Hi, Laurent Pinchart:

在 2017年03月04日 01:20, Laurent Pinchart 写道:
> From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>
> The DWC HDMI TX controller interfaces with a companion PHY. While
> Synopsys provides multiple standard PHYs, SoC vendors can also integrate
> a custom PHY.
>
> Modularize PHY configuration to support vendor PHYs through platform
> data. The existing PHY configuration code was originally written to
> support the DWC HDMI 3D TX PHY, and seems to be compatible with the DWC
> MLP PHY. The HDMI 2.0 PHY will require a separate configuration
> function.
>
> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Tested-by: Neil Armstrong <narmstrong@baylibre.com>
> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
> ---
> Changes since v1:
>
> - Check pdata->phy_configure in hdmi_phy_configure() to avoid
>    dereferencing NULL pointer.
> ---
>   drivers/gpu/drm/bridge/dw-hdmi.c | 109 ++++++++++++++++++++++++++-------------
>   include/drm/bridge/dw_hdmi.h     |   7 +++
>   2 files changed, 81 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index cb2703862be2..b835d81bb471 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
>   	const char *name;
>   	unsigned int gen;
>   	bool has_svsret;
> +	int (*configure)(struct dw_hdmi *hdmi,
> +			 const struct dw_hdmi_plat_data *pdata,
> +			 unsigned long mpixelclock);
>   };
>   
>   struct dw_hdmi {
> @@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
>   	return true;
>   }
>   
> -static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
> -				 unsigned char addr)
> +void dw_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);
> @@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
>   		    HDMI_PHY_I2CM_OPERATION_ADDR);
>   	hdmi_phy_wait_i2c_done(hdmi, 1000);
>   }
> +EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
>   
>   static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
>   {
> @@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi)
>   	return 0;
>   }
>   
> -static int hdmi_phy_configure(struct dw_hdmi *hdmi)
> +/*
> + * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available
> + * information the DWC MHL PHY has the same register layout and is thus also
> + * supported by this function.
> + */
> +static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
> +		const struct dw_hdmi_plat_data *pdata,
> +		unsigned long mpixelclock)
>   {
> -	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
> -	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
>   	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
>   	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
>   	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
>   
>   	/* PLL/MPLL Cfg - always match on final entry */
>   	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    mpll_config->mpixelclock)
> +		if (mpixelclock <= mpll_config->mpixelclock)
>   			break;
>   
>   	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    curr_ctrl->mpixelclock)
> +		if (mpixelclock <= curr_ctrl->mpixelclock)
>   			break;
>   
>   	for (; phy_config->mpixelclock != ~0UL; phy_config++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    phy_config->mpixelclock)
> +		if (mpixelclock <= phy_config->mpixelclock)
>   			break;
>   
>   	if (mpll_config->mpixelclock == ~0UL ||
>   	    curr_ctrl->mpixelclock == ~0UL ||
> -	    phy_config->mpixelclock == ~0UL) {
> -		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
> -			hdmi->hdmi_data.video_mode.mpixelclock);
> +	    phy_config->mpixelclock == ~0UL)
>   		return -EINVAL;
> -	}
> +
> +	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
> +			      HDMI_3D_TX_PHY_CPCE_CTRL);
> +	dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
> +			      HDMI_3D_TX_PHY_GMPCTRL);
> +	dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
> +			      HDMI_3D_TX_PHY_CURRCTRL);
> +
> +	dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
> +	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
> +			      HDMI_3D_TX_PHY_MSM_CTRL);
> +
> +	dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
> +	dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
> +			      HDMI_3D_TX_PHY_CKSYMTXCTRL);
> +	dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
> +			      HDMI_3D_TX_PHY_VLEVCTRL);
> +
> +	/* Override and disable clock termination. */
> +	dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
> +			      HDMI_3D_TX_PHY_CKCALCTRL);
> +
> +	return 0;
> +}
> +
> +static int hdmi_phy_configure(struct dw_hdmi *hdmi)
> +{
> +	const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
> +	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
> +	unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
> +	int ret;
>   
>   	dw_hdmi_phy_power_off(hdmi);
>   
> @@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>   		    HDMI_PHY_I2CM_SLAVE_ADDR);
>   	hdmi_phy_test_clear(hdmi, 0);
>   
> -	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
> -			   HDMI_3D_TX_PHY_CPCE_CTRL);
> -	hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
> -			   HDMI_3D_TX_PHY_GMPCTRL);
> -	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
> -			   HDMI_3D_TX_PHY_CURRCTRL);
> -
> -	hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
> -	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
> -			   HDMI_3D_TX_PHY_MSM_CTRL);
> -
> -	hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM);
> -	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
> -			   HDMI_3D_TX_PHY_CKSYMTXCTRL);
> -	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
> -			   HDMI_3D_TX_PHY_VLEVCTRL);
> -
> -	/* Override and disable clock termination. */
> -	hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
> -			   HDMI_3D_TX_PHY_CKCALCTRL);
> +	/* Write to the PHY as configured by the platform */
> +	if (pdata->configure_phy)
> +		ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
> +	else
> +		ret = phy->configure(hdmi, pdata, mpixelclock);
> +	if (ret) {
> +		dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n",
> +			mpixelclock);
> +		return ret;
> +	}
>   
>   	return dw_hdmi_phy_power_on(hdmi);
>   }
> @@ -1895,24 +1919,31 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
>   		.name = "DWC MHL PHY + HEAC PHY",
>   		.gen = 2,
>   		.has_svsret = true,
> +		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>   	}, {
>   		.type = DW_HDMI_PHY_DWC_MHL_PHY,
>   		.name = "DWC MHL PHY",
>   		.gen = 2,
>   		.has_svsret = true,
> +		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>   	}, {
>   		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
>   		.name = "DWC HDMI 3D TX PHY + HEAC PHY",
>   		.gen = 2,
> +		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>   	}, {
>   		.type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
>   		.name = "DWC HDMI 3D TX PHY",
>   		.gen = 2,
> +		.configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>   	}, {
>   		.type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
>   		.name = "DWC HDMI 2.0 TX PHY",
>   		.gen = 2,
>   		.has_svsret = true,
After this commit, the dw-hdmi on RK3368/RK3399 run into the
"DWC HDMI 2.0 TX PHY requires platform support error".
the phy-type of RK3368/RK3399 is 0xf3, and phy register layout is
compatible with DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC.
Is here missing a default phy configure function?
> +	}, {
> +		.type = DW_HDMI_PHY_VENDOR_PHY,
> +		.name = "Vendor PHY",
>   	}
>   };
>   
> @@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
>   			hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
>   			hdmi->phy.name = dw_hdmi_phys[i].name;
>   			hdmi->phy.data = (void *)&dw_hdmi_phys[i];
> +
> +			if (!dw_hdmi_phys[i].configure &&
> +			    !hdmi->plat_data->configure_phy) {
> +				dev_err(hdmi->dev, "%s requires platform support\n",
> +					hdmi->phy.name);
> +				return -ENODEV;
> +			}
> +
>   			return 0;
>   		}
>   	}
> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
> index 0f583ca7e66e..dd330259a3dc 100644
> --- a/include/drm/bridge/dw_hdmi.h
> +++ b/include/drm/bridge/dw_hdmi.h
> @@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
>   	const struct dw_hdmi_mpll_config *mpll_cfg;
>   	const struct dw_hdmi_curr_ctrl *cur_ctr;
>   	const struct dw_hdmi_phy_config *phy_config;
> +	int (*configure_phy)(struct dw_hdmi *hdmi,
> +			     const struct dw_hdmi_plat_data *pdata,
> +			     unsigned long mpixelclock);
>   };
>   
>   int dw_hdmi_probe(struct platform_device *pdev,
> @@ -91,4 +94,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
>   void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
>   void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
>   
> +/* PHY configuration */
> +void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
> +			   unsigned char addr);
> +
>   #endif /* __IMX_HDMI_H__ */


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration
  2017-04-24  7:46   ` 郑阳
@ 2017-04-26 11:04     ` Jose Abreu
  2017-04-27  4:16       ` 郑阳
  0 siblings, 1 reply; 35+ messages in thread
From: Jose Abreu @ 2017-04-26 11:04 UTC (permalink / raw)
  To: yang.zheng, dri-devel; +Cc: 杨悦书, 蔡枫, xhc

Hi,


On 24-04-2017 08:46, 郑阳 wrote:
> Hi, Laurent Pinchart:
>
> 在 2017年03月04日 01:20, Laurent Pinchart 写道:
>> From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>>
>> The DWC HDMI TX controller interfaces with a companion PHY. While
>> Synopsys provides multiple standard PHYs, SoC vendors can also
>> integrate
>> a custom PHY.
>>
>> Modularize PHY configuration to support vendor PHYs through
>> platform
>> data. The existing PHY configuration code was originally
>> written to
>> support the DWC HDMI 3D TX PHY, and seems to be compatible
>> with the DWC
>> MLP PHY. The HDMI 2.0 PHY will require a separate configuration
>> function.
>>
>> Signed-off-by: Kieran Bingham
>> <kieran.bingham+renesas@ideasonboard.com>
>> Signed-off-by: Laurent Pinchart
>> <laurent.pinchart+renesas@ideasonboard.com>
>> Tested-by: Neil Armstrong <narmstrong@baylibre.com>
>> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
>> ---
>> Changes since v1:
>>
>> - Check pdata->phy_configure in hdmi_phy_configure() to avoid
>>    dereferencing NULL pointer.
>> ---
>>   drivers/gpu/drm/bridge/dw-hdmi.c | 109
>> ++++++++++++++++++++++++++-------------
>>   include/drm/bridge/dw_hdmi.h     |   7 +++
>>   2 files changed, 81 insertions(+), 35 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c
>> b/drivers/gpu/drm/bridge/dw-hdmi.c
>> index cb2703862be2..b835d81bb471 100644
>> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
>> @@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
>>       const char *name;
>>       unsigned int gen;
>>       bool has_svsret;
>> +    int (*configure)(struct dw_hdmi *hdmi,
>> +             const struct dw_hdmi_plat_data *pdata,
>> +             unsigned long mpixelclock);
>>   };
>>     struct dw_hdmi {
>> @@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct
>> dw_hdmi *hdmi, int msec)
>>       return true;
>>   }
>>   -static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi,
>> unsigned short data,
>> -                 unsigned char addr)
>> +void dw_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);
>> @@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct
>> dw_hdmi *hdmi, unsigned short data,
>>               HDMI_PHY_I2CM_OPERATION_ADDR);
>>       hdmi_phy_wait_i2c_done(hdmi, 1000);
>>   }
>> +EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
>>     static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi
>> *hdmi, bool enable)
>>   {
>> @@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct
>> dw_hdmi *hdmi)
>>       return 0;
>>   }
>>   -static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>> +/*
>> + * PHY configuration function for the DWC HDMI 3D TX PHY.
>> Based on the available
>> + * information the DWC MHL PHY has the same register layout
>> and is thus also
>> + * supported by this function.
>> + */
>> +static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi
>> *hdmi,
>> +        const struct dw_hdmi_plat_data *pdata,
>> +        unsigned long mpixelclock)
>>   {
>> -    const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
>> -    const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
>>       const struct dw_hdmi_mpll_config *mpll_config =
>> pdata->mpll_cfg;
>>       const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
>>       const struct dw_hdmi_phy_config *phy_config =
>> pdata->phy_config;
>>         /* PLL/MPLL Cfg - always match on final entry */
>>       for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>> -            mpll_config->mpixelclock)
>> +        if (mpixelclock <= mpll_config->mpixelclock)
>>               break;
>>         for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>> -            curr_ctrl->mpixelclock)
>> +        if (mpixelclock <= curr_ctrl->mpixelclock)
>>               break;
>>         for (; phy_config->mpixelclock != ~0UL; phy_config++)
>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>> -            phy_config->mpixelclock)
>> +        if (mpixelclock <= phy_config->mpixelclock)
>>               break;
>>         if (mpll_config->mpixelclock == ~0UL ||
>>           curr_ctrl->mpixelclock == ~0UL ||
>> -        phy_config->mpixelclock == ~0UL) {
>> -        dev_err(hdmi->dev, "Pixel clock %d - unsupported by
>> HDMI\n",
>> -            hdmi->hdmi_data.video_mode.mpixelclock);
>> +        phy_config->mpixelclock == ~0UL)
>>           return -EINVAL;
>> -    }
>> +
>> +    dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
>> +                  HDMI_3D_TX_PHY_CPCE_CTRL);
>> +    dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
>> +                  HDMI_3D_TX_PHY_GMPCTRL);
>> +    dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
>> +                  HDMI_3D_TX_PHY_CURRCTRL);
>> +
>> +    dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
>> +    dw_hdmi_phy_i2c_write(hdmi,
>> HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
>> +                  HDMI_3D_TX_PHY_MSM_CTRL);
>> +
>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->term,
>> HDMI_3D_TX_PHY_TXTERM);
>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
>> +                  HDMI_3D_TX_PHY_CKSYMTXCTRL);
>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
>> +                  HDMI_3D_TX_PHY_VLEVCTRL);
>> +
>> +    /* Override and disable clock termination. */
>> +    dw_hdmi_phy_i2c_write(hdmi,
>> HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
>> +                  HDMI_3D_TX_PHY_CKCALCTRL);
>> +
>> +    return 0;
>> +}
>> +
>> +static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>> +{
>> +    const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
>> +    const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
>> +    unsigned long mpixelclock =
>> hdmi->hdmi_data.video_mode.mpixelclock;
>> +    int ret;
>>         dw_hdmi_phy_power_off(hdmi);
>>   @@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct
>> dw_hdmi *hdmi)
>>               HDMI_PHY_I2CM_SLAVE_ADDR);
>>       hdmi_phy_test_clear(hdmi, 0);
>>   -    hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
>> -               HDMI_3D_TX_PHY_CPCE_CTRL);
>> -    hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
>> -               HDMI_3D_TX_PHY_GMPCTRL);
>> -    hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
>> -               HDMI_3D_TX_PHY_CURRCTRL);
>> -
>> -    hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
>> -    hdmi_phy_i2c_write(hdmi,
>> HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
>> -               HDMI_3D_TX_PHY_MSM_CTRL);
>> -
>> -    hdmi_phy_i2c_write(hdmi, phy_config->term,
>> HDMI_3D_TX_PHY_TXTERM);
>> -    hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
>> -               HDMI_3D_TX_PHY_CKSYMTXCTRL);
>> -    hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
>> -               HDMI_3D_TX_PHY_VLEVCTRL);
>> -
>> -    /* Override and disable clock termination. */
>> -    hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
>> -               HDMI_3D_TX_PHY_CKCALCTRL);
>> +    /* Write to the PHY as configured by the platform */
>> +    if (pdata->configure_phy)
>> +        ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
>> +    else
>> +        ret = phy->configure(hdmi, pdata, mpixelclock);
>> +    if (ret) {
>> +        dev_err(hdmi->dev, "PHY configuration failed (clock
>> %lu)\n",
>> +            mpixelclock);
>> +        return ret;
>> +    }
>>         return dw_hdmi_phy_power_on(hdmi);
>>   }
>> @@ -1895,24 +1919,31 @@ static const struct dw_hdmi_phy_data
>> dw_hdmi_phys[] = {
>>           .name = "DWC MHL PHY + HEAC PHY",
>>           .gen = 2,
>>           .has_svsret = true,
>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>       }, {
>>           .type = DW_HDMI_PHY_DWC_MHL_PHY,
>>           .name = "DWC MHL PHY",
>>           .gen = 2,
>>           .has_svsret = true,
>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>       }, {
>>           .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
>>           .name = "DWC HDMI 3D TX PHY + HEAC PHY",
>>           .gen = 2,
>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>       }, {
>>           .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
>>           .name = "DWC HDMI 3D TX PHY",
>>           .gen = 2,
>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>       }, {
>>           .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
>>           .name = "DWC HDMI 2.0 TX PHY",
>>           .gen = 2,
>>           .has_svsret = true,
> After this commit, the dw-hdmi on RK3368/RK3399 run into the
> "DWC HDMI 2.0 TX PHY requires platform support error".
> the phy-type of RK3368/RK3399 is 0xf3, and phy register layout is
> compatible with DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC.
> Is here missing a default phy configure function?

If this has the same register layout then this patch should solve
the problem:

----------------------------------------------------------------
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 4e1f54a..ff96864 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2159,6 +2159,7 @@ static irqreturn_t dw_hdmi_irq(int irq,
void *dev_id)
                .name = "DWC HDMI 2.0 TX PHY",
                .gen = 2,
                .has_svsret = true,
+               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
        }, {
                .type = DW_HDMI_PHY_VENDOR_PHY,
                .name = "Vendor PHY",
----------------------------------------------------------------

Please test and let me know if its ok. This shouldn't impact
other platforms which supply custom configuration function by
pdata as the check for pdata configure() is done before checking
the internal configure().

Best regards,
Jose Miguel Abreu

>> +    }, {
>> +        .type = DW_HDMI_PHY_VENDOR_PHY,
>> +        .name = "Vendor PHY",
>>       }
>>   };
>>   @@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct
>> dw_hdmi *hdmi)
>>               hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
>>               hdmi->phy.name = dw_hdmi_phys[i].name;
>>               hdmi->phy.data = (void *)&dw_hdmi_phys[i];
>> +
>> +            if (!dw_hdmi_phys[i].configure &&
>> +                !hdmi->plat_data->configure_phy) {
>> +                dev_err(hdmi->dev, "%s requires platform
>> support\n",
>> +                    hdmi->phy.name);
>> +                return -ENODEV;
>> +            }
>> +
>>               return 0;
>>           }
>>       }
>> diff --git a/include/drm/bridge/dw_hdmi.h
>> b/include/drm/bridge/dw_hdmi.h
>> index 0f583ca7e66e..dd330259a3dc 100644
>> --- a/include/drm/bridge/dw_hdmi.h
>> +++ b/include/drm/bridge/dw_hdmi.h
>> @@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
>>       const struct dw_hdmi_mpll_config *mpll_cfg;
>>       const struct dw_hdmi_curr_ctrl *cur_ctr;
>>       const struct dw_hdmi_phy_config *phy_config;
>> +    int (*configure_phy)(struct dw_hdmi *hdmi,
>> +                 const struct dw_hdmi_plat_data *pdata,
>> +                 unsigned long mpixelclock);
>>   };
>>     int dw_hdmi_probe(struct platform_device *pdev,
>> @@ -91,4 +94,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi
>> *hdmi, unsigned int rate);
>>   void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
>>   void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
>>   +/* PHY configuration */
>> +void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned
>> short data,
>> +               unsigned char addr);
>> +
>>   #endif /* __IMX_HDMI_H__ */
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.freedesktop.org_mailman_listinfo_dri-2Ddevel&d=DwIGaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=yaVFU4TjGY0gVF8El1uKcisy6TPsyCl9uN7Wsis-qhY&m=cjy3Og8_l5PxS4qa2_RekJB_Bi_J4sVXR1zH24rY7ng&s=bH0i9klWoHnYe5d9wM4Ei2u_2bkGUeZJZV5J7BsBCqE&e=


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration
  2017-04-26 11:04     ` Jose Abreu
@ 2017-04-27  4:16       ` 郑阳
  0 siblings, 0 replies; 35+ messages in thread
From: 郑阳 @ 2017-04-27  4:16 UTC (permalink / raw)
  To: Jose Abreu, dri-devel; +Cc: 杨悦书, 蔡枫, xhc

Hi, Jose Abreu:

Thanks for your patch, it works fine on RK3399 / RK3368。

在 2017年04月26日 19:04, Jose Abreu 写道:
> Hi,
>
>
> On 24-04-2017 08:46, 郑阳 wrote:
>> Hi, Laurent Pinchart:
>>
>> 在 2017年03月04日 01:20, Laurent Pinchart 写道:
>>> From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>>>
>>> The DWC HDMI TX controller interfaces with a companion PHY. While
>>> Synopsys provides multiple standard PHYs, SoC vendors can also
>>> integrate
>>> a custom PHY.
>>>
>>> Modularize PHY configuration to support vendor PHYs through
>>> platform
>>> data. The existing PHY configuration code was originally
>>> written to
>>> support the DWC HDMI 3D TX PHY, and seems to be compatible
>>> with the DWC
>>> MLP PHY. The HDMI 2.0 PHY will require a separate configuration
>>> function.
>>>
>>> Signed-off-by: Kieran Bingham
>>> <kieran.bingham+renesas@ideasonboard.com>
>>> Signed-off-by: Laurent Pinchart
>>> <laurent.pinchart+renesas@ideasonboard.com>
>>> Tested-by: Neil Armstrong <narmstrong@baylibre.com>
>>> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
>>> ---
>>> Changes since v1:
>>>
>>> - Check pdata->phy_configure in hdmi_phy_configure() to avoid
>>>     dereferencing NULL pointer.
>>> ---
>>>    drivers/gpu/drm/bridge/dw-hdmi.c | 109
>>> ++++++++++++++++++++++++++-------------
>>>    include/drm/bridge/dw_hdmi.h     |   7 +++
>>>    2 files changed, 81 insertions(+), 35 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c
>>> b/drivers/gpu/drm/bridge/dw-hdmi.c
>>> index cb2703862be2..b835d81bb471 100644
>>> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
>>> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
>>> @@ -118,6 +118,9 @@ struct dw_hdmi_phy_data {
>>>        const char *name;
>>>        unsigned int gen;
>>>        bool has_svsret;
>>> +    int (*configure)(struct dw_hdmi *hdmi,
>>> +             const struct dw_hdmi_plat_data *pdata,
>>> +             unsigned long mpixelclock);
>>>    };
>>>      struct dw_hdmi {
>>> @@ -860,8 +863,8 @@ static bool hdmi_phy_wait_i2c_done(struct
>>> dw_hdmi *hdmi, int msec)
>>>        return true;
>>>    }
>>>    -static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi,
>>> unsigned short data,
>>> -                 unsigned char addr)
>>> +void dw_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);
>>> @@ -873,6 +876,7 @@ static void hdmi_phy_i2c_write(struct
>>> dw_hdmi *hdmi, unsigned short data,
>>>                HDMI_PHY_I2CM_OPERATION_ADDR);
>>>        hdmi_phy_wait_i2c_done(hdmi, 1000);
>>>    }
>>> +EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
>>>      static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi
>>> *hdmi, bool enable)
>>>    {
>>> @@ -993,37 +997,67 @@ static int dw_hdmi_phy_power_on(struct
>>> dw_hdmi *hdmi)
>>>        return 0;
>>>    }
>>>    -static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>>> +/*
>>> + * PHY configuration function for the DWC HDMI 3D TX PHY.
>>> Based on the available
>>> + * information the DWC MHL PHY has the same register layout
>>> and is thus also
>>> + * supported by this function.
>>> + */
>>> +static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi
>>> *hdmi,
>>> +        const struct dw_hdmi_plat_data *pdata,
>>> +        unsigned long mpixelclock)
>>>    {
>>> -    const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
>>> -    const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
>>>        const struct dw_hdmi_mpll_config *mpll_config =
>>> pdata->mpll_cfg;
>>>        const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
>>>        const struct dw_hdmi_phy_config *phy_config =
>>> pdata->phy_config;
>>>          /* PLL/MPLL Cfg - always match on final entry */
>>>        for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
>>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>>> -            mpll_config->mpixelclock)
>>> +        if (mpixelclock <= mpll_config->mpixelclock)
>>>                break;
>>>          for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
>>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>>> -            curr_ctrl->mpixelclock)
>>> +        if (mpixelclock <= curr_ctrl->mpixelclock)
>>>                break;
>>>          for (; phy_config->mpixelclock != ~0UL; phy_config++)
>>> -        if (hdmi->hdmi_data.video_mode.mpixelclock <=
>>> -            phy_config->mpixelclock)
>>> +        if (mpixelclock <= phy_config->mpixelclock)
>>>                break;
>>>          if (mpll_config->mpixelclock == ~0UL ||
>>>            curr_ctrl->mpixelclock == ~0UL ||
>>> -        phy_config->mpixelclock == ~0UL) {
>>> -        dev_err(hdmi->dev, "Pixel clock %d - unsupported by
>>> HDMI\n",
>>> -            hdmi->hdmi_data.video_mode.mpixelclock);
>>> +        phy_config->mpixelclock == ~0UL)
>>>            return -EINVAL;
>>> -    }
>>> +
>>> +    dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
>>> +                  HDMI_3D_TX_PHY_CPCE_CTRL);
>>> +    dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
>>> +                  HDMI_3D_TX_PHY_GMPCTRL);
>>> +    dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
>>> +                  HDMI_3D_TX_PHY_CURRCTRL);
>>> +
>>> +    dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
>>> +    dw_hdmi_phy_i2c_write(hdmi,
>>> HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
>>> +                  HDMI_3D_TX_PHY_MSM_CTRL);
>>> +
>>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->term,
>>> HDMI_3D_TX_PHY_TXTERM);
>>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
>>> +                  HDMI_3D_TX_PHY_CKSYMTXCTRL);
>>> +    dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
>>> +                  HDMI_3D_TX_PHY_VLEVCTRL);
>>> +
>>> +    /* Override and disable clock termination. */
>>> +    dw_hdmi_phy_i2c_write(hdmi,
>>> HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
>>> +                  HDMI_3D_TX_PHY_CKCALCTRL);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>>> +{
>>> +    const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
>>> +    const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
>>> +    unsigned long mpixelclock =
>>> hdmi->hdmi_data.video_mode.mpixelclock;
>>> +    int ret;
>>>          dw_hdmi_phy_power_off(hdmi);
>>>    @@ -1042,26 +1076,16 @@ static int hdmi_phy_configure(struct
>>> dw_hdmi *hdmi)
>>>                HDMI_PHY_I2CM_SLAVE_ADDR);
>>>        hdmi_phy_test_clear(hdmi, 0);
>>>    -    hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce,
>>> -               HDMI_3D_TX_PHY_CPCE_CTRL);
>>> -    hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp,
>>> -               HDMI_3D_TX_PHY_GMPCTRL);
>>> -    hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0],
>>> -               HDMI_3D_TX_PHY_CURRCTRL);
>>> -
>>> -    hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL);
>>> -    hdmi_phy_i2c_write(hdmi,
>>> HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK,
>>> -               HDMI_3D_TX_PHY_MSM_CTRL);
>>> -
>>> -    hdmi_phy_i2c_write(hdmi, phy_config->term,
>>> HDMI_3D_TX_PHY_TXTERM);
>>> -    hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
>>> -               HDMI_3D_TX_PHY_CKSYMTXCTRL);
>>> -    hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
>>> -               HDMI_3D_TX_PHY_VLEVCTRL);
>>> -
>>> -    /* Override and disable clock termination. */
>>> -    hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE,
>>> -               HDMI_3D_TX_PHY_CKCALCTRL);
>>> +    /* Write to the PHY as configured by the platform */
>>> +    if (pdata->configure_phy)
>>> +        ret = pdata->configure_phy(hdmi, pdata, mpixelclock);
>>> +    else
>>> +        ret = phy->configure(hdmi, pdata, mpixelclock);
>>> +    if (ret) {
>>> +        dev_err(hdmi->dev, "PHY configuration failed (clock
>>> %lu)\n",
>>> +            mpixelclock);
>>> +        return ret;
>>> +    }
>>>          return dw_hdmi_phy_power_on(hdmi);
>>>    }
>>> @@ -1895,24 +1919,31 @@ static const struct dw_hdmi_phy_data
>>> dw_hdmi_phys[] = {
>>>            .name = "DWC MHL PHY + HEAC PHY",
>>>            .gen = 2,
>>>            .has_svsret = true,
>>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>>        }, {
>>>            .type = DW_HDMI_PHY_DWC_MHL_PHY,
>>>            .name = "DWC MHL PHY",
>>>            .gen = 2,
>>>            .has_svsret = true,
>>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>>        }, {
>>>            .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC,
>>>            .name = "DWC HDMI 3D TX PHY + HEAC PHY",
>>>            .gen = 2,
>>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>>        }, {
>>>            .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY,
>>>            .name = "DWC HDMI 3D TX PHY",
>>>            .gen = 2,
>>> +        .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>>>        }, {
>>>            .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
>>>            .name = "DWC HDMI 2.0 TX PHY",
>>>            .gen = 2,
>>>            .has_svsret = true,
>> After this commit, the dw-hdmi on RK3368/RK3399 run into the
>> "DWC HDMI 2.0 TX PHY requires platform support error".
>> the phy-type of RK3368/RK3399 is 0xf3, and phy register layout is
>> compatible with DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC.
>> Is here missing a default phy configure function?
> If this has the same register layout then this patch should solve
> the problem:
>
> ----------------------------------------------------------------
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 4e1f54a..ff96864 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2159,6 +2159,7 @@ static irqreturn_t dw_hdmi_irq(int irq,
> void *dev_id)
>                  .name = "DWC HDMI 2.0 TX PHY",
>                  .gen = 2,
>                  .has_svsret = true,
> +               .configure = hdmi_phy_configure_dwc_hdmi_3d_tx,
>          }, {
>                  .type = DW_HDMI_PHY_VENDOR_PHY,
>                  .name = "Vendor PHY",
> ----------------------------------------------------------------
>
> Please test and let me know if its ok. This shouldn't impact
> other platforms which supply custom configuration function by
> pdata as the check for pdata configure() is done before checking
> the internal configure().
>
> Best regards,
> Jose Miguel Abreu
>
>>> +    }, {
>>> +        .type = DW_HDMI_PHY_VENDOR_PHY,
>>> +        .name = "Vendor PHY",
>>>        }
>>>    };
>>>    @@ -1943,6 +1974,14 @@ static int dw_hdmi_detect_phy(struct
>>> dw_hdmi *hdmi)
>>>                hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops;
>>>                hdmi->phy.name = dw_hdmi_phys[i].name;
>>>                hdmi->phy.data = (void *)&dw_hdmi_phys[i];
>>> +
>>> +            if (!dw_hdmi_phys[i].configure &&
>>> +                !hdmi->plat_data->configure_phy) {
>>> +                dev_err(hdmi->dev, "%s requires platform
>>> support\n",
>>> +                    hdmi->phy.name);
>>> +                return -ENODEV;
>>> +            }
>>> +
>>>                return 0;
>>>            }
>>>        }
>>> diff --git a/include/drm/bridge/dw_hdmi.h
>>> b/include/drm/bridge/dw_hdmi.h
>>> index 0f583ca7e66e..dd330259a3dc 100644
>>> --- a/include/drm/bridge/dw_hdmi.h
>>> +++ b/include/drm/bridge/dw_hdmi.h
>>> @@ -78,6 +78,9 @@ struct dw_hdmi_plat_data {
>>>        const struct dw_hdmi_mpll_config *mpll_cfg;
>>>        const struct dw_hdmi_curr_ctrl *cur_ctr;
>>>        const struct dw_hdmi_phy_config *phy_config;
>>> +    int (*configure_phy)(struct dw_hdmi *hdmi,
>>> +                 const struct dw_hdmi_plat_data *pdata,
>>> +                 unsigned long mpixelclock);
>>>    };
>>>      int dw_hdmi_probe(struct platform_device *pdev,
>>> @@ -91,4 +94,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi
>>> *hdmi, unsigned int rate);
>>>    void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
>>>    void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
>>>    +/* PHY configuration */
>>> +void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned
>>> short data,
>>> +               unsigned char addr);
>>> +
>>>    #endif /* __IMX_HDMI_H__ */
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.freedesktop.org_mailman_listinfo_dri-2Ddevel&d=DwIGaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=yaVFU4TjGY0gVF8El1uKcisy6TPsyCl9uN7Wsis-qhY&m=cjy3Og8_l5PxS4qa2_RekJB_Bi_J4sVXR1zH24rY7ng&s=bH0i9klWoHnYe5d9wM4Ei2u_2bkGUeZJZV5J7BsBCqE&e=
>
>
>
>


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2017-04-27  4:16 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03 17:19 [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support Laurent Pinchart
2017-03-03 17:19 ` Laurent Pinchart
2017-03-03 17:19 ` [PATCH v5 01/10] drm: bridge: dw-hdmi: Remove unused functions Laurent Pinchart
2017-03-03 17:19   ` Laurent Pinchart
2017-03-04  1:11   ` [PATCH v5.1 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory Laurent Pinchart
2017-03-04  1:11     ` Laurent Pinchart
2017-03-03 17:19 ` [PATCH v5 02/10] drm: bridge: dw-hdmi: Move CSC configuration out of PHY code Laurent Pinchart
2017-03-03 17:19   ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 03/10] drm: bridge: dw-hdmi: Enable CSC even for DVI Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-05 23:35   ` [PATCH v5.1 " Laurent Pinchart
2017-03-05 23:35     ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-05 23:35   ` [PATCH v5.1 " Laurent Pinchart
2017-03-05 23:35     ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 06/10] drm: bridge: dw-hdmi: Create PHY operations Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-05 23:36   ` [PATCH v5.1 " Laurent Pinchart
2017-03-05 23:36     ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 07/10] drm: bridge: dw-hdmi: Add support for custom PHY configuration Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-04-24  7:46   ` 郑阳
2017-04-26 11:04     ` Jose Abreu
2017-04-27  4:16       ` 郑阳
2017-03-03 17:20 ` [PATCH v5 08/10] drm: bridge: dw-hdmi: Remove device type from platform data Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 09/10] drm: bridge: dw-hdmi: Switch to regmap for register access Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-03 17:20 ` [PATCH v5 10/10] drm: bridge: dw-hdmi: Move the driver to a separate directory Laurent Pinchart
2017-03-03 17:20   ` Laurent Pinchart
2017-03-10 11:10 ` [PATCH v5 00/10] drm: bridge: dw-hdmi: Refactor PHY support Archit Taneja
2017-03-10 11:10   ` Archit Taneja

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.