summaryrefslogtreecommitdiff
path: root/sound/soc/sof/amd/acp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/amd/acp.c')
-rw-r--r--sound/soc/sof/amd/acp.c389
1 files changed, 357 insertions, 32 deletions
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index f89ad86260b4..b059039c9e0d 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -22,11 +22,20 @@
#include "../ops.h"
#include "acp.h"
#include "acp-dsp-offset.h"
+#include "../../amd/acp/soc_amd_sdw_common.h"
+#include "acp7x.h"
static bool enable_fw_debug;
module_param(enable_fw_debug, bool, 0444);
MODULE_PARM_DESC(enable_fw_debug, "Enable Firmware debug");
+static const u32 acp7x_sof_sdw_ext_stat[ACP7X_SDW_MAX_MANAGER_COUNT] = {
+ ACP7X_SDW_STAT << 0,
+ ACP7X_SDW_STAT << 1,
+ ACP7X_SDW_STAT << 2,
+ ACP7X_SDW_STAT << 3,
+};
+
static struct acp_quirk_entry quirk_valve_galileo = {
.signed_fw_image = true,
.skip_iram_dram_size_mod = true,
@@ -581,30 +590,196 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
+/* ACP7X SoundWire IO data tables */
+
+const struct sof_amd_acp7x_sdw_err_regs acp7x_sdw_err_regs[ACP7X_SDW_MAX_MANAGER_COUNT] = {
+ { ACP7X_SW_ERR_STAT_MASK << 0,
+ ACP7X_SW_FIFO_ERROR_REASON + (0 * 0x2000),
+ ACP7X_SW_ERROR_REASON1 + (0 * 0x2000),
+ ACP7X_SW_ERROR_REASON2 + (0 * 0x2000) },
+ { ACP7X_SW_ERR_STAT_MASK << 1,
+ ACP7X_SW_FIFO_ERROR_REASON + (1 * 0x2000),
+ ACP7X_SW_ERROR_REASON1 + (1 * 0x2000),
+ ACP7X_SW_ERROR_REASON2 + (1 * 0x2000) },
+ { ACP7X_SW_ERR_STAT_MASK << 2,
+ ACP7X_SW_FIFO_ERROR_REASON + (2 * 0x2000),
+ ACP7X_SW_ERROR_REASON1 + (2 * 0x2000),
+ ACP7X_SW_ERROR_REASON2 + (2 * 0x2000) },
+ { ACP7X_SW_ERR_STAT_MASK << 3,
+ ACP7X_SW_FIFO_ERROR_REASON + (3 * 0x2000),
+ ACP7X_SW_ERROR_REASON1 + (3 * 0x2000),
+ ACP7X_SW_ERROR_REASON2 + (3 * 0x2000) },
+};
+
+const struct acp7x_sdw_wake_src acp7x_sdw_wake_sources[] = {
+ { ACP7X_SDW_HOST_WAKE_STAT << 0, ACP7X_SW_PME_STS + (0 * 4),
+ ACP7X_SW_WAKE_EN_MASK << 0, 0 },
+ { ACP7X_SDW_HOST_WAKE_STAT << 1, ACP7X_SW_PME_STS + (1 * 4),
+ ACP7X_SW_WAKE_EN_MASK << 1, 1 },
+ { ACP7X_SDW_HOST_WAKE_STAT << 2, ACP7X_SW_PME_STS + (2 * 4),
+ ACP7X_SW_WAKE_EN_MASK << 2, 2 },
+ { ACP7X_SDW_HOST_WAKE_STAT << 3, ACP7X_SW_PME_STS + (3 * 4),
+ ACP7X_SW_WAKE_EN_MASK << 3, 3 },
+};
+
+/* ACP7X SoundWire IO interrupt and wake helpers */
+
+static void sof_amd_acp7x_handle_one_sdw_err(struct snd_sof_dev *sdev, u32 *err_stat,
+ u32 acp_error_stat_reg,
+ const struct sof_amd_acp7x_sdw_err_regs *regs)
+{
+ if (!(*err_stat & regs->err_stat_mask))
+ return;
+
+ *err_stat &= ~regs->err_stat_mask;
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, acp_error_stat_reg, *err_stat);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, regs->fifo_err_reason, 0);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, regs->err_reason1, 0);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, regs->err_reason2, 0);
+}
+
+/* Clears SoundWire error registers for all managers; runs in hard IRQ context. */
+static void sof_amd_acp7x_clear_sdw_err_regs(struct snd_sof_dev *sdev)
+{
+ const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
+ u32 err_stat;
+ unsigned int instance;
+
+ err_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->acp_error_stat);
+
+ for (instance = 0; instance < ACP7X_SDW_MAX_MANAGER_COUNT; instance++)
+ sof_amd_acp7x_handle_one_sdw_err(sdev, &err_stat, desc->acp_error_stat,
+ &acp7x_sdw_err_regs[instance]);
+}
+
+static void sof_amd_handle_acp7x_sdw_wake_event(struct acp_dev_data *adata)
+{
+ struct amd_sdw_manager *amd_manager;
+ unsigned int instance;
+
+ for (instance = 0; instance < ACP7X_SDW_MAX_MANAGER_COUNT; instance++) {
+ if (!adata->acp7x_sdw_wake_event[instance])
+ continue;
+ if (!adata->sdw->pdev[instance])
+ continue;
+
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[instance]->dev);
+ if (amd_manager)
+ pm_request_resume(amd_manager->dev);
+ adata->acp7x_sdw_wake_event[instance] = false;
+ }
+}
+
+static int sof_amd_check_and_handle_acp7x_sdw_wake_irq(struct snd_sof_dev *sdev)
+{
+ struct acp_dev_data *adata = sdev->pdata->hw_pdata;
+ const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
+ unsigned int ext_intr_stat1;
+ unsigned int sdw_pme_stat, sdw_wake_en;
+ unsigned int i;
+ bool sdw_wake_irq = false;
+
+ ext_intr_stat1 = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat1);
+
+ for (i = 0; i < ARRAY_SIZE(acp7x_sdw_wake_sources); i++) {
+ const struct acp7x_sdw_wake_src *src = &acp7x_sdw_wake_sources[i];
+
+ bool woke = false;
+
+ if (ext_intr_stat1 & src->host_stat_mask) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1,
+ src->host_stat_mask);
+ woke = true;
+ }
+
+ sdw_pme_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, src->pme_sts_reg);
+ if (sdw_pme_stat) {
+ sdw_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_WAKE_EN);
+ sdw_wake_en &= ~src->wake_en_mask;
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_SW_WAKE_EN, sdw_wake_en);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, src->pme_sts_reg, sdw_pme_stat);
+ woke = true;
+ }
+
+ if (woke) {
+ adata->acp7x_sdw_wake_event[src->instance] = true;
+ sdw_wake_irq = true;
+ }
+ }
+
+ if (sdw_wake_irq) {
+ sof_amd_handle_acp7x_sdw_wake_event(adata);
+ return WAKE_IRQ_HANDLED;
+ }
+ return WAKE_IRQ_NONE;
+}
+
+static void sof_acp7x_handle_sdw_manager_irq(struct snd_sof_dev *sdev,
+ struct acp_dev_data *adata,
+ const struct sof_amd_acp_desc *desc,
+ unsigned int instance,
+ u32 ext_stat_mask)
+{
+ struct amd_sdw_manager *amd_manager;
+ unsigned int sdw_intr_stat;
+ u32 sw_intr_reg = ACP7X_EXTERNAL_SW_INTR_STAT + (instance * 4);
+
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, ext_stat_mask);
+ sdw_intr_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, sw_intr_reg);
+ if (sdw_intr_stat & ACP7X_EXTERNAL_SDW_STAT) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, sw_intr_reg, ACP7X_EXTERNAL_SDW_STAT);
+ if (!adata->sdw->pdev[instance])
+ return;
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[instance]->dev);
+ if (amd_manager)
+ schedule_work(&amd_manager->amd_sdw_irq_thread);
+ }
+}
+
static irqreturn_t acp7x_irq_handler(int irq, void *dev_id)
{
struct snd_sof_dev *sdev = dev_id;
+ struct acp_dev_data *adata = sdev->pdata->hw_pdata;
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
unsigned int base = desc->dsp_intr_base;
unsigned int val;
unsigned int ext_intr_stat;
- int irq_flag = 0;
+ unsigned int instance;
+ int irq_flag = 0, wake_irq_flag = 0;
+ bool dsp_irq = false;
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
if (val & ACP_DSP_TO_HOST_IRQ) {
snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET,
ACP_DSP_TO_HOST_IRQ);
- return IRQ_WAKE_THREAD;
+ dsp_irq = true;
}
ext_intr_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat);
- if (ext_intr_stat & ACP_ERROR_IRQ_MASK) {
- snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, ACP_ERROR_IRQ_MASK);
- snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_error_stat, 0);
+
+ if (adata->sdw) {
+ for (instance = 0; instance < ACP7X_SDW_MAX_MANAGER_COUNT; instance++) {
+ if (ext_intr_stat & acp7x_sof_sdw_ext_stat[instance]) {
+ sof_acp7x_handle_sdw_manager_irq(sdev, adata, desc, instance,
+ acp7x_sof_sdw_ext_stat[instance]);
+ irq_flag = 1;
+ }
+ }
+ }
+
+ if (adata->sdw)
+ wake_irq_flag = sof_amd_check_and_handle_acp7x_sdw_wake_irq(sdev);
+
+ if (ext_intr_stat & ACP7X_ERROR_IRQ) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, ACP7X_ERROR_IRQ);
+ sof_amd_acp7x_clear_sdw_err_regs(sdev);
irq_flag = 1;
}
- if (irq_flag)
+ if (dsp_irq)
+ return IRQ_WAKE_THREAD;
+
+ if (irq_flag || wake_irq_flag)
return IRQ_HANDLED;
return IRQ_NONE;
@@ -728,6 +903,8 @@ static int acp_init(struct snd_sof_dev *sdev)
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
struct acp_dev_data *acp_data;
unsigned int sdw0_wake_en, sdw1_wake_en;
+ u32 sdw_wake_en, intr_mask;
+ unsigned int i;
int ret;
/* power on */
@@ -771,6 +948,20 @@ static int acp_init(struct snd_sof_dev *sdev)
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_PME_EN, 1);
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_DSP0_IDMA_ERROR_MASK,
ACP7X_IDMA_ERROR_MASK);
+ /*
+ * Enable host-wake interrupt per manager based on SW_WAKE_EN:
+ * SW_WAKE_EN bit i enables ACP7X_SW_HOST_WAKE_MASK << i in INTR_CNTL1.
+ */
+ sdw_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_WAKE_EN);
+ intr_mask = 0;
+ for (i = 0; i < ACP7X_SDW_MAX_MANAGER_COUNT; i++) {
+ if (sdw_wake_en & BIT(i))
+ intr_mask |= ACP7X_SW_HOST_WAKE_MASK << i;
+ }
+ if (intr_mask)
+ snd_sof_dsp_update_bits(sdev, ACP_DSP_BAR,
+ ACP7X_EXTERNAL_INTR_CNTL1,
+ intr_mask, intr_mask);
break;
}
return 0;
@@ -779,15 +970,30 @@ static int acp_init(struct snd_sof_dev *sdev)
static bool check_acp_sdw_enable_status(struct snd_sof_dev *sdev)
{
struct acp_dev_data *acp_data;
- u32 sdw0_en, sdw1_en;
+ u32 sdw0_en, sdw1_en, sdw2_en, sdw3_en;
acp_data = sdev->pdata->hw_pdata;
if (!acp_data->sdw)
return false;
- sdw0_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW0_EN);
- sdw1_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW1_EN);
- acp_data->sdw_en_stat = sdw0_en || sdw1_en;
+ switch (acp_data->pci_rev) {
+ case ACP63_PCI_ID:
+ case ACP70_PCI_ID:
+ case ACP71_PCI_ID:
+ case ACP72_PCI_ID:
+ sdw0_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW0_EN);
+ sdw1_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW1_EN);
+ acp_data->sdw_en_stat = sdw0_en || sdw1_en;
+ break;
+ case ACP7B_PCI_ID:
+ case ACP7F_PCI_ID:
+ sdw0_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_EN + (0 * 0x2000));
+ sdw1_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_EN + (1 * 0x2000));
+ sdw2_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_EN + (2 * 0x2000));
+ sdw3_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_EN + (3 * 0x2000));
+ acp_data->sdw_en_stat = sdw0_en || sdw1_en || sdw2_en || sdw3_en;
+ break;
+ }
return acp_data->sdw_en_stat;
}
@@ -853,6 +1059,31 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev)
}
EXPORT_SYMBOL_NS(amd_sof_acp_resume, "SND_SOC_SOF_AMD_COMMON");
+static void acp_sof_scan_pdm_devices(struct snd_sof_dev *sdev,
+ struct acpi_device *pdm_dev)
+{
+ struct acp_dev_data *acp_data = sdev->pdata->hw_pdata;
+ struct fwnode_handle *fwnode, *child;
+ u32 ep_port_val;
+
+ fwnode = acpi_fwnode_handle(pdm_dev);
+ child = fwnode_get_next_child_node(fwnode, NULL);
+ if (!child)
+ return;
+
+ if (!fwnode_property_read_u32(child, "acp-audio-ep-port", &ep_port_val)) {
+ if (ep_port_val == ACP_DEV_PORT_PDM)
+ acp_data->pdm_sel = ACP7X_PDM_DMIC0;
+ else if (ep_port_val == ACP_DEV_PORT_PDM2)
+ acp_data->pdm_sel = ACP7X_PDM_DMIC1;
+ else
+ dev_warn(sdev->dev,
+ "acp-audio-ep-port: unrecognized value %u\n",
+ ep_port_val);
+ }
+ fwnode_handle_put(child);
+}
+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_AMD_SOUNDWIRE)
static int acp_sof_scan_sdw_devices(struct snd_sof_dev *sdev, u64 addr)
{
@@ -1038,6 +1269,8 @@ skip_soundwire:
free_ipc_irq:
free_irq(sdev->ipc_irq, sdev);
+ if (adata->sdw)
+ amd_sof_sdw_exit(sdev);
unregister_dev:
platform_device_unregister(adata->dmic_dev);
return ret;
@@ -1048,12 +1281,12 @@ void amd_sof_acp_remove(struct snd_sof_dev *sdev)
{
struct acp_dev_data *adata = sdev->pdata->hw_pdata;
- if (adata->sdw)
- amd_sof_sdw_exit(sdev);
-
if (sdev->ipc_irq)
free_irq(sdev->ipc_irq, sdev);
+ if (adata->sdw)
+ amd_sof_sdw_exit(sdev);
+
if (adata->dmic_dev)
platform_device_unregister(adata->dmic_dev);
@@ -1068,6 +1301,7 @@ int amd_sof_acp7x_probe(struct snd_sof_dev *sdev)
const struct sof_amd_acp_desc *chip;
const union acpi_object *obj;
struct acpi_device *adev;
+ struct acpi_device *pdm_dev;
unsigned int addr;
unsigned int irqflags;
int ret;
@@ -1120,7 +1354,27 @@ int amd_sof_acp7x_probe(struct snd_sof_dev *sdev)
goto unregister_dev;
}
+ /* scan SoundWire capabilities exposed by DSDT */
+ ret = acp_sof_scan_sdw_devices(sdev, chip->sdw_acpi_dev_addr);
+ if (ret < 0) {
+ dev_dbg(sdev->dev, "skipping SoundWire, not detected with ACPI scan\n");
+ goto skip_soundwire;
+ }
+ ret = amd_sof_sdw_probe(sdev);
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: SoundWire probe error\n");
+ goto free_ipc_irq;
+ }
+ if (adata->info.link_mask)
+ adata->is_sdw_dev = true;
+
+skip_soundwire:
if (adev) {
+ /* DMIC ACPI child address is 2 on ACP7x platforms */
+ pdm_dev = acpi_find_child_device(adev, ACP7X_DMIC_ADDR, 0);
+ if (pdm_dev)
+ acp_sof_scan_pdm_devices(sdev, pdm_dev);
+
if (!acpi_dev_get_property(adev, "acp-sof-signed-firmware-image",
ACPI_TYPE_INTEGER, &obj))
adata->acp_sof_signed_firmware_image = obj->integer.value;
@@ -1158,6 +1412,8 @@ int amd_sof_acp7x_probe(struct snd_sof_dev *sdev)
free_ipc_irq:
free_irq(sdev->ipc_irq, sdev);
+ if (adata->sdw)
+ amd_sof_sdw_exit(sdev);
unregister_dev:
platform_device_unregister(adata->dmic_dev);
return ret;
@@ -1171,6 +1427,9 @@ void amd_sof_acp7x_remove(struct snd_sof_dev *sdev)
if (sdev->ipc_irq)
free_irq(sdev->ipc_irq, sdev);
+ if (adata->sdw)
+ amd_sof_sdw_exit(sdev);
+
if (adata->dmic_dev)
platform_device_unregister(adata->dmic_dev);
@@ -1178,6 +1437,44 @@ void amd_sof_acp7x_remove(struct snd_sof_dev *sdev)
}
EXPORT_SYMBOL_NS(amd_sof_acp7x_remove, "SND_SOC_SOF_AMD_COMMON");
+static void handle_amd_sof_acp7x_sdw_pme_event(struct snd_sof_dev *sdev)
+{
+ struct acp_dev_data *adata;
+ struct amd_sdw_manager *amd_manager;
+ u32 sdw_pme_stat;
+ u32 sdw_wake_en;
+ u32 pme_reg;
+ u32 wake_mask;
+ unsigned int instance;
+
+ adata = sdev->pdata->hw_pdata;
+ if (!adata->sdw)
+ return;
+
+ for (instance = 0; instance < ACP7X_SDW_MAX_MANAGER_COUNT; instance++) {
+ pme_reg = ACP7X_SW_PME_STS + (instance * 4);
+ wake_mask = ACP7X_SW_WAKE_EN_MASK << instance;
+
+ sdw_pme_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, pme_reg);
+ if (!sdw_pme_stat)
+ continue;
+
+ mutex_lock(&adata->acp_lock);
+ sdw_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP7X_SW_WAKE_EN);
+ sdw_wake_en &= ~wake_mask;
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_SW_WAKE_EN, sdw_wake_en);
+ mutex_unlock(&adata->acp_lock);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, pme_reg, sdw_pme_stat);
+
+ if (!adata->sdw->pdev[instance])
+ continue;
+
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[instance]->dev);
+ if (amd_manager)
+ pm_request_resume(amd_manager->dev);
+ }
+}
+
int amd_sof_acp7x_suspend(struct snd_sof_dev *sdev, u32 target_state)
{
struct acp_dev_data *acp_data;
@@ -1186,6 +1483,11 @@ int amd_sof_acp7x_suspend(struct snd_sof_dev *sdev, u32 target_state)
acp_data = sdev->pdata->hw_pdata;
+ if (acp_data->is_sdw_dev && check_acp_sdw_enable_status(sdev)) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_ZSC_DSP_CTRL, 1);
+ return acp_dsp_reset(sdev);
+ }
+
ret = acp_reset(sdev);
if (ret) {
dev_err(sdev->dev, "ACP Reset failed\n");
@@ -1197,7 +1499,8 @@ int amd_sof_acp7x_suspend(struct snd_sof_dev *sdev, u32 target_state)
enable = true;
break;
default:
- break;
+ dev_err(sdev->dev, "Unexpected PCI revision: 0x%x\n", acp_data->pci_rev);
+ return -EINVAL;
}
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, enable);
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_ZSC_DSP_CTRL, 1);
@@ -1206,13 +1509,25 @@ int amd_sof_acp7x_suspend(struct snd_sof_dev *sdev, u32 target_state)
}
EXPORT_SYMBOL_NS(amd_sof_acp7x_suspend, "SND_SOC_SOF_AMD_COMMON");
-int amd_sof_acp7x_resume(struct snd_sof_dev *sdev)
+int amd_sof_acp7x_suspend_runtime(struct snd_sof_dev *sdev)
+{
+ return amd_sof_acp7x_suspend(sdev, 0);
+}
+EXPORT_SYMBOL_NS(amd_sof_acp7x_suspend_runtime, "SND_SOC_SOF_AMD_COMMON");
+
+int amd_sof_acp7x_resume_runtime(struct snd_sof_dev *sdev)
{
struct acp_dev_data *acp_data;
int ret;
acp_data = sdev->pdata->hw_pdata;
+ if (acp_data->sdw_en_stat) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_ZSC_DSP_CTRL, 0);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_PME_EN, 1);
+ return acp_dsp_reset(sdev);
+ }
+
ret = acp_init(sdev);
if (ret) {
dev_err(sdev->dev, "ACP Init failed\n");
@@ -1224,30 +1539,40 @@ int amd_sof_acp7x_resume(struct snd_sof_dev *sdev)
return ret;
}
- switch (acp_data->pci_rev) {
- case ACP7B_PCI_ID:
- case ACP7F_PCI_ID:
- snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_PME_EN, 1);
- break;
- default:
- break;
- }
+ if (acp_data->is_sdw_dev)
+ handle_amd_sof_acp7x_sdw_pme_event(sdev);
return 0;
}
-EXPORT_SYMBOL_NS(amd_sof_acp7x_resume, "SND_SOC_SOF_AMD_COMMON");
+EXPORT_SYMBOL_NS(amd_sof_acp7x_resume_runtime, "SND_SOC_SOF_AMD_COMMON");
-int amd_sof_acp7x_suspend_runtime(struct snd_sof_dev *sdev)
+int amd_sof_acp7x_resume(struct snd_sof_dev *sdev)
{
- return amd_sof_acp7x_suspend(sdev, 0);
-}
-EXPORT_SYMBOL_NS(amd_sof_acp7x_suspend_runtime, "SND_SOC_SOF_AMD_COMMON");
+ struct acp_dev_data *acp_data;
+ int ret;
-int amd_sof_acp7x_resume_runtime(struct snd_sof_dev *sdev)
-{
- return amd_sof_acp7x_resume(sdev);
+ acp_data = sdev->pdata->hw_pdata;
+
+ if (acp_data->sdw_en_stat) {
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_ZSC_DSP_CTRL, 0);
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP7X_PME_EN, 1);
+ return acp_dsp_reset(sdev);
+ }
+
+ ret = acp_init(sdev);
+ if (ret) {
+ dev_err(sdev->dev, "ACP Init failed\n");
+ return ret;
+ }
+ ret = acp_memory_init(sdev);
+ if (ret) {
+ dev_err(sdev->dev, "ACP Memory init failed\n");
+ return ret;
+ }
+
+ return 0;
}
-EXPORT_SYMBOL_NS(amd_sof_acp7x_resume_runtime, "SND_SOC_SOF_AMD_COMMON");
+EXPORT_SYMBOL_NS(amd_sof_acp7x_resume, "SND_SOC_SOF_AMD_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("AMD ACP sof driver");