ALSA: intel-nhlt: add helper to detect SSP link mask

The NHLT information can be used to figure out which SSPs are enabled
in a platform.

The 'SSP' link type is too broad for machine drivers, since it can
cover the Bluetooth sideband and the analog audio codec connections,
so this helper exposes a parameter to filter with the device
type (DEVICE_I2S refers to analog audio codec in NHLT parlance).

The helper returns a mask, since more than one SSP may be used for
analog audio, e.g. the NHLT spec describes the use of SSP0 for
amplifiers and SSP1 for headset codec. Note that if more than one bit
is set, it's impossible to determine which SSP is connected to what
external component. Additional platform-specific information based on
e.g. DMI quirks would still be required in the machine driver to
configure the relevant dailinks.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20220308192610.392950-5-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Pierre-Louis Bossart 2022-03-08 13:25:54 -06:00 committed by Mark Brown
parent 92c1b7c0f7
commit 0c470db039
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 37 additions and 7 deletions

View File

@ -18,6 +18,13 @@ enum nhlt_link_type {
NHLT_LINK_INVALID NHLT_LINK_INVALID
}; };
enum nhlt_device_type {
NHLT_DEVICE_BT = 0,
NHLT_DEVICE_DMIC = 1,
NHLT_DEVICE_I2S = 4,
NHLT_DEVICE_INVALID
};
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT)
struct wav_fmt { struct wav_fmt {
@ -41,13 +48,6 @@ struct wav_fmt_ext {
u8 sub_fmt[16]; u8 sub_fmt[16];
} __packed; } __packed;
enum nhlt_device_type {
NHLT_DEVICE_BT = 0,
NHLT_DEVICE_DMIC = 1,
NHLT_DEVICE_I2S = 4,
NHLT_DEVICE_INVALID
};
struct nhlt_specific_cfg { struct nhlt_specific_cfg {
u32 size; u32 size;
u8 caps[]; u8 caps[];
@ -133,6 +133,9 @@ void intel_nhlt_free(struct nhlt_acpi_table *addr);
int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt);
bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type); bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type);
int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type);
struct nhlt_specific_cfg * struct nhlt_specific_cfg *
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
u32 bus_id, u8 link_type, u8 vbps, u8 bps, u32 bus_id, u8 link_type, u8 vbps, u8 bps,
@ -163,6 +166,11 @@ static inline bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt,
return false; return false;
} }
static inline int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type)
{
return 0;
}
static inline struct nhlt_specific_cfg * static inline struct nhlt_specific_cfg *
intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt,
u32 bus_id, u8 link_type, u8 vbps, u8 bps, u32 bus_id, u8 link_type, u8 vbps, u8 bps,

View File

@ -130,6 +130,28 @@ bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type)
} }
EXPORT_SYMBOL(intel_nhlt_has_endpoint_type); EXPORT_SYMBOL(intel_nhlt_has_endpoint_type);
int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type)
{
struct nhlt_endpoint *epnt;
int ssp_mask = 0;
int i;
if (!nhlt || (device_type != NHLT_DEVICE_BT && device_type != NHLT_DEVICE_I2S))
return 0;
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (i = 0; i < nhlt->endpoint_count; i++) {
if (epnt->linktype == NHLT_LINK_SSP && epnt->device_type == device_type) {
/* for SSP the virtual bus id is the SSP port */
ssp_mask |= BIT(epnt->virtual_bus_id);
}
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
return ssp_mask;
}
EXPORT_SYMBOL(intel_nhlt_ssp_endpoint_mask);
static struct nhlt_specific_cfg * static struct nhlt_specific_cfg *
nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch, nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch,
u32 rate, u8 vbps, u8 bps) u32 rate, u8 vbps, u8 bps)