Skip to content

Commit

Permalink
drm/meson: dw-hdmi: Disable clocks on driver teardown
Browse files Browse the repository at this point in the history
The HDMI driver request clocks early, but never disable them, leaving
the clocks on even when the driver is removed.

Fix it by slightly refactoring the clock code, and register a devm
action that will eventually disable/unprepare the enabled clocks.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201120094205.525228-2-maz@kernel.org
  • Loading branch information
Marc Zyngier authored and Neil Armstrong committed Nov 20, 2020
1 parent f0aee45 commit 1dfeea9
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions drivers/gpu/drm/meson/meson_dw_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ struct meson_dw_hdmi {
struct reset_control *hdmitx_apb;
struct reset_control *hdmitx_ctrl;
struct reset_control *hdmitx_phy;
struct clk *hdmi_pclk;
struct clk *venci_clk;
struct regulator *hdmi_supply;
u32 irq_stat;
struct dw_hdmi *hdmi;
Expand Down Expand Up @@ -946,6 +944,29 @@ static void meson_disable_regulator(void *data)
regulator_disable(data);
}

static void meson_disable_clk(void *data)
{
clk_disable_unprepare(data);
}

static int meson_enable_clk(struct device *dev, char *name)
{
struct clk *clk;
int ret;

clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
dev_err(dev, "Unable to get %s pclk\n", name);
return PTR_ERR(clk);
}

ret = clk_prepare_enable(clk);
if (!ret)
ret = devm_add_action_or_reset(dev, meson_disable_clk, clk);

return ret;
}

static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
void *data)
{
Expand Down Expand Up @@ -1026,19 +1047,13 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
if (IS_ERR(meson_dw_hdmi->hdmitx))
return PTR_ERR(meson_dw_hdmi->hdmitx);

meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
dev_err(dev, "Unable to get HDMI pclk\n");
return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
}
clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
ret = meson_enable_clk(dev, "isfr");
if (ret)
return ret;

meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
if (IS_ERR(meson_dw_hdmi->venci_clk)) {
dev_err(dev, "Unable to get venci clk\n");
return PTR_ERR(meson_dw_hdmi->venci_clk);
}
clk_prepare_enable(meson_dw_hdmi->venci_clk);
ret = meson_enable_clk(dev, "venci");
if (ret)
return ret;

dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
&meson_dw_hdmi_regmap_config);
Expand Down

0 comments on commit 1dfeea9

Please sign in to comment.