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, 86 insertions, 53 deletions
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 1188ec51816b..14a2f8701350 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -155,9 +155,27 @@ struct sdw_intel_ops sdw_callback = {
.free_stream = sdw_free_stream,
};
+void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
+{
+ struct sof_intel_hda_dev *hdev;
+
+ hdev = sdev->pdata->hw_pdata;
+
+ if (!hdev->sdw)
+ return;
+
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC2,
+ HDA_DSP_REG_ADSPIC2_SNDW,
+ enable ? HDA_DSP_REG_ADSPIC2_SNDW : 0);
+}
+
void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
{
- sdw_intel_enable_irq(sdev->bar[HDA_DSP_BAR], enable);
+ const struct sof_intel_dsp_desc *chip;
+
+ chip = get_chip_info(sdev->pdata);
+ if (chip && chip->enable_sdw_irq)
+ chip->enable_sdw_irq(sdev, enable);
}
static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
@@ -220,10 +238,45 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev)
return 0;
}
+int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev)
+{
+ struct sof_intel_hda_dev *hdev;
+ struct sdw_intel_ctx *ctx;
+ u32 caps;
+
+ hdev = sdev->pdata->hw_pdata;
+ ctx = hdev->sdw;
+
+ caps = snd_sof_dsp_read(sdev, HDA_DSP_BAR, ctx->shim_base + SDW_SHIM_LCAP);
+ caps &= SDW_SHIM_LCAP_LCOUNT_MASK;
+
+ /* Check HW supported vs property value */
+ if (caps < ctx->count) {
+ dev_err(sdev->dev,
+ "BIOS master count %d is larger than hardware capabilities %d\n",
+ ctx->count, caps);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hda_sdw_check_lcount(struct snd_sof_dev *sdev)
+{
+ const struct sof_intel_dsp_desc *chip;
+
+ chip = get_chip_info(sdev->pdata);
+ if (chip && chip->read_sdw_lcount)
+ return chip->read_sdw_lcount(sdev);
+
+ return 0;
+}
+
int hda_sdw_startup(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hdev;
struct snd_sof_pdata *pdata = sdev->pdata;
+ int ret;
hdev = sdev->pdata->hw_pdata;
@@ -233,6 +286,10 @@ int hda_sdw_startup(struct snd_sof_dev *sdev)
if (pdata->machine && !pdata->machine->mach_params.link_mask)
return 0;
+ ret = hda_sdw_check_lcount(sdev);
+ if (ret < 0)
+ return ret;
+
return sdw_intel_startup(hdev->sdw);
}
@@ -383,12 +440,6 @@ 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");
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI);
-module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444);
-MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver");
-#endif
-
static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = {
{HDA_DSP_ROM_CSE_ERROR, "error: cse error"},
{HDA_DSP_ROM_CSE_WRONG_RESPONSE, "error: cse wrong response"},
@@ -625,7 +676,6 @@ static bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
{
- struct hdac_bus *bus = sof_to_bus(sdev);
u32 adspis;
u32 intsts;
u32 intctl;
@@ -637,7 +687,7 @@ void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS);
intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL);
ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS);
- rirbsts = snd_hdac_chip_readb(bus, RIRBSTS);
+ rirbsts = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, AZX_REG_RIRBSTS);
dev_err(sdev->dev, "hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n",
intsts, intctl, rirbsts);
@@ -681,6 +731,17 @@ void hda_ipc4_dump(struct snd_sof_dev *sdev)
hipci, hipcie, hipct, hipcte, hipcctl);
}
+bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev)
+{
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+ const struct sof_intel_dsp_desc *chip = hda->desc;
+ u32 val;
+
+ val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->ipc_req);
+
+ return !!(val & chip->ipc_req_mask);
+}
+
static int hda_init(struct snd_sof_dev *sdev)
{
struct hda_bus *hbus;
@@ -692,7 +753,7 @@ static int hda_init(struct snd_sof_dev *sdev)
bus = sof_to_bus(sdev);
/* HDA bus init */
- sof_hda_bus_init(bus, &pci->dev);
+ sof_hda_bus_init(sdev, &pci->dev);
if (sof_hda_position_quirk == SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS)
bus->use_posbuf = 0;
@@ -787,7 +848,7 @@ static int check_nhlt_ssp_mclk_mask(struct snd_sof_dev *sdev, int ssp_num)
return intel_nhlt_ssp_mclk_mask(nhlt, ssp_num);
}
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
const char *sof_tplg_filename,
@@ -867,9 +928,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_sof_pdata *pdata = sdev->pdata;
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- struct hdac_ext_link *hlink;
-#endif
struct sof_intel_hda_dev *hdev = pdata->hw_pdata;
u32 link_mask;
int ret = 0;
@@ -879,13 +937,15 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
/* Init HDA controller after i915 init */
- ret = hda_dsp_ctrl_init_chip(sdev, true);
+ ret = hda_dsp_ctrl_init_chip(sdev);
if (ret < 0) {
dev_err(bus->dev, "error: init chip failed with ret: %d\n",
ret);
return ret;
}
+ hda_bus_ml_get_capabilities(bus);
+
/* scan SoundWire capabilities exposed by DSDT */
ret = hda_sdw_acpi_scan(sdev);
if (ret < 0) {
@@ -914,37 +974,15 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
skip_soundwire:
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- if (bus->mlcap)
- snd_hdac_ext_bus_get_ml_capabilities(bus);
-
/* create codec instances */
- hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
+ hda_codec_probe_bus(sdev);
if (!HDA_IDISP_CODEC(bus->codec_mask))
hda_codec_i915_display_power(sdev, false);
- /*
- * we are done probing so decrement link counts
- */
- list_for_each_entry(hlink, &bus->hlink_list, list)
- snd_hdac_ext_bus_link_put(bus, hlink);
-#endif
- return 0;
-}
+ hda_bus_ml_put_all(bus);
-static void hda_check_for_state_change(struct snd_sof_dev *sdev)
-{
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- struct hdac_bus *bus = sof_to_bus(sdev);
- unsigned int codec_mask;
-
- codec_mask = snd_hdac_chip_readw(bus, STATESTS);
- if (codec_mask) {
- hda_codec_jack_check(sdev);
- snd_hdac_chip_writew(bus, STATESTS, codec_mask);
- }
-#endif
+ return 0;
}
static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
@@ -996,7 +1034,7 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context)
hda_sdw_process_wakeen(sdev);
}
- hda_check_for_state_change(sdev);
+ hda_codec_check_for_state_change(sdev);
/* enable GIE interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
@@ -1192,10 +1230,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
/* cancel any attempt for DSP D0I3 */
cancel_delayed_work_sync(&hda->d0i3_work);
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- /* codec removal, invoke bus_device_remove */
- snd_hdac_ext_bus_device_remove(bus);
-#endif
+ hda_codec_device_remove(sdev);
hda_sdw_exit(sdev);
@@ -1223,16 +1258,14 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
pci_free_irq_vectors(pci);
hda_dsp_stream_free(sdev);
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- snd_hdac_link_free_all(bus);
-#endif
+
+ hda_bus_ml_free(sof_to_bus(sdev));
iounmap(sdev->bar[HDA_DSP_BAR]);
iounmap(bus->remap_addr);
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
- snd_hdac_ext_bus_exit(bus);
-#endif
+ sof_hda_bus_exit(sdev);
+
hda_codec_i915_exit(sdev);
return 0;
@@ -1246,7 +1279,7 @@ int hda_power_down_dsp(struct snd_sof_dev *sdev)
return hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
}
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
static void hda_generic_machine_select(struct snd_sof_dev *sdev,
struct snd_soc_acpi_mach **mach)
{
@@ -1325,7 +1358,7 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
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;
+ mach_params->common_hdmi_codec_drv = true;
}
}
#else