Skip to content

Commit 2e00b0a

Browse files
author
Codrin Ciubotariu
committed
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>
1 parent f823ae2 commit 2e00b0a

1 file changed

Lines changed: 41 additions & 28 deletions

File tree

sound/soc/atmel/mchp-asrc.c

Lines changed: 41 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;
@@ -715,7 +715,6 @@ static int mchp_asrc_bes_get(struct mchp_asrc_dev *priv, struct snd_pcm_substrea
715715
params_format(&dpcm->hw_params), params_width(&dpcm->hw_params),
716716
params_channels(&dpcm->hw_params));
717717

718-
period_bytes = snd_pcm_lib_period_bytes(substream_be);
719718
for (i = 0; i < priv->trig_count; i++) {
720719
struct mchp_asrc_be_trigger *trig_be = &priv->trig[i];
721720
struct mchp_asrc_be_rtm *rtm_be;
@@ -730,7 +729,6 @@ static int mchp_asrc_bes_get(struct mchp_asrc_dev *priv, struct snd_pcm_substrea
730729
if (set_trig)
731730
rtm_be->trig = trig_be;
732731
rtm_be->hw_params = &dpcm->hw_params;
733-
rtm_be->maxburst = mchp_asrc_period_to_burst(period_bytes);
734732

735733
/* keep the order */
736734
list_add_tail(&rtm_be->list, head);
@@ -987,11 +985,11 @@ static void mchp_asrc_tc_free(struct mchp_asrc_dev *priv, struct mchp_asrc_pcm_p
987985
MCHP_ASRC_CH_CONF_THROPMODE_MASK | MCHP_ASRC_CH_CONF_RHROPMODE_MASK, 0);
988986
}
989987

990-
static void mchp_asrc_maxburst_limit(int thr_opmode, int rhr_opmode,
991-
int dsps_used, bool is_mono,
988+
/* apply HW DMA Chunk Size limitations */
989+
static void mchp_asrc_maxburst_limit(int thr_opmode, int rhr_opmode, bool is_mono,
992990
int *maxburst)
993991
{
994-
if ((thr_opmode == 0 || rhr_opmode == 0 || dsps_used == 1) &&
992+
if ((thr_opmode == 0 || rhr_opmode == 0) &&
995993
*maxburst > 4) {
996994
if (is_mono)
997995
*maxburst = 4;
@@ -1031,9 +1029,9 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
10311029
int ratio_min;
10321030
struct list_head *list_head_bes;
10331031
int i;
1034-
int maxburst[MCHP_ASRC_NB_STEREO_CH] = {0};
10351032
struct opmode_to_slot const *be_opm;
10361033
struct xmit_ch *tc;
1034+
bool is_mono = false;
10371035

10381036
dev_dbg(priv->dev, "%s() DAI %s id %d rate=%u format=%#x width=%u channels=%u\n",
10391037
__func__, dai->name, dai->id, fs, params ? params_format(params) : 0,
@@ -1093,11 +1091,8 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
10931091
dsps_req = (ret + 1) / 2;
10941092

10951093
if (!pcm->is_hostless) {
1096-
int period_size = snd_pcm_lib_period_bytes(substream);
1097-
10981094
pcm->rtm_fe.hw_params = params;
10991095
pcm->rtm_fe.trig = NULL;
1100-
pcm->rtm_fe.maxburst = mchp_asrc_period_to_burst(period_size);
11011096

11021097
/* keep the order */
11031098
if (is_playback)
@@ -1167,12 +1162,17 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
11671162
struct mchp_asrc_slot const *slot_be = rtm_be->slot;
11681163
int chan_be = params_channels(rtm_be->hw_params);
11691164
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);
11701169

11711170
/* treat odd streams, set only last DSP as mono */
11721171
if (chan_be % 2) {
11731172
dsp = slot_be->first_dsp + slot_be->dsp_count - 1;
11741173
ch_conf |= MCHP_ASRC_CH_CONF_MONO(dsp);
11751174
ch_conf_mask |= MCHP_ASRC_CH_CONF_MONO(dsp);
1175+
is_mono = true;
11761176
}
11771177

11781178
for (dsp = slot_be->first_dsp;
@@ -1191,23 +1191,32 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
11911191
if (max_sr < params_rate(rtm_be->hw_params))
11921192
max_sr = params_rate(rtm_be->hw_params);
11931193

1194-
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;
11951198

1196-
mchp_asrc_maxburst_limit(priv->thr_opmode, priv->rhr_opmode, slot_be->dsp_count,
1197-
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);
11981202
}
11991203

12001204
list_for_each_entry(rtm_be, &pcm->list_head_out, list) {
12011205
struct mchp_asrc_be_trigger *trig_be = rtm_be->trig;
12021206
struct mchp_asrc_slot const *slot_be = rtm_be->slot;
12031207
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);
12041212
u32 idx = trig_be ? trig_be->idx : 0;
12051213

12061214
/* treat odd streams, set only last DSP as mono */
12071215
if (chan_be % 2) {
12081216
dsp = slot_be->first_dsp + slot_be->dsp_count - 1;
12091217
ch_conf |= MCHP_ASRC_CH_CONF_MONO(dsp);
12101218
ch_conf_mask |= MCHP_ASRC_CH_CONF_MONO(dsp);
1219+
is_mono = true;
12111220
}
12121221

12131222
for (dsp = slot_be->first_dsp;
@@ -1226,15 +1235,19 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12261235
if (max_sr < params_rate(rtm_be->hw_params))
12271236
max_sr = params_rate(rtm_be->hw_params);
12281237

1229-
if (!maxburst[slot_be->slot_id] ||
1230-
maxburst[slot_be->slot_id] > rtm_be->maxburst)
1231-
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;
12321242

1233-
mchp_asrc_maxburst_limit(priv->thr_opmode, priv->rhr_opmode,
1234-
slot_be->dsp_count, chan_be % 2,
1235-
&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);
12361246
}
12371247

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+
12381251
/* set DMAengine data for each IN/OUT AIF */
12391252
INIT_LIST_HEAD(&dma->dma_in_list);
12401253
list_for_each_entry(rtm_be, &pcm->list_head_in, list) {
@@ -1256,7 +1269,7 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12561269
ret = -ENOMEM;
12571270
goto __cleanup_dma_bes;
12581271
}
1259-
dma_data_be->maxburst = maxburst[slot_be->slot_id];
1272+
dma_data_be->maxburst = pcm->maxburst;
12601273

12611274
/* keep the order of the BEs */
12621275
list_add_tail(&dma_be->list, &dma->dma_in_list);
@@ -1288,13 +1301,13 @@ static int mchp_asrc_hw_params(struct snd_pcm_substream *substream,
12881301
ret = -ENOMEM;
12891302
goto __cleanup_dma_bes;
12901303
}
1291-
dma_data_be->maxburst = maxburst[slot_be->slot_id];
1304+
dma_data_be->maxburst = pcm->maxburst;
12921305

12931306
/* needed only once, since the same DPSs are used for IN and OUT AIFs */
12941307
for (dsp = slot_be->first_dsp; dsp < slot_be->first_dsp + slot_be->dsp_count;
12951308
dsp++) {
12961309
ch_conf |= mchp_asrc_burst_to_chunk(dsp,
1297-
maxburst[slot_be->slot_id]);
1310+
pcm->maxburst);
12981311
ch_conf_mask |= MCHP_ASRC_CH_CONF_CHUNK_MASK(dsp);
12991312
}
13001313

0 commit comments

Comments
 (0)