From f0e1f9b1d3033fa0e91d1a5ba81fe3331ec5451d Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 23 Jul 2018 17:07:47 +0800 Subject: [PATCH 1/7] ASoC: SOF: refine Kconfig for SOF HDA. Signed-off-by: Keyon Jie --- sound/soc/intel/boards/Kconfig | 1 - sound/soc/sof/intel/Kconfig | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) 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..3d60b9df44797a 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -93,7 +93,14 @@ 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_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 From 642a02a5c2517daf71e104833af4aec87e83ca3a Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 23 Jul 2018 18:23:49 +0800 Subject: [PATCH 2/7] ASoC: SOF: hda: enable IRQ before codec probing We need register/enable irq handler before init_caps, where we are doing codec probing for HDMI/HDA, otherwise the probing may fail. We also need to use PCI_IRQ_LEGACY mode at the moment, as PCI_IRQ_MSI doesn't work for HDMI yet, may need more debug to fix it. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda.c | 124 ++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 65 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a65dca8c446326..d461740dfe219a 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -338,9 +338,6 @@ static int hda_init(struct snd_sof_dev *sdev) struct hdac_bus *bus; struct hdac_ext_bus_ops *ext_ops; 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) @@ -375,9 +372,6 @@ static int hda_init(struct snd_sof_dev *sdev) 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 */ sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr; sdev->bar[HDA_DSP_PP_BAR] = bus->ppcap; @@ -473,12 +467,11 @@ static int hda_init(struct snd_sof_dev *sdev) 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, @@ -524,22 +517,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,27 +547,69 @@ 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); + /* + * register our IRQ + * let's try to enable msi firstly + * if it fails, use legacy interrupt mode + * TODO: support interrupt mode selection with kernel parameter + * support msi multiple vectors + */ +// 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; + sdev->ipc_irq = pci->irq; + } else { + dev_info(sdev->dev, "use msi interrupt mode\n"); + sdev->hda->irq = pci_irq_vector(pci, 0); + /* ipc irq number is the same of hda irq */ + sdev->ipc_irq = sdev->hda->irq; + } + + dev_dbg(sdev->dev, "using HDA IRQ %d\n", sdev->hda->irq); + ret = request_threaded_irq(sdev->hda->irq, hda_dsp_stream_interrupt, + hda_dsp_stream_threaded_handler, + IRQF_SHARED, "AudioHDA", sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", + sdev->hda->irq); + goto free_streams; + } + + dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); + ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler, + chip->ops->irq_thread, IRQF_SHARED, + "AudioDSP", sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n", + sdev->ipc_irq); + goto free_hda_irq; + } + + pci_set_master(pci); + synchronize_irq(pci->irq); + /* init HDA capabilities */ ret = hda_init_caps(sdev); if (ret < 0) - goto stream_err; + 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 stream_err; + goto free_ipc_irq; } /* clear stream status */ @@ -616,45 +647,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) 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 - * if it fails, use legacy interrupt mode - * TODO: support interrupt mode selection with kernel parameter - * support msi multiple vectors - */ - ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); - if (ret < 0) { - dev_info(sdev->dev, "use legacy interrupt mode\n"); - sdev->hda->irq = pci->irq; - sdev->ipc_irq = pci->irq; - } else { - dev_info(sdev->dev, "use msi interrupt mode\n"); - sdev->hda->irq = pci_irq_vector(pci, 0); - /* ipc irq number is the same of hda irq */ - sdev->ipc_irq = sdev->hda->irq; - } - - dev_dbg(sdev->dev, "using HDA IRQ %d\n", sdev->hda->irq); - ret = request_threaded_irq(sdev->hda->irq, hda_dsp_stream_interrupt, - hda_dsp_stream_threaded_handler, - IRQF_SHARED, "AudioHDA", sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", - sdev->hda->irq); - goto stream_err; - } - - dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); - ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler, - chip->ops->irq_thread, IRQF_SHARED, - "AudioDSP", sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n", - sdev->ipc_irq); - goto irq_err; - } - /* re-enable CGCTL.MISCBDCGE after reset */ hda_dsp_ctrl_enable_miscbdcge(sdev, true); @@ -676,10 +668,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 */ From 2189fa7c8b559bd980ae39ff8d22d53a196d0708 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 24 Jul 2018 12:15:50 +0800 Subject: [PATCH 3/7] ASoC: SOF: use hdac_bus to manage streams This patch doesn't replace struct sof_intel_hda_dev with hda_bus, but embed hda_bus in sof_intel_hda_dev. It's becasue there are a few memebers of sof_intel_hda_dev are not in hda_bus. Host streams are managed by hdac_bus's stream_list now. Compiling okay. But not test yet. May have conflict with Keyon's PR today. I'll rebase and merge it to Keyon's PR later. Signed-off-by: Mengdong Lin --- sound/soc/sof/intel/hda-codec.c | 8 +- sound/soc/sof/intel/hda-ctrl.c | 2 +- sound/soc/sof/intel/hda-loader.c | 14 +- sound/soc/sof/intel/hda-stream.c | 229 +++++++++++++++++-------------- sound/soc/sof/intel/hda.c | 29 +--- sound/soc/sof/intel/hda.h | 20 +-- sound/soc/sof/sof-priv.h | 4 +- 7 files changed, 159 insertions(+), 147 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 83a544b974aa98..d35ca8a1085128 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -51,7 +51,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 +92,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; @@ -116,8 +115,7 @@ int hda_codec_probe_bus(struct snd_sof_dev *sdev) 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 */ diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index eac0815de78734..a55801a3d93433 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -145,7 +145,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); diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 372ccfaac30647..fbb3943422380e 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -242,17 +242,19 @@ static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, 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 sof_intel_hda_stream *s, *stream = NULL; + 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->tag == tag) { + 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-stream.c b/sound/soc/sof/intel/hda-stream.c index d753a83c746b72..988145066c8f32 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -116,19 +116,44 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, return 0; } + +/* get next unused stream */ +struct sof_intel_hda_stream * +hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + struct sof_intel_hda_stream *s, *stream = NULL; + + /* get an unused playback stream */ + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == direction && !s->open) { + s->open = true; + 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 * 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 sof_intel_hda_stream *s, *stream = NULL; /* 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->open) { + s->open = true; + stream = s; break; } } @@ -144,15 +169,15 @@ hda_dsp_stream_get_pstream(struct snd_sof_dev *sdev) struct sof_intel_hda_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 sof_intel_hda_stream *s, *stream = NULL; /* 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->open) { + s->open = true; + stream = s; break; } } @@ -164,17 +189,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 sof_intel_hda_stream *s; + + /* find used stream */ + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == direction + && s->open && s->tag == tag) { + s->open = 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 sof_intel_hda_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->open && s->tag == tag) { + s->open = false; return 0; } } @@ -186,14 +230,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 sof_intel_hda_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->open && s->tag == tag) { + s->open = false; return 0; } } @@ -256,7 +300,7 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, 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 sof_intel_dsp_bdl *bdl; int ret, timeout = HDA_DSP_STREAM_RESET_TIMEOUT; u32 val, mask; @@ -382,7 +426,7 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, 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 */ @@ -408,7 +452,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)) @@ -440,63 +484,40 @@ irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) 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 sof_intel_hda_stream *s; + //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->open) { sd_status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - hdev->pstream[i].sd_offset + + s->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 + + s->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,7 +527,7 @@ 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 hdac_bus *bus = sof_to_bus(sdev); struct sof_intel_hda_stream *stream; struct pci_dev *pci = sdev->pci; int i, num_playback, num_capture, num_total, ret; @@ -520,9 +541,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 +557,30 @@ 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; @@ -598,15 +620,21 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) HDA_DSP_BDL_SIZE, &stream->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->posbuf = (__le32 *)(bus->posbuf.area + (stream->index) * 8); + + list_add_tail(&stream->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] + @@ -646,11 +674,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) HDA_DSP_BDL_SIZE, &stream->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->posbuf = (__le32 *)(bus->posbuf.area + (stream->index) * 8); + + list_add_tail(&stream->list, &bus->stream_list); } return 0; @@ -658,30 +689,22 @@ 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; - - /* free position buffer */ - if (hdev->posbuffer.area) - snd_dma_free_pages(&hdev->posbuffer); + struct hdac_bus *bus = sof_to_bus(sdev); + struct sof_intel_hda_stream *s, *_s; - /* 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); - } + /* free position buffer */ + 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); + kfree(s); } } diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d461740dfe219a..0331e7211c47af 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -339,12 +339,8 @@ static int hda_init(struct snd_sof_dev *sdev) struct hdac_ext_bus_ops *ext_ops; struct pci_dev *pci = sdev->pci; - hbus = devm_kzalloc(&pci->dev, sizeof(*hbus), GFP_KERNEL); - if (!hbus) - return -ENOMEM; - - 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) @@ -383,7 +379,7 @@ static int hda_init(struct snd_sof_dev *sdev) 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; @@ -492,9 +488,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = sdev->pci; struct sof_intel_hda_dev *hdev; + struct hdac_bus *bus; struct sof_intel_hda_stream *stream; const struct sof_intel_dsp_desc *chip; - int i; int ret = 0; /* set DSP arch ops */ @@ -613,20 +609,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) } /* 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, + bus = sof_to_bus(sdev); + list_for_each_entry(stream, &bus->stream_list, list) { + 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, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 6ff873f66be456..4dcee28a16d423 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -52,6 +52,9 @@ #define SOF_HDA_SPIB_CAP_ID 0x4 #define SOF_HDA_DRSM_CAP_ID 0x5 +/* DPIB entry size: 8 Bytes = 2 DWords */ +#define SOF_HDA_DPIB_ENTRY_SIZE 0x8 + #define SOF_HDA_SPIB_BASE 0x08 #define SOF_HDA_SPIB_INTERVAL 0x08 #define SOF_HDA_SPIB_SPIB 0x00 @@ -358,6 +361,8 @@ struct sof_intel_hda_stream { /* PCM */ struct snd_pcm_substream *substream; + + struct list_head list; /* list of streams on the bus */ }; #define SOF_HDA_PLAYBACK_STREAMS 16 @@ -368,18 +373,11 @@ 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; @@ -453,10 +451,14 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, struct sof_intel_hda_stream *stream, struct sof_intel_dsp_bdl *bdl, int size, struct snd_pcm_hw_params *params); + +struct sof_intel_hda_stream * + hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction); struct sof_intel_hda_stream * hda_dsp_stream_get_cstream(struct snd_sof_dev *sdev); struct sof_intel_hda_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, 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. From d1c671e86c39e6622bfdb2d47106fb1081cceea5 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Mon, 23 Jul 2018 22:47:23 -0400 Subject: [PATCH 4/7] ASoC: SOF: Replace sof_intel_hda_stream with hdac_ext_stream In previous patch, hdac_bus is used to manage the host streams, but the stream structure is still struct sof_intel_hda_stream. This patch replaces struct sof_intel_hda_stream with hdac_ext_stream, but the stream management is still using BSD implementation of SOF, not the GPL implemenation of HDA core. Please note that - hdac_bus maintains a stream list of hdac_stream, which is embeded in struct hdac_ext_stream. - pcm runtime's private data points to hdac_stream, not hdac_ext_stream. Compiling okay. Not tested yet. Signed-off-by: Mengdong Lin --- sound/soc/sof/intel/hda-loader.c | 51 ++++--- sound/soc/sof/intel/hda-pcm.c | 24 ++-- sound/soc/sof/intel/hda-stream.c | 233 +++++++++++++++++-------------- sound/soc/sof/intel/hda-trace.c | 14 +- sound/soc/sof/intel/hda.c | 7 +- sound/soc/sof/intel/hda.h | 63 +++------ 6 files changed, 198 insertions(+), 194 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index fbb3943422380e..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,28 +220,30 @@ 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; } @@ -243,14 +251,15 @@ static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, static int cl_copy_fw(struct snd_sof_dev *sdev, int tag) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s, *stream = NULL; + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; int ret, status; /* get stream with tag */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == SNDRV_PCM_STREAM_PLAYBACK - && s->tag == tag) { - stream = s; + && s->stream_tag == tag) { + stream = stream_to_hdac_ext_stream(s); break; } } 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 988145066c8f32..956f9dc80a6efe 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); @@ -118,17 +119,18 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, /* get next unused stream */ -struct sof_intel_hda_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 sof_intel_hda_stream *s, *stream = NULL; + 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->open) { - s->open = true; - stream = s; + if (s->direction == direction && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); break; } } @@ -142,18 +144,19 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) } /* 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 hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s, *stream = NULL; + 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 == SNDRV_PCM_STREAM_PLAYBACK - && !s->open) { - s->open = true; - stream = s; + && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); break; } } @@ -166,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 hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s, *stream = NULL; + struct hdac_ext_stream *stream = NULL; + struct hdac_stream *s; /* get an unused capture stream */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == SNDRV_PCM_STREAM_CAPTURE - && !s->open) { - s->open = true; - stream = s; + && !s->opened) { + s->opened = true; + stream = stream_to_hdac_ext_stream(s); break; } } @@ -193,13 +197,13 @@ hda_dsp_stream_get_cstream(struct snd_sof_dev *sdev) int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int tag) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s; + struct hdac_stream *s; /* find used stream */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == direction - && s->open && s->tag == tag) { - s->open = false; + && s->opened && s->stream_tag == tag) { + s->opened = false; return 0; } } @@ -212,13 +216,13 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int tag) int hda_dsp_stream_put_pstream(struct snd_sof_dev *sdev, int tag) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s; + struct hdac_stream *s; /* find used playback stream */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == SNDRV_PCM_STREAM_PLAYBACK - && s->open && s->tag == tag) { - s->open = false; + && s->opened && s->stream_tag == tag) { + s->opened = false; return 0; } } @@ -231,13 +235,13 @@ int hda_dsp_stream_put_pstream(struct snd_sof_dev *sdev, int tag) int hda_dsp_stream_put_cstream(struct snd_sof_dev *sdev, int tag) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s; + struct hdac_stream *s; /* find used capture stream */ list_for_each_entry(s, &bus->stream_list, list) { if (s->direction == SNDRV_PCM_STREAM_CAPTURE - && s->open && s->tag == tag) { - s->open = false; + && s->opened && s->stream_tag == tag) { + s->opened = false; return 0; } } @@ -247,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); @@ -296,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 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; @@ -311,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); @@ -321,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); @@ -345,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); @@ -361,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; @@ -393,34 +402,34 @@ 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) @@ -430,20 +439,20 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, 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; @@ -485,7 +494,8 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) { struct snd_sof_dev *sdev = (struct snd_sof_dev *)context; struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s; + 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; @@ -493,10 +503,11 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) /* check streams */ list_for_each_entry(s, &bus->stream_list, list) { if (status & (1 << s->index) - && !s->open) { + && !s->opened) { + sd_offset = SOF_STREAM_SD_OFFSET(s); sd_status = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - s->sd_offset + + sd_offset + SOF_HDA_ADSP_REG_CL_SD_STS) & 0xff; @@ -504,7 +515,7 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) s->index, sd_status); snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - s->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); @@ -528,8 +539,10 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) int hda_dsp_stream_init(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *stream; + 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; @@ -600,33 +613,35 @@ 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; +#endif - 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; + hstream = &stream->hstream; + 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 *)(bus->posbuf.area + - (stream->index) * 8); + hstream->posbuf = (__le32 *)(bus->posbuf.area + + (hstream->index) * 8); - list_add_tail(&stream->list, &bus->stream_list); + list_add_tail(&hstream->list, &bus->stream_list); } /* create playback streams */ @@ -655,33 +670,36 @@ 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; +#endif - 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; + hstream = &stream->hstream; + 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 *)(bus->posbuf.area + - (stream->index) * 8); + hstream->posbuf = (__le32 *)(bus->posbuf.area + + (hstream->index) * 8); - list_add_tail(&stream->list, &bus->stream_list); + list_add_tail(&hstream->list, &bus->stream_list); } return 0; @@ -690,8 +708,8 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) void hda_dsp_stream_free(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); - struct sof_intel_hda_stream *s, *_s; - + struct hdac_stream *s, *_s; + struct hdac_ext_stream *stream; /* free position buffer */ if (bus->posbuf.area) @@ -704,7 +722,8 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev) if (s->bdl.area) snd_dma_free_pages(&s->bdl); list_del(&s->list); - kfree(s); + 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 0331e7211c47af..c2cd686bd90275 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -489,9 +489,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) struct pci_dev *pci = sdev->pci; struct sof_intel_hda_dev *hdev; struct hdac_bus *bus; - struct sof_intel_hda_stream *stream; + struct hdac_stream *stream; const struct sof_intel_dsp_desc *chip; - int ret = 0; + int sd_offset, ret = 0; /* set DSP arch ops */ sdev->arch_ops = &sof_xtensa_arch_ops; @@ -611,8 +611,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) /* 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, - stream->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); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 4dcee28a16d423..a34884a27ac721 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -49,12 +49,12 @@ #define SOF_HDA_PPCTL_PIE BIT(31) #define SOF_HDA_PPCTL_GPROCEN BIT(30) -#define SOF_HDA_SPIB_CAP_ID 0x4 -#define SOF_HDA_DRSM_CAP_ID 0x5 - /* 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 + #define SOF_HDA_SPIB_BASE 0x08 #define SOF_HDA_SPIB_INTERVAL 0x08 #define SOF_HDA_SPIB_SPIB 0x00 @@ -103,6 +103,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 \ @@ -329,42 +330,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; - - struct list_head list; /* list of streams on the bus */ -}; - #define SOF_HDA_PLAYBACK_STREAMS 16 #define SOF_HDA_CAPTURE_STREAMS 16 #define SOF_HDA_PLAYBACK 0 @@ -379,11 +344,15 @@ struct sof_intel_hda_dev { const struct sof_intel_dsp_desc *desc; /*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. */ @@ -439,30 +408,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 sof_intel_hda_stream * +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); /* From 7cc5debf7c5533b52352f04571402c975b752680 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 24 Jul 2018 20:15:21 +0800 Subject: [PATCH 5/7] ASoC: SOF: hda: initial bus pointer for stream to fix a NULL pointer issue. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-stream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 956f9dc80a6efe..d94c9d86d5c879 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -622,6 +622,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) #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; @@ -679,6 +680,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) #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; From 3ea24e92ee558e6a07263e7ec143a0a258e2b86b Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 25 Jul 2018 16:00:48 +0800 Subject: [PATCH 6/7] ASoC: SOF: hda: refine makefile for with/without HDA support 1. add hda-bus to handle hda bus initialization, for both with/without HDA links support. 2. split hda-codec out from hda-common, and compile it when SOF_HDA is selected. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/Kconfig | 1 + sound/soc/sof/intel/Makefile | 5 +- sound/soc/sof/intel/hda-bus.c | 135 ++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/intel/hda-bus.c diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 3d60b9df44797a..163b1b0c0200e2 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -95,6 +95,7 @@ config SND_SOC_SOF_HDA_COMMON config SND_SOC_SOF_HDA 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 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; +} From bd37bda408463b371d578fefd73ca9daa81e25af Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Wed, 25 Jul 2018 16:32:23 +0800 Subject: [PATCH 7/7] ASoC: SOF: hda: refine to support both with/without HDA links. We uses CONFIG_SND_SOC_SOF_HDA to enable HDA links on SOF, here refine SOF HDA code to split them and make both select/unselect the config CONFIG_SND_SOC_SOF_HDA works. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/hda-codec.c | 7 +++- sound/soc/sof/intel/hda-ctrl.c | 30 ++++++++++---- sound/soc/sof/intel/hda-stream.c | 5 ++- sound/soc/sof/intel/hda.c | 70 ++++++-------------------------- sound/soc/sof/intel/hda.h | 12 ++++++ 5 files changed, 53 insertions(+), 71 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index d35ca8a1085128..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" @@ -112,6 +111,7 @@ 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) { @@ -129,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 a55801a3d93433..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 @@ -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-stream.c b/sound/soc/sof/intel/hda-stream.c index d94c9d86d5c879..f77421e2e831bb 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -475,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) { @@ -483,11 +484,12 @@ 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) @@ -579,7 +581,6 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) return -ENOMEM; } - /* mem alloc for the CORB/RIRB ringbuffers */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, PAGE_SIZE, &bus->rb); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index c2cd686bd90275..591999fff73c3e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -306,38 +306,13 @@ 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; + int ret; hbus = sof_to_hbus(sdev); bus = sof_to_bus(sdev); @@ -346,7 +321,7 @@ static int hda_init(struct snd_sof_dev *sdev) #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; @@ -363,20 +338,19 @@ 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); - - /* 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 = sof_to_bus(sdev); @@ -440,26 +414,6 @@ 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) { /* diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index a34884a27ac721..a9b574050a5926 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -43,6 +43,9 @@ #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 @@ -461,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.