ASoC: Intel: Skylake: Add dsp and ipc init helpers
authorJeeja KP <jeeja.kp@intel.com>
Tue, 21 Jul 2015 18:23:56 +0000 (23:53 +0530)
committerMark Brown <broonie@kernel.org>
Thu, 23 Jul 2015 16:39:01 +0000 (17:39 +0100)
This helper function will be used by the Skylake driver for dsp and
ipc initialization if processing pipe capability is supported.

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/Makefile
sound/soc/intel/skylake/skl-messages.c [new file with mode: 0644]
sound/soc/intel/skylake/skl.h

index b35faef..27db221 100644 (file)
@@ -1,4 +1,4 @@
-snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o
+snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o
 
 obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
 
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
new file mode 100644 (file)
index 0000000..7c07b76
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  skl-message.c - HDA DSP interface for FW registration, Pipe and Module
+ *  configurations
+ *
+ *  Copyright (C) 2015 Intel Corp
+ *  Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
+ *        Jeeja KP <jeeja.kp@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include "skl-sst-dsp.h"
+#include "skl-sst-ipc.h"
+#include "skl.h"
+#include "../common/sst-dsp.h"
+#include "../common/sst-dsp-priv.h"
+
+static int skl_alloc_dma_buf(struct device *dev,
+               struct snd_dma_buffer *dmab, size_t size)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+
+       if (!bus)
+               return -ENODEV;
+
+       return  bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab);
+}
+
+static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
+{
+       struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+
+       if (!bus)
+               return -ENODEV;
+
+       bus->io_ops->dma_free_pages(bus, dmab);
+
+       return 0;
+}
+
+int skl_init_dsp(struct skl *skl)
+{
+       void __iomem *mmio_base;
+       struct hdac_ext_bus *ebus = &skl->ebus;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       int irq = bus->irq;
+       struct skl_dsp_loader_ops loader_ops;
+       int ret;
+
+       loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
+       loader_ops.free_dma_buf = skl_free_dma_buf;
+
+       /* enable ppcap interrupt */
+       snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
+       snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true);
+
+       /* read the BAR of the ADSP MMIO */
+       mmio_base = pci_ioremap_bar(skl->pci, 4);
+       if (mmio_base == NULL) {
+               dev_err(bus->dev, "ioremap error\n");
+               return -ENXIO;
+       }
+
+       ret = skl_sst_dsp_init(bus->dev, mmio_base, irq,
+                       loader_ops, &skl->skl_sst);
+
+       dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
+
+       return ret;
+}
+
+void skl_free_dsp(struct skl *skl)
+{
+       struct hdac_ext_bus *ebus = &skl->ebus;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct skl_sst *ctx =  skl->skl_sst;
+
+       /* disable  ppcap interrupt */
+       snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
+
+       skl_sst_dsp_cleanup(bus->dev, ctx);
+       if (ctx->dsp->addr.lpe)
+               iounmap(ctx->dsp->addr.lpe);
+}
+
+int skl_suspend_dsp(struct skl *skl)
+{
+       struct skl_sst *ctx = skl->skl_sst;
+       int ret;
+
+       /* if ppcap is not supported return 0 */
+       if (!skl->ebus.ppcap)
+               return 0;
+
+       ret = skl_dsp_sleep(ctx->dsp);
+       if (ret < 0)
+               return ret;
+
+       /* disable ppcap interrupt */
+       snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
+       snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false);
+
+       return 0;
+}
+
+int skl_resume_dsp(struct skl *skl)
+{
+       struct skl_sst *ctx = skl->skl_sst;
+
+       /* if ppcap is not supported return 0 */
+       if (!skl->ebus.ppcap)
+               return 0;
+
+       /* enable ppcap interrupt */
+       snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
+       snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true);
+
+       return skl_dsp_wake(ctx->dsp);
+}
index 31dafa8..f7fdbb0 100644 (file)
@@ -56,6 +56,7 @@ struct skl {
        struct platform_device *dmic_dev;
 
        void __iomem *nhlt; /* nhlt ptr */
+       struct skl_sst *skl_sst; /* sst skl ctx */
 };
 
 #define skl_to_ebus(s) (&(s)->ebus)
@@ -75,4 +76,9 @@ void __iomem *skl_nhlt_init(struct device *dev);
 void skl_nhlt_free(void __iomem *addr);
 struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
                        u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
+
+int skl_init_dsp(struct skl *skl);
+void skl_free_dsp(struct skl *skl);
+int skl_suspend_dsp(struct skl *skl);
+int skl_resume_dsp(struct skl *skl);
 #endif /* __SOUND_SOC_SKL_H */