|
@@ -137,6 +137,36 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
|
|
|
+{
|
|
|
+ const struct hdmi_platform_config *config = hdmi->config;
|
|
|
+ struct device *dev = &hdmi->pdev->dev;
|
|
|
+ int i, ret;
|
|
|
+
|
|
|
+ if (enable) {
|
|
|
+ for (i = 0; i < config->hpd_clk_cnt; i++) {
|
|
|
+ if (config->hpd_freq && config->hpd_freq[i]) {
|
|
|
+ ret = clk_set_rate(hdmi->hpd_clks[i],
|
|
|
+ config->hpd_freq[i]);
|
|
|
+ if (ret)
|
|
|
+ dev_warn(dev,
|
|
|
+ "failed to set clk %s (%d)\n",
|
|
|
+ config->hpd_clk_names[i], ret);
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = clk_prepare_enable(hdmi->hpd_clks[i]);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev,
|
|
|
+ "failed to enable hpd clk: %s (%d)\n",
|
|
|
+ config->hpd_clk_names[i], ret);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (i = config->hpd_clk_cnt - 1; i >= 0; i--)
|
|
|
+ clk_disable_unprepare(hdmi->hpd_clks[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int hpd_enable(struct hdmi_connector *hdmi_connector)
|
|
|
{
|
|
|
struct hdmi *hdmi = hdmi_connector->hdmi;
|
|
@@ -167,22 +197,8 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- for (i = 0; i < config->hpd_clk_cnt; i++) {
|
|
|
- if (config->hpd_freq && config->hpd_freq[i]) {
|
|
|
- ret = clk_set_rate(hdmi->hpd_clks[i],
|
|
|
- config->hpd_freq[i]);
|
|
|
- if (ret)
|
|
|
- dev_warn(dev, "failed to set clk %s (%d)\n",
|
|
|
- config->hpd_clk_names[i], ret);
|
|
|
- }
|
|
|
-
|
|
|
- ret = clk_prepare_enable(hdmi->hpd_clks[i]);
|
|
|
- if (ret) {
|
|
|
- dev_err(dev, "failed to enable hpd clk: %s (%d)\n",
|
|
|
- config->hpd_clk_names[i], ret);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
- }
|
|
|
+ pm_runtime_get_sync(dev);
|
|
|
+ enable_hpd_clocks(hdmi, true);
|
|
|
|
|
|
msm_hdmi_set_mode(hdmi, false);
|
|
|
msm_hdmi_phy_reset(hdmi);
|
|
@@ -225,8 +241,8 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
|
|
|
|
|
|
msm_hdmi_set_mode(hdmi, false);
|
|
|
|
|
|
- for (i = 0; i < config->hpd_clk_cnt; i++)
|
|
|
- clk_disable_unprepare(hdmi->hpd_clks[i]);
|
|
|
+ enable_hpd_clocks(hdmi, false);
|
|
|
+ pm_runtime_put_autosuspend(dev);
|
|
|
|
|
|
ret = gpio_config(hdmi, false);
|
|
|
if (ret)
|
|
@@ -285,7 +301,16 @@ void msm_hdmi_connector_irq(struct drm_connector *connector)
|
|
|
|
|
|
static enum drm_connector_status detect_reg(struct hdmi *hdmi)
|
|
|
{
|
|
|
- uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
|
|
|
+ uint32_t hpd_int_status;
|
|
|
+
|
|
|
+ pm_runtime_get_sync(&hdmi->pdev->dev);
|
|
|
+ enable_hpd_clocks(hdmi, true);
|
|
|
+
|
|
|
+ hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
|
|
|
+
|
|
|
+ enable_hpd_clocks(hdmi, false);
|
|
|
+ pm_runtime_put_autosuspend(&hdmi->pdev->dev);
|
|
|
+
|
|
|
return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
|
|
|
connector_status_connected : connector_status_disconnected;
|
|
|
}
|