diff options
| author | Mark Brown <broonie@kernel.org> | 2025-10-30 19:07:15 +0300 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2025-10-30 19:07:15 +0300 |
| commit | db66398fb03ee3599ec7387ceb5121b95e648eb3 (patch) | |
| tree | e5cabf4ac92400f4690ebae4de2240779ecf2ed4 | |
| parent | 3d8096fd378b0b4dae356e6f037d03da83f559d2 (diff) | |
| parent | cf6bf51b53252284bafc7377a4d8dbf10f048b4d (diff) | |
| download | linux-db66398fb03ee3599ec7387ceb5121b95e648eb3.tar.xz | |
Add support for an external Master Clock in the
Merge series from Herve Codina <herve.codina@bootlin.com>:
The Cirrus CS4271 codec can have its Master Clock provided by an
external clock when no crystal is used.
This series adds support for this external Master clock.
| -rw-r--r-- | Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml | 10 | ||||
| -rw-r--r-- | sound/soc/codecs/cs4271.c | 33 |
2 files changed, 40 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml index 68fbf5cc208f..d286eb169915 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml @@ -25,6 +25,16 @@ properties: reg: maxItems: 1 + clocks: + items: + - description: + Master clock connected to the MCLK pin if MCLK is an input (i.e. no + crystal used). + + clock-names: + items: + - const: mclk + spi-cpha: true spi-cpol: true diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 0ed73ba3625c..a24e926ba282 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -10,6 +10,7 @@ * DAPM support not implemented. */ +#include <linux/clk.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/delay.h> @@ -163,6 +164,7 @@ struct cs4271_private { /* enable soft reset workaround */ bool enable_soft_reset; struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; + struct clk *clk; }; static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = { @@ -505,6 +507,7 @@ static int cs4271_soc_suspend(struct snd_soc_component *component) return ret; regcache_mark_dirty(cs4271->regmap); + clk_disable_unprepare(cs4271->clk); regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); return 0; @@ -522,6 +525,12 @@ static int cs4271_soc_resume(struct snd_soc_component *component) return ret; } + ret = clk_prepare_enable(cs4271->clk); + if (ret) { + dev_err(component->dev, "Failed to enable clk: %d\n", ret); + return ret; + } + /* Do a proper reset after power up */ cs4271_reset(component); @@ -576,22 +585,29 @@ static int cs4271_component_probe(struct snd_soc_component *component) cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; } + ret = clk_prepare_enable(cs4271->clk); + if (ret) { + dev_err(component->dev, "Failed to enable clk: %d\n", ret); + goto err_disable_regulators; + } + /* Reset codec */ cs4271_reset(component); ret = regcache_sync(cs4271->regmap); if (ret < 0) - return ret; + goto err_disable_clk; ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN | CS4271_MODE2_CPEN, CS4271_MODE2_PDN | CS4271_MODE2_CPEN); if (ret < 0) - return ret; + goto err_disable_clk; ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN, 0); if (ret < 0) - return ret; + goto err_disable_clk; + /* Power-up sequence requires 85 uS */ udelay(85); @@ -601,6 +617,12 @@ static int cs4271_component_probe(struct snd_soc_component *component) CS4271_MODE2_MUTECAEQUB); return 0; + +err_disable_clk: + clk_disable_unprepare(cs4271->clk); +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); + return ret; } static void cs4271_component_remove(struct snd_soc_component *component) @@ -612,6 +634,7 @@ static void cs4271_component_remove(struct snd_soc_component *component) regcache_mark_dirty(cs4271->regmap); regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); + clk_disable_unprepare(cs4271->clk); }; static const struct snd_soc_component_driver soc_component_dev_cs4271 = { @@ -646,6 +669,10 @@ static int cs4271_common_probe(struct device *dev, "error retrieving RESET GPIO\n"); gpiod_set_consumer_name(cs4271->reset, "CS4271 Reset"); + cs4271->clk = devm_clk_get_optional(dev, "mclk"); + if (IS_ERR(cs4271->clk)) + return dev_err_probe(dev, PTR_ERR(cs4271->clk), "Failed to get mclk\n"); + for (i = 0; i < ARRAY_SIZE(supply_names); i++) cs4271->supplies[i].supply = supply_names[i]; |
