134 lines
4.1 KiB
Diff
134 lines
4.1 KiB
Diff
|
From d713ab9c0b469ce41e3a3caef4b67b401b274753 Mon Sep 17 00:00:00 2001
|
||
|
From: Samuel Holland <samuel@sholland.org>
|
||
|
Date: Sat, 26 Sep 2020 20:56:18 -0500
|
||
|
Subject: [PATCH 257/469] ASoC: sun8i-codec: Enable bus clock at STANDBY and
|
||
|
higher bias
|
||
|
|
||
|
For codec variants that have a bus clock, that clock must be running to
|
||
|
receive interrupts. Since jack and mic accessory detection should work
|
||
|
even when no audio is playing, that means the bus clock should be
|
||
|
enabled any time the system is on.
|
||
|
|
||
|
Accomplish that by tying the bus clock to the runtime PM state, which is
|
||
|
then tied to the bias level not being OFF. Since the codec sets
|
||
|
idle_bias_on, bias will generally never be OFF. However, we can set
|
||
|
suspend_bias_off to maintain the power savings of gating the bus clock
|
||
|
during suspend, when we don't expect jack/accessory detection to work.
|
||
|
|
||
|
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||
|
---
|
||
|
sound/soc/sunxi/sun8i-codec.c | 41 ++++++++++++++++++++++++++++-------
|
||
|
1 file changed, 33 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
|
||
|
index 4c0d0d7d3e58..ef995ff5353b 100644
|
||
|
--- a/sound/soc/sunxi/sun8i-codec.c
|
||
|
+++ b/sound/soc/sunxi/sun8i-codec.c
|
||
|
@@ -177,12 +177,14 @@ struct sun8i_codec_aif {
|
||
|
};
|
||
|
|
||
|
struct sun8i_codec_quirks {
|
||
|
- bool legacy_widgets : 1;
|
||
|
- bool lrck_inversion : 1;
|
||
|
+ bool bus_clock : 1;
|
||
|
+ bool legacy_widgets : 1;
|
||
|
+ bool lrck_inversion : 1;
|
||
|
};
|
||
|
|
||
|
struct sun8i_codec {
|
||
|
struct regmap *regmap;
|
||
|
+ struct clk *clk_bus;
|
||
|
struct clk *clk_module;
|
||
|
const struct sun8i_codec_quirks *quirks;
|
||
|
struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS];
|
||
|
@@ -197,6 +199,14 @@ static int sun8i_codec_runtime_resume(struct device *dev)
|
||
|
struct sun8i_codec *scodec = dev_get_drvdata(dev);
|
||
|
int ret;
|
||
|
|
||
|
+ if (scodec->clk_bus) {
|
||
|
+ ret = clk_prepare_enable(scodec->clk_bus);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "Failed to enable the bus clock\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
regcache_cache_only(scodec->regmap, false);
|
||
|
|
||
|
ret = regcache_sync(scodec->regmap);
|
||
|
@@ -215,6 +225,9 @@ static int sun8i_codec_runtime_suspend(struct device *dev)
|
||
|
regcache_cache_only(scodec->regmap, true);
|
||
|
regcache_mark_dirty(scodec->regmap);
|
||
|
|
||
|
+ if (scodec->clk_bus)
|
||
|
+ clk_disable_unprepare(scodec->clk_bus);
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -1277,6 +1290,7 @@ static const struct snd_soc_component_driver sun8i_soc_component = {
|
||
|
.num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes),
|
||
|
.probe = sun8i_codec_component_probe,
|
||
|
.idle_bias_on = 1,
|
||
|
+ .suspend_bias_off = 1,
|
||
|
.endianness = 1,
|
||
|
};
|
||
|
|
||
|
@@ -1299,6 +1313,18 @@ static int sun8i_codec_probe(struct platform_device *pdev)
|
||
|
if (!scodec)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
+ scodec->quirks = of_device_get_match_data(&pdev->dev);
|
||
|
+
|
||
|
+ platform_set_drvdata(pdev, scodec);
|
||
|
+
|
||
|
+ if (scodec->quirks->bus_clock) {
|
||
|
+ scodec->clk_bus = devm_clk_get(&pdev->dev, "bus");
|
||
|
+ if (IS_ERR(scodec->clk_bus)) {
|
||
|
+ dev_err(&pdev->dev, "Failed to get the bus clock\n");
|
||
|
+ return PTR_ERR(scodec->clk_bus);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
scodec->clk_module = devm_clk_get(&pdev->dev, "mod");
|
||
|
if (IS_ERR(scodec->clk_module)) {
|
||
|
dev_err(&pdev->dev, "Failed to get the module clock\n");
|
||
|
@@ -1311,17 +1337,14 @@ static int sun8i_codec_probe(struct platform_device *pdev)
|
||
|
return PTR_ERR(base);
|
||
|
}
|
||
|
|
||
|
- scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base,
|
||
|
- &sun8i_codec_regmap_config);
|
||
|
+ scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||
|
+ &sun8i_codec_regmap_config);
|
||
|
if (IS_ERR(scodec->regmap)) {
|
||
|
dev_err(&pdev->dev, "Failed to create our regmap\n");
|
||
|
return PTR_ERR(scodec->regmap);
|
||
|
}
|
||
|
|
||
|
- scodec->quirks = of_device_get_match_data(&pdev->dev);
|
||
|
-
|
||
|
- platform_set_drvdata(pdev, scodec);
|
||
|
-
|
||
|
+ regcache_cache_only(scodec->regmap, true);
|
||
|
pm_runtime_enable(&pdev->dev);
|
||
|
if (!pm_runtime_enabled(&pdev->dev)) {
|
||
|
ret = sun8i_codec_runtime_resume(&pdev->dev);
|
||
|
@@ -1357,11 +1380,13 @@ static void sun8i_codec_remove(struct platform_device *pdev)
|
||
|
}
|
||
|
|
||
|
static const struct sun8i_codec_quirks sun8i_a33_quirks = {
|
||
|
+ .bus_clock = true,
|
||
|
.legacy_widgets = true,
|
||
|
.lrck_inversion = true,
|
||
|
};
|
||
|
|
||
|
static const struct sun8i_codec_quirks sun50i_a64_quirks = {
|
||
|
+ .bus_clock = true,
|
||
|
};
|
||
|
|
||
|
static const struct of_device_id sun8i_codec_of_match[] = {
|
||
|
--
|
||
|
2.34.1
|
||
|
|