aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/atmel
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/atmel')
-rw-r--r--sound/soc/atmel/atmel-i2s.c2
-rw-r--r--sound/soc/atmel/atmel_wm8904.c2
-rw-r--r--sound/soc/atmel/mchp-i2s-mcc.c44
-rw-r--r--sound/soc/atmel/mchp-pdmc.c99
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c2
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/atmel/sam9x5_wm8731.c2
-rw-r--r--sound/soc/atmel/tse850-pcm5142.c2
9 files changed, 88 insertions, 69 deletions
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
index 6c20c643f321..762199faf872 100644
--- a/sound/soc/atmel/atmel-i2s.c
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -733,7 +733,7 @@ static struct platform_driver atmel_i2s_driver = {
.of_match_table = atmel_i2s_dt_ids,
},
.probe = atmel_i2s_probe,
- .remove_new = atmel_i2s_remove,
+ .remove = atmel_i2s_remove,
};
module_platform_driver(atmel_i2s_driver);
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
index b7f16ea0cdfc..0f4021c6c588 100644
--- a/sound/soc/atmel/atmel_wm8904.c
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -187,7 +187,7 @@ static struct platform_driver atmel_asoc_wm8904_driver = {
.pm = &snd_soc_pm_ops,
},
.probe = atmel_asoc_wm8904_probe,
- .remove_new = atmel_asoc_wm8904_remove,
+ .remove = atmel_asoc_wm8904_remove,
};
module_platform_driver(atmel_asoc_wm8904_driver);
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 193dd7acceb0..17d138bb9064 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -221,6 +221,15 @@
#define MCHP_I2SMCC_MAX_CHANNELS 8
#define MCHP_I2MCC_TDM_SLOT_WIDTH 32
+/*
+ * ---- DMA chunk size allowed ----
+ */
+#define MCHP_I2SMCC_DMA_8_WORD_CHUNK 8
+#define MCHP_I2SMCC_DMA_4_WORD_CHUNK 4
+#define MCHP_I2SMCC_DMA_2_WORD_CHUNK 2
+#define MCHP_I2SMCC_DMA_1_WORD_CHUNK 1
+#define DMA_BURST_ALIGNED(_p, _s, _w) !(_p % (_s * _w))
+
static const struct regmap_config mchp_i2s_mcc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -504,12 +513,30 @@ static int mchp_i2s_mcc_is_running(struct mchp_i2s_mcc_dev *dev)
return !!(sr & (MCHP_I2SMCC_SR_TXEN | MCHP_I2SMCC_SR_RXEN));
}
+static inline int mchp_i2s_mcc_period_to_maxburst(int period_size, int sample_size)
+{
+ int p_size = period_size;
+ int s_size = sample_size;
+
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_8_WORD_CHUNK))
+ return MCHP_I2SMCC_DMA_8_WORD_CHUNK;
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_4_WORD_CHUNK))
+ return MCHP_I2SMCC_DMA_4_WORD_CHUNK;
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_I2SMCC_DMA_2_WORD_CHUNK))
+ return MCHP_I2SMCC_DMA_2_WORD_CHUNK;
+ return MCHP_I2SMCC_DMA_1_WORD_CHUNK;
+}
+
static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
unsigned long rate = 0;
struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai);
+ int sample_bytes = params_physical_width(params) / 8;
+ int period_bytes = params_period_size(params) *
+ params_channels(params) * sample_bytes;
+ int maxburst;
u32 mra = 0;
u32 mrb = 0;
unsigned int channels = params_channels(params);
@@ -519,9 +546,9 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
int ret;
bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
- dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
+ dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u period_bytes=%d\n",
__func__, params_rate(params), params_format(params),
- params_width(params), params_channels(params));
+ params_width(params), params_channels(params), period_bytes);
switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
@@ -630,11 +657,12 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream,
* We must have the same burst size configured
* in the DMA transfer and in out IP
*/
- mrb |= MCHP_I2SMCC_MRB_DMACHUNK(channels);
+ maxburst = mchp_i2s_mcc_period_to_maxburst(period_bytes, sample_bytes);
+ mrb |= MCHP_I2SMCC_MRB_DMACHUNK(maxburst);
if (is_playback)
- dev->playback.maxburst = 1 << (fls(channels) - 1);
+ dev->playback.maxburst = maxburst;
else
- dev->capture.maxburst = 1 << (fls(channels) - 1);
+ dev->capture.maxburst = maxburst;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
@@ -908,14 +936,14 @@ static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops = {
static struct snd_soc_dai_driver mchp_i2s_mcc_dai = {
.playback = {
- .stream_name = "I2SMCC-Playback",
+ .stream_name = "Playback",
.channels_min = 1,
.channels_max = 8,
.rates = MCHP_I2SMCC_RATES,
.formats = MCHP_I2SMCC_FORMATS,
},
.capture = {
- .stream_name = "I2SMCC-Capture",
+ .stream_name = "Capture",
.channels_min = 1,
.channels_max = 8,
.rates = MCHP_I2SMCC_RATES,
@@ -1101,7 +1129,7 @@ static struct platform_driver mchp_i2s_mcc_driver = {
.of_match_table = mchp_i2s_mcc_dt_ids,
},
.probe = mchp_i2s_mcc_probe,
- .remove_new = mchp_i2s_mcc_remove,
+ .remove = mchp_i2s_mcc_remove,
};
module_platform_driver(mchp_i2s_mcc_driver);
diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c
index dcc4e14b3dde..939cd44ebc8a 100644
--- a/sound/soc/atmel/mchp-pdmc.c
+++ b/sound/soc/atmel/mchp-pdmc.c
@@ -90,6 +90,15 @@
#define MCHP_PDMC_DS_NO 2
#define MCHP_PDMC_EDGE_NO 2
+/*
+ * ---- DMA chunk size allowed ----
+ */
+#define MCHP_PDMC_DMA_8_WORD_CHUNK 8
+#define MCHP_PDMC_DMA_4_WORD_CHUNK 4
+#define MCHP_PDMC_DMA_2_WORD_CHUNK 2
+#define MCHP_PDMC_DMA_1_WORD_CHUNK 1
+#define DMA_BURST_ALIGNED(_p, _s, _w) !(_p % (_s * _w))
+
struct mic_map {
int ds_pos;
int clk_edge;
@@ -115,6 +124,7 @@ struct mchp_pdmc {
int mic_no;
int sinc_order;
bool audio_filter_en;
+ atomic_t busy_stream;
};
static const char *const mchp_pdmc_sinc_filter_order_text[] = {
@@ -158,6 +168,10 @@ 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 (atomic_read(&dd->busy_stream))
+ return -EBUSY;
+
if (val == dd->sinc_order)
return 0;
@@ -184,6 +198,9 @@ 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 (atomic_read(&dd->busy_stream))
+ return -EBUSY;
+
if (dd->audio_filter_en == af)
return 0;
@@ -370,52 +387,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};
@@ -511,15 +486,18 @@ static u32 mchp_pdmc_mr_set_osr(int audio_filter_en, unsigned int osr)
return 0;
}
-static inline int mchp_pdmc_period_to_maxburst(int period_size)
+static inline int mchp_pdmc_period_to_maxburst(int period_size, int sample_size)
{
- if (!(period_size % 8))
- return 8;
- if (!(period_size % 4))
- return 4;
- if (!(period_size % 2))
- return 2;
- return 1;
+ int p_size = period_size;
+ int s_size = sample_size;
+
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_PDMC_DMA_8_WORD_CHUNK))
+ return MCHP_PDMC_DMA_8_WORD_CHUNK;
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_PDMC_DMA_4_WORD_CHUNK))
+ return MCHP_PDMC_DMA_4_WORD_CHUNK;
+ if (DMA_BURST_ALIGNED(p_size, s_size, MCHP_PDMC_DMA_2_WORD_CHUNK))
+ return MCHP_PDMC_DMA_2_WORD_CHUNK;
+ return MCHP_PDMC_DMA_1_WORD_CHUNK;
}
static struct snd_pcm_chmap_elem mchp_pdmc_std_chmaps[] = {
@@ -547,14 +525,18 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
unsigned int channels = params_channels(params);
unsigned int osr = 0, osr_start;
unsigned int fs = params_rate(params);
+ int sample_bytes = params_physical_width(params) / 8;
+ int period_bytes = params_period_size(params) *
+ params_channels(params) * sample_bytes;
+ int maxburst;
u32 mr_val = 0;
u32 cfgr_val = 0;
int i;
int ret;
- dev_dbg(comp->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
+ dev_dbg(comp->dev, "%s() rate=%u format=%#x width=%u channels=%u period_bytes=%d\n",
__func__, params_rate(params), params_format(params),
- params_width(params), params_channels(params));
+ params_width(params), params_channels(params), period_bytes);
if (channels > dd->mic_no) {
dev_err(comp->dev, "more channels %u than microphones %d\n",
@@ -571,6 +553,11 @@ 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
+ */
+ atomic_set(&dd->busy_stream, 1);
for (osr_start = dd->audio_filter_en ? 64 : 8;
osr_start <= 256 && best_diff_rate; osr_start *= 2) {
long round_rate;
@@ -608,7 +595,8 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
mr_val |= FIELD_PREP(MCHP_PDMC_MR_SINCORDER_MASK, dd->sinc_order);
- dd->addr.maxburst = mchp_pdmc_period_to_maxburst(snd_pcm_lib_period_bytes(substream));
+ maxburst = mchp_pdmc_period_to_maxburst(period_bytes, sample_bytes);
+ dd->addr.maxburst = maxburst;
mr_val |= FIELD_PREP(MCHP_PDMC_MR_CHUNK_MASK, dd->addr.maxburst);
dev_dbg(comp->dev, "maxburst set to %d\n", dd->addr.maxburst);
@@ -760,6 +748,7 @@ static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = {
};
static struct snd_soc_dai_driver mchp_pdmc_dai = {
+ .name = "mchp-pdmc",
.capture = {
.stream_name = "Capture",
.channels_min = 1,
@@ -1125,6 +1114,8 @@ static void mchp_pdmc_remove(struct platform_device *pdev)
{
struct mchp_pdmc *dd = platform_get_drvdata(pdev);
+ atomic_set(&dd->busy_stream, 0);
+
if (!pm_runtime_status_suspended(dd->dev))
mchp_pdmc_runtime_suspend(dd->dev);
@@ -1153,7 +1144,7 @@ static struct platform_driver mchp_pdmc_driver = {
.pm = pm_ptr(&mchp_pdmc_pm_ops),
},
.probe = mchp_pdmc_probe,
- .remove_new = mchp_pdmc_remove,
+ .remove = mchp_pdmc_remove,
};
module_platform_driver(mchp_pdmc_driver);
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index 33ce5e54482b..b2507a1491b7 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -1194,7 +1194,7 @@ static void mchp_spdifrx_remove(struct platform_device *pdev)
static struct platform_driver mchp_spdifrx_driver = {
.probe = mchp_spdifrx_probe,
- .remove_new = mchp_spdifrx_remove,
+ .remove = mchp_spdifrx_remove,
.driver = {
.name = "mchp_spdifrx",
.of_match_table = mchp_spdifrx_dt_ids,
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index a201a96fa690..4c60ea652896 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -888,7 +888,7 @@ static void mchp_spdiftx_remove(struct platform_device *pdev)
static struct platform_driver mchp_spdiftx_driver = {
.probe = mchp_spdiftx_probe,
- .remove_new = mchp_spdiftx_remove,
+ .remove = mchp_spdiftx_remove,
.driver = {
.name = "mchp_spdiftx",
.of_match_table = mchp_spdiftx_dt_ids,
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index d3ec9826d505..335e216ea7b4 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -207,7 +207,7 @@ static struct platform_driver at91sam9g20ek_audio_driver = {
.of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
},
.probe = at91sam9g20ek_audio_probe,
- .remove_new = at91sam9g20ek_audio_remove,
+ .remove = at91sam9g20ek_audio_remove,
};
module_platform_driver(at91sam9g20ek_audio_driver);
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c
index d1c1f370a9cd..1b5ef4e9d2b8 100644
--- a/sound/soc/atmel/sam9x5_wm8731.c
+++ b/sound/soc/atmel/sam9x5_wm8731.c
@@ -196,7 +196,7 @@ static struct platform_driver sam9x5_wm8731_driver = {
.of_match_table = of_match_ptr(sam9x5_wm8731_of_match),
},
.probe = sam9x5_wm8731_driver_probe,
- .remove_new = sam9x5_wm8731_driver_remove,
+ .remove = sam9x5_wm8731_driver_remove,
};
module_platform_driver(sam9x5_wm8731_driver);
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c
index 5d208e0b4b90..0a9efd5f2861 100644
--- a/sound/soc/atmel/tse850-pcm5142.c
+++ b/sound/soc/atmel/tse850-pcm5142.c
@@ -431,7 +431,7 @@ static struct platform_driver tse850_driver = {
.of_match_table = tse850_dt_ids,
},
.probe = tse850_probe,
- .remove_new = tse850_remove,
+ .remove = tse850_remove,
};
module_platform_driver(tse850_driver);