summaryrefslogtreecommitdiff
path: root/sound/soc/sof/intel/hda.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/intel/hda.c')
-rw-r--r--sound/soc/sof/intel/hda.c139
1 files changed, 66 insertions, 73 deletions
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 2c0d4d06ab36..c8fb082209ce 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -41,7 +41,7 @@
#define EXCEPT_MAX_HDR_SIZE 0x400
#define HDA_EXT_ROM_STATUS_SIZE 8
-int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
+int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
@@ -60,7 +60,7 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
/* DAI already configured, reset it before reconfiguring it */
if (sof_dai->configured) {
- ret = hda_ctrl_dai_widget_free(w);
+ ret = hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE);
if (ret < 0)
return ret;
}
@@ -78,8 +78,10 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
return ret;
}
- /* set HW_PARAMS flag */
- config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_PARAMS);
+ /* set HW_PARAMS flag along with quirks */
+ config->flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS |
+ quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
+
/* send DAI_CONFIG IPC */
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
@@ -94,7 +96,7 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
return 0;
}
-int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
+int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags)
{
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_soc_component *component = swidget->scomp;
@@ -117,8 +119,9 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
config = &sof_dai->dai_config[sof_dai->current_config];
- /* set HW_FREE flag */
- config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_MASK, SOF_DAI_CONFIG_FLAGS_HW_FREE);
+ /* set HW_FREE flag along with any quirks */
+ config->flags = SOF_DAI_CONFIG_FLAGS_HW_FREE |
+ quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size,
&reply, sizeof(reply));
@@ -134,17 +137,6 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
return sof_widget_free(sdev, swidget);
}
-static const struct sof_intel_dsp_desc
- *get_chip_info(struct snd_sof_pdata *pdata)
-{
- const struct sof_dev_desc *desc = pdata->desc;
- const struct sof_intel_dsp_desc *chip_info;
-
- chip_info = desc->chip_info;
-
- return chip_info;
-}
-
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
/*
@@ -184,23 +176,19 @@ static int sdw_dai_config_ipc(struct snd_sof_dev *sdev,
config->alh.stream_id = alh_stream_id;
if (setup)
- return hda_ctrl_dai_widget_setup(w);
+ return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE);
- return hda_ctrl_dai_widget_free(w);
+ return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE);
}
static int sdw_params_stream(struct device *dev,
struct sdw_intel_stream_params_data *params_data)
{
- struct snd_pcm_substream *substream = params_data->substream;
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_soc_dai *d = params_data->dai;
struct snd_soc_dapm_widget *w;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- w = d->playback_widget;
- else
- w = d->capture_widget;
+ w = snd_soc_dai_get_widget(d, params_data->stream);
return sdw_dai_config_ipc(sdev, w, params_data->link_id, params_data->alh_stream_id,
d->id, true);
@@ -209,15 +197,11 @@ static int sdw_params_stream(struct device *dev,
static int sdw_free_stream(struct device *dev,
struct sdw_intel_stream_free_data *free_data)
{
- struct snd_pcm_substream *substream = free_data->substream;
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_soc_dai *d = free_data->dai;
struct snd_soc_dapm_widget *w;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- w = d->playback_widget;
- else
- w = d->capture_widget;
+ w = snd_soc_dai_get_widget(d, free_data->stream);
/* send invalid stream_id */
return sdw_dai_config_ipc(sdev, w, free_data->link_id, 0xFFFF, d->id, false);
@@ -440,6 +424,10 @@ MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode");
#define hda_use_msi (1)
#endif
+int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS;
+module_param_named(position_quirk, sof_hda_position_quirk, int, 0444);
+MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk");
+
static char *hda_model;
module_param(hda_model, charp, 0444);
MODULE_PARM_DESC(hda_model, "Use the given HDA board model.");
@@ -478,7 +466,7 @@ static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = {
{HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"},
};
-static void hda_dsp_get_status(struct snd_sof_dev *sdev)
+static void hda_dsp_get_status(struct snd_sof_dev *sdev, const char *level)
{
u32 status;
int i;
@@ -488,8 +476,8 @@ static void hda_dsp_get_status(struct snd_sof_dev *sdev)
for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) {
if (status == hda_dsp_rom_msg[i].code) {
- dev_err(sdev->dev, "%s - code %8.8x\n",
- hda_dsp_rom_msg[i].msg, status);
+ dev_printk(level, sdev->dev, "%s - code %8.8x\n",
+ hda_dsp_rom_msg[i].msg, status);
return;
}
}
@@ -527,7 +515,8 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
}
/* dump the first 8 dwords representing the extended ROM status */
-static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags)
+static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, const char *level,
+ u32 flags)
{
char msg[128];
int len = 0;
@@ -539,18 +528,19 @@ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags)
len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value);
}
- dev_err(sdev->dev, "extended rom status: %s", msg);
+ dev_printk(level, sdev->dev, "extended rom status: %s", msg);
}
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
{
+ char *level = flags & SOF_DBG_DUMP_OPTIONAL ? KERN_DEBUG : KERN_ERR;
struct sof_ipc_dsp_oops_xtensa xoops;
struct sof_ipc_panic_info panic_info;
u32 stack[HDA_DSP_STACK_DUMP_SIZE];
/* print ROM/FW status */
- hda_dsp_get_status(sdev);
+ hda_dsp_get_status(sdev, level);
if (flags & SOF_DBG_DUMP_REGS) {
u32 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_STATUS);
@@ -558,10 +548,10 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
HDA_DSP_STACK_DUMP_SIZE);
- snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
- stack, HDA_DSP_STACK_DUMP_SIZE);
+ sof_print_oops_and_stack(sdev, level, status, panic, &xoops,
+ &panic_info, stack, HDA_DSP_STACK_DUMP_SIZE);
} else {
- hda_dsp_dump_ext_rom_status(sdev, flags);
+ hda_dsp_dump_ext_rom_status(sdev, level, flags);
}
}
@@ -618,7 +608,10 @@ static int hda_init(struct snd_sof_dev *sdev)
/* HDA bus init */
sof_hda_bus_init(bus, &pci->dev);
- bus->use_posbuf = 1;
+ if (sof_hda_position_quirk == SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS)
+ bus->use_posbuf = 0;
+ else
+ bus->use_posbuf = 1;
bus->bdl_pos_adj = 0;
bus->sync_write = 1;
@@ -915,6 +908,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
goto err;
}
+ sdev->num_cores = chip->cores_num;
+
hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return -ENOMEM;
@@ -1050,9 +1045,9 @@ err:
int hda_dsp_remove(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+ const struct sof_intel_dsp_desc *chip = hda->desc;
struct hdac_bus *bus = sof_to_bus(sdev);
struct pci_dev *pci = to_pci_dev(sdev->dev);
- const struct sof_intel_dsp_desc *chip = hda->desc;
/* cancel any attempt for DSP D0I3 */
cancel_delayed_work_sync(&hda->d0i3_work);
@@ -1077,7 +1072,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
/* disable cores */
if (chip)
- snd_sof_dsp_core_power_down(sdev, chip->host_managed_cores_mask);
+ hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
/* disable DSP */
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
@@ -1104,7 +1099,8 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-static int hda_generic_machine_select(struct snd_sof_dev *sdev)
+static void hda_generic_machine_select(struct snd_sof_dev *sdev,
+ struct snd_soc_acpi_mach **mach)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_acpi_mach_params *mach_params;
@@ -1136,7 +1132,7 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
* - one HDMI codec, and/or
* - one external HDAudio codec
*/
- if (!pdata->machine && codec_num <= 2) {
+ if (!*mach && codec_num <= 2) {
hda_mach = snd_soc_acpi_intel_hda_machines;
dev_info(bus->dev, "using HDA machine driver %s now\n",
@@ -1151,10 +1147,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
tplg_filename = hda_mach->sof_tplg_filename;
ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
if (ret < 0)
- return ret;
+ return;
hda_mach->mach_params.dmic_num = dmic_num;
- pdata->machine = hda_mach;
pdata->tplg_filename = tplg_filename;
if (codec_num == 2) {
@@ -1164,23 +1159,22 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
*/
hda_mach->mach_params.link_mask = 0;
}
+
+ *mach = hda_mach;
}
}
/* used by hda machine driver to create dai links */
- if (pdata->machine) {
- mach_params = (struct snd_soc_acpi_mach_params *)
- &pdata->machine->mach_params;
+ if (*mach) {
+ mach_params = &(*mach)->mach_params;
mach_params->codec_mask = bus->codec_mask;
mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
}
-
- return 0;
}
#else
-static int hda_generic_machine_select(struct snd_sof_dev *sdev)
+static void hda_generic_machine_select(struct snd_sof_dev *sdev,
+ struct snd_soc_acpi_mach **mach)
{
- return 0;
}
#endif
@@ -1263,7 +1257,7 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
return true;
}
-static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
+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;
@@ -1281,7 +1275,7 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
* machines, for mixed cases with I2C/I2S the detection relies
* on the HID list.
*/
- if (link_mask && !pdata->machine) {
+ if (link_mask) {
for (mach = pdata->desc->alt_machines;
mach && mach->link_mask; mach++) {
/*
@@ -1316,7 +1310,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
if (mach && mach->link_mask) {
int dmic_num = 0;
- pdata->machine = mach;
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
mach->mach_params.platform = dev_name(sdev->dev);
@@ -1338,9 +1331,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
int ret;
ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num);
-
if (ret < 0)
- return ret;
+ return NULL;
pdata->tplg_filename = tplg_filename;
}
@@ -1350,35 +1342,36 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
"SoundWire machine driver %s topology %s\n",
mach->drv_name,
pdata->tplg_filename);
- } else {
- dev_info(sdev->dev,
- "No SoundWire machine driver found\n");
+
+ return mach;
}
+
+ dev_info(sdev->dev, "No SoundWire machine driver found\n");
}
- return 0;
+ return NULL;
}
#else
-static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
+static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
{
- return 0;
+ return NULL;
}
#endif
-void hda_set_mach_params(const struct snd_soc_acpi_mach *mach,
+void hda_set_mach_params(struct snd_soc_acpi_mach *mach,
struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *pdata = sdev->pdata;
const struct sof_dev_desc *desc = pdata->desc;
struct snd_soc_acpi_mach_params *mach_params;
- mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
+ mach_params = &mach->mach_params;
mach_params->platform = dev_name(sdev->dev);
mach_params->num_dai_drivers = desc->ops->num_drv;
mach_params->dai_drivers = desc->ops->drv;
}
-void hda_machine_select(struct snd_sof_dev *sdev)
+struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *sof_pdata = sdev->pdata;
const struct sof_dev_desc *desc = sof_pdata->desc;
@@ -1393,8 +1386,6 @@ void hda_machine_select(struct snd_sof_dev *sdev)
if (!sof_pdata->tplg_filename)
sof_pdata->tplg_filename = mach->sof_tplg_filename;
- sof_pdata->machine = mach;
-
if (mach->link_mask) {
mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask;
@@ -1404,16 +1395,18 @@ void hda_machine_select(struct snd_sof_dev *sdev)
/*
* If I2S fails, try SoundWire
*/
- hda_sdw_machine_select(sdev);
+ if (!mach)
+ mach = hda_sdw_machine_select(sdev);
/*
* Choose HDA generic machine driver if mach is NULL.
* Otherwise, set certain mach params.
*/
- hda_generic_machine_select(sdev);
-
- if (!sof_pdata->machine)
+ hda_generic_machine_select(sdev, &mach);
+ if (!mach)
dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
+
+ return mach;
}
int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)