From 7a117225b15b2d1dc021ab9fc36687c1e61ad2b1 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 7 Nov 2024 15:49:57 +0200 Subject: [PATCH 01/16] ASoC: SOF: Intel: hda: handle only paused streams in hda_dai_suspend() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit hda_dai_suspend() was added to handle paused stream during system suspend. But as a side effect, it also ends up cleaning up the DMA data for those streams that were prepared but not triggered before a system suspend. Since these streams will not receive the prepare callback after resuming, we need to preserve the DMA data during suspend. So, add the check to handle only those streams that are in the paused state to avoid losing the DMA data for all other streams. Link: https://github.com/thesofproject/linux/issues/5080 Signed-off-by: Ranjani Sridharan Reviewed-by: Fred Oh Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Peter Ujfalusi Link: https://patch.msgid.link/20241107134957.25160-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 1c823f9eea57..f1a8491bba9e 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -617,6 +617,10 @@ static int hda_dai_suspend(struct hdac_bus *bus) sdai = swidget->private; ops = sdai->platform_private; + if (rtd->dpcm[hext_stream->link_substream->stream].state != + SND_SOC_DPCM_STATE_PAUSED) + continue; + /* for consistency with TRIGGER_SUSPEND */ if (ops->post_trigger) { ret = ops->post_trigger(sdev, cpu_dai, -- 2.51.0 From fa24fdc8ae9e6f6fe7a4f7676a4d8c14433a86c0 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Thu, 7 Nov 2024 15:54:40 +0800 Subject: [PATCH 02/16] ASoC: ux500: Remove redundant casts In the function ux500_msp_drv_probe, the 'int' type cast in front of the PTR_ERR() macro is redundant, thus remove it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20241107075440.2770-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index a2dd739fdf2d..7798957c6504 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -733,7 +733,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape"); if (IS_ERR(drvdata->reg_vape)) { - ret = (int)PTR_ERR(drvdata->reg_vape); + ret = PTR_ERR(drvdata->reg_vape); dev_err(&pdev->dev, "%s: ERROR: Failed to get Vape supply (%d)!\n", __func__, ret); @@ -743,7 +743,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(drvdata->pclk)) { - ret = (int)PTR_ERR(drvdata->pclk); + ret = PTR_ERR(drvdata->pclk); dev_err(&pdev->dev, "%s: ERROR: devm_clk_get of pclk failed (%d)!\n", __func__, ret); @@ -752,7 +752,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev) drvdata->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(drvdata->clk)) { - ret = (int)PTR_ERR(drvdata->clk); + ret = PTR_ERR(drvdata->clk); dev_err(&pdev->dev, "%s: ERROR: devm_clk_get failed (%d)!\n", __func__, ret); -- 2.51.0 From 8509bb1f11a1fed710271631c2e06fd66452f510 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 7 Nov 2024 16:51:41 +0100 Subject: [PATCH 03/16] ASoC: dt-bindings: add stm32mp25 support for sai Add STM32MP25 support for STM32 SAI peripheral, through "st,stm32mp25-sai" compatible. Signed-off-by: Olivier Moysan Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241107155143.1340523-2-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- .../bindings/sound/st,stm32-sai.yaml | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml index 68f97b462598..4a7129d0b157 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml @@ -20,6 +20,7 @@ properties: enum: - st,stm32f4-sai - st,stm32h7-sai + - st,stm32mp25-sai reg: items: @@ -43,9 +44,11 @@ properties: const: 1 clocks: + minItems: 1 maxItems: 3 clock-names: + minItems: 1 maxItems: 3 access-controllers: @@ -156,7 +159,13 @@ allOf: items: - const: x8k - const: x11k - else: + + - if: + properties: + compatible: + contains: + const: st,stm32mph7-sai + then: properties: clocks: items: @@ -170,6 +179,21 @@ allOf: - const: x8k - const: x11k + - if: + properties: + compatible: + contains: + const: st,stm32mp25-sai + then: + properties: + clocks: + items: + - description: pclk feeds the peripheral bus interface. + + clock-names: + items: + - const: pclk + additionalProperties: false examples: -- 2.51.0 From 2cfe1ff22555717bf63526f9e6ea096dde13cc59 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 7 Nov 2024 16:51:42 +0100 Subject: [PATCH 04/16] ASoC: stm32: sai: add stm32mp25 support Add STM32MP25 support for STM32 SAI. On STM32MP25 the SAI driver does not manage SAI kernel clock rate by chosing its parent clock, dependending on audio stream rate. The driver requests a rate change on SAI kernel clock instead. This rate change is performed with the following guidelines: - Chose highest rate multiple of the audio stream (Try to get clock accuracy within 1000 ppm) - Ensure clock rate compatibility between SAI sub-blocks A&B and between instances sharing the same flexgen. Use clk_rate_exclusive API to fulfill this requirement. The STM32 SAI peripheral does not support the DMA burst mode on STM32MP25. Add a field in compatible structure to manage DMA burst support capability. Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20241107155143.1340523-3-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 58 +++++++++++--- sound/soc/stm/stm32_sai.h | 6 ++ sound/soc/stm/stm32_sai_sub.c | 144 ++++++++++++++++++++++++++++++++-- 3 files changed, 191 insertions(+), 17 deletions(-) diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index b45ee7e24f22..bc8180fc8462 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -19,26 +19,42 @@ #include "stm32_sai.h" +static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai); + static const struct stm32_sai_conf stm32_sai_conf_f4 = { .version = STM_SAI_STM32F4, .fifo_size = 8, .has_spdif_pdm = false, + .get_sai_ck_parent = stm32_sai_get_parent_clk, }; /* - * Default settings for stm32 H7 socs and next. + * Default settings for STM32H7x socs and STM32MP1x. * These default settings will be overridden if the soc provides * support of hardware configuration registers. + * - STM32H7: rely on default settings + * - STM32MP1: retrieve settings from registers */ static const struct stm32_sai_conf stm32_sai_conf_h7 = { .version = STM_SAI_STM32H7, .fifo_size = 8, .has_spdif_pdm = true, + .get_sai_ck_parent = stm32_sai_get_parent_clk, +}; + +/* + * STM32MP2x: + * - do not use SAI parent clock source selection + * - do not use DMA burst mode + */ +static const struct stm32_sai_conf stm32_sai_conf_mp25 = { + .no_dma_burst = true, }; static const struct of_device_id stm32_sai_ids[] = { { .compatible = "st,stm32f4-sai", .data = (void *)&stm32_sai_conf_f4 }, { .compatible = "st,stm32h7-sai", .data = (void *)&stm32_sai_conf_h7 }, + { .compatible = "st,stm32mp25-sai", .data = (void *)&stm32_sai_conf_mp25 }, {} }; @@ -148,6 +164,29 @@ error: return ret; } +static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai) +{ + struct device *dev = &sai->pdev->dev; + + sai->clk_x8k = devm_clk_get(dev, "x8k"); + if (IS_ERR(sai->clk_x8k)) { + if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER) + dev_err(dev, "missing x8k parent clock: %ld\n", + PTR_ERR(sai->clk_x8k)); + return PTR_ERR(sai->clk_x8k); + } + + sai->clk_x11k = devm_clk_get(dev, "x11k"); + if (IS_ERR(sai->clk_x11k)) { + if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER) + dev_err(dev, "missing x11k parent clock: %ld\n", + PTR_ERR(sai->clk_x11k)); + return PTR_ERR(sai->clk_x11k); + } + + return 0; +} + static int stm32_sai_probe(struct platform_device *pdev) { struct stm32_sai_data *sai; @@ -160,6 +199,8 @@ static int stm32_sai_probe(struct platform_device *pdev) if (!sai) return -ENOMEM; + sai->pdev = pdev; + sai->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sai->base)) return PTR_ERR(sai->base); @@ -178,15 +219,11 @@ static int stm32_sai_probe(struct platform_device *pdev) "missing bus clock pclk\n"); } - sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(sai->clk_x8k)) - return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x8k), - "missing x8k parent clock\n"); - - sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(sai->clk_x11k)) - return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x11k), - "missing x11k parent clock\n"); + if (sai->conf.get_sai_ck_parent) { + ret = sai->conf.get_sai_ck_parent(sai); + if (ret) + return ret; + } /* init irqs */ sai->irq = platform_get_irq(pdev, 0); @@ -227,7 +264,6 @@ static int stm32_sai_probe(struct platform_device *pdev) } clk_disable_unprepare(sai->pclk); - sai->pdev = pdev; sai->set_sync = &stm32_sai_set_sync; platform_set_drvdata(pdev, sai); diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h index 33e4bff8c2f5..07b71133db2a 100644 --- a/sound/soc/stm/stm32_sai.h +++ b/sound/soc/stm/stm32_sai.h @@ -264,16 +264,22 @@ enum stm32_sai_syncout { STM_SAI_SYNC_OUT_B, }; +struct stm32_sai_data; + /** * struct stm32_sai_conf - SAI configuration + * @get_sai_ck_parent: get parent clock of SAI kernel clock * @version: SAI version * @fifo_size: SAI fifo size as words number * @has_spdif_pdm: SAI S/PDIF and PDM features support flag + * @no_dma_burst: Support only DMA single transfers if set */ struct stm32_sai_conf { + int (*get_sai_ck_parent)(struct stm32_sai_data *sai); u32 version; u32 fifo_size; bool has_spdif_pdm; + bool no_dma_burst; }; /** diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index a772bc8ea7be..27b7fdef7cb0 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -60,6 +60,9 @@ #define SAI_MCLK_NAME_LEN 32 #define SAI_RATE_11K 11025 +#define SAI_MAX_SAMPLE_RATE_8K 192000 +#define SAI_MAX_SAMPLE_RATE_11K 176400 +#define SAI_CK_RATE_TOLERANCE 1000 /* ppm */ /** * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) @@ -80,6 +83,7 @@ * @dir: SAI block direction (playback or capture). set at init * @master: SAI block mode flag. (true=master, false=slave) set at init * @spdif: SAI S/PDIF iec60958 mode flag. set at init + * @sai_ck_used: flag set while exclusivity on SAI kernel clock is active * @fmt: SAI block format. relevant only for custom protocols. set at init * @sync: SAI block synchronization mode. (none, internal or external) * @synco: SAI block ext sync source (provider setting). (none, sub-block A/B) @@ -93,6 +97,8 @@ * @iec958: iec958 data * @ctrl_lock: control lock * @irq_lock: prevent race condition with IRQ + * @set_sai_ck_rate: set SAI kernel clock rate + * @put_sai_ck_rate: put SAI kernel clock rate */ struct stm32_sai_sub_data { struct platform_device *pdev; @@ -112,6 +118,7 @@ struct stm32_sai_sub_data { int dir; bool master; bool spdif; + bool sai_ck_used; int fmt; int sync; int synco; @@ -125,6 +132,8 @@ struct stm32_sai_sub_data { struct snd_aes_iec958 iec958; struct mutex ctrl_lock; /* protect resources accessed by controls */ spinlock_t irq_lock; /* used to prevent race condition with IRQ */ + int (*set_sai_ck_rate)(struct stm32_sai_sub_data *sai, unsigned int rate); + void (*put_sai_ck_rate)(struct stm32_sai_sub_data *sai); }; enum stm32_sai_fifo_th { @@ -351,8 +360,26 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai, return ret; } -static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai, - unsigned int rate) +static bool stm32_sai_rate_accurate(unsigned int max_rate, unsigned int rate) +{ + u64 delta, dividend; + int ratio; + + ratio = DIV_ROUND_CLOSEST(max_rate, rate); + if (!ratio) + return false; + + dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate))); + delta = div_u64(dividend, max_rate); + + if (delta <= SAI_CK_RATE_TOLERANCE) + return true; + + return false; +} + +static int stm32_sai_set_parent_clk(struct stm32_sai_sub_data *sai, + unsigned int rate) { struct platform_device *pdev = sai->pdev; struct clk *parent_clk = sai->pdata->clk_x8k; @@ -370,6 +397,92 @@ static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai, return ret; } +static void stm32_sai_put_parent_rate(struct stm32_sai_sub_data *sai) +{ + if (sai->sai_ck_used) { + sai->sai_ck_used = false; + clk_rate_exclusive_put(sai->sai_ck); + } +} + +static int stm32_sai_set_parent_rate(struct stm32_sai_sub_data *sai, + unsigned int rate) +{ + struct platform_device *pdev = sai->pdev; + unsigned int sai_ck_rate, sai_ck_max_rate, sai_curr_rate, sai_new_rate; + int div, ret; + + /* + * Set maximum expected kernel clock frequency + * - mclk on or spdif: + * f_sai_ck = MCKDIV * mclk-fs * fs + * Here typical 256 ratio is assumed for mclk-fs + * - mclk off: + * f_sai_ck = MCKDIV * FRL * fs + * Where FRL=[8..256], MCKDIV=[1..n] (n depends on SAI version) + * Set constraint MCKDIV * FRL <= 256, to ensure MCKDIV is in available range + * f_sai_ck = sai_ck_max_rate * pow_of_two(FRL) / 256 + */ + if (!(rate % SAI_RATE_11K)) + sai_ck_max_rate = SAI_MAX_SAMPLE_RATE_11K * 256; + else + sai_ck_max_rate = SAI_MAX_SAMPLE_RATE_8K * 256; + + if (!sai->sai_mclk && !STM_SAI_PROTOCOL_IS_SPDIF(sai)) + sai_ck_max_rate /= DIV_ROUND_CLOSEST(256, roundup_pow_of_two(sai->fs_length)); + + /* + * Request exclusivity, as the clock is shared by SAI sub-blocks and by + * some SAI instances. This allows to ensure that the rate cannot be + * changed while one or more SAIs are using the clock. + */ + clk_rate_exclusive_get(sai->sai_ck); + sai->sai_ck_used = true; + + /* + * Check current kernel clock rate. If it gives the expected accuracy + * return immediately. + */ + sai_curr_rate = clk_get_rate(sai->sai_ck); + if (stm32_sai_rate_accurate(sai_ck_max_rate, sai_curr_rate)) + return 0; + + /* + * Otherwise try to set the maximum rate and check the new actual rate. + * If the new rate does not give the expected accuracy, try to set + * lower rates for the kernel clock. + */ + sai_ck_rate = sai_ck_max_rate; + div = 1; + do { + /* Check new rate accuracy. Return if ok */ + sai_new_rate = clk_round_rate(sai->sai_ck, sai_ck_rate); + if (stm32_sai_rate_accurate(sai_ck_rate, sai_new_rate)) { + ret = clk_set_rate(sai->sai_ck, sai_ck_rate); + if (ret) { + dev_err(&pdev->dev, "Error %d setting sai_ck rate. %s", + ret, ret == -EBUSY ? + "Active stream rates may be in conflict\n" : "\n"); + goto err; + } + + return 0; + } + + /* Try a lower frequency */ + div++; + sai_ck_rate = sai_ck_max_rate / div; + } while (sai_ck_rate > rate); + + /* No accurate rate found */ + dev_err(&pdev->dev, "Failed to find an accurate rate"); + +err: + stm32_sai_put_parent_rate(sai); + + return -EINVAL; +} + static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { @@ -565,11 +678,15 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, clk_rate_exclusive_put(sai->sai_mclk); sai->mclk_rate = 0; } + + if (sai->put_sai_ck_rate) + sai->put_sai_ck_rate(sai); + return 0; } - /* If master clock is used, set parent clock now */ - ret = stm32_sai_set_parent_clock(sai, freq); + /* If master clock is used, configure SAI kernel clock now */ + ret = sai->set_sai_ck_rate(sai, freq); if (ret) return ret; @@ -993,7 +1110,7 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, int ret; if (!sai->sai_mclk) { - ret = stm32_sai_set_parent_clock(sai, rate); + ret = sai->set_sai_ck_rate(sai, rate); if (ret) return ret; } @@ -1154,6 +1271,14 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(sai->sai_ck); + /* + * Release kernel clock if following conditions are fulfilled + * - Master clock is not used. Kernel clock won't be released trough sysclk + * - Put handler is defined. Involve that clock is managed exclusively + */ + if (!sai->sai_mclk && sai->put_sai_ck_rate) + sai->put_sai_ck_rate(sai); + spin_lock_irqsave(&sai->irq_lock, flags); sai->substream = NULL; spin_unlock_irqrestore(&sai->irq_lock, flags); @@ -1188,7 +1313,7 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai) * constraints). */ sai->dma_params.maxburst = 4; - if (sai->pdata->conf.fifo_size < 8) + if (sai->pdata->conf.fifo_size < 8 || sai->pdata->conf.no_dma_burst) sai->dma_params.maxburst = 1; /* Buswidth will be set by framework at runtime */ sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; @@ -1526,6 +1651,13 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) return -EINVAL; } + if (sai->pdata->conf.get_sai_ck_parent) { + sai->set_sai_ck_rate = stm32_sai_set_parent_clk; + } else { + sai->set_sai_ck_rate = stm32_sai_set_parent_rate; + sai->put_sai_ck_rate = stm32_sai_put_parent_rate; + } + ret = stm32_sai_sub_parse_of(pdev, sai); if (ret) return ret; -- 2.51.0 From c69b7edc10d2fff4bcb3dd464ee26cbf22818fec Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 7 Nov 2024 15:47:11 +0100 Subject: [PATCH 05/16] ASoC: dt-bindings: add stm32mp25 support for i2s Add STM32MP25 support for STM32 I2S peripheral, through "st,stm32mp25-i2s" compatible. Signed-off-by: Olivier Moysan Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241107144712.1305638-2-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- .../bindings/sound/st,stm32-i2s.yaml | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml index 8978f6bd63e5..b4f44f9c7c7d 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml @@ -13,13 +13,11 @@ description: The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. Only some SPI instances support I2S. -allOf: - - $ref: dai-common.yaml# - properties: compatible: enum: - st,stm32h7-i2s + - st,stm32mp25-i2s "#sound-dai-cells": const: 0 @@ -33,6 +31,7 @@ properties: - description: clock feeding the internal clock generator. - description: I2S parent clock for sampling rates multiple of 8kHz. - description: I2S parent clock for sampling rates multiple of 11.025kHz. + minItems: 2 clock-names: items: @@ -40,6 +39,7 @@ properties: - const: i2sclk - const: x8k - const: x11k + minItems: 2 interrupts: maxItems: 1 @@ -79,6 +79,36 @@ required: - dmas - dma-names +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + contains: + const: st,stm32h7-i2s + + then: + properties: + clocks: + minItems: 4 + + clock-names: + minItems: 4 + + - if: + properties: + compatible: + contains: + const: st,stm32mp25-i2s + + then: + properties: + clocks: + maxItems: 2 + + clock-names: + maxItems: 2 + unevaluatedProperties: false examples: -- 2.51.0 From 20bf873dcc860507965077ab73bfd4335314b6e2 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 7 Nov 2024 15:47:12 +0100 Subject: [PATCH 06/16] ASoC: stm32: i2s: add stm32mp25 support Add STM32MP25 support for STM32 I2S. On STM32MP25 the I2S driver does not manage I2S kernel clock rate by choosing its parent clock, depending on audio stream rate. The driver requests a rate change on I2S kernel clock instead. It tries to set the higher possible rate, which is a multiple of the audio stream rate and which gives an accuracy of at least 1000 ppm. Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20241107144712.1305638-3-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 211 ++++++++++++++++++++++++++++++++++---- 1 file changed, 189 insertions(+), 22 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index faa00103ee7f..19dc61008a75 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -200,10 +200,13 @@ enum i2s_datlen { #define STM32_I2S_NAME_LEN 32 #define STM32_I2S_RATE_11K 11025 +#define STM32_I2S_MAX_SAMPLE_RATE_8K 192000 +#define STM32_I2S_MAX_SAMPLE_RATE_11K 176400 +#define STM32_I2S_CLK_RATE_TOLERANCE 1000 /* ppm */ /** * struct stm32_i2s_data - private data of I2S - * @regmap_conf: I2S register map configuration pointer + * @conf: I2S configuration pointer * @regmap: I2S register map pointer * @pdev: device data pointer * @dai_drv: DAI driver pointer @@ -224,11 +227,14 @@ enum i2s_datlen { * @divider: prescaler division ratio * @div: prescaler div field * @odd: prescaler odd field + * @i2s_clk_flg: flag set while exclusivity on I2S kernel clock is active * @refcount: keep count of opened streams on I2S * @ms_flg: master mode flag. + * @set_i2s_clk_rate: set I2S kernel clock rate + * @put_i2s_clk_rate: put I2S kernel clock rate */ struct stm32_i2s_data { - const struct regmap_config *regmap_conf; + const struct stm32_i2s_conf *conf; struct regmap *regmap; struct platform_device *pdev; struct snd_soc_dai_driver *dai_drv; @@ -249,8 +255,21 @@ struct stm32_i2s_data { unsigned int divider; unsigned int div; bool odd; + bool i2s_clk_flg; int refcount; int ms_flg; + int (*set_i2s_clk_rate)(struct stm32_i2s_data *i2s, unsigned int rate); + void (*put_i2s_clk_rate)(struct stm32_i2s_data *i2s); +}; + +/** + * struct stm32_i2s_conf - I2S configuration + * @regmap_conf: regmap configuration pointer + * @get_i2s_clk_parent: get parent clock of I2S kernel clock + */ +struct stm32_i2s_conf { + const struct regmap_config *regmap_conf; + int (*get_i2s_clk_parent)(struct stm32_i2s_data *i2s); }; struct stm32_i2smclk_data { @@ -261,6 +280,8 @@ struct stm32_i2smclk_data { #define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) +static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s); + static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, unsigned long input_rate, unsigned long output_rate) @@ -312,6 +333,33 @@ static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) cgfr_mask, cgfr); } +static bool stm32_i2s_rate_accurate(struct stm32_i2s_data *i2s, + unsigned int max_rate, unsigned int rate) +{ + struct platform_device *pdev = i2s->pdev; + u64 delta, dividend; + int ratio; + + if (!rate) { + dev_err(&pdev->dev, "Unexpected null rate\n"); + return false; + } + + ratio = DIV_ROUND_CLOSEST(max_rate, rate); + if (!ratio) + return false; + + dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate))); + delta = div_u64(dividend, max_rate); + + if (delta <= STM32_I2S_CLK_RATE_TOLERANCE) + return true; + + dev_dbg(&pdev->dev, "Rate [%u] not accurate\n", rate); + + return false; +} + static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, unsigned int rate) { @@ -332,6 +380,87 @@ static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, return ret; } +static void stm32_i2s_put_parent_rate(struct stm32_i2s_data *i2s) +{ + if (i2s->i2s_clk_flg) { + i2s->i2s_clk_flg = false; + clk_rate_exclusive_put(i2s->i2sclk); + } +} + +static int stm32_i2s_set_parent_rate(struct stm32_i2s_data *i2s, + unsigned int rate) +{ + struct platform_device *pdev = i2s->pdev; + unsigned int i2s_clk_rate, i2s_clk_max_rate, i2s_curr_rate, i2s_new_rate; + int ret, div; + + /* + * Set maximum expected kernel clock frequency + * - mclk on: + * f_i2s_ck = MCKDIV * mclk-fs * fs + * Here typical 256 ratio is assumed for mclk-fs + * - mclk off: + * f_i2s_ck = MCKDIV * FRL * fs + * Where FRL=[16,32], MCKDIV=[1..256] + * f_i2s_ck = i2s_clk_max_rate * 32 / 256 + */ + if (!(rate % STM32_I2S_RATE_11K)) + i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_11K * 256; + else + i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_8K * 256; + + if (!i2s->i2smclk) + i2s_clk_max_rate /= 8; + + /* Request exclusivity, as the clock may be shared by I2S instances */ + clk_rate_exclusive_get(i2s->i2sclk); + i2s->i2s_clk_flg = true; + + /* + * Check current kernel clock rate. If it gives the expected accuracy + * return immediately. + */ + i2s_curr_rate = clk_get_rate(i2s->i2sclk); + if (stm32_i2s_rate_accurate(i2s, i2s_clk_max_rate, i2s_curr_rate)) + return 0; + + /* + * Otherwise try to set the maximum rate and check the new actual rate. + * If the new rate does not give the expected accuracy, try to set + * lower rates for the kernel clock. + */ + i2s_clk_rate = i2s_clk_max_rate; + div = 1; + do { + /* Check new rate accuracy. Return if ok */ + i2s_new_rate = clk_round_rate(i2s->i2sclk, i2s_clk_rate); + if (stm32_i2s_rate_accurate(i2s, i2s_clk_rate, i2s_new_rate)) { + ret = clk_set_rate(i2s->i2sclk, i2s_clk_rate); + if (ret) { + dev_err(&pdev->dev, "Error %d setting i2s_clk_rate rate. %s", + ret, ret == -EBUSY ? + "Active stream rates may be in conflict\n" : "\n"); + goto err; + } + + return 0; + } + + /* Try a lower frequency */ + div++; + i2s_clk_rate = i2s_clk_max_rate / div; + } while (i2s_clk_rate > rate); + + /* no accurate rate found */ + dev_err(&pdev->dev, "Failed to find an accurate rate"); + +err: + stm32_i2s_put_parent_rate(i2s); + + return -EINVAL; +} + static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { @@ -635,12 +764,16 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, clk_rate_exclusive_put(i2s->i2smclk); i2s->mclk_rate = 0; } + + if (i2s->put_i2s_clk_rate) + i2s->put_i2s_clk_rate(i2s); + return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); } /* If master clock is used, set parent clock now */ - ret = stm32_i2s_set_parent_clock(i2s, freq); + ret = i2s->set_i2s_clk_rate(i2s, freq); if (ret) return ret; ret = clk_set_rate_exclusive(i2s->i2smclk, freq); @@ -667,10 +800,11 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, u32 cgfr; int ret; - if (!(rate % 11025)) - clk_set_parent(i2s->i2sclk, i2s->x11kclk); - else - clk_set_parent(i2s->i2sclk, i2s->x8kclk); + if (!i2s->mclk_rate) { + ret = i2s->set_i2s_clk_rate(i2s, rate); + if (ret) + return ret; + } i2s_clock_rate = clk_get_rate(i2s->i2sclk); /* @@ -915,6 +1049,14 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(i2s->i2sclk); + /* + * Release kernel clock if following conditions are fulfilled + * - Master clock is not used. Kernel clock won't be released trough sysclk + * - Put handler is defined. Involve that clock is managed exclusively + */ + if (!i2s->i2smclk && i2s->put_i2s_clk_rate) + i2s->put_i2s_clk_rate(i2s); + spin_lock_irqsave(&i2s->irq_lock, flags); i2s->substream = NULL; spin_unlock_irqrestore(&i2s->irq_lock, flags); @@ -1012,14 +1154,36 @@ static int stm32_i2s_dais_init(struct platform_device *pdev, return 0; } +static const struct stm32_i2s_conf stm32_i2s_conf_h7 = { + .regmap_conf = &stm32_h7_i2s_regmap_conf, + .get_i2s_clk_parent = stm32_i2s_get_parent_clk, +}; + +static const struct stm32_i2s_conf stm32_i2s_conf_mp25 = { + .regmap_conf = &stm32_h7_i2s_regmap_conf +}; + static const struct of_device_id stm32_i2s_ids[] = { - { - .compatible = "st,stm32h7-i2s", - .data = &stm32_h7_i2s_regmap_conf - }, + { .compatible = "st,stm32h7-i2s", .data = &stm32_i2s_conf_h7 }, + { .compatible = "st,stm32mp25-i2s", .data = &stm32_i2s_conf_mp25 }, {}, }; +static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s) +{ + struct device *dev = &i2s->pdev->dev; + + i2s->x8kclk = devm_clk_get(dev, "x8k"); + if (IS_ERR(i2s->x8kclk)) + return dev_err_probe(dev, PTR_ERR(i2s->x8kclk), "Cannot get x8k parent clock\n"); + + i2s->x11kclk = devm_clk_get(dev, "x11k"); + if (IS_ERR(i2s->x11kclk)) + return dev_err_probe(dev, PTR_ERR(i2s->x11kclk), "Cannot get x11k parent clock\n"); + + return 0; +} + static int stm32_i2s_parse_dt(struct platform_device *pdev, struct stm32_i2s_data *i2s) { @@ -1031,8 +1195,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, if (!np) return -ENODEV; - i2s->regmap_conf = device_get_match_data(&pdev->dev); - if (!i2s->regmap_conf) + i2s->conf = device_get_match_data(&pdev->dev); + if (!i2s->conf) return -EINVAL; i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); @@ -1052,15 +1216,18 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk), "Could not get i2sclk\n"); - i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(i2s->x8kclk)) - return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk), - "Could not get x8k parent clock\n"); + if (i2s->conf->get_i2s_clk_parent) { + i2s->set_i2s_clk_rate = stm32_i2s_set_parent_clock; + } else { + i2s->set_i2s_clk_rate = stm32_i2s_set_parent_rate; + i2s->put_i2s_clk_rate = stm32_i2s_put_parent_rate; + } - i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(i2s->x11kclk)) - return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk), - "Could not get x11k parent clock\n"); + if (i2s->conf->get_i2s_clk_parent) { + ret = i2s->conf->get_i2s_clk_parent(i2s); + if (ret) + return ret; + } /* Register mclk provider if requested */ if (of_property_present(np, "#clock-cells")) { @@ -1126,7 +1293,7 @@ static int stm32_i2s_probe(struct platform_device *pdev) return ret; i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", - i2s->base, i2s->regmap_conf); + i2s->base, i2s->conf->regmap_conf); if (IS_ERR(i2s->regmap)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap), "Regmap init error\n"); -- 2.51.0 From f3c889745cd3500bcbce6f6c8cb7e343f067ac18 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Fri, 25 Oct 2024 17:09:38 +0800 Subject: [PATCH 07/16] ASoC: mediatek: mt8183: Remove unnecessary variable assignments In the function mt8183_dai_i2s_register, the variable 'ret' is redundant, thus remove it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20241025090938.3480-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-dai-i2s.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c index 65e46ebe7be6..5cf5592336d3 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c @@ -1036,7 +1036,6 @@ static int mt8183_dai_i2s_set_priv(struct mtk_base_afe *afe) int mt8183_dai_i2s_register(struct mtk_base_afe *afe) { struct mtk_base_afe_dai *dai; - int ret; dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); if (!dai) @@ -1055,9 +1054,5 @@ int mt8183_dai_i2s_register(struct mtk_base_afe *afe) dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes); /* set all dai i2s private data */ - ret = mt8183_dai_i2s_set_priv(afe); - if (ret) - return ret; - - return 0; + return mt8183_dai_i2s_set_priv(afe); } -- 2.51.0 From 08aa540a196a672b8597fb611e2dc25e42986bd9 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Fri, 8 Nov 2024 09:16:17 +0800 Subject: [PATCH 08/16] ASoC: sma1307: Fix invalid logical judgement In the function sma1307_dai_hw_params_amp, the variable 'ret' has not been assigned a value, so the logical judgement is invalid, thus fix it. Signed-off-by: Tang Bin Link: https://patch.msgid.link/20241108011617.2284-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/codecs/sma1307.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index 985a247b3310..81638768ac12 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1191,7 +1191,6 @@ static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component); unsigned int bclk = 0; - int ret = 0; if (sma1307->format == SND_SOC_DAIFMT_DSP_A) bclk = params_rate(params) * sma1307->frame_size; @@ -1336,8 +1335,6 @@ static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream, params_format(params)); return -EINVAL; } - if (ret < 0) - return -EINVAL; return 0; } -- 2.51.0 From c5bbc47f8e094f4489934a244ee1c14947a5075e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 7 Nov 2024 12:02:03 +0200 Subject: [PATCH 09/16] ASoC: Intel: Kconfig: Only select SND_SOC_SDCA if ACPI is enabled The SDCA module have hard dependency to compile on ACPI, it can only be selected if ACPI is also enabled. The SDCA header provides inline prototypes for other modules to compile in case SND_SOC_SDCA is not enabled. Fixes: 845cb1ddf1fc ("ASoC: Intel: Kconfig: select SND_SOC_SDCA by SND_SOC_ACPI_INTEL_SDCA_QUIRKS") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411070806.UhCRpZok-lkp@intel.com/ Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Link: https://patch.msgid.link/20241107100204.24952-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 46b45f390ae9..502129772856 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -78,7 +78,7 @@ config SND_SOC_ACPI_INTEL_MATCH config SND_SOC_ACPI_INTEL_SDCA_QUIRKS tristate - select SND_SOC_SDCA + select SND_SOC_SDCA if ACPI endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL -- 2.51.0 From 4f1636e7b0384c43856e1442755f48d7c690c2a9 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 7 Nov 2024 12:02:04 +0200 Subject: [PATCH 10/16] ASoC: Intel: Kconfig: Revert make SND_SOC_ACPI_INTEL_MATCH depend on ACPI The acpi-intel-match should be compiled even if ACPI is not selected. The ACPI is not compile time requirement, but the exported symbols are needed for other modules. Fixes: b6bd3f3b6357 ("ASoC: Intel: Kconfig: make SND_SOC_ACPI_INTEL_MATCH depend on ACPI") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411070806.UhCRpZok-lkp@intel.com/ Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Link: https://patch.msgid.link/20241107100204.24952-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 502129772856..2db494b0e3cf 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -70,8 +70,7 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_ACPI_INTEL_MATCH tristate - depends on ACPI - select SND_SOC_ACPI + select SND_SOC_ACPI if ACPI select SND_SOC_ACPI_INTEL_SDCA_QUIRKS # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. -- 2.51.0 From ed7bca5b2b891caedf2ed3ffc427eba23559da95 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Fri, 18 Oct 2024 03:54:47 +0100 Subject: [PATCH 11/16] ASoC: qcom: sm8250: add handling of secondary MI2S clock Add handling of clock related to secondary MI2S_RX in sm8250_snd_startup(). Cc: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Signed-off-by: Alexey Klimov Link: https://patch.msgid.link/20241018025452.1362293-2-alexey.klimov@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/sm8250.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index 91e9bba192c0..45e0c33fc3f3 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -63,6 +63,14 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) snd_soc_dai_set_fmt(cpu_dai, fmt); snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); break; + case SECONDARY_MI2S_RX: + codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; + snd_soc_dai_set_sysclk(cpu_dai, + Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, + MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); + snd_soc_dai_set_fmt(cpu_dai, fmt); + snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); + break; case TERTIARY_MI2S_RX: codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; snd_soc_dai_set_sysclk(cpu_dai, -- 2.51.0 From e90dbd3839f554bef35786c4bec8276455691b20 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Sat, 9 Nov 2024 11:22:31 -0800 Subject: [PATCH 12/16] ASoC: machine: update documentation 1. Added clocking details. 2. Updated ways to register the dai's 3. Bit more detail about card registration details. Signed-off-by: anish kumar Reviewed-by: Bagas Sanjaya Link: https://patch.msgid.link/20241109192231.11623-1-yesanishhere@gmail.com Signed-off-by: Mark Brown --- Documentation/sound/soc/machine.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/sound/soc/machine.rst b/Documentation/sound/soc/machine.rst index 515c9444deaf..9db132bc0070 100644 --- a/Documentation/sound/soc/machine.rst +++ b/Documentation/sound/soc/machine.rst @@ -71,6 +71,18 @@ struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. .ops = &corgi_ops, }; +In the above struct, dai’s are registered using names but you can pass +either dai name or device tree node but not both. Also, names used here +for cpu/codec/platform dais should be globally unique. + +Additionaly below example macro can be used to register cpu, codec and +platform dai:: + + SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp, + DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); + struct snd_soc_card then sets up the machine with its DAIs. e.g. :: @@ -81,6 +93,10 @@ struct snd_soc_card then sets up the machine with its DAIs. e.g. .num_links = 1, }; +Following this, ``devm_snd_soc_register_card`` can be used to register +the sound card. During the registration, the individual components +such as the codec, CPU, and platform are probed. If all these components +are successfully probed, the sound card gets registered. Machine Power Map ----------------- @@ -95,3 +111,13 @@ Machine Controls ---------------- Machine specific audio mixer controls can be added in the DAI init function. + + +Clocking Controls +----------------- + +As previously noted, clock configuration is handled within the machine driver. +For details on the clock APIs that the machine driver can utilize for +setup, please refer to Documentation/sound/soc/clocking.rst. However, the +callback needs to be registered by the CPU/Codec/Platform drivers to configure +the clocks that is needed for the corresponding device operation. -- 2.51.0 From 725570f96321f3e0ae1c6a1f80482d2907538d07 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 Nov 2024 00:53:47 +0100 Subject: [PATCH 13/16] ASoC: max98088: Remove duplicate DACs This codec only has one set of left and right DACs, remove the duplicate DACs with duplicated bits controlling them as the userspace can set those controls to mismatched value. This most likely does break userspace ABI, but there seem to be no in-kernel users. Signed-off-by: Marek Vasut Link: https://patch.msgid.link/20241108235453.196289-1-marex@denx.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98088.c | 80 ++++++++++++------------------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 8b0645c63462..adb17a458ca3 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -515,10 +515,8 @@ static const struct snd_kcontrol_new max98088_snd_controls[] = { /* Left speaker mixer switch */ static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), @@ -529,10 +527,8 @@ static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { /* Right speaker mixer switch */ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), @@ -543,10 +539,8 @@ static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { /* Left headphone mixer switch */ static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), @@ -557,10 +551,8 @@ static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { /* Right headphone mixer switch */ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), @@ -571,10 +563,8 @@ static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { /* Left earpiece/receiver mixer switch */ static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), @@ -585,10 +575,8 @@ static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { /* Right earpiece/receiver mixer switch */ static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), + SOC_DAPM_SINGLE("Left DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), @@ -717,13 +705,9 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), - SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", + SND_SOC_DAPM_DAC("DACL", "HiFi Playback", M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", - M98088_REG_4D_PWR_EN_OUT, 0, 0), - SND_SOC_DAPM_DAC("DACL2", "Aux Playback", - M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR2", "Aux Playback", + SND_SOC_DAPM_DAC("DACR", "HiFi Playback", M98088_REG_4D_PWR_EN_OUT, 0, 0), SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, @@ -819,10 +803,8 @@ static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { static const struct snd_soc_dapm_route max98088_audio_map[] = { /* Left headphone output mixer */ - {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left HP Mixer", "Left DAC Switch", "DACL"}, + {"Left HP Mixer", "Right DAC Switch", "DACR"}, {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, @@ -831,10 +813,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, /* Right headphone output mixer */ - {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right HP Mixer", "Left DAC2 Switch", "DACL2" }, - {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right HP Mixer", "Left DAC Switch", "DACL"}, + {"Right HP Mixer", "Right DAC Switch", "DACR"}, {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, @@ -843,10 +823,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, /* Left speaker output mixer */ - {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left SPK Mixer", "Left DAC Switch", "DACL"}, + {"Left SPK Mixer", "Right DAC Switch", "DACR"}, {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, @@ -855,10 +833,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, /* Right speaker output mixer */ - {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right SPK Mixer", "Left DAC Switch", "DACL"}, + {"Right SPK Mixer", "Right DAC Switch", "DACR"}, {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, @@ -867,10 +843,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, /* Earpiece/Receiver output mixer */ - {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, + {"Left REC Mixer", "Left DAC Switch", "DACL"}, + {"Left REC Mixer", "Right DAC Switch", "DACR"}, {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, @@ -879,10 +853,8 @@ static const struct snd_soc_dapm_route max98088_audio_map[] = { {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, /* Earpiece/Receiver output mixer */ - {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, + {"Right REC Mixer", "Left DAC Switch", "DACL"}, + {"Right REC Mixer", "Right DAC Switch", "DACR"}, {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, -- 2.51.0 From 1bd775da9ba919b87b2313a78d5957afc1a62dde Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 6 Nov 2024 00:10:44 +0000 Subject: [PATCH 14/16] ASoC: add symmetric_ prefix for dai->rate/channels/sample_bits snd_soc_dai has rate/channels/sample_bits parameter, but it is only valid if symmetry is being enforced by symmetric_xxx flag on driver. It is very difficult to know about it from current naming, and easy to misunderstand it. add symmetric_ prefix for it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfmd8bnf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 6 ++--- sound/soc/mediatek/mt8188/mt8188-dai-pcm.c | 2 +- sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 2 +- sound/soc/mediatek/mt8365/mt8365-dai-dmic.c | 6 ++--- sound/soc/mediatek/mt8365/mt8365-dai-pcm.c | 2 +- sound/soc/soc-compress.c | 4 +-- sound/soc/soc-pcm.c | 29 +++++++++++---------- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index b275201b02f6..aab57c19f62b 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -449,9 +449,9 @@ struct snd_soc_dai { struct snd_soc_dai_stream stream[SNDRV_PCM_STREAM_LAST + 1]; /* Symmetry data - only valid if symmetry is being enforced */ - unsigned int rate; - unsigned int channels; - unsigned int sample_bits; + unsigned int symmetric_rate; + unsigned int symmetric_channels; + unsigned int symmetric_sample_bits; /* parent platform/codec */ struct snd_soc_component *component; diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c b/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c index 5bc854a8f3df..8ca7cc75e21d 100644 --- a/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-dai-pcm.c @@ -128,7 +128,7 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, unsigned int lrck_inv; unsigned int bck_inv; unsigned int fmt; - unsigned int bit_width = dai->sample_bits; + unsigned int bit_width = dai->symmetric_sample_bits; unsigned int val = 0; unsigned int mask = 0; int fs = 0; diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c index 6d6d79300d51..cdc16057d50e 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -127,7 +127,7 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, unsigned int lrck_inv; unsigned int bck_inv; unsigned int fmt; - unsigned int bit_width = dai->sample_bits; + unsigned int bit_width = dai->symmetric_sample_bits; unsigned int val = 0; unsigned int mask = 0; int fs = 0; diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c index f9945c2a2cd1..0bac143b48bf 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c @@ -118,13 +118,13 @@ static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe, unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1; unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2; unsigned int val = 0; - unsigned int rate = dai->rate; - int reg = get_chan_reg(dai->channels); + unsigned int rate = dai->symmetric_rate; + int reg = get_chan_reg(dai->symmetric_channels); if (reg < 0) return -EINVAL; - dmic_data->dmic_channel = dai->channels; + dmic_data->dmic_channel = dai->symmetric_channels; val |= DMIC_TOP_CON_SDM3_LEVEL_MODE; diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c index f85ec07249c3..3373b88da28e 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c @@ -44,7 +44,7 @@ static int mt8365_dai_configure_pcm1(struct snd_pcm_substream *substream, bool lrck_inv = pcm_priv->lrck_inv; bool bck_inv = pcm_priv->bck_inv; unsigned int fmt = pcm_priv->format; - unsigned int bit_width = dai->sample_bits; + unsigned int bit_width = dai->symmetric_sample_bits; unsigned int val = 0; if (!slave_mode) { diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 3c514703fa33..563dc0767c17 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -69,10 +69,10 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) snd_soc_dai_digital_mute(codec_dai, 1, stream); if (!snd_soc_dai_active(cpu_dai)) - cpu_dai->rate = 0; + cpu_dai->symmetric_rate = 0; if (!snd_soc_dai_active(codec_dai)) - codec_dai->rate = 0; + codec_dai->symmetric_rate = 0; snd_soc_link_compr_shutdown(cstream, rollback); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fb7f25fd8ec5..1150455619aa 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -447,13 +447,13 @@ static void soc_pcm_set_dai_params(struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) { if (params) { - dai->rate = params_rate(params); - dai->channels = params_channels(params); - dai->sample_bits = snd_pcm_format_physical_width(params_format(params)); + dai->symmetric_rate = params_rate(params); + dai->symmetric_channels = params_channels(params); + dai->symmetric_sample_bits = snd_pcm_format_physical_width(params_format(params)); } else { - dai->rate = 0; - dai->channels = 0; - dai->sample_bits = 0; + dai->symmetric_rate = 0; + dai->symmetric_channels = 0; + dai->symmetric_sample_bits = 0; } } @@ -467,14 +467,14 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, return 0; #define __soc_pcm_apply_symmetry(name, NAME) \ - if (soc_dai->name && (soc_dai->driver->symmetric_##name || \ - rtd->dai_link->symmetric_##name)) { \ + if (soc_dai->symmetric_##name && \ + (soc_dai->driver->symmetric_##name || rtd->dai_link->symmetric_##name)) { \ dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\ - #name, soc_dai->name); \ + #name, soc_dai->symmetric_##name); \ \ ret = snd_pcm_hw_constraint_single(substream->runtime, \ SNDRV_PCM_HW_PARAM_##NAME,\ - soc_dai->name); \ + soc_dai->symmetric_##name); \ if (ret < 0) { \ dev_err(soc_dai->dev, \ "ASoC: Unable to apply %s constraint: %d\n",\ @@ -510,9 +510,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) \ for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ if (!snd_soc_dai_is_dummy(cpu_dai) && \ - cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \ + cpu_dai->symmetric_##xxx && \ + cpu_dai->symmetric_##xxx != d.symmetric_##xxx) { \ dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \ - #xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \ + #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \ + d.name, d.symmetric_##xxx); \ return -EINVAL; \ } @@ -783,8 +785,7 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd, /* Make sure DAI parameters cleared if the DAI becomes inactive */ for_each_rtd_dais(rtd, i, dai) { - if (snd_soc_dai_active(dai) == 0 && - (dai->rate || dai->channels || dai->sample_bits)) + if (snd_soc_dai_active(dai) == 0) soc_pcm_set_dai_params(dai, NULL); } } -- 2.51.0 From 98d34ddd43de0b040bd3ff74b511be7074b0b310 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Tue, 5 Nov 2024 14:59:41 +0100 Subject: [PATCH 15/16] ASoC: dt-bindings: stm32: add missing port property Add missing port property in STM32 SPDIFRX binding. This will prevent potential warning: Unevaluated properties are not allowed ('port' was unexpected) Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20241105135942.526624-1-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml index 3dedc81ec12f..56c5738ea4c5 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml +++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml @@ -50,6 +50,10 @@ properties: resets: maxItems: 1 + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + access-controllers: minItems: 1 maxItems: 2 -- 2.51.0 From 9a59718a5340aa0240a442115eb499de2ed18ee4 Mon Sep 17 00:00:00 2001 From: Suraj Sonawane Date: Thu, 7 Nov 2024 12:06:09 +0530 Subject: [PATCH 16/16] ASoc: SOF: ipc4-pcm: fix uninit-value in sof_ipc4_pcm_dai_link_fixup_rate Fix an issue detected by the Smatch tool: sound/soc/sof/ipc4-pcm.c: sof_ipc4_pcm_dai_link_fixup_rate() error: uninitialized symbol 'be_rate'. The warning highlights a case where `be_rate` could remain uninitialized if `num_input_formats` is zero, which would cause undefined behavior when setting `rate->min` and `rate->max` based on `be_rate`. To address this issue, a `WARN_ON_ONCE(!num_input_formats)` check was added to ensure `num_input_formats` is greater than zero. If this condition fails, the function returns `-EINVAL`, preventing the use of an uninitialized `be_rate`. This change improves the robustness of the function by catching an invalid state early and providing better feedback during development. Signed-off-by: Suraj Sonawane Link: https://patch.msgid.link/20241107063609.11627-1-surajsonawane0215@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4df2be3d39eb..18fff2df76f9 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -603,6 +603,9 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, unsigned int be_rate; int i; + if (WARN_ON_ONCE(!num_input_formats)) + return -EINVAL; + /* * Copier does not change sampling rate, so we * need to only consider the input pin information. -- 2.51.0