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@xxxxxxxxxx> Signed-off-by: Jiada Wang <jiada_wang@xxxxxxxxxx> --- 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@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@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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel