Skip to content

Commit e5f2061

Browse files
Codrin CiubotariuAndrei Simion
authored andcommitted
ASoC: atmel: mchp-asrc: rework maxburst calculation
Rework the maxburst calculations so that all HW limitations are taken into account. Also, snd_pcm_lib_period_bytes() can't be used at this time since substream->runtime members are not initialized. Fixes: 264353f ("ASoC: atmel: Add ASRC driver") Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> (cherry picked from linux-6.1-trunk/at91/sound) Signed-off-by: Andrei Simion <andrei.simion@microchip.com>
1 parent 17e194b commit e5f2061

1 file changed

Lines changed: 42 additions & 28 deletions

File tree

sound/soc/atmel/mchp-asrc.c

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/io.h>
1414
#include <linux/lcm.h>
1515
#include <linux/list.h>
16+
#include <linux/minmax.h>
1617
#include <linux/module.h>
1718
#include <linux/slab.h>
1819

@@ -365,7 +366,6 @@ struct mchp_asrc_be_rtm {
365366
struct mchp_asrc_be_trigger *trig; /* backpointer */
366367
struct snd_pcm_hw_params *hw_params; // used by the links that are not BE
367368
struct mchp_asrc_slot const *slot;
368-
int maxburst;
369369
struct list_head list;
370370
};
371371

@@ -388,6 +388,7 @@ struct mchp_asrc_pcm_priv {
388388
struct xmit_ch *tc;
389389
struct mchp_asrc_be_rtm rtm_fe; /* used for FE --- BEs links */
390390
int refcount;
391+
int maxburst;
391392
bool is_hostless;
392393
};
393394

@@ -405,18 +406,18 @@ struct mchp_asrc_dev {
405406
int rhr_opmode;
406407
};
407408

408-
static inline int mchp_asrc_period_to_burst(int period_size)
409+
static inline int mchp_asrc_period_to_burst(int period_size, int sample_size)
409410
{
410-
if (!(period_size % 16))
411+
if (!(period_size % (sample_size * 16)))
411412
return 16;
412413

413-
if (!(period_size % 8))
414+
if (!(period_size % (sample_size * 8)))
414415
return 8;
415416

416-
if (!(period_size % 4))
417+
if (!(period_size % (sample_size * 4)))
417418
return 4;
418419

419-
if (!(period_size % 2))
420+
if (!(period_size % (sample_size * 2)))
420421
return 2;
421422

422423
return 1;
@@ -700,7 +701,6 @@ static int mchp_asrc_bes_get(struct mchp_asrc_dev *priv, struct snd_pcm_substrea
700701
struct snd_soc_pcm_runtime *be = dpcm->be;
701702
struct snd_soc_dai *dai = asoc_rtd_to_cpu(be, 0);
702703
struct snd_pcm_substream *substream_be;
703-
int period_bytes;
704704

705705
if (dpcm->fe != rtd)
706706
continue;
@@ -717,7 +717,6 @@ static int mchp_asrc_bes_get(struct mchp_asrc_dev *priv, struct snd_pcm_substrea
717717
params_width(&be->dpcm[substream->stream].hw_params),
718718
params_channels(&be->dpcm[substream->stream].hw_params));
719719

720-
period_bytes = snd_pcm_lib_period_bytes(substream_be);
721720
for (i = 0; i < priv->trig_count; i++) {
722721
struct mchp_asrc_be_trigger *trig_be = &priv->trig[i];
723722
struct mchp_asrc_be_rtm *rtm_be;
@@ -731,8 +730,8 @@ static int mchp_asrc_bes_get(struct mchp_asrc_dev *priv, struct snd_pcm_substrea
731730
rtm_be = trig_be->rtm[substream->stream];
732731
if (set_trig)
733732
rtm_be->trig = trig_be;
733+
734734
rtm_be->hw_params = &be->dpcm[substream->stream].hw_params;
735-
rtm_be->maxburst = mchp_asrc_period_to_burst(period_bytes);
736735

737736
/* keep the order */
738737
list_add_tail(&rtm_be->list, head);
@@ -989,11 +988,11 @@ static void mchp_asrc_tc_free(struct mchp_asrc_dev *priv, struct mchp_asrc_pcm_p
989988
MCHP_ASRC_CH_CONF_THROPMODE_MASK | MCHP_ASRC_CH_CONF_RHROPMODE_MASK, 0);
990989
}
991990

992-
static void mchp_asrc_maxburst_limit(int thr_opmode, int rhr_opmode,
993-
int dsps_used, bool is_mono,
991+
/* apply HW DMA Chunk Size limitations */
992+
static void mchp_asrc_maxburst_limit(int thr_opmode, int rhr_opmode, bool is_mono,
994993
int *maxburst)
995994
{
996-
if ((thr_opmode == 0 || rhr_opmode == 0 || dsps_used == 1) &&
995+
if ((thr_opmode == 0 || rhr_opmode == 0) &&
997996
*maxburst > 4) {
998997
if (is_mono)
999998
*maxburst = 4;
@@ -1032,9 +1031,9 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
10321031
int ratio_min;
10331032
struct list_head *list_head_bes;
10341033
int i;
1035-
int maxburst[MCHP_ASRC_NB_STEREO_CH] = {0};
10361034
struct opmode_to_slot const *be_opm;
10371035
struct xmit_ch *tc;
1036+
bool is_mono = false;
10381037

10391038
dev_dbg(priv->dev, "%s() DAI %s id %d rate=%u format=%#x width=%u channels=%u\n",
10401039
__func__, dai->name, dai->id, fs, params ? params_format(params) : 0,
@@ -1092,11 +1091,8 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
10921091
goto __cleanup_bes;
10931092

10941093
if (!pcm->is_hostless) {
1095-
int period_size = snd_pcm_lib_period_bytes(substream);
1096-
10971094
pcm->rtm_fe.hw_params = params;
10981095
pcm->rtm_fe.trig = NULL;
1099-
pcm->rtm_fe.maxburst = mchp_asrc_period_to_burst(period_size);
11001096

11011097
/* keep the order */
11021098
if (is_playback)
@@ -1166,12 +1162,17 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
11661162
struct mchp_asrc_slot const *slot_be = rtm_be->slot;
11671163
int chan_be = params_channels(rtm_be->hw_params);
11681164
u32 idx = trig_be ? trig_be->idx : 0;
1165+
int physical_width = params_physical_width(rtm_be->hw_params) / 8;
1166+
int period_bytes = params_period_size(rtm_be->hw_params) *
1167+
params_channels(rtm_be->hw_params) * physical_width;
1168+
int maxburst = mchp_asrc_period_to_burst(period_bytes, physical_width);
11691169

11701170
/* treat odd streams, set only last DSP as mono */
11711171
if (chan_be % 2) {
11721172
dsp = slot_be->first_dsp + slot_be->dsp_count - 1;
11731173
ch_conf |= MCHP_ASRC_CH_CONF_MONO(dsp);
11741174
ch_conf_mask |= MCHP_ASRC_CH_CONF_MONO(dsp);
1175+
is_mono = true;
11751176
}
11761177

11771178
for (dsp = slot_be->first_dsp;
@@ -1190,23 +1191,32 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
11901191
if (max_sr < params_rate(rtm_be->hw_params))
11911192
max_sr = params_rate(rtm_be->hw_params);
11921193

1193-
maxburst[slot_be->slot_id] = rtm_be->maxburst;
1194+
if (pcm->maxburst)
1195+
pcm->maxburst = min(pcm->maxburst, maxburst);
1196+
else
1197+
pcm->maxburst = maxburst;
11941198

1195-
mchp_asrc_maxburst_limit(priv->thr_opmode, priv->rhr_opmode, slot_be->dsp_count,
1196-
chan_be % 2, &maxburst[slot_be->slot_id]);
1199+
dev_dbg(priv->dev, "%s: period bytes %d, width %d -> maxburst %d\n",
1200+
trig_be ? trig_be->phandle->np->full_name : dai->name,
1201+
period_bytes, physical_width, maxburst);
11971202
}
11981203

11991204
list_for_each_entry(rtm_be, &pcm->list_head_out, list) {
12001205
struct mchp_asrc_be_trigger *trig_be = rtm_be->trig;
12011206
struct mchp_asrc_slot const *slot_be = rtm_be->slot;
12021207
int chan_be = params_channels(rtm_be->hw_params);
1208+
int physical_width = params_physical_width(rtm_be->hw_params) / 8;
1209+
int period_bytes = params_period_size(rtm_be->hw_params) *
1210+
params_channels(rtm_be->hw_params) * physical_width;
1211+
int maxburst = mchp_asrc_period_to_burst(period_bytes, physical_width);
12031212
u32 idx = trig_be ? trig_be->idx : 0;
12041213

12051214
/* treat odd streams, set only last DSP as mono */
12061215
if (chan_be % 2) {
12071216
dsp = slot_be->first_dsp + slot_be->dsp_count - 1;
12081217
ch_conf |= MCHP_ASRC_CH_CONF_MONO(dsp);
12091218
ch_conf_mask |= MCHP_ASRC_CH_CONF_MONO(dsp);
1219+
is_mono = true;
12101220
}
12111221

12121222
for (dsp = slot_be->first_dsp;
@@ -1225,15 +1235,19 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12251235
if (max_sr < params_rate(rtm_be->hw_params))
12261236
max_sr = params_rate(rtm_be->hw_params);
12271237

1228-
if (!maxburst[slot_be->slot_id] ||
1229-
maxburst[slot_be->slot_id] > rtm_be->maxburst)
1230-
maxburst[slot_be->slot_id] = rtm_be->maxburst;
1238+
if (pcm->maxburst)
1239+
pcm->maxburst = min(pcm->maxburst, maxburst);
1240+
else
1241+
pcm->maxburst = maxburst;
12311242

1232-
mchp_asrc_maxburst_limit(priv->thr_opmode, priv->rhr_opmode,
1233-
slot_be->dsp_count, chan_be % 2,
1234-
&maxburst[slot_be->slot_id]);
1243+
dev_dbg(priv->dev, "%s: period bytes %d, width %d -> maxburst %d\n",
1244+
trig_be ? trig_be->phandle->np->full_name : dai->name,
1245+
period_bytes, physical_width, maxburst);
12351246
}
12361247

1248+
mchp_asrc_maxburst_limit(priv->thr_opmode, priv->rhr_opmode, is_mono, &pcm->maxburst);
1249+
dev_dbg(priv->dev, "maxburst value to be used by all DSPs: %d\n", pcm->maxburst);
1250+
12371251
/* set DMAengine data for each IN/OUT AIF */
12381252
INIT_LIST_HEAD(&dma->dma_in_list);
12391253
list_for_each_entry(rtm_be, &pcm->list_head_in, list) {
@@ -1255,7 +1269,7 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12551269
ret = -ENOMEM;
12561270
goto __cleanup_dma_bes;
12571271
}
1258-
dma_data_be->maxburst = maxburst[slot_be->slot_id];
1272+
dma_data_be->maxburst = pcm->maxburst;
12591273

12601274
/* keep the order of the BEs */
12611275
list_add_tail(&dma_be->list, &dma->dma_in_list);
@@ -1287,13 +1301,13 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12871301
ret = -ENOMEM;
12881302
goto __cleanup_dma_bes;
12891303
}
1290-
dma_data_be->maxburst = maxburst[slot_be->slot_id];
1304+
dma_data_be->maxburst = pcm->maxburst;
12911305

12921306
/* needed only once, since the same DPSs are used for IN and OUT AIFs */
12931307
for (dsp = slot_be->first_dsp; dsp < slot_be->first_dsp + slot_be->dsp_count;
12941308
dsp++) {
12951309
ch_conf |= mchp_asrc_burst_to_chunk(dsp,
1296-
maxburst[slot_be->slot_id]);
1310+
pcm->maxburst);
12971311
ch_conf_mask |= MCHP_ASRC_CH_CONF_CHUNK_MASK(dsp);
12981312
}
12991313

0 commit comments

Comments
 (0)