From: Andrei Simion <andrei.simion@microchip.com>
To: <claudiu.beznea@tuxon.dev>, <lgirdwood@gmail.com>,
<broonie@kernel.org>, <perex@perex.cz>, <tiwai@suse.com>,
<nicolas.ferre@microchip.com>, <alexandre.belloni@bootlin.com>
Cc: <alsa-devel@alsa-project.org>, <linux-sound@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>,
Codrin Ciubotariu <codrin.ciubotariu@microchip.com>,
Andrei Simion <andrei.simion@microchip.com>
Subject: [PATCH 3/3] ASoC: atmel: mchp-pdmc: Retain Non-Runtime Controls
Date: Wed, 11 Sep 2024 15:29:09 +0300 [thread overview]
Message-ID: <20240911122909.133399-4-andrei.simion@microchip.com> (raw)
In-Reply-To: <20240911122909.133399-1-andrei.simion@microchip.com>
From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
Avoid removing these controls, as doing so can cause issues if the stream
is initiated from another control. Ensure these controls remain intact when
the stream is started or finished. Instead of removing them, return an
-EBUSY error code to indicate that the controller is busy, especially when
the audio filter and the SINC filter are in use.
[andrei.simion@microchip.com: Reword the commit title and the commit
message. Adapt the code from kernel v6.1 -> v6.6 -> latest kernel version.]
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
Signed-off-by: Andrei Simion <andrei.simion@microchip.com>
---
sound/soc/atmel/mchp-pdmc.c | 78 ++++++++++++++++---------------------
1 file changed, 34 insertions(+), 44 deletions(-)
diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c
index d97d153ee375..758b3c550b97 100644
--- a/sound/soc/atmel/mchp-pdmc.c
+++ b/sound/soc/atmel/mchp-pdmc.c
@@ -14,6 +14,7 @@
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/spinlock.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
@@ -113,6 +114,7 @@ struct mchp_pdmc_chmap {
struct mchp_pdmc {
struct mic_map channel_mic_map[MCHP_PDMC_MAX_CHANNELS];
+ spinlock_t busy_lock; /* lock protecting busy */
struct device *dev;
struct snd_dmaengine_dai_dma_data addr;
struct regmap *regmap;
@@ -124,6 +126,7 @@ struct mchp_pdmc {
int mic_no;
int sinc_order;
bool audio_filter_en;
+ u8 busy:1;
};
static const char *const mchp_pdmc_sinc_filter_order_text[] = {
@@ -167,10 +170,19 @@ static int mchp_pdmc_sinc_order_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
- if (val == dd->sinc_order)
+
+ spin_lock(&dd->busy_lock);
+ if (dd->busy) {
+ spin_unlock((&dd->busy_lock));
+ return -EBUSY;
+ }
+ if (val == dd->sinc_order) {
+ spin_unlock((&dd->busy_lock));
return 0;
+ }
dd->sinc_order = val;
+ spin_unlock((&dd->busy_lock));
return 1;
}
@@ -193,10 +205,18 @@ static int mchp_pdmc_af_put(struct snd_kcontrol *kcontrol,
struct mchp_pdmc *dd = snd_soc_component_get_drvdata(component);
bool af = uvalue->value.integer.value[0] ? true : false;
- if (dd->audio_filter_en == af)
+ spin_lock(&dd->busy_lock);
+ if (dd->busy) {
+ spin_unlock((&dd->busy_lock));
+ return -EBUSY;
+ }
+ if (dd->audio_filter_en == af) {
+ spin_unlock((&dd->busy_lock));
return 0;
+ }
dd->audio_filter_en = af;
+ spin_unlock((&dd->busy_lock));
return 1;
}
@@ -379,52 +399,10 @@ static const struct snd_kcontrol_new mchp_pdmc_snd_controls[] = {
},
};
-static int mchp_pdmc_close(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- return snd_soc_add_component_controls(component, mchp_pdmc_snd_controls,
- ARRAY_SIZE(mchp_pdmc_snd_controls));
-}
-
-static int mchp_pdmc_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- int i;
-
- /* remove controls that can't be changed at runtime */
- for (i = 0; i < ARRAY_SIZE(mchp_pdmc_snd_controls); i++) {
- const struct snd_kcontrol_new *control = &mchp_pdmc_snd_controls[i];
- struct snd_ctl_elem_id id;
- int err;
-
- if (component->name_prefix)
- snprintf(id.name, sizeof(id.name), "%s %s", component->name_prefix,
- control->name);
- else
- strscpy(id.name, control->name, sizeof(id.name));
-
- id.numid = 0;
- id.iface = control->iface;
- id.device = control->device;
- id.subdevice = control->subdevice;
- id.index = control->index;
- err = snd_ctl_remove_id(component->card->snd_card, &id);
- if (err < 0)
- dev_err(component->dev, "%d: Failed to remove %s\n", err,
- control->name);
- }
-
- return 0;
-}
-
static const struct snd_soc_component_driver mchp_pdmc_dai_component = {
.name = "mchp-pdmc",
.controls = mchp_pdmc_snd_controls,
.num_controls = ARRAY_SIZE(mchp_pdmc_snd_controls),
- .open = &mchp_pdmc_open,
- .close = &mchp_pdmc_close,
- .legacy_dai_naming = 1,
- .trigger_start = SND_SOC_TRIGGER_ORDER_LDC,
};
static const unsigned int mchp_pdmc_1mic[] = {1};
@@ -587,6 +565,13 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
cfgr_val |= MCHP_PDMC_CFGR_BSSEL(i);
}
+ /*
+ * from these point forward, we consider the controller busy, so the
+ * audio filter and SINC order can't be changed
+ */
+ spin_lock(&dd->busy_lock);
+ dd->busy = 1;
+ spin_unlock((&dd->busy_lock));
for (osr_start = dd->audio_filter_en ? 64 : 8;
osr_start <= 256 && best_diff_rate; osr_start *= 2) {
long round_rate;
@@ -1099,6 +1084,7 @@ static int mchp_pdmc_probe(struct platform_device *pdev)
*/
dd->audio_filter_en = true;
dd->sinc_order = 3;
+ spin_lock_init(&dd->busy_lock);
dd->addr.addr = (dma_addr_t)res->start + MCHP_PDMC_RHR;
platform_set_drvdata(pdev, dd);
@@ -1143,6 +1129,10 @@ static void mchp_pdmc_remove(struct platform_device *pdev)
{
struct mchp_pdmc *dd = platform_get_drvdata(pdev);
+ spin_lock(&dd->busy_lock);
+ dd->busy = 0;
+ spin_unlock((&dd->busy_lock));
+
if (!pm_runtime_status_suspended(dd->dev))
mchp_pdmc_runtime_suspend(dd->dev);
--
2.34.1
next prev parent reply other threads:[~2024-09-11 12:30 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-11 12:29 [PATCH 0/3] Improvements for mchp-pdmc Andrei Simion
2024-09-11 12:29 ` [PATCH 1/3] ASoC: atmel: mchp-pdmc: Improve maxburst calculation for better performance Andrei Simion
2024-09-11 12:29 ` [PATCH 2/3] ASoC: atmel: mchp-pdmc: Add snd_soc_dai_driver name Andrei Simion
2024-09-11 12:29 ` Andrei Simion [this message]
2024-09-12 7:23 ` [PATCH 3/3] ASoC: atmel: mchp-pdmc: Retain Non-Runtime Controls claudiu beznea
2024-09-12 9:53 ` Andrei Simion
2024-09-12 16:42 ` [PATCH 0/3] Improvements for mchp-pdmc Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240911122909.133399-4-andrei.simion@microchip.com \
--to=andrei.simion@microchip.com \
--cc=alexandre.belloni@bootlin.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=claudiu.beznea@tuxon.dev \
--cc=codrin.ciubotariu@microchip.com \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=nicolas.ferre@microchip.com \
--cc=perex@perex.cz \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox