aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.h5
-rw-r--r--sound/soc/intel/skylake/skl.c55
-rw-r--r--sound/soc/intel/skylake/skl.h3
3 files changed, 60 insertions, 3 deletions
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
index 1bbcdb471cf2..d59d1ba62a43 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
@@ -55,6 +55,11 @@ struct skl_sst {
/* IPC messaging */
struct sst_generic_ipc ipc;
+
+ /* callback for miscbdge */
+ void (*enable_miscbdcge)(struct device *dev, bool enable);
+ /*Is CGCTL.MISCBDCGE disabled*/
+ bool miscbdcg_disabled;
};
struct skl_ipc_init_instance_msg {
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index b69649aa7809..dd38f5feb7c0 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -29,6 +29,8 @@
#include <sound/pcm.h>
#include "../common/sst-acpi.h"
#include "skl.h"
+#include "skl-sst-dsp.h"
+#include "skl-sst-ipc.h"
/*
* initialize the PCI registers
@@ -59,6 +61,49 @@ static void skl_init_pci(struct skl *skl)
skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0);
}
+static void update_pci_dword(struct pci_dev *pci,
+ unsigned int reg, u32 mask, u32 val)
+{
+ u32 data = 0;
+
+ pci_read_config_dword(pci, reg, &data);
+ data &= ~mask;
+ data |= (val & mask);
+ pci_write_config_dword(pci, reg, data);
+}
+
+/*
+ * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits
+ *
+ * @dev: device pointer
+ * @enable: enable/disable flag
+ */
+static void skl_enable_miscbdcge(struct device *dev, bool enable)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+ u32 val;
+
+ val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0;
+
+ update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val);
+}
+
+/*
+ * While performing reset, controller may not come back properly causing
+ * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
+ * (init chip) and then again set CGCTL.MISCBDCGE to 1
+ */
+static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
+{
+ int ret;
+
+ skl_enable_miscbdcge(bus->dev, false);
+ ret = snd_hdac_bus_init_chip(bus, full_reset);
+ skl_enable_miscbdcge(bus->dev, true);
+
+ return ret;
+}
+
/* called from IRQ */
static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr)
{
@@ -145,7 +190,9 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
return ret;
snd_hdac_bus_stop_chip(bus);
+ skl_enable_miscbdcge(bus->dev, false);
snd_hdac_bus_enter_link_reset(bus);
+ skl_enable_miscbdcge(bus->dev, true);
return 0;
}
@@ -156,7 +203,7 @@ static int _skl_resume(struct hdac_ext_bus *ebus)
struct hdac_bus *bus = ebus_to_hbus(ebus);
skl_init_pci(skl);
- snd_hdac_bus_init_chip(bus, true);
+ skl_init_chip(bus, true);
return skl_resume_dsp(skl);
}
@@ -380,7 +427,7 @@ static int skl_codec_create(struct hdac_ext_bus *ebus)
* back to the sanity state.
*/
snd_hdac_bus_stop_chip(bus);
- snd_hdac_bus_init_chip(bus, true);
+ skl_init_chip(bus, true);
}
}
}
@@ -490,7 +537,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
/* initialize chip */
skl_init_pci(skl);
- snd_hdac_bus_init_chip(bus, true);
+ skl_init_chip(bus, true);
/* codec detection */
if (!bus->codec_mask) {
@@ -539,6 +586,8 @@ static int skl_probe(struct pci_dev *pci,
dev_dbg(bus->dev, "error failed to register dsp\n");
goto out_mach_free;
}
+ skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
+
}
if (ebus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(ebus);
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index 36a1b8c5f6d0..8a08bb727991 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -48,6 +48,9 @@
#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
+#define AZX_PCIREG_CGCTL 0x48
+#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
+
struct skl_dsp_resource {
u32 max_mcps;
u32 max_mem;