Skip to content

Commit 2264b15

Browse files
Amadeusz SławińskigShahr
authored andcommitted
ASoC: Intel: avs: Constrain path based on BE capabilities
For i2s and DMIC copiers constraint stream capabilities based on available NHLT configuration. This allows topology to provide generic configuration that handles more hardware, while filtering unavailable ones at runtime. Signed-off-by: Amadeusz Sławiński <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Cezary Rojewski <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 4a2eaad commit 2264b15

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

sound/soc/intel/avs/path.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,78 @@ avs_path_find_variant(struct avs_dev *adev,
115115
return NULL;
116116
}
117117

118+
static struct acpi_nhlt_config *
119+
avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t);
120+
121+
int avs_path_set_constraint(struct avs_dev *adev, struct avs_tplg_path_template *template,
122+
struct snd_pcm_hw_constraint_list *rate_list,
123+
struct snd_pcm_hw_constraint_list *channels_list,
124+
struct snd_pcm_hw_constraint_list *sample_bits_list)
125+
{
126+
struct avs_tplg_path *path_template;
127+
unsigned int *rlist, *clist, *slist;
128+
size_t i;
129+
130+
i = 0;
131+
list_for_each_entry(path_template, &template->path_list, node)
132+
i++;
133+
134+
rlist = kcalloc(i, sizeof(rlist), GFP_KERNEL);
135+
clist = kcalloc(i, sizeof(clist), GFP_KERNEL);
136+
slist = kcalloc(i, sizeof(slist), GFP_KERNEL);
137+
138+
i = 0;
139+
list_for_each_entry(path_template, &template->path_list, node) {
140+
struct avs_tplg_pipeline *pipeline_template;
141+
142+
list_for_each_entry(pipeline_template, &path_template->ppl_list, node) {
143+
struct avs_tplg_module *module_template;
144+
145+
list_for_each_entry(module_template, &pipeline_template->mod_list, node) {
146+
const guid_t *type = &module_template->cfg_ext->type;
147+
struct acpi_nhlt_config *blob;
148+
149+
if (!guid_equal(type, &AVS_COPIER_MOD_UUID) &&
150+
!guid_equal(type, &AVS_WOVHOSTM_MOD_UUID))
151+
continue;
152+
153+
switch (module_template->cfg_ext->copier.dma_type) {
154+
case AVS_DMA_DMIC_LINK_INPUT:
155+
case AVS_DMA_I2S_LINK_OUTPUT:
156+
case AVS_DMA_I2S_LINK_INPUT:
157+
break;
158+
default:
159+
continue;
160+
}
161+
162+
blob = avs_nhlt_config_or_default(adev, module_template);
163+
if (IS_ERR(blob))
164+
continue;
165+
166+
rlist[i] = path_template->fe_fmt->sampling_freq;
167+
clist[i] = path_template->fe_fmt->num_channels;
168+
slist[i] = path_template->fe_fmt->bit_depth;
169+
i++;
170+
}
171+
}
172+
}
173+
174+
if (i) {
175+
rate_list->count = i;
176+
rate_list->list = rlist;
177+
channels_list->count = i;
178+
channels_list->list = clist;
179+
sample_bits_list->count = i;
180+
sample_bits_list->list = slist;
181+
} else {
182+
kfree(rlist);
183+
kfree(clist);
184+
kfree(slist);
185+
}
186+
187+
return i;
188+
}
189+
118190
static void avs_init_node_id(union avs_connector_node_id *node_id,
119191
struct avs_tplg_modcfg_ext *te, u32 dma_id)
120192
{

sound/soc/intel/avs/path.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ int avs_path_reset(struct avs_path *path);
6969
int avs_path_pause(struct avs_path *path);
7070
int avs_path_run(struct avs_path *path, int trigger);
7171

72+
int avs_path_set_constraint(struct avs_dev *adev, struct avs_tplg_path_template *template,
73+
struct snd_pcm_hw_constraint_list *rate_list,
74+
struct snd_pcm_hw_constraint_list *channels_list,
75+
struct snd_pcm_hw_constraint_list *sample_bits_list);
76+
7277
int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod,
7378
struct soc_mixer_control *mc, long *input);
7479
int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod,

sound/soc/intel/avs/pcm.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ struct avs_dma_data {
3131
struct hdac_ext_stream *host_stream;
3232
};
3333

34+
struct snd_pcm_hw_constraint_list rate_list;
35+
struct snd_pcm_hw_constraint_list channels_list;
36+
struct snd_pcm_hw_constraint_list sample_bits_list;
37+
3438
struct work_struct period_elapsed_work;
3539
struct snd_pcm_substream *substream;
3640
};
@@ -74,6 +78,45 @@ void avs_period_elapsed(struct snd_pcm_substream *substream)
7478
schedule_work(&data->period_elapsed_work);
7579
}
7680

81+
static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
82+
static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
83+
{
84+
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
85+
struct snd_pcm_runtime *runtime = substream->runtime;
86+
struct snd_pcm_hw_constraint_list *r, *c, *s;
87+
struct avs_tplg_path_template *template;
88+
struct avs_dma_data *data;
89+
int ret;
90+
91+
ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
92+
if (ret < 0)
93+
return ret;
94+
95+
data = snd_soc_dai_get_dma_data(dai, substream);
96+
r = &(data->rate_list);
97+
c = &(data->channels_list);
98+
s = &(data->sample_bits_list);
99+
100+
template = avs_dai_find_path_template(dai, !rtd->dai_link->no_pcm, substream->stream);
101+
ret = avs_path_set_constraint(data->adev, template, r, c, s);
102+
if (ret <= 0)
103+
return ret;
104+
105+
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, r);
106+
if (ret < 0)
107+
return ret;
108+
109+
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, c);
110+
if (ret < 0)
111+
return ret;
112+
113+
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, s);
114+
if (ret < 0)
115+
return ret;
116+
117+
return 0;
118+
}
119+
77120
static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
78121
{
79122
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
@@ -101,7 +144,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d
101144
if (rtd->dai_link->ignore_suspend)
102145
adev->num_lp_paths++;
103146

104-
return 0;
147+
return avs_hw_constraints_init(substream, dai);
105148
}
106149

107150
static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
@@ -114,6 +157,10 @@ static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc
114157
if (rtd->dai_link->ignore_suspend)
115158
data->adev->num_lp_paths--;
116159

160+
kfree(data->rate_list.list);
161+
kfree(data->channels_list.list);
162+
kfree(data->sample_bits_list.list);
163+
117164
snd_soc_dai_set_dma_data(dai, substream, NULL);
118165
kfree(data);
119166
}

0 commit comments

Comments
 (0)