[PATCH 59/72] imx-drm: hdmi: set DI clock source to DI pre clock
Steve Longerbeam
slongerbeam at gmail.com
Fri Oct 31 15:54:42 PDT 2014
If DI is firstly bound to ldb and then re-bound to HDMI,
DI clock source will still be routed to LDB clock by ldb driver.
In HDMI driver's encoder_prepare, we have to set DI clock source to
the parent di_pre clock mux to ensure we are having correct clock
chain to drive HDMI display.
Signed-off-by: Steve Longerbeam <steve_longerbeam at mentor.com>
Signed-off-by: Jiada Wang <jiada_wang at mentor.com>
---
arch/arm/boot/dts/imx6dl.dtsi | 8 ++++++++
arch/arm/boot/dts/imx6q.dtsi | 12 ++++++++++++
arch/arm/boot/dts/imx6qdl.dtsi | 3 ---
drivers/staging/imx-drm/imx-hdmi.c | 32 +++++++++++++++++++++++++++++++-
4 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 05af0f4..7d1a1bf 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -104,6 +104,14 @@
&hdmi {
compatible = "fsl,imx6dl-hdmi";
+ clocks = <&clks IMX6QDL_CLK_HDMI_IAHB>, <&clks IMX6QDL_CLK_HDMI_ISFR>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI1_SEL>;
+ clock-names = "iahb", "isfr",
+ "di0_pre_sel", "di1_pre_sel",
+ "di0_sel", "di1_sel";
};
&ldb {
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 9d1f88c..7d0a7bc 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -235,6 +235,18 @@
&hdmi {
compatible = "fsl,imx6q-hdmi";
+ clocks = <&clks IMX6QDL_CLK_HDMI_IAHB>, <&clks IMX6QDL_CLK_HDMI_ISFR>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI1_PRE_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI0_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI1_SEL>;
+ clock-names = "iahb", "isfr",
+ "di0_pre_sel", "di1_pre_sel", "di2_pre_sel", "di3_pre_sel",
+ "di0_sel", "di1_sel", "di2_sel", "di3_sel";
port at 2 {
reg = <2>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 13d6b50..4e3a3e8 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -810,9 +810,6 @@
reg = <0x00120000 0x9000>;
interrupts = <0 115 0x04>;
gpr = <&gpr>;
- clocks = <&clks IMX6QDL_CLK_HDMI_IAHB>,
- <&clks IMX6QDL_CLK_HDMI_ISFR>;
- clock-names = "iahb", "isfr";
status = "disabled";
port at 0 {
diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c
index 4ef1c0a..d97fa18 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -118,6 +118,8 @@ struct imx_hdmi {
struct device *dev;
struct clk *isfr_clk;
struct clk *iahb_clk;
+ struct clk *di_pre_sel[4];
+ struct clk *di_sel[4];
struct hdmi_data_info hdmi_data;
int vic;
@@ -1452,8 +1454,13 @@ static void imx_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode)
static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
{
struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
+ int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
imx_hdmi_poweroff(hdmi);
+
+ /* set DI clock mux to DI pre clock mux */
+ clk_set_parent(hdmi->di_sel[mux], hdmi->di_pre_sel[mux]);
+
imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24, NULL);
}
@@ -1593,7 +1600,7 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
struct device_node *ddc_node;
struct imx_hdmi *hdmi;
struct resource *iores;
- int ret;
+ int i, ret;
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
@@ -1629,6 +1636,29 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(hdmi->regmap))
return PTR_ERR(hdmi->regmap);
+ for (i = 0; i < 4; i++) {
+ char clkname[16];
+
+ sprintf(clkname, "di%d_pre_sel", i);
+ hdmi->di_pre_sel[i] = devm_clk_get(hdmi->dev, clkname);
+ if (IS_ERR(hdmi->di_pre_sel[i])) {
+ ret = PTR_ERR(hdmi->di_pre_sel[i]);
+ hdmi->di_pre_sel[i] = NULL;
+ break;
+ }
+
+ sprintf(clkname, "di%d_sel", i);
+ hdmi->di_sel[i] = devm_clk_get(hdmi->dev, clkname);
+ if (IS_ERR(hdmi->di_sel[i])) {
+ ret = PTR_ERR(hdmi->di_sel[i]);
+ hdmi->di_pre_sel[i] = NULL;
+ hdmi->di_sel[i] = NULL;
+ break;
+ }
+ }
+ if (i == 0)
+ return ret;
+
hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
if (IS_ERR(hdmi->isfr_clk)) {
ret = PTR_ERR(hdmi->isfr_clk);
--
1.7.9.5
More information about the dri-devel
mailing list