diff options
Diffstat (limited to 'drivers/gpu/drm/msm/hdmi')
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 64 |
3 files changed, 51 insertions, 21 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index a968cad509c2..17e069a133a4 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -239,6 +239,8 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->pwr_clks[i] = clk; } + pm_runtime_enable(&pdev->dev); + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); hdmi->i2c = msm_hdmi_i2c_init(hdmi); diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index ae40e7179d4f..7e357077ed26 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -35,6 +35,8 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) const struct hdmi_platform_config *config = hdmi->config; int i, ret; + pm_runtime_get_sync(&hdmi->pdev->dev); + for (i = 0; i < config->pwr_reg_cnt; i++) { ret = regulator_enable(hdmi->pwr_regs[i]); if (ret) { @@ -84,6 +86,8 @@ static void power_off(struct drm_bridge *bridge) config->pwr_reg_names[i], ret); } } + + pm_runtime_put_autosuspend(&hdmi->pdev->dev); } #define AVI_IFRAME_LINE_NUMBER 1 @@ -97,7 +101,7 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) u32 val; int len; - drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); + drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer)); if (len < 0) { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index a2515b466ce5..c0848dfedd50 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -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; } @@ -407,7 +432,6 @@ static int msm_hdmi_connector_mode_valid(struct drm_connector *connector, } static const struct drm_connector_funcs hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .detect = hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = hdmi_connector_destroy, |