FROMLIST: drm/rockchip: dw_hdmi: introduce the VPLL clock setting
authorYakir Yang <ykk@rock-chips.com>
Mon, 11 Jul 2016 10:12:29 +0000 (18:12 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 14 Jul 2016 06:04:23 +0000 (14:04 +0800)
For RK3399 HDMI, there is an external clock need for HDMI PHY,
and it should keep the same clock rate with VOP DCLK.

VPLL have supported the clock for HDMI PHY, but there is no
clock divider bewteen VPLL and HDMI PHY. So we need to set the
VPLL rate manually in HDMI driver.

Change-Id: I73abc382ff43bfa93d150c3449693f207029549f
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
(am from https://patchwork.kernel.org/patch/9223327/)

Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c

index 4e573d2d6d2b9cc412a55f296ccb5509b16f4616..4e23ca433940a78474fe675efa7c8d2c14b02868 100644 (file)
@@ -17,7 +17,8 @@ Required properties:
 
 Optional properties
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
+- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec",
+                      phandle to the VPLL clock, name should be "vpll".
 
 Example:
 hdmi: hdmi@ff980000 {
index 329099b6e0c99519a37875cec8b26c85b36bfbd2..701bb739dd3fc15cd5f9a46de17e14212017206c 100644 (file)
@@ -7,10 +7,12 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
@@ -33,6 +35,7 @@ struct rockchip_hdmi {
        struct regmap *regmap;
        struct drm_encoder encoder;
        enum dw_hdmi_devtype dev_type;
+       struct clk *vpll_clk;
 };
 
 #define to_rockchip_hdmi(x)    container_of(x, struct rockchip_hdmi, x)
@@ -145,6 +148,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
        struct device_node *np = hdmi->dev->of_node;
+       int ret;
 
        hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
        if (IS_ERR(hdmi->regmap)) {
@@ -152,6 +156,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
                return PTR_ERR(hdmi->regmap);
        }
 
+       hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
+       if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
+               hdmi->vpll_clk = NULL;
+       } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
+               return -EPROBE_DEFER;
+       } else if (IS_ERR(hdmi->vpll_clk)) {
+               dev_err(hdmi->dev, "failed to get grf clock\n");
+               return PTR_ERR(hdmi->vpll_clk);
+       }
+
+       ret = clk_prepare_enable(hdmi->vpll_clk);
+       if (ret) {
+               dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -194,6 +214,9 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
                                              struct drm_display_mode *mode,
                                              struct drm_display_mode *adj_mode)
 {
+       struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
+
+       clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
 }
 
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)