/* * skl-message.c - HDA DSP interface for FW registration, Pipe and Module * configurations * * Copyright (C) 2015 Intel Corp * Author:Rafal Redzimski * Jeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * 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 #include #include #include #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); }