Skip to content

Commit

Permalink
ASoC: SOF: Intel: hda: add tplg quirk flag for BT audio offload
Browse files Browse the repository at this point in the history
Add an new quirk flag SND_SOC_ACPI_TPLG_INTEL_BT_OFFLOAD to fixup tplg
file name with '-bt-sspX' suffix when the support of BT audio offload
is found in NHLT table. SSP port mask of BT offload will be sent to
machine driver to setup BE dai link with correct SSP port number.

Signed-off-by: Brent Lu <brent.lu@intel.com>
  • Loading branch information
brentlu committed Jul 27, 2024
1 parent dc9dd7b commit 36f1768
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
8 changes: 8 additions & 0 deletions include/sound/soc-acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
* @subsystem_rev: optional PCI SSID revision value
* @subsystem_id_set: true if a value has been written to
* subsystem_vendor and subsystem_device.
* @bt_link_mask: BT offload link enabled on the board
*/
struct snd_soc_acpi_mach_params {
u32 acpi_ipc_irq_index;
Expand All @@ -89,6 +90,7 @@ struct snd_soc_acpi_mach_params {
unsigned short subsystem_device;
unsigned short subsystem_rev;
bool subsystem_id_set;
u32 bt_link_mask;
};

/**
Expand Down Expand Up @@ -165,6 +167,12 @@ struct snd_soc_acpi_link_adr {
*/
#define SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME BIT(4)

/*
* when set the BT offload name suffix '-bt' will be appended to topology file
* name if the feature is implemented in ACPI NHLT table
*/
#define SND_SOC_ACPI_TPLG_INTEL_BT_OFFLOAD BIT(5)

/**
* snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are
* related to the hardware, except for the firmware and topology file names.
Expand Down
58 changes: 52 additions & 6 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ static int mclk_id_override = -1;
module_param_named(mclk_id, mclk_id_override, int, 0444);
MODULE_PARM_DESC(mclk_id, "SOF SSP mclk_id");

static int bt_link_mask_override = 0x0;
module_param_named(bt_link_mask, bt_link_mask_override, int, 0444);
MODULE_PARM_DESC(bt_link_mask, "SOF BT offload link mask");

static int hda_init(struct snd_sof_dev *sdev)
{
struct hda_bus *hbus;
Expand Down Expand Up @@ -529,7 +533,7 @@ static int check_dmic_num(struct snd_sof_dev *sdev)
return dmic_num;
}

static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev)
static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev, u8 device_type)
{
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
struct nhlt_acpi_table *nhlt;
Expand All @@ -540,9 +544,10 @@ static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev)
return ssp_mask;

if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP)) {
ssp_mask = intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S);
ssp_mask = intel_nhlt_ssp_endpoint_mask(nhlt, device_type);
if (ssp_mask)
dev_info(sdev->dev, "NHLT_DEVICE_I2S detected, ssp_mask %#x\n", ssp_mask);
dev_info(sdev->dev, "NHLT device %d detected, ssp_mask %#x\n",
device_type, ssp_mask);
}

return ssp_mask;
Expand Down Expand Up @@ -1201,6 +1206,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
u32 interface_mask = hda_get_interface_mask(sdev);
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata);
struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_acpi_mach *mach = NULL;
enum snd_soc_acpi_intel_codec codec_type, amp_type;
Expand All @@ -1209,6 +1215,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
bool amp_name_valid;
bool i2s_mach_found = false;
bool sdw_mach_found = false;
int ssp_num;


/* Try I2S or DMIC if it is supported */
if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) {
Expand Down Expand Up @@ -1302,19 +1310,57 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
sof_pdata->tplg_filename = tplg_filename;
}

/* report BT offload link mask to machine driver */
mach->mach_params.bt_link_mask = check_nhlt_ssp_mask(sdev, NHLT_DEVICE_BT);

/* allow for module parameter override */
if (bt_link_mask_override != 0x00) {
dev_dbg(sdev->dev,
"overriding bt link mask detected in NHLT tables 0x%x by kernel param 0x%x\n",
mach->mach_params.bt_link_mask,
bt_link_mask_override);
mach->mach_params.bt_link_mask = bt_link_mask_override;
}

if (tplg_fixup &&
mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_BT_OFFLOAD &&
mach->mach_params.bt_link_mask) {
if (hweight_long(mach->mach_params.bt_link_mask) > 1) {
dev_warn(sdev->dev, "invalid bt link mask 0x%x found\n",
mach->mach_params.bt_link_mask);
return NULL;
}

/* fls returns 1-based results, SSPs indices are 0-based */
ssp_num = fls(mach->mach_params.bt_link_mask) - 1;

if (ssp_num >= chip->ssp_count) {
dev_err(sdev->dev, "invalid SSP %d, max on this platform is %d\n",
ssp_num, chip->ssp_count);
return NULL;
}

tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s-bt-ssp%d",
sof_pdata->tplg_filename,
ssp_num);
if (!tplg_filename)
return NULL;

sof_pdata->tplg_filename = tplg_filename;
}

if (mach->link_mask) {
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
}

/* report SSP link mask to machine driver */
mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev);
mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev, NHLT_DEVICE_I2S);

if (tplg_fixup &&
mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER &&
mach->mach_params.i2s_link_mask) {
const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata);
int ssp_num;
int mclk_mask;

if (hweight_long(mach->mach_params.i2s_link_mask) > 1 &&
Expand Down

0 comments on commit 36f1768

Please sign in to comment.