diff options
author | Stefan Potyra <Stefan.Potyra@elektrobit.com> | 2017-12-06 10:03:24 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-12-06 10:25:48 -0500 |
commit | c7b92172a61b91936be985cb9bc499a4ebc6489b (patch) | |
tree | 927cc2940609c0c4e94c52cd7d916ee187774842 | |
parent | 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff) |
ASoC: rockchip: disable clock on error
Disable the clocks in rk_spdif_probe when an error occurs after one
of the clocks has been enabled previously.
Found by Linux Driver Verification project (linuxtesting.org).
Fixes: f874b80e1571 ASoC: rockchip: Add rockchip SPDIF transceiver driver
Signed-off-by: Stefan Potyra <Stefan.Potyra@elektrobit.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/rockchip/rockchip_spdif.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index ee5055d47d13..a89fe9b6463b 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c | |||
@@ -322,26 +322,30 @@ static int rk_spdif_probe(struct platform_device *pdev) | |||
322 | spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); | 322 | spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); |
323 | if (IS_ERR(spdif->mclk)) { | 323 | if (IS_ERR(spdif->mclk)) { |
324 | dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); | 324 | dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); |
325 | return PTR_ERR(spdif->mclk); | 325 | ret = PTR_ERR(spdif->mclk); |
326 | goto err_disable_hclk; | ||
326 | } | 327 | } |
327 | 328 | ||
328 | ret = clk_prepare_enable(spdif->mclk); | 329 | ret = clk_prepare_enable(spdif->mclk); |
329 | if (ret) { | 330 | if (ret) { |
330 | dev_err(spdif->dev, "clock enable failed %d\n", ret); | 331 | dev_err(spdif->dev, "clock enable failed %d\n", ret); |
331 | return ret; | 332 | goto err_disable_clocks; |
332 | } | 333 | } |
333 | 334 | ||
334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 335 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
335 | regs = devm_ioremap_resource(&pdev->dev, res); | 336 | regs = devm_ioremap_resource(&pdev->dev, res); |
336 | if (IS_ERR(regs)) | 337 | if (IS_ERR(regs)) { |
337 | return PTR_ERR(regs); | 338 | ret = PTR_ERR(regs); |
339 | goto err_disable_clocks; | ||
340 | } | ||
338 | 341 | ||
339 | spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, | 342 | spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, |
340 | &rk_spdif_regmap_config); | 343 | &rk_spdif_regmap_config); |
341 | if (IS_ERR(spdif->regmap)) { | 344 | if (IS_ERR(spdif->regmap)) { |
342 | dev_err(&pdev->dev, | 345 | dev_err(&pdev->dev, |
343 | "Failed to initialise managed register map\n"); | 346 | "Failed to initialise managed register map\n"); |
344 | return PTR_ERR(spdif->regmap); | 347 | ret = PTR_ERR(spdif->regmap); |
348 | goto err_disable_clocks; | ||
345 | } | 349 | } |
346 | 350 | ||
347 | spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; | 351 | spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; |
@@ -373,6 +377,10 @@ static int rk_spdif_probe(struct platform_device *pdev) | |||
373 | 377 | ||
374 | err_pm_runtime: | 378 | err_pm_runtime: |
375 | pm_runtime_disable(&pdev->dev); | 379 | pm_runtime_disable(&pdev->dev); |
380 | err_disable_clocks: | ||
381 | clk_disable_unprepare(spdif->mclk); | ||
382 | err_disable_hclk: | ||
383 | clk_disable_unprepare(spdif->hclk); | ||
376 | 384 | ||
377 | return ret; | 385 | return ret; |
378 | } | 386 | } |