From: Jeeja KP jeeja.kp@intel.com
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 --- sound/soc/intel/skylake/Makefile | 2 +- sound/soc/intel/skylake/skl-messages.c | 133 +++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl.h | 6 ++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/skylake/skl-messages.c
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index b35faef05779..27db22178204 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -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 index 000000000000..7c07b76bf0bf --- /dev/null +++ b/sound/soc/intel/skylake/skl-messages.c @@ -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); +} diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 31dafa8a0594..f7fdbb02947f 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -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 */