Commit 411efa18 authored by Maxime Ripard's avatar Maxime Ripard

drm/vc4: hdmi: Move the HSM clock enable to runtime_pm

In order to access the HDMI controller, we need to make sure the HSM
clock is enabled. If we were to access it with the clock disabled, the
CPU would completely hang, resulting in an hard crash.

Since we have different code path that would require it, let's move that
clock enable / disable to runtime_pm that will take care of the
reference counting for us.

Fixes: 4f6e3d66 ("drm/vc4: Add runtime PM support to the HDMI encoder driver")
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Reviewed-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210525091059.234116-3-maxime@cerno.tech
parent c336a5ee
...@@ -473,7 +473,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, ...@@ -473,7 +473,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
clk_disable_unprepare(vc4_hdmi->hsm_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock);
ret = pm_runtime_put(&vc4_hdmi->pdev->dev); ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
...@@ -784,13 +783,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, ...@@ -784,13 +783,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
return; return;
} }
ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
if (ret) {
DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
clk_disable_unprepare(vc4_hdmi->pixel_clock);
return;
}
vc4_hdmi_cec_update_clk_div(vc4_hdmi); vc4_hdmi_cec_update_clk_div(vc4_hdmi);
/* /*
...@@ -801,7 +793,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, ...@@ -801,7 +793,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
(hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000)); (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000));
if (ret) { if (ret) {
DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
clk_disable_unprepare(vc4_hdmi->hsm_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock);
return; return;
} }
...@@ -809,7 +800,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, ...@@ -809,7 +800,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
if (ret) { if (ret) {
DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
clk_disable_unprepare(vc4_hdmi->hsm_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock);
return; return;
} }
...@@ -1929,6 +1919,29 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) ...@@ -1929,6 +1919,29 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int vc4_hdmi_runtime_suspend(struct device *dev)
{
struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
clk_disable_unprepare(vc4_hdmi->hsm_clock);
return 0;
}
static int vc4_hdmi_runtime_resume(struct device *dev)
{
struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
if (ret)
return ret;
return 0;
}
#endif
static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{ {
const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
...@@ -2165,11 +2178,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = { ...@@ -2165,11 +2178,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = {
{} {}
}; };
static const struct dev_pm_ops vc4_hdmi_pm_ops = {
SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend,
vc4_hdmi_runtime_resume,
NULL)
};
struct platform_driver vc4_hdmi_driver = { struct platform_driver vc4_hdmi_driver = {
.probe = vc4_hdmi_dev_probe, .probe = vc4_hdmi_dev_probe,
.remove = vc4_hdmi_dev_remove, .remove = vc4_hdmi_dev_remove,
.driver = { .driver = {
.name = "vc4_hdmi", .name = "vc4_hdmi",
.of_match_table = vc4_hdmi_dt_match, .of_match_table = vc4_hdmi_dt_match,
.pm = &vc4_hdmi_pm_ops,
}, },
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment