drm/meson: dw-hdmi: Disable clocks on driver teardown
[ Upstream commit 1dfeea904550c11eccf3fd5f6256e4b0f0208dfe ] 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 Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
ddbed6d027
commit
d0ef2d7940
@@ -145,8 +145,6 @@ struct meson_dw_hdmi {
|
|||||||
struct reset_control *hdmitx_apb;
|
struct reset_control *hdmitx_apb;
|
||||||
struct reset_control *hdmitx_ctrl;
|
struct reset_control *hdmitx_ctrl;
|
||||||
struct reset_control *hdmitx_phy;
|
struct reset_control *hdmitx_phy;
|
||||||
struct clk *hdmi_pclk;
|
|
||||||
struct clk *venci_clk;
|
|
||||||
struct regulator *hdmi_supply;
|
struct regulator *hdmi_supply;
|
||||||
u32 irq_stat;
|
u32 irq_stat;
|
||||||
struct dw_hdmi *hdmi;
|
struct dw_hdmi *hdmi;
|
||||||
@@ -946,6 +944,29 @@ static void meson_disable_regulator(void *data)
|
|||||||
regulator_disable(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,
|
static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
@@ -1026,19 +1047,13 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
|||||||
if (IS_ERR(meson_dw_hdmi->hdmitx))
|
if (IS_ERR(meson_dw_hdmi->hdmitx))
|
||||||
return PTR_ERR(meson_dw_hdmi->hdmitx);
|
return PTR_ERR(meson_dw_hdmi->hdmitx);
|
||||||
|
|
||||||
meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
|
ret = meson_enable_clk(dev, "isfr");
|
||||||
if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
|
if (ret)
|
||||||
dev_err(dev, "Unable to get HDMI pclk\n");
|
return ret;
|
||||||
return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
|
|
||||||
}
|
|
||||||
clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
|
|
||||||
|
|
||||||
meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
|
ret = meson_enable_clk(dev, "venci");
|
||||||
if (IS_ERR(meson_dw_hdmi->venci_clk)) {
|
if (ret)
|
||||||
dev_err(dev, "Unable to get venci clk\n");
|
return ret;
|
||||||
return PTR_ERR(meson_dw_hdmi->venci_clk);
|
|
||||||
}
|
|
||||||
clk_prepare_enable(meson_dw_hdmi->venci_clk);
|
|
||||||
|
|
||||||
dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
|
dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
|
||||||
&meson_dw_hdmi_regmap_config);
|
&meson_dw_hdmi_regmap_config);
|
||||||
|
Reference in New Issue
Block a user