diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 96fe5eeead4dd5..142c67e2941423 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -274,7 +274,6 @@ config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "SKL/KBL/BXT/APL with HDA Codecs" select SND_SOC_HDAC_HDMI select SND_SOC_HDAC_HDA - select SND_SOC_SOF_HDA if SND_SOC_SOF_HDA_COMMON help This adds support for ASoC machine driver for Intel platforms SKL/KBL/BXT/APL with iDisp, HDA audio codecs. diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 959a60d0ee4c7c..163b1b0c0200e2 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -93,7 +93,15 @@ config SND_SOC_SOF_HDA_COMMON select SND_SOC_ACPI_INTEL_MATCH config SND_SOC_SOF_HDA - tristate + tristate "SOF support for HDA Links(HDA/HDMI)" depends on SND_SOC_SOF_HDA_COMMON + select SND_HDA_EXT_CORE + select SND_SOC_HDAC_HDA + select SND_SOC_HDAC_HDMI + help + This adds support for HDA links(HDA/HDMI) with Sound Open Firmware + for Intel(R) platforms. + Say Y if you want to enble HDA links with SOF. + If unsure select "N". endif ## SND_SOC_SOF_INTEL diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index ae2b7778200ab5..accb3d4d209d21 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -7,10 +7,13 @@ snd-sof-intel-hsw-objs := hsw.o snd-sof-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ - hda-dai.o hda-codec.o \ + hda-dai.o hda-bus.o \ skl.o apl.o cnl.o +snd-sof-intel-hda-objs := hda-codec.o + obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-intel-byt.o obj-$(CONFIG_SND_SOC_SOF_HASWELL) += snd-sof-intel-hsw.o obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-intel-bdw.o obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o +obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c new file mode 100644 index 00000000000000..2fb31f0fdbfd71 --- /dev/null +++ b/sound/soc/sof/intel/hda-bus.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Authors: Jeeja KP + * Keyon Jie + */ + +#include + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + +static const struct hdac_bus_ops bus_ops = { + .command = snd_hdac_bus_send_cmd, + .get_response = snd_hdac_bus_get_response, +}; + +/* + * process queued unsolicited events + */ +static void hda_process_unsol_events(struct work_struct *work) +{ + struct hdac_bus *bus = container_of(work, struct hdac_bus, unsol_work); + struct hdac_device *codec; + struct hdac_driver *drv; + unsigned int rp, caddr, res; + + while (bus->unsol_rp != bus->unsol_wp) { + rp = (bus->unsol_rp + 1) % HDA_UNSOL_QUEUE_SIZE; + bus->unsol_rp = rp; + rp <<= 1; + res = bus->unsol_queue[rp]; + caddr = bus->unsol_queue[rp + 1]; + if (!(caddr & (1 << 4))) /* no unsolicited event? */ + continue; + codec = bus->caddr_tbl[caddr & 0x0f]; + if (!codec || !codec->dev.driver) + continue; + drv = drv_to_hdac_driver(codec->dev.driver); + if (drv->unsol_event) + drv->unsol_event(codec, res); + } +} + +#endif + +static void sof_hda_writel(u32 value, u32 __iomem *addr) +{ + writel(value, addr); +} + +static u32 sof_hda_readl(u32 __iomem *addr) +{ + return readl(addr); +} + +static void sof_hda_writew(u16 value, u16 __iomem *addr) +{ + writew(value, addr); +} + +static u16 sof_hda_readw(u16 __iomem *addr) +{ + return readw(addr); +} + +static void sof_hda_writeb(u8 value, u8 __iomem *addr) +{ + writeb(value, addr); +} + +static u8 sof_hda_readb(u8 __iomem *addr) +{ + return readb(addr); +} + +static int sof_hda_dma_alloc_pages(struct hdac_bus *bus, int type, + size_t size, struct snd_dma_buffer *buf) +{ + return snd_dma_alloc_pages(type, bus->dev, size, buf); +} + +static void sof_hda_dma_free_pages(struct hdac_bus *bus, + struct snd_dma_buffer *buf) +{ + snd_dma_free_pages(buf); +} + +static const struct hdac_io_ops io_ops = { + .reg_writel = sof_hda_writel, + .reg_readl = sof_hda_readl, + .reg_writew = sof_hda_writew, + .reg_readw = sof_hda_readw, + .reg_writeb = sof_hda_writeb, + .reg_readb = sof_hda_readb, + .dma_alloc_pages = sof_hda_dma_alloc_pages, + .dma_free_pages = sof_hda_dma_free_pages, +}; + +/* + * This can be used for both with/without hda link support. + * Returns 0 if successful, or a negative error code. + */ +int sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, + const struct hdac_ext_bus_ops *ext_ops) +{ + static int idx; + + memset(bus, 0, sizeof(*bus)); + bus->dev = dev; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + bus->ops = &bus_ops; +#endif + bus->io_ops = &io_ops; + INIT_LIST_HEAD(&bus->stream_list); + INIT_LIST_HEAD(&bus->codec_list); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + INIT_WORK(&bus->unsol_work, hda_process_unsol_events); +#endif + spin_lock_init(&bus->reg_lock); + mutex_init(&bus->cmd_mutex); + bus->irq = -1; + + bus->ext_ops = ext_ops; + INIT_LIST_HEAD(&bus->hlink_list); + bus->idx = idx++; + + mutex_init(&bus->lock); + bus->cmd_dma_state = true; + + return 0; +} diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 83a544b974aa98..ad499f14f889ff 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2017 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation. All rights reserved. * * Authors: Jeeja KP * Keyon Jie @@ -22,7 +22,6 @@ #include #include #include -#include #include "../../../pci/hda/hda_codec.h" #include "../../codecs/hdac_hda.h" @@ -51,7 +50,7 @@ static void hda_codec_load_module(struct hda_codec *codec) {} /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int addr) { - struct hda_bus *hbus = sdev->hbus; + struct hda_bus *hbus = sof_to_hbus(sdev); unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res = -1; @@ -92,8 +91,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int addr) /* Codec initialization */ int hda_codec_probe_bus(struct snd_sof_dev *sdev) { - struct hda_bus *hbus = sdev->hbus; - struct hdac_bus *bus = &hbus->core; + struct hdac_bus *bus = sof_to_bus(sdev); int c, max_slots, ret = 0; max_slots = HDA_MAX_CODECS; @@ -113,11 +111,11 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL(hda_codec_probe_bus); int hda_codec_i915_init(struct snd_sof_dev *sdev) { - struct hda_bus *hbus = sdev->hbus; - struct hdac_bus *bus = &hbus->core; + struct hdac_bus *bus = sof_to_bus(sdev); int ret; /* i915 exposes a HDA codec for HDMI audio */ @@ -131,4 +129,7 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL(hda_codec_i915_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index eac0815de78734..69893556851214 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -86,8 +86,9 @@ int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev) int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) { + struct hdac_bus *bus = sof_to_bus(sdev); u32 cap, offset, feature; - int ret = -ENODEV, count = 0; + int count = 0; offset = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_LLCH); @@ -103,21 +104,30 @@ int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) case SOF_HDA_PP_CAP_ID: dev_dbg(sdev->dev, "found DSP capability at 0x%x\n", offset); - sdev->bar[HDA_DSP_PP_BAR] = sdev->bar[HDA_DSP_HDA_BAR] + - offset; - ret = 0; + bus->ppcap = bus->remap_addr + offset; + sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap; break; case SOF_HDA_SPIB_CAP_ID: dev_dbg(sdev->dev, "found SPIB capability at 0x%x\n", offset); - sdev->bar[HDA_DSP_SPIB_BAR] = - sdev->bar[HDA_DSP_HDA_BAR] + offset; + bus->spbcap = bus->remap_addr + offset; + sdev->bar[HDA_DSP_SPIB_BAR] = bus->spbcap; break; case SOF_HDA_DRSM_CAP_ID: dev_dbg(sdev->dev, "found DRSM capability at 0x%x\n", offset); - sdev->bar[HDA_DSP_DRSM_BAR] = - sdev->bar[HDA_DSP_HDA_BAR] + offset; + bus->drsmcap = bus->remap_addr + offset; + sdev->bar[HDA_DSP_DRSM_BAR] = bus->drsmcap; + break; + case SOF_HDA_GTS_CAP_ID: + dev_dbg(sdev->dev, "found GTS capability at 0x%x\n", + offset); + bus->gtscap = bus->remap_addr + offset; + break; + case SOF_HDA_ML_CAP_ID: + dev_dbg(sdev->dev, "found ML capability at 0x%x\n", + offset); + bus->mlcap = bus->remap_addr + offset; break; default: dev_vdbg(sdev->dev, "found capability %d at 0x%x\n", @@ -128,7 +138,7 @@ int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) offset = cap & SOF_HDA_CAP_NEXT_MASK; } while (count++ <= SOF_HDA_MAX_CAPS && offset); - return ret; + return 0; } void hda_dsp_ctrl_enable_miscbdcge(struct snd_sof_dev *sdev, bool enable) @@ -138,6 +148,7 @@ void hda_dsp_ctrl_enable_miscbdcge(struct snd_sof_dev *sdev, bool enable) snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_MISCBDCGE_MASK, val); } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* * While performing reset, controller may not come back properly causing * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset @@ -145,7 +156,7 @@ void hda_dsp_ctrl_enable_miscbdcge(struct snd_sof_dev *sdev, bool enable) */ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) { - struct hdac_bus *bus = &sdev->hbus->core; + struct hdac_bus *bus = sof_to_bus(sdev); int ret; hda_dsp_ctrl_enable_miscbdcge(sdev, false); @@ -154,4 +165,5 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) return ret; } +#endif diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 372ccfaac30647..6d169c70c317e6 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -38,7 +38,8 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab, int direction) { - struct sof_intel_hda_stream *stream = NULL; + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *hstream; struct pci_dev *pci = sdev->pci; int ret; @@ -53,6 +54,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, dev_err(sdev->dev, "error: no stream available\n"); return -ENODEV; } + hstream = &stream->hstream; /* allocate DMA buffer */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab); @@ -61,8 +63,8 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, goto error; } - stream->config = format; - stream->bufsize = size; + hstream->format_val = format; + hstream->bufsize = size; ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); if (ret < 0) { @@ -72,10 +74,10 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_ENABLE, size); - return stream->tag; + return hstream->stream_tag; error: - hda_dsp_stream_put_pstream(sdev, stream->tag); + hda_dsp_stream_put_pstream(sdev, hstream->stream_tag); snd_dma_free_pages(dmab); return ret; } @@ -188,8 +190,11 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, } static int cl_trigger(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, int cmd) + struct hdac_ext_stream *stream, int cmd) { + struct hdac_stream *hstream = &stream->hstream; + int sd_offset = SOF_STREAM_SD_OFFSET(hstream); + /* code loader is special case that reuses stream ops */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -197,16 +202,17 @@ static int cl_trigger(struct snd_sof_dev *sdev, HDA_DSP_CL_TRIGGER_TIMEOUT); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - 1 << stream->index, 1 << stream->index); + 1 << hstream->index, + 1 << hstream->index); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset, + sd_offset, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK); - stream->running = true; + hstream->running = true; return 0; default: return hda_dsp_stream_trigger(sdev, stream, cmd); @@ -214,45 +220,50 @@ static int cl_trigger(struct snd_sof_dev *sdev, } static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, - struct sof_intel_hda_stream *stream) + struct hdac_ext_stream *stream) { + struct hdac_stream *hstream = &stream->hstream; + int sd_offset = SOF_STREAM_SD_OFFSET(hstream); int ret; ret = hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0); /* TODO: spin lock ?*/ - stream->open = 0; - stream->running = 0; - stream->substream = NULL; + hstream->opened = 0; + hstream->running = 0; + hstream->substream = NULL; /* reset BDL address */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, 0); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, 0); snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, 0); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, 0); - snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, 0); + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset, 0); snd_dma_free_pages(dmab); dmab->area = NULL; - stream->bufsize = 0; - stream->config = 0; + hstream->bufsize = 0; + hstream->format_val = 0; return ret; } static int cl_copy_fw(struct snd_sof_dev *sdev, int tag) { - struct sof_intel_hda_stream *stream = NULL; - struct sof_intel_hda_dev *hdev = sdev->hda; - int ret, status, i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; + int ret, status; /* get stream with tag */ - for (i = 0; i < hdev->num_playback; i++) { - if (hdev->pstream[i].tag == tag) { - stream = &hdev->pstream[i]; + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == SNDRV_PCM_STREAM_PLAYBACK + && s->stream_tag == tag) { + stream = stream_to_hdac_ext_stream(s); break; } } + if (!stream) { dev_err(sdev->dev, "error: could not get stream with stream tag%d\n", diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 0abb2e5778cae2..dacfb040373811 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -98,7 +98,8 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct sof_intel_hda_stream *stream = substream->runtime->private_data; + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream); struct snd_dma_buffer *dmab; int ret; u32 size, rate, bits; @@ -107,12 +108,12 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, rate = get_mult_div(sdev, params_rate(params)); bits = get_bits(sdev, params_width(params)); - stream->substream = substream; + hstream->substream = substream; dmab = substream->runtime->dma_buffer_p; - stream->config = rate | bits | (params_channels(params) - 1); - stream->bufsize = size; + hstream->format_val = rate | bits | (params_channels(params) - 1); + hstream->bufsize = size; ret = hda_dsp_stream_hw_params(sdev, stream, dmab, params); if (ret < 0) { @@ -123,13 +124,14 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, /* disable SPIB, to enable buffer wrap for stream */ hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0); - return stream->tag; + return hstream->stream_tag; } int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int cmd) { - struct sof_intel_hda_stream *stream = substream->runtime->private_data; + struct hdac_stream *hstream = substream->runtime->private_data; + struct hdac_ext_stream *stream = stream_to_hdac_ext_stream(hstream); return hda_dsp_stream_trigger(sdev, stream, cmd); } @@ -137,7 +139,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { - struct sof_intel_hda_stream *stream; + struct hdac_ext_stream *stream; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) stream = hda_dsp_stream_get_pstream(sdev); @@ -150,20 +152,20 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, } /* binding pcm substream to hda stream */ - substream->runtime->private_data = stream; + substream->runtime->private_data = &stream->hstream; return 0; } int hda_dsp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { - struct sof_intel_hda_stream *stream = substream->runtime->private_data; + struct hdac_stream *hstream = substream->runtime->private_data; int ret; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = hda_dsp_stream_put_pstream(sdev, stream->tag); + ret = hda_dsp_stream_put_pstream(sdev, hstream->stream_tag); else - ret = hda_dsp_stream_put_cstream(sdev, stream->tag); + ret = hda_dsp_stream_put_cstream(sdev, hstream->stream_tag); if (ret) { dev_dbg(sdev->dev, "stream %s not opened!\n", substream->name); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index d753a83c746b72..f77421e2e831bb 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -41,7 +41,7 @@ */ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, - struct sof_intel_hda_stream *stream, + struct hdac_stream *stream, struct sof_intel_dsp_bdl *bdl, int size, struct snd_pcm_hw_params *params) { @@ -93,9 +93,10 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, } int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, + struct hdac_ext_stream *stream, int enable, u32 size) { + struct hdac_stream *hstream = &stream->hstream; u32 mask = 0; if (!sdev->bar[HDA_DSP_SPIB_BAR]) { @@ -103,12 +104,12 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, return -EINVAL; } - mask |= (1 << stream->index); + mask |= (1 << hstream->index); /* enable/disable SPIB for the stream */ snd_sof_dsp_update_bits(sdev, HDA_DSP_SPIB_BAR, SOF_HDA_ADSP_REG_CL_SPBFIFO_SPBFCCTL, mask, - enable << stream->index); + enable << hstream->index); /* set the SPIB value */ hda_dsp_write(sdev, stream->spib_addr, size); @@ -116,19 +117,46 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, return 0; } + +/* get next unused stream */ +struct hdac_ext_stream * +hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; + + /* get an unused playback stream */ + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == direction && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); + break; + } + } + + /* stream found ? */ + if (!stream) + dev_err(sdev->dev, "error: no free %s streams\n", + direction ==SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture" ); + + return stream; +} + /* get next unused playback stream */ -struct sof_intel_hda_stream * +struct hdac_ext_stream * hda_dsp_stream_get_pstream(struct snd_sof_dev *sdev) { - struct sof_intel_hda_dev *hdev = sdev->hda; - struct sof_intel_hda_stream *stream = NULL; - int i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; /* get an unused playback stream */ - for (i = 0; i < hdev->num_playback; i++) { - if (!hdev->pstream[i].open) { - hdev->pstream[i].open = true; - stream = &hdev->pstream[i]; + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == SNDRV_PCM_STREAM_PLAYBACK + && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); break; } } @@ -141,18 +169,19 @@ hda_dsp_stream_get_pstream(struct snd_sof_dev *sdev) } /* get next unused capture stream */ -struct sof_intel_hda_stream * +struct hdac_ext_stream * hda_dsp_stream_get_cstream(struct snd_sof_dev *sdev) { - struct sof_intel_hda_dev *hdev = sdev->hda; - struct sof_intel_hda_stream *stream = NULL; - int i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; /* get an unused capture stream */ - for (i = 0; i < hdev->num_capture; i++) { - if (!hdev->cstream[i].open) { - hdev->cstream[i].open = true; - stream = &hdev->cstream[i]; + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == SNDRV_PCM_STREAM_CAPTURE + && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); break; } } @@ -164,17 +193,36 @@ hda_dsp_stream_get_cstream(struct snd_sof_dev *sdev) return stream; } +/* free a stream */ +int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int tag) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *s; + + /* find used stream */ + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == direction + && s->opened && s->stream_tag == tag) { + s->opened = false; + return 0; + } + } + + dev_dbg(sdev->dev, "tag %d not opened!\n", tag); + return -ENODEV; +} + /* free playback stream */ int hda_dsp_stream_put_pstream(struct snd_sof_dev *sdev, int tag) { - struct sof_intel_hda_dev *hdev = sdev->hda; - int i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *s; /* find used playback stream */ - for (i = 0; i < hdev->num_playback; i++) { - if (hdev->pstream[i].open && - hdev->pstream[i].tag == tag) { - hdev->pstream[i].open = false; + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == SNDRV_PCM_STREAM_PLAYBACK + && s->opened && s->stream_tag == tag) { + s->opened = false; return 0; } } @@ -186,14 +234,14 @@ int hda_dsp_stream_put_pstream(struct snd_sof_dev *sdev, int tag) /* free capture stream */ int hda_dsp_stream_put_cstream(struct snd_sof_dev *sdev, int tag) { - struct sof_intel_hda_dev *hdev = sdev->hda; - int i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *s; /* find used capture stream */ - for (i = 0; i < hdev->num_capture; i++) { - if (hdev->cstream[i].open && - hdev->cstream[i].tag == tag) { - hdev->cstream[i].open = false; + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == SNDRV_PCM_STREAM_CAPTURE + && s->opened && s->stream_tag == tag) { + s->opened = false; return 0; } } @@ -203,41 +251,44 @@ int hda_dsp_stream_put_cstream(struct snd_sof_dev *sdev, int tag) } int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, int cmd) + struct hdac_ext_stream *stream, int cmd) { + struct hdac_stream *hstream = &stream->hstream; + int sd_offset = SOF_STREAM_SD_OFFSET(hstream); + /* cmd must be for audio stream */ switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_START: snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - 1 << stream->index, - 1 << stream->index); + 1 << hstream->index, + 1 << hstream->index); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset, + sd_offset, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK); - stream->running = true; + hstream->running = true; break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset, + sd_offset, SOF_HDA_SD_CTL_DMA_START | SOF_HDA_CL_DMA_SD_INT_MASK, 0x0); - snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, stream->sd_offset + + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK); - stream->running = false; + hstream->running = false; snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - 1 << stream->index, 0x0); + 1 << hstream->index, 0x0); break; default: dev_err(sdev->dev, "error: unknown command: %d\n", cmd); @@ -252,12 +303,14 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, * and normal stream. */ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, + struct hdac_ext_stream *stream, struct snd_dma_buffer *dmab, struct snd_pcm_hw_params *params) { - struct sof_intel_hda_dev *hdev = sdev->hda; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *hstream = &stream->hstream; struct sof_intel_dsp_bdl *bdl; + int sd_offset = SOF_STREAM_SD_OFFSET(hstream); int ret, timeout = HDA_DSP_STREAM_RESET_TIMEOUT; u32 val, mask; @@ -267,7 +320,7 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, } /* decouple host and link DMA */ - mask = 0x1 << stream->index; + mask = 0x1 << hstream->index; snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, mask); @@ -277,21 +330,21 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, } /* clear stream status */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK | SOF_HDA_SD_CTL_DMA_START, 0); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_CL_DMA_SD_INT_MASK); /* stream reset */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, 0x1, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, 0x1, 0x1); udelay(3); do { val = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset); + sd_offset); if (val & 0x1) break; } while (--timeout); @@ -301,14 +354,14 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, } timeout = HDA_DSP_STREAM_RESET_TIMEOUT; - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, 0x1, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, 0x1, 0x0); /* wait for hardware to report that stream is out of reset */ udelay(3); do { val = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset); + sd_offset); if ((val & 0x1) == 0) break; } while (--timeout); @@ -317,31 +370,31 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return -ETIMEDOUT; } - if (stream->posbuf) - *stream->posbuf = 0; + if (hstream->posbuf) + *hstream->posbuf = 0; /* reset BDL address */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, 0x0); snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, 0x0); /* clear stream status */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK | SOF_HDA_SD_CTL_DMA_START, 0); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_CL_DMA_SD_INT_MASK); - stream->frags = 0; + hstream->frags = 0; - bdl = (struct sof_intel_dsp_bdl *)stream->bdl.area; - ret = hda_dsp_stream_setup_bdl(sdev, dmab, stream, bdl, - stream->bufsize, params); + bdl = (struct sof_intel_dsp_bdl *)hstream->bdl.area; + ret = hda_dsp_stream_setup_bdl(sdev, dmab, hstream, bdl, + hstream->bufsize, params); if (ret < 0) { dev_err(sdev->dev, "error: set up of BDL failed\n"); return ret; @@ -349,57 +402,57 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, /* set up stream descriptor for DMA */ /* program stream tag */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_SD_CTL_STREAM_TAG_MASK, - stream->tag << + hstream->stream_tag << SOF_HDA_CL_SD_CTL_STREAM_TAG_SHIFT); /* program cyclic buffer length */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_CBL, - stream->bufsize); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_CBL, + hstream->bufsize); /* program stream format */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + + sd_offset + SOF_HDA_ADSP_REG_CL_SD_FORMAT, - 0xffff, stream->config); + 0xffff, hstream->format_val); /* program last valid index */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_LVI, - 0xffff, (stream->frags - 1)); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_LVI, + 0xffff, (hstream->frags - 1)); /* program BDL address */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, - (u32)stream->bdl.addr); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL, + (u32)hstream->bdl.addr); snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, - upper_32_bits(stream->bdl.addr)); + sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU, + upper_32_bits(hstream->bdl.addr)); /* enable position buffer */ if (!(snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE) & SOF_HDA_ADSP_DPLBASE_ENABLE)) snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE, - (u32)hdev->posbuffer.addr | + (u32)bus->posbuf.addr | SOF_HDA_ADSP_DPLBASE_ENABLE); /* set interrupt enable bits */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, stream->sd_offset, + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_CL_DMA_SD_INT_MASK); /* read FIFO size */ - if (stream->direction == SNDRV_PCM_STREAM_PLAYBACK) { - stream->fifo_size = + if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK) { + hstream->fifo_size = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + + sd_offset + SOF_HDA_ADSP_REG_CL_SD_FIFOSIZE); - stream->fifo_size &= 0xffff; - stream->fifo_size += 1; + hstream->fifo_size &= 0xffff; + hstream->fifo_size += 1; } else { - stream->fifo_size = 0; + hstream->fifo_size = 0; } return ret; @@ -408,7 +461,7 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) { struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; - struct hdac_bus *bus = &sdev->hbus->core; + struct hdac_bus *bus = sof_to_bus(sdev); u32 status; if (!pm_runtime_active(sdev->dev)) @@ -422,6 +475,7 @@ irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) return IRQ_NONE; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* clear rirb int */ status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_RIRBSTS); if (status & RIRB_INT_MASK) { @@ -430,73 +484,53 @@ irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_RIRBSTS, RIRB_INT_MASK); } +#endif spin_unlock(&bus->reg_lock); return snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS) - ? IRQ_WAKE_THREAD : IRQ_HANDLED; + & SOF_HDA_INT_ALL_STREAM ? IRQ_WAKE_THREAD : IRQ_HANDLED; } irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) { struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; - struct sof_intel_hda_dev *hdev = sdev->hda; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *s; + int sd_offset; + //struct sof_intel_hda_dev *hdev = sdev->hda; u32 status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); u32 sd_status; - int i; - /* check playback streams */ - for (i = 0; i < hdev->num_playback; i++) { - /* is IRQ for this stream ? */ - if (status & (1 << hdev->pstream[i].index)) { + /* check streams */ + list_for_each_entry(s, &bus->stream_list, list) { + if (status & (1 << s->index) + && !s->opened) { + sd_offset = SOF_STREAM_SD_OFFSET(s); sd_status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - hdev->pstream[i].sd_offset + + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS) & 0xff; - dev_dbg(sdev->dev, "pstream %d status 0x%x\n", - i, sd_status); + dev_dbg(sdev->dev, "stream %d status 0x%x\n", + s->index, sd_status); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - hdev->pstream[i].sd_offset + + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS, SOF_HDA_CL_DMA_SD_INT_MASK, SOF_HDA_CL_DMA_SD_INT_MASK); - if (!hdev->pstream[i].substream || - !hdev->pstream[i].running || + if (!s->substream || + !s->running || (sd_status & SOF_HDA_CL_DMA_SD_INT_MASK) == 0) continue; - } - } - - /* check capture streams */ - for (i = 0; i < hdev->num_capture; i++) { - /* is IRQ for this stream ? */ - if (status & (1 << hdev->cstream[i].index)) { - sd_status = - snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - hdev->cstream[i].sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS) & - 0xff; - - dev_dbg(sdev->dev, "cstream %d status 0x%x\n", - i, sd_status); - - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - hdev->cstream[i].sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); - if (!hdev->cstream[i].substream || - !hdev->cstream[i].running || - (sd_status & SOF_HDA_CL_DMA_SD_INT_MASK) == 0) - continue; } } + // TODO: legacy code call snd_pcm_period_elapsed(hstr->substream); // we probably dont need this since we get updates via IPC/SRAM/ // TODO: evaluate. @@ -506,9 +540,11 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) int hda_dsp_stream_init(struct snd_sof_dev *sdev) { - struct sof_intel_hda_dev *hdev = sdev->hda; - struct sof_intel_hda_stream *stream; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_ext_stream *stream; + struct hdac_stream *hstream; struct pci_dev *pci = sdev->pci; + int sd_offset; int i, num_playback, num_capture, num_total, ret; u32 gcap; @@ -520,9 +556,6 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) num_playback = (gcap >> 12) & 0x0f; num_total = num_playback + num_capture; - hdev->num_capture = num_capture; - hdev->num_playback = num_playback; - dev_dbg(sdev->dev, "detected %d playback and %d capture streams\n", num_playback, num_capture); @@ -539,26 +572,29 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) } /* mem alloc for the position buffer */ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, 8, - &hdev->posbuffer); + /* TODO: check postion buffer update */ + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, + SOF_HDA_DPIB_ENTRY_SIZE * num_total, + &bus->posbuf); if (ret < 0) { dev_err(sdev->dev, "error: posbuffer dma alloc failed\n"); return -ENOMEM; } - if (sdev->hbus) { - /* mem alloc for the CORB/RIRB ringbuffers */ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, - PAGE_SIZE, &sdev->hbus->core.rb); - if (ret < 0) { - dev_err(sdev->dev, "error: RB alloc failed\n"); - return -ENOMEM; - } + /* mem alloc for the CORB/RIRB ringbuffers */ + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, + PAGE_SIZE, &bus->rb); + if (ret < 0) { + dev_err(sdev->dev, "error: RB alloc failed\n"); + return -ENOMEM; } /* create capture streams */ for (i = 0; i < num_capture; i++) { - stream = &hdev->cstream[i]; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + SOF_HDA_PPHC_BASE + SOF_HDA_PPHC_INTERVAL * i; @@ -578,35 +614,44 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) SOF_HDA_SPIB_MAXFIFO; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_DRSM) + /* FIXME: Remove? HDAC doesn't use DRSM so has no drsm_addr */ /* do we support DRSM */ if (sdev->bar[HDA_DSP_DRSM_BAR]) stream->drsm_addr = sdev->bar[HDA_DSP_DRSM_BAR] + SOF_HDA_DRSM_BASE + SOF_HDA_DRSM_INTERVAL * i; - - stream->sd_offset = 0x20 * i + SOF_HDA_ADSP_LOADER_BASE; - stream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + - stream->sd_offset; - - stream->tag = i + 1; - stream->open = false; - stream->running = false; - stream->direction = SNDRV_PCM_STREAM_CAPTURE; - stream->index = i; +#endif + + hstream = &stream->hstream; + hstream->bus = bus; + hstream->index = i; + sd_offset = SOF_STREAM_SD_OFFSET(hstream); + hstream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + sd_offset; + hstream->stream_tag = i + 1; + hstream->opened = false; + hstream->running = false; + hstream->direction = SNDRV_PCM_STREAM_CAPTURE; /* memory alloc for stream BDL */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, - HDA_DSP_BDL_SIZE, &stream->bdl); + HDA_DSP_BDL_SIZE, &hstream->bdl); if (ret < 0) { dev_err(sdev->dev, "error: stream bdl dma alloc failed\n"); + kfree(stream); return -ENOMEM; } - stream->posbuf = (__le32 *)(hdev->posbuffer.area + - (stream->index) * 8); + hstream->posbuf = (__le32 *)(bus->posbuf.area + + (hstream->index) * 8); + + list_add_tail(&hstream->list, &bus->stream_list); } /* create playback streams */ for (i = num_capture; i < num_total; i++) { - stream = &hdev->pstream[i - num_capture]; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; /* we always have DSP support */ stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + @@ -627,30 +672,37 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) SOF_HDA_SPIB_MAXFIFO; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_DRSM) + /* FIXME: Remove? HDAC doesn't use DRSM so has no drsm_addr */ /* do we support DRSM */ if (sdev->bar[HDA_DSP_DRSM_BAR]) stream->drsm_addr = sdev->bar[HDA_DSP_DRSM_BAR] + SOF_HDA_DRSM_BASE + SOF_HDA_DRSM_INTERVAL * i; - - stream->sd_offset = 0x20 * i + SOF_HDA_ADSP_LOADER_BASE; - stream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + - stream->sd_offset; - stream->tag = i - num_capture + 1; - stream->open = false; - stream->running = false; - stream->direction = SNDRV_PCM_STREAM_PLAYBACK; - stream->index = i; +#endif + + hstream = &stream->hstream; + hstream->bus = bus; + hstream->index = i; + sd_offset = SOF_STREAM_SD_OFFSET(hstream); + hstream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + sd_offset; + hstream->stream_tag = i - num_capture + 1; + hstream->opened = false; + hstream->running = false; + hstream->direction = SNDRV_PCM_STREAM_PLAYBACK; /* mem alloc for stream BDL */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, - HDA_DSP_BDL_SIZE, &stream->bdl); + HDA_DSP_BDL_SIZE, &hstream->bdl); if (ret < 0) { dev_err(sdev->dev, "error: stream bdl dma alloc failed\n"); + kfree(stream); return -ENOMEM; } - stream->posbuf = (__le32 *)(hdev->posbuffer.area + - (stream->index) * 8); + hstream->posbuf = (__le32 *)(bus->posbuf.area + + (hstream->index) * 8); + + list_add_tail(&hstream->list, &bus->stream_list); } return 0; @@ -658,30 +710,23 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) void hda_dsp_stream_free(struct snd_sof_dev *sdev) { - struct sof_intel_hda_dev *hdev = sdev->hda; - struct sof_intel_hda_stream *stream; - int i; + struct hdac_bus *bus = sof_to_bus(sdev); + struct hdac_stream *s, *_s; + struct hdac_ext_stream *stream; /* free position buffer */ - if (hdev->posbuffer.area) - snd_dma_free_pages(&hdev->posbuffer); - - /* free capture streams */ - for (i = 0; i < hdev->num_capture; i++) { - stream = &hdev->cstream[i]; - - /* free bdl buffer */ - if (stream->bdl.area) - snd_dma_free_pages(&stream->bdl); - } + if (bus->posbuf.area) + snd_dma_free_pages(&bus->posbuf); - /* free playback streams */ - for (i = 0; i < hdev->num_playback; i++) { - stream = &hdev->pstream[i]; + list_for_each_entry_safe(s, _s, &bus->stream_list, list) { + /* TODO: decouple */ /* free bdl buffer */ - if (stream->bdl.area) - snd_dma_free_pages(&stream->bdl); + if (s->bdl.area) + snd_dma_free_pages(&s->bdl); + list_del(&s->list); + stream = stream_to_hdac_ext_stream(s); + kfree(stream); } } diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index 2b88768cb903bb..8c6369c9b6e7ae 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -36,11 +36,12 @@ static int hda_dsp_trace_prepare(struct snd_sof_dev *sdev) { - struct sof_intel_hda_stream *stream = sdev->hda->dtrace_stream; + struct hdac_ext_stream *stream = sdev->hda->dtrace_stream; + struct hdac_stream *hstream = &stream->hstream; struct snd_dma_buffer *dmab = &sdev->dmatb; int ret; - stream->bufsize = sdev->dmatb.bytes; + hstream->bufsize = sdev->dmatb.bytes; ret = hda_dsp_stream_hw_params(sdev, stream, dmab, NULL); if (ret < 0) @@ -59,7 +60,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *tag) return -ENODEV; } - *tag = sdev->hda->dtrace_stream->tag; + *tag = sdev->hda->dtrace_stream->hstream.stream_tag; /* * initialize capture stream, set BDL address and return corresponding @@ -70,10 +71,13 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *tag) int hda_dsp_trace_release(struct snd_sof_dev *sdev) { + struct hdac_stream *hstream; + if (sdev->hda->dtrace_stream) { - sdev->hda->dtrace_stream->open = false; + hstream = &sdev->hda->dtrace_stream->hstream; + hstream->opened = false; hda_dsp_stream_put_cstream(sdev, - sdev->hda->dtrace_stream->tag); + hstream->stream_tag); sdev->hda->dtrace_stream = NULL; return 0; } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a65dca8c446326..591999fff73c3e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -306,54 +306,22 @@ static const struct sof_intel_dsp_desc *get_chip_info(int pci_id) return NULL; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - -#if 0 -static int sof_hda_acquire_irq(struct hda_bus *hbus, int do_disconnect) -{ - int ret; - - /* register our IRQ */ - ret = request_threaded_irq(hbus->pci->irq, sof_hda_stream_interrupt, - sof_hda_stream_threaded_handler, - IRQF_SHARED, "SOFHDA", &hbus->core); - - if (ret) { - dev_err(hbus->core.dev, - "unable to grab IRQ %d, disabling device\n", - hbus->pci->irq); - return ret; - } - - hbus->core.irq = hbus->pci->irq; - pci_intx(hbus->pci, 1); - - return 0; -} -#endif - static int hda_init(struct snd_sof_dev *sdev) { struct hda_bus *hbus; struct hdac_bus *bus; - struct hdac_ext_bus_ops *ext_ops; + struct hdac_ext_bus_ops *ext_ops = NULL; struct pci_dev *pci = sdev->pci; - //struct hdac_ext_link *hlink = NULL; - //int err; - //unsigned short gcap; - - hbus = devm_kzalloc(&pci->dev, sizeof(*hbus), GFP_KERNEL); - if (!hbus) - return -ENOMEM; + int ret; - sdev->hbus = hbus; - bus = &hbus->core; + hbus = sof_to_hbus(sdev); + bus = sof_to_bus(sdev); /* HDA bus init */ #if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA) ext_ops = snd_soc_hdac_hda_get_ops(); #endif - snd_hdac_ext_bus_init(bus, &pci->dev, NULL, NULL, ext_ops); + sof_hda_bus_init(bus, &pci->dev, ext_ops); bus->use_posbuf = 1; bus->bdl_pos_adj = 0; @@ -370,26 +338,22 @@ static int hda_init(struct snd_sof_dev *sdev) return -ENXIO; } - // FIXME: we do this alot ! - hda_dsp_ctrl_init_chip(sdev, true); - - snd_hdac_bus_parse_capabilities(bus); - - //if (sof_hda_acquire_irq(hbus, 0) < 0) - // return -EBUSY; - - /* update BARs for sof, don't need parse them again */ + /* HDA base */ sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr; - sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap; - sdev->bar[HDA_DSP_SPIB_BAR] = bus->spbcap; - sdev->bar[HDA_DSP_DRSM_BAR] = bus->drsmcap; - return 0; + /* get controller capabilities */ + ret = hda_dsp_ctrl_get_caps(sdev); + if (ret < 0) + dev_err(&pci->dev, "error: get caps error\n"); + + return ret; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + static int hda_init_caps(struct snd_sof_dev *sdev) { - struct hdac_bus *bus = &sdev->hbus->core; + struct hdac_bus *bus = sof_to_bus(sdev); struct pci_dev *pci = sdev->pci; struct hdac_ext_link *hlink = NULL; int ret = 0; @@ -450,35 +414,14 @@ static int hda_init_caps(struct snd_sof_dev *sdev) #else -static int hda_init(struct snd_sof_dev *sdev) -{ - struct pci_dev *pci = sdev->pci; - int ret; - - /* HDA base */ - sdev->bar[HDA_DSP_HDA_BAR] = pci_ioremap_bar(pci, HDA_DSP_HDA_BAR); - if (!sdev->bar[HDA_DSP_HDA_BAR]) { - dev_err(&pci->dev, "error: ioremap error\n"); - return -ENXIO; - } - - /* get controller capabilities */ - ret = hda_dsp_ctrl_get_caps(sdev); - if (ret < 0) - dev_err(&pci->dev, "error: get caps error\n"); - - return 0; -} - static int hda_init_caps(struct snd_sof_dev *sdev) { /* - * 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 + * set CGCTL.MISCBDCGE to 0 during reset and set back to 1 + * when reset finished. + * TODO: maybe no need for init_caps? */ - snd_sof_pci_update_bits(sdev, PCI_CGCTL, - PCI_CGCTL_MISCBDCGE_MASK, 0); + hda_dsp_ctrl_enable_miscbdcge(sdev, 0); /* clear WAKESTS */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, @@ -499,10 +442,10 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = sdev->pci; struct sof_intel_hda_dev *hdev; - struct sof_intel_hda_stream *stream; + struct hdac_bus *bus; + struct hdac_stream *stream; const struct sof_intel_dsp_desc *chip; - int i; - int ret = 0; + int sd_offset, ret = 0; /* set DSP arch ops */ sdev->arch_ops = &sof_xtensa_arch_ops; @@ -524,22 +467,18 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) /* set up HDA base */ ret = hda_init(sdev); if (ret < 0) - goto err; + return ret; /* DSP base */ sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); if (!sdev->bar[HDA_DSP_BAR]) { dev_err(&pci->dev, "error: ioremap error\n"); - ret = -ENXIO; - goto err; + return -ENXIO; } sdev->mmio_bar = HDA_DSP_BAR; sdev->mailbox_bar = HDA_DSP_BAR; - pci_set_master(pci); - synchronize_irq(pci->irq); - /* allow 64bit DMA address if supported by H/W */ if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(64))) { dev_dbg(&pci->dev, "DMA mask is 64 bit\n"); @@ -558,64 +497,15 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * not all errors are due to memory issues, but trying * to free everything does not harm */ - goto stream_err; + goto err; } /* - * clear bits 0-2 of PCI register TCSEL (at offset 0x44) - * TCSEL == Traffic Class Select Register, which sets PCI express QOS - * Ensuring these bits are 0 clears playback static on some HD Audio - * codecs. PCI register TCSEL is defined in the Intel manuals. + * clear TCSEL to clear playback on some HD Audio + * codecs. PCI TCSEL is defined in the Intel manuals. */ snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); - /* init HDA capabilities */ - ret = hda_init_caps(sdev); - if (ret < 0) - goto stream_err; - - /* reset HDA controller */ - ret = hda_dsp_ctrl_link_reset(sdev); - if (ret < 0) { - dev_err(&pci->dev, "error: failed to reset HDA controller\n"); - goto stream_err; - } - - /* clear stream status */ - for (i = 0 ; i < hdev->num_capture ; i++) { - stream = &hdev->cstream[i]; - if (stream) - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); - } - - for (i = 0 ; i < hdev->num_playback ; i++) { - stream = &hdev->pstream[i]; - if (stream) - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - stream->sd_offset + - SOF_HDA_ADSP_REG_CL_SD_STS, - SOF_HDA_CL_DMA_SD_INT_MASK, - SOF_HDA_CL_DMA_SD_INT_MASK); - } - - /* clear WAKESTS */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK, - SOF_HDA_WAKESTS_INT_MASK); - - /* clear interrupt status register */ - snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); - - /* enable CIE and GIE interrupts */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, - SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); - /* * register our IRQ * let's try to enable msi firstly @@ -623,7 +513,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * TODO: support interrupt mode selection with kernel parameter * support msi multiple vectors */ - ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); +// ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); + /* todo: MSI mode doesn't work for HDMI yet, debug it later */ + ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_LEGACY); if (ret < 0) { dev_info(sdev->dev, "use legacy interrupt mode\n"); sdev->hda->irq = pci->irq; @@ -642,7 +534,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", sdev->hda->irq); - goto stream_err; + goto free_streams; } dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); @@ -652,9 +544,49 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n", sdev->ipc_irq); - goto irq_err; + goto free_hda_irq; } + pci_set_master(pci); + synchronize_irq(pci->irq); + + /* init HDA capabilities */ + ret = hda_init_caps(sdev); + if (ret < 0) + goto free_ipc_irq; + + /* reset HDA controller */ + ret = hda_dsp_ctrl_link_reset(sdev); + if (ret < 0) { + dev_err(&pci->dev, "error: failed to reset HDA controller\n"); + goto free_ipc_irq; + } + + /* clear stream status */ + bus = sof_to_bus(sdev); + list_for_each_entry(stream, &bus->stream_list, list) { + sd_offset = SOF_STREAM_SD_OFFSET(stream); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + sd_offset + + SOF_HDA_ADSP_REG_CL_SD_STS, + SOF_HDA_CL_DMA_SD_INT_MASK, + SOF_HDA_CL_DMA_SD_INT_MASK); + } + + /* clear WAKESTS */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, + SOF_HDA_WAKESTS_INT_MASK, + SOF_HDA_WAKESTS_INT_MASK); + + /* clear interrupt status register */ + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM); + + /* enable CIE and GIE interrupts */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, + SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); + /* re-enable CGCTL.MISCBDCGE after reset */ hda_dsp_ctrl_enable_miscbdcge(sdev, true); @@ -676,10 +608,12 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) return 0; -irq_err: +free_ipc_irq: + free_irq(sdev->ipc_irq, sdev); +free_hda_irq: free_irq(sdev->hda->irq, sdev); -stream_err: pci_free_irq_vectors(pci); +free_streams: hda_dsp_stream_free(sdev); err: /* disable DSP */ diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 6ff873f66be456..a9b574050a5926 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -43,12 +43,18 @@ #define SOF_HDA_CAP_ID_MASK (0xFFF << SOF_HDA_CAP_ID_OFF) #define SOF_HDA_CAP_NEXT_MASK 0xFFFF +#define SOF_HDA_GTS_CAP_ID 0x1 +#define SOF_HDA_ML_CAP_ID 0x2 + #define SOF_HDA_PP_CAP_ID 0x3 #define SOF_HDA_REG_PP_PPCH 0x10 #define SOF_HDA_REG_PP_PPCTL 0x04 #define SOF_HDA_PPCTL_PIE BIT(31) #define SOF_HDA_PPCTL_GPROCEN BIT(30) +/* DPIB entry size: 8 Bytes = 2 DWords */ +#define SOF_HDA_DPIB_ENTRY_SIZE 0x8 + #define SOF_HDA_SPIB_CAP_ID 0x4 #define SOF_HDA_DRSM_CAP_ID 0x5 @@ -100,6 +106,7 @@ #define SOF_HDA_ADSP_REG_CL_SD_FIFOL 0x14 #define SOF_HDA_ADSP_REG_CL_SD_BDLPL 0x18 #define SOF_HDA_ADSP_REG_CL_SD_BDLPU 0x1C +#define SOF_HDA_ADSP_SD_ENTRY_SIZE 0x20 /* CL: Software Position Based FIFO Capability Registers */ #define SOF_DSP_REG_CL_SPBFIFO \ @@ -326,40 +333,6 @@ struct sof_intel_dsp_desc { struct snd_sof_dsp_ops *ops; }; -/* per stream data for HDA DSP Frontend */ -struct sof_intel_hda_stream { - - /* addresses for stream HDA functions */ - void __iomem *pphc_addr; - void __iomem *pplc_addr; - void __iomem *spib_addr; - void __iomem *fifo_addr; - void __iomem *drsm_addr; - - /* runtime state */ - u32 dpib; - u32 lpib; - int tag; - int direction; - bool open; - bool running; - u32 index; - - /* buffer & descriptors */ - struct snd_dma_buffer bdl; - void __iomem *sd_addr; /* stream descriptor pointer */ - int sd_offset; /* Stream descriptor offset */ - unsigned int bufsize; /* size of the play buffer in bytes */ - unsigned int fifo_size; /* FIFO size */ - - __le32 *posbuf; /* position buffer pointer */ - unsigned int frags; /* number for period in the play buffer */ - unsigned int config; /* format config value */ - - /* PCM */ - struct snd_pcm_substream *substream; -}; - #define SOF_HDA_PLAYBACK_STREAMS 16 #define SOF_HDA_CAPTURE_STREAMS 16 #define SOF_HDA_PLAYBACK 0 @@ -368,24 +341,21 @@ struct sof_intel_hda_stream { /* represents DSP HDA controller frontend - i.e. host facing control */ struct sof_intel_hda_dev { + struct hda_bus hbus; + /* hw config */ const struct sof_intel_dsp_desc *desc; - /* streams */ - struct sof_intel_hda_stream pstream[SOF_HDA_PLAYBACK_STREAMS]; - struct sof_intel_hda_stream cstream[SOF_HDA_CAPTURE_STREAMS]; - int num_capture; - int num_playback; - - /* position buffers */ - struct snd_dma_buffer posbuffer; - /*trace */ - struct sof_intel_hda_stream *dtrace_stream; + struct hdac_ext_stream *dtrace_stream; int irq; }; +#define SOF_STREAM_SD_OFFSET(s) \ + (SOF_HDA_ADSP_SD_ENTRY_SIZE * ((s)->index) \ + + SOF_HDA_ADSP_LOADER_BASE) + /* * DSP Core services. */ @@ -441,26 +411,30 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, int hda_dsp_stream_init(struct snd_sof_dev *sdev); void hda_dsp_stream_free(struct snd_sof_dev *sdev); int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, + struct hdac_ext_stream *stream, struct snd_dma_buffer *dmab, struct snd_pcm_hw_params *params); int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, int cmd); + struct hdac_ext_stream *stream, int cmd); irqreturn_t hda_dsp_stream_interrupt(int irq, void *context); irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context); int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, - struct sof_intel_hda_stream *stream, + struct hdac_stream *stream, struct sof_intel_dsp_bdl *bdl, int size, struct snd_pcm_hw_params *params); -struct sof_intel_hda_stream * + +struct hdac_ext_stream * + hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction); +struct hdac_ext_stream * hda_dsp_stream_get_cstream(struct snd_sof_dev *sdev); -struct sof_intel_hda_stream * +struct hdac_ext_stream * hda_dsp_stream_get_pstream(struct snd_sof_dev *sdev); +int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag); int hda_dsp_stream_put_pstream(struct snd_sof_dev *sdev, int stream_tag); int hda_dsp_stream_put_cstream(struct snd_sof_dev *sdev, int stream_tag); int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, - struct sof_intel_hda_stream *stream, + struct hdac_ext_stream *stream, int enable, u32 size); /* @@ -490,11 +464,20 @@ int hda_dsp_ctrl_link_reset(struct snd_sof_dev *sdev); void hda_dsp_ctrl_enable_miscbdcge(struct snd_sof_dev *sdev, bool enable); int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* * HDA Codec operations. */ int hda_codec_probe_bus(struct snd_sof_dev *sdev); int hda_codec_i915_init(struct snd_sof_dev *sdev); +#endif + +/* + * HDA bus operations. + */ +int sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, + const struct hdac_ext_bus_ops *ext_ops); + /* * Trace Control. diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index e1c2d1deb5f667..faa56f2e29bcd7 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -298,7 +298,6 @@ struct snd_sof_dev { struct snd_sof_pdata *pdata; const struct snd_sof_dsp_ops *ops; struct sof_intel_hda_dev *hda; /* for HDA based DSP HW FIXME: delete this and use hbus instead */ - struct hda_bus *hbus; const struct sof_arch_ops *arch_ops; /* IPC */ @@ -355,6 +354,9 @@ struct snd_sof_dev { void *private; /* core does not touch this */ }; +#define sof_to_bus(s) (&(s)->hda->hbus.core) +#define sof_to_hbus(s) (&(s)->hda->hbus) + /* * SOF platform private struct used as drvdata of * platform dev (e.g. pci/acpi/spi...) drvdata.