FROMLIST: drm/rockchip: dw_hdmi: introduce the VPLL clock setting
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / dw_hdmi-rockchip.c
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)