Commit af2ab6cc authored by Mark Brown's avatar Mark Brown

ASoc: SOF: misc updates for 6.10

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

Fixes when fw_lib_prefix is not set, updated error messages, improved
dmesg logs to SoundWire configurations not supported by ACPI
tables/topology and support for IEC61937 passthrough.
parents 34c43ad9 eed4872a
......@@ -326,8 +326,27 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev)
debugfs_create_str("fw_path", 0444, fw_profile,
(char **)&plat_data->fw_filename_prefix);
debugfs_create_str("fw_lib_path", 0444, fw_profile,
(char **)&plat_data->fw_lib_prefix);
/* library path is not valid for IPC3 */
if (plat_data->ipc_type != SOF_IPC_TYPE_3) {
/*
* fw_lib_prefix can be NULL if the vendor/platform does not
* support loadable libraries
*/
if (plat_data->fw_lib_prefix) {
debugfs_create_str("fw_lib_path", 0444, fw_profile,
(char **)&plat_data->fw_lib_prefix);
} else {
static char *fw_lib_path;
fw_lib_path = devm_kasprintf(sdev->dev, GFP_KERNEL,
"Not supported");
if (!fw_lib_path)
return -ENOMEM;
debugfs_create_str("fw_lib_path", 0444, fw_profile,
(char **)&fw_lib_path);
}
}
debugfs_create_str("tplg_path", 0444, fw_profile,
(char **)&plat_data->tplg_filename_prefix);
debugfs_create_str("fw_name", 0444, fw_profile,
......
......@@ -1645,6 +1645,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
{
struct snd_sof_pdata *pdata = sdev->pdata;
const struct snd_soc_acpi_link_adr *link;
struct sdw_extended_slave_id *ids;
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
u32 link_mask;
......@@ -1653,92 +1654,109 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
hdev = pdata->hw_pdata;
link_mask = hdev->info.link_mask;
if (!link_mask) {
dev_info(sdev->dev, "SoundWire links not enabled\n");
return NULL;
}
if (!hdev->sdw) {
dev_dbg(sdev->dev, "SoundWire context not allocated\n");
return NULL;
}
if (!hdev->sdw->num_slaves) {
dev_warn(sdev->dev, "No SoundWire peripheral detected in ACPI tables\n");
return NULL;
}
/*
* Select SoundWire machine driver if needed using the
* alternate tables. This case deals with SoundWire-only
* machines, for mixed cases with I2C/I2S the detection relies
* on the HID list.
*/
if (link_mask) {
for (mach = pdata->desc->alt_machines;
mach && mach->link_mask; mach++) {
/*
* On some platforms such as Up Extreme all links
* are enabled but only one link can be used by
* external codec. Instead of exact match of two masks,
* first check whether link_mask of mach is subset of
* link_mask supported by hw and then go on searching
* link_adr
*/
if (~link_mask & mach->link_mask)
continue;
/* No need to match adr if there is no links defined */
if (!mach->links)
break;
link = mach->links;
for (i = 0; i < hdev->info.count && link->num_adr;
i++, link++) {
/*
* Try next machine if any expected Slaves
* are not found on this link.
*/
if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
hdev->sdw->ids,
hdev->sdw->num_slaves))
break;
}
/* Found if all Slaves are checked */
if (i == hdev->info.count || !link->num_adr)
break;
}
if (mach && mach->link_mask) {
int dmic_num = 0;
bool tplg_fixup;
const char *tplg_filename;
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
for (mach = pdata->desc->alt_machines;
mach && mach->link_mask; mach++) {
/*
* On some platforms such as Up Extreme all links
* are enabled but only one link can be used by
* external codec. Instead of exact match of two masks,
* first check whether link_mask of mach is subset of
* link_mask supported by hw and then go on searching
* link_adr
*/
if (~link_mask & mach->link_mask)
continue;
if (pdata->tplg_filename) {
tplg_fixup = false;
} else {
tplg_fixup = true;
tplg_filename = mach->sof_tplg_filename;
}
/* No need to match adr if there is no links defined */
if (!mach->links)
break;
link = mach->links;
for (i = 0; i < hdev->info.count && link->num_adr;
i++, link++) {
/*
* DMICs use up to 4 pins and are typically pin-muxed with SoundWire
* link 2 and 3, or link 1 and 2, thus we only try to enable dmics
* if all conditions are true:
* a) 2 or fewer links are used by SoundWire
* b) the NHLT table reports the presence of microphones
* Try next machine if any expected Slaves
* are not found on this link.
*/
if (hweight_long(mach->link_mask) <= 2) {
int ret;
ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "",
&dmic_num, tplg_fixup);
if (ret < 0)
return NULL;
}
if (tplg_fixup)
pdata->tplg_filename = tplg_filename;
mach->mach_params.dmic_num = dmic_num;
if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
hdev->sdw->ids,
hdev->sdw->num_slaves))
break;
}
/* Found if all Slaves are checked */
if (i == hdev->info.count || !link->num_adr)
break;
}
if (mach && mach->link_mask) {
int dmic_num = 0;
bool tplg_fixup;
const char *tplg_filename;
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
if (pdata->tplg_filename) {
tplg_fixup = false;
} else {
tplg_fixup = true;
tplg_filename = mach->sof_tplg_filename;
}
dev_dbg(sdev->dev,
"SoundWire machine driver %s topology %s\n",
mach->drv_name,
pdata->tplg_filename);
/*
* DMICs use up to 4 pins and are typically pin-muxed with SoundWire
* link 2 and 3, or link 1 and 2, thus we only try to enable dmics
* if all conditions are true:
* a) 2 or fewer links are used by SoundWire
* b) the NHLT table reports the presence of microphones
*/
if (hweight_long(mach->link_mask) <= 2) {
int ret;
return mach;
ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "",
&dmic_num, tplg_fixup);
if (ret < 0)
return NULL;
}
if (tplg_fixup)
pdata->tplg_filename = tplg_filename;
mach->mach_params.dmic_num = dmic_num;
dev_info(sdev->dev, "No SoundWire machine driver found\n");
dev_dbg(sdev->dev,
"SoundWire machine driver %s topology %s\n",
mach->drv_name,
pdata->tplg_filename);
return mach;
}
dev_info(sdev->dev, "No SoundWire machine driver found for the ACPI-reported configuration:\n");
ids = hdev->sdw->ids;
for (i = 0; i < hdev->sdw->num_slaves; i++)
dev_info(sdev->dev, "link %d mfg_id 0x%04x part_id 0x%04x version %#x\n",
ids[i].link_id, ids[i].id.mfg_id, ids[i].id.part_id, ids[i].id.sdw_version);
return NULL;
}
#else
......
......@@ -407,6 +407,52 @@ static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swi
}
}
static int
sof_ipc4_update_card_components_string(struct snd_sof_widget *swidget,
struct snd_sof_pcm *spcm, int dir)
{
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
struct snd_soc_component *scomp = spcm->scomp;
struct snd_soc_card *card = scomp->card;
const char *pt_marker = "iec61937-pcm";
/*
* Update the card's components list with iec61937-pcm and a list of PCM
* ids where ChainDMA is enabled.
* These PCMs can be used for bytestream passthrough.
*/
if (!pipeline->use_chain_dma)
return 0;
if (card->components) {
const char *tmp = card->components;
if (strstr(card->components, pt_marker))
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s,%d",
card->components,
spcm->pcm.pcm_id);
else
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s %s:%d",
card->components,
pt_marker,
spcm->pcm.pcm_id);
devm_kfree(card->dev, tmp);
} else {
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s:%d", pt_marker,
spcm->pcm.pcm_id);
}
if (!card->components)
return -ENOMEM;
return 0;
}
static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
{
struct sof_ipc4_available_audio_format *available_fmt;
......@@ -452,6 +498,10 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
if (!spcm)
goto skip_gtw_cfg;
ret = sof_ipc4_update_card_components_string(swidget, spcm, dir);
if (ret)
goto free_available_fmt;
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
......
......@@ -1531,10 +1531,9 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
/* check token parsing reply */
if (ret < 0) {
dev_err(scomp->dev,
"error: failed to add widget id %d type %d name : %s stream %s\n",
tw->shift, swidget->id, tw->name,
strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0
? tw->sname : "none");
"failed to add widget type %d name : %s stream %s\n",
swidget->id, tw->name, strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0
? tw->sname : "none");
goto widget_free;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment