Skip to content

Commit 15fa179

Browse files
Amadeusz Sławińskitiwai
authored andcommitted
ALSA: hda: Fill gaps in NHLT endpoint-interface
Two key operations missings are: endpoint presence-check and retrieval of matching endpoint hardware configuration (blob). Add operations for both use cases. Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20211126140355.1042684-2-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 6dd21ad commit 15fa179

2 files changed

Lines changed: 131 additions & 8 deletions

File tree

include/sound/intel-nhlt.h

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
#include <linux/acpi.h>
1212

13+
enum nhlt_link_type {
14+
NHLT_LINK_HDA = 0,
15+
NHLT_LINK_DSP = 1,
16+
NHLT_LINK_DMIC = 2,
17+
NHLT_LINK_SSP = 3,
18+
NHLT_LINK_INVALID
19+
};
20+
1321
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
1422

1523
struct wav_fmt {
@@ -33,14 +41,6 @@ struct wav_fmt_ext {
3341
u8 sub_fmt[16];
3442
} __packed;
3543

36-
enum nhlt_link_type {
37-
NHLT_LINK_HDA = 0,
38-
NHLT_LINK_DSP = 1,
39-
NHLT_LINK_DMIC = 2,
40-
NHLT_LINK_SSP = 3,
41-
NHLT_LINK_INVALID
42-
};
43-
4444
enum nhlt_device_type {
4545
NHLT_DEVICE_BT = 0,
4646
NHLT_DEVICE_DMIC = 1,
@@ -132,6 +132,12 @@ void intel_nhlt_free(struct nhlt_acpi_table *addr);
132132

133133
int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt);
134134

135+
bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type);
136+
struct nhlt_specific_cfg *
137+
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
138+
u32 bus_id, u8 link_type, u8 vbps, u8 bps,
139+
u8 num_ch, u32 rate, u8 dir, u8 dev_type);
140+
135141
#else
136142

137143
struct nhlt_acpi_table;
@@ -150,6 +156,21 @@ static inline int intel_nhlt_get_dmic_geo(struct device *dev,
150156
{
151157
return 0;
152158
}
159+
160+
static inline bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt,
161+
u8 link_type)
162+
{
163+
return false;
164+
}
165+
166+
static inline struct nhlt_specific_cfg *
167+
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
168+
u32 bus_id, u8 link_type, u8 vbps, u8 bps,
169+
u8 num_ch, u32 rate, u8 dir, u8 dev_type)
170+
{
171+
return NULL;
172+
}
173+
153174
#endif
154175

155176
#endif

sound/hda/intel-nhlt.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,105 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
110110
return dmic_geo;
111111
}
112112
EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);
113+
114+
bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type)
115+
{
116+
struct nhlt_endpoint *epnt;
117+
int i;
118+
119+
if (!nhlt)
120+
return false;
121+
122+
epnt = (struct nhlt_endpoint *)nhlt->desc;
123+
for (i = 0; i < nhlt->endpoint_count; i++) {
124+
if (epnt->linktype == link_type)
125+
return true;
126+
127+
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
128+
}
129+
return false;
130+
}
131+
EXPORT_SYMBOL(intel_nhlt_has_endpoint_type);
132+
133+
static struct nhlt_specific_cfg *
134+
nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch,
135+
u32 rate, u8 vbps, u8 bps)
136+
{
137+
struct nhlt_fmt_cfg *cfg = fmt->fmt_config;
138+
struct wav_fmt *wfmt;
139+
u16 _bps, _vbps;
140+
int i;
141+
142+
dev_dbg(dev, "Endpoint format count=%d\n", fmt->fmt_count);
143+
144+
for (i = 0; i < fmt->fmt_count; i++) {
145+
wfmt = &cfg->fmt_ext.fmt;
146+
_bps = wfmt->bits_per_sample;
147+
_vbps = cfg->fmt_ext.sample.valid_bits_per_sample;
148+
149+
dev_dbg(dev, "Endpoint format: ch=%d fmt=%d/%d rate=%d\n",
150+
wfmt->channels, _vbps, _bps, wfmt->samples_per_sec);
151+
152+
if (wfmt->channels == num_ch && wfmt->samples_per_sec == rate &&
153+
vbps == _vbps && bps == _bps)
154+
return &cfg->config;
155+
156+
cfg = (struct nhlt_fmt_cfg *)(cfg->config.caps + cfg->config.size);
157+
}
158+
159+
return NULL;
160+
}
161+
162+
static bool nhlt_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt,
163+
u32 bus_id, u8 link_type, u8 dir, u8 dev_type)
164+
{
165+
dev_dbg(dev, "Endpoint: vbus_id=%d link_type=%d dir=%d dev_type = %d\n",
166+
epnt->virtual_bus_id, epnt->linktype,
167+
epnt->direction, epnt->device_type);
168+
169+
if ((epnt->virtual_bus_id != bus_id) ||
170+
(epnt->linktype != link_type) ||
171+
(epnt->direction != dir))
172+
return false;
173+
174+
/* link of type DMIC bypasses device_type check */
175+
return epnt->linktype == NHLT_LINK_DMIC ||
176+
epnt->device_type == dev_type;
177+
}
178+
179+
struct nhlt_specific_cfg *
180+
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
181+
u32 bus_id, u8 link_type, u8 vbps, u8 bps,
182+
u8 num_ch, u32 rate, u8 dir, u8 dev_type)
183+
{
184+
struct nhlt_specific_cfg *cfg;
185+
struct nhlt_endpoint *epnt;
186+
struct nhlt_fmt *fmt;
187+
int i;
188+
189+
if (!nhlt)
190+
return NULL;
191+
192+
dev_dbg(dev, "Looking for configuration:\n");
193+
dev_dbg(dev, " vbus_id=%d link_type=%d dir=%d, dev_type=%d\n",
194+
bus_id, link_type, dir, dev_type);
195+
dev_dbg(dev, " ch=%d fmt=%d/%d rate=%d\n", num_ch, vbps, bps, rate);
196+
dev_dbg(dev, "Endpoint count=%d\n", nhlt->endpoint_count);
197+
198+
epnt = (struct nhlt_endpoint *)nhlt->desc;
199+
200+
for (i = 0; i < nhlt->endpoint_count; i++) {
201+
if (nhlt_check_ep_match(dev, epnt, bus_id, link_type, dir, dev_type)) {
202+
fmt = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
203+
204+
cfg = nhlt_get_specific_cfg(dev, fmt, num_ch, rate, vbps, bps);
205+
if (cfg)
206+
return cfg;
207+
}
208+
209+
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
210+
}
211+
212+
return NULL;
213+
}
214+
EXPORT_SYMBOL(intel_nhlt_get_endpoint_blob);

0 commit comments

Comments
 (0)