Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support BT audio offload on HDA machines #5123

Merged
merged 2 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 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
13 changes: 13 additions & 0 deletions sound/soc/intel/boards/skl_hda_dsp_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ SND_SOC_DAILINK_DEF(dmic_codec,
SND_SOC_DAILINK_DEF(dmic16k,
DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));

SND_SOC_DAILINK_DEF(bt_offload_pin,
DAILINK_COMP_ARRAY(COMP_CPU(""))); /* initialized in driver probe function */
SND_SOC_DAILINK_DEF(dummy,
DAILINK_COMP_ARRAY(COMP_DUMMY()));

SND_SOC_DAILINK_DEF(platform,
DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));

Expand Down Expand Up @@ -132,6 +137,14 @@ struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = {
.no_pcm = 1,
SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
},
{
.name = NULL, /* initialized in driver probe function */
.id = 8,
.dpcm_playback = 1,
.dpcm_capture = 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot if those flags still exist or have been removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet removed. still doing some cleanups
https://patchwork.kernel.org/project/alsa-devel/list/?series=874792

.no_pcm = 1,
SND_SOC_DAILINK_REG(bt_offload_pin, dummy, platform),
},
};

int skl_hda_hdmi_jack_init(struct snd_soc_card *card)
Expand Down
4 changes: 3 additions & 1 deletion sound/soc/intel/boards/skl_hda_dsp_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "../../codecs/hdac_hda.h"
#include "hda_dsp_common.h"

#define HDA_DSP_MAX_BE_DAI_LINKS 7
#define HDA_DSP_MAX_BE_DAI_LINKS 8

struct skl_hda_hdmi_pcm {
struct list_head head;
Expand All @@ -35,6 +35,8 @@ struct skl_hda_private {
const char *platform_name;
bool common_hdmi_codec_drv;
bool idisp_codec;
bool bt_offload_present;
int ssp_bt;
};

extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS];
Expand Down
37 changes: 33 additions & 4 deletions sound/soc/intel/boards/skl_hda_dsp_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,20 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
#define IDISP_DAI_COUNT 3
#define HDAC_DAI_COUNT 2
#define DMIC_DAI_COUNT 2
#define BT_DAI_COUNT 1

/* there are two routes per iDisp output */
#define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2)
#define IDISP_CODEC_MASK 0x4

#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000

static int skl_hda_fill_card_info(struct snd_soc_card *card,
static int skl_hda_fill_card_info(struct device *dev, struct snd_soc_card *card,
struct snd_soc_acpi_mach_params *mach_params)
{
struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_dai_link *dai_link;
struct snd_soc_dai_link *bt_link;
u32 codec_count, codec_mask;
int i, num_links, num_route;

Expand All @@ -120,7 +122,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,

if (codec_mask == IDISP_CODEC_MASK) {
/* topology with iDisp as the only HDA codec */
num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT;
num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT + BT_DAI_COUNT;
num_route = IDISP_ROUTE_COUNT;

/*
Expand All @@ -129,7 +131,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
* num_links of dai links need to be registered
* to ASoC.
*/
for (i = 0; i < DMIC_DAI_COUNT; i++) {
for (i = 0; i < (DMIC_DAI_COUNT + BT_DAI_COUNT); i++) {
skl_hda_be_dai_links[IDISP_DAI_COUNT + i] =
skl_hda_be_dai_links[IDISP_DAI_COUNT +
HDAC_DAI_COUNT + i];
Expand All @@ -150,6 +152,28 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
}
}

if (!ctx->bt_offload_present) {
/* remove last link since bt audio offload is not supported */
num_links -= BT_DAI_COUNT;
} else {
if (codec_mask == IDISP_CODEC_MASK)
bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + DMIC_DAI_COUNT];
else
bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + HDAC_DAI_COUNT + DMIC_DAI_COUNT];

/* complete the link name and dai name with SSP port number */
bt_link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT",
ctx->ssp_bt);
plbossart marked this conversation as resolved.
Show resolved Hide resolved
if (!bt_link->name)
return -ENOMEM;

bt_link->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"SSP%d Pin",
ctx->ssp_bt);
if (!bt_link->cpus->dai_name)
return -ENOMEM;
}

card->num_links = num_links;
card->num_dapm_routes = num_route;

Expand Down Expand Up @@ -213,7 +237,12 @@ static int skl_hda_audio_probe(struct platform_device *pdev)

snd_soc_card_set_drvdata(card, ctx);

ret = skl_hda_fill_card_info(card, &mach->mach_params);
if (hweight_long(mach->mach_params.bt_link_mask) == 1) {
ctx->bt_offload_present = true;
ctx->ssp_bt = fls(mach->mach_params.bt_link_mask) - 1;
}

ret = skl_hda_fill_card_info(&pdev->dev, card, &mach->mach_params);
if (ret < 0) {
dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
return ret;
Expand Down
37 changes: 32 additions & 5 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;
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,11 @@ 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 %s(%d) detected, ssp_mask %#x\n",
device_type == NHLT_DEVICE_BT ? "BT" : "I2S",
device_type, ssp_mask);
}

return ssp_mask;
Expand Down Expand Up @@ -1233,8 +1239,29 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
* Otherwise, set certain mach params.
*/
hda_generic_machine_select(sdev, &mach);
if (!mach)
if (!mach) {
dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
return NULL;
}

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

dev_info(sdev->dev, "BT link detected in NHLT tables: %#x\n",
mach->mach_params.bt_link_mask);

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

if (hweight_long(mach->mach_params.bt_link_mask) > 1) {
dev_warn(sdev->dev, "invalid BT link mask %#x found, reset the mask\n",
mach->mach_params.bt_link_mask);
mach->mach_params.bt_link_mask = 0;
}
plbossart marked this conversation as resolved.
Show resolved Hide resolved

/*
* Fixup tplg file name by appending dmic num, ssp num, codec/amplifier
Expand Down Expand Up @@ -1308,7 +1335,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
}

/* 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 &&
Expand Down
Loading