Skip to content

Commit 3716791

Browse files
chadmedmarcan
authored andcommitted
ASoC: macaudio: constrain frontend channel counts
In order to support the wide range of audio arrangements possible on this platform in a generic way, it is necessary for the frontend PCMs to be populated with enough TDM slots to cover all intended use cases. Userspace therefore attempts to open "phantom" channels when a frontend has more channels than its associated backend, which results in garbled audio samples and dropped frames. We must therefore dynamically constrain the frontends when they are started to ensure that userspace can never open more channels than are present on the hardware being represented by the frontend in question. Signed-off-by: James Calligeros <[email protected]>
1 parent 1bfa127 commit 3716791

1 file changed

Lines changed: 25 additions & 0 deletions

File tree

sound/soc/apple/macaudio.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct macaudio_snd_data {
5252
int jack_plugin_state;
5353

5454
bool has_speakers;
55+
unsigned int max_channels;
5556

5657
struct macaudio_link_props {
5758
/* frontend props */
@@ -345,6 +346,10 @@ static int macaudio_parse_of(struct macaudio_snd_data *ma)
345346
ncodecs_per_cpu = num_codecs / num_bes;
346347
nchannels = num_codecs * (speakers ? 1 : 2);
347348

349+
/* Save the max number of channels on the platform */
350+
if (nchannels > ma->max_channels)
351+
ma->max_channels = nchannels;
352+
348353
/*
349354
* If there is a single speaker, assign two channels to it, because
350355
* it can do downmix.
@@ -455,6 +460,25 @@ static int macaudio_dpcm_hw_params(struct snd_pcm_substream *substream,
455460
return 0;
456461
}
457462

463+
static int macaudio_fe_startup(struct snd_pcm_substream *substream)
464+
{
465+
466+
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
467+
struct macaudio_snd_data *ma = snd_soc_card_get_drvdata(rtd->card);
468+
int ret;
469+
470+
/* The FEs must never have more channels than the hardware */
471+
ret = snd_pcm_hw_constraint_minmax(substream->runtime,
472+
SNDRV_PCM_HW_PARAM_CHANNELS, 0, ma->max_channels);
473+
474+
if (ret < 0) {
475+
dev_err(rtd->dev, "Failed to constrain FE %d! %d", rtd->dai_link->id, ret);
476+
return ret;
477+
}
478+
479+
return 0;
480+
}
481+
458482
static int macaudio_fe_hw_params(struct snd_pcm_substream *substream,
459483
struct snd_pcm_hw_params *params)
460484
{
@@ -495,6 +519,7 @@ static void macaudio_dpcm_shutdown(struct snd_pcm_substream *substream)
495519
}
496520

497521
static const struct snd_soc_ops macaudio_fe_ops = {
522+
.startup = macaudio_fe_startup,
498523
.shutdown = macaudio_dpcm_shutdown,
499524
.hw_params = macaudio_fe_hw_params,
500525
};

0 commit comments

Comments
 (0)