Commit 4b15c497 authored by Mark Brown's avatar Mark Brown

Merge series "SOF fixes and updates for FW boot" from Ranjani Sridharan...

Merge series "SOF fixes and updates for FW boot" from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

This series includes fixes and updates for the FW boot sequence for
Intel platforms.

Ranjani Sridharan (7):
  ALSA: hda: fix VS_LTRC register name
  ASoC: SOF: Intel: hda: Add helper function to program ICCMAX stream
  ASoC: SOF: Intel: hda: modify the signature of get_stream_with_tag()
  ASoC: SOF: Intel: hda: define macro for code loader stream format
  ASoC: SOF: Intel: hda: Define FW boot sequence with ICCMAX
  ASoC: SOF: Intel: hda: Add sof_tgl_ops for TGL platforms
  ASoC: SOF: Intel: hda: Simplify error handling during FW boot

Yong Zhi (1):
  ASoC: SOF: Intel: hda: Remove unused parameters in cl_dsp_init()

 include/sound/hda_register.h     |   2 +-
 sound/soc/sof/intel/Makefile     |   2 +-
 sound/soc/sof/intel/cnl.c        |  23 +----
 sound/soc/sof/intel/hda-ipc.h    |   4 +
 sound/soc/sof/intel/hda-loader.c | 145 ++++++++++++++++++-------------
 sound/soc/sof/intel/hda-stream.c |  69 +++++++++++++++
 sound/soc/sof/intel/hda.h        |   6 ++
 sound/soc/sof/intel/tgl.c        | 137 +++++++++++++++++++++++++++++
 sound/soc/sof/sof-pci-dev.c      |   2 +-
 9 files changed, 306 insertions(+), 84 deletions(-)
 create mode 100644 sound/soc/sof/intel/tgl.c

--
2.25.1
parents c1c277b2 01d42d5a
...@@ -119,7 +119,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; ...@@ -119,7 +119,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_VS_EM3U 0x103C #define AZX_REG_VS_EM3U 0x103C
#define AZX_REG_VS_EM4L 0x1040 #define AZX_REG_VS_EM4L 0x1040
#define AZX_REG_VS_EM4U 0x1044 #define AZX_REG_VS_EM4U 0x1044
#define AZX_REG_VS_LTRC 0x1048 #define AZX_REG_VS_LTRP 0x1048
#define AZX_REG_VS_D0I3C 0x104A #define AZX_REG_VS_D0I3C 0x104A
#define AZX_REG_VS_PCE 0x104B #define AZX_REG_VS_PCE 0x104B
#define AZX_REG_VS_L2MAGC 0x1050 #define AZX_REG_VS_L2MAGC 0x1050
......
...@@ -8,7 +8,7 @@ snd-sof-intel-ipc-objs := intel-ipc.o ...@@ -8,7 +8,7 @@ snd-sof-intel-ipc-objs := intel-ipc.o
snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.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-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \
hda-dai.o hda-bus.o \ hda-dai.o hda-bus.o \
apl.o cnl.o apl.o cnl.o tgl.o
snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o
snd-sof-intel-hda-objs := hda-codec.o snd-sof-intel-hda-objs := hda-codec.o
......
...@@ -29,7 +29,7 @@ static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { ...@@ -29,7 +29,7 @@ static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
static void cnl_ipc_host_done(struct snd_sof_dev *sdev); static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev); static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
{ {
struct snd_sof_dev *sdev = context; struct snd_sof_dev *sdev = context;
u32 hipci; u32 hipci;
...@@ -163,8 +163,7 @@ static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg, ...@@ -163,8 +163,7 @@ static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
return false; return false;
} }
static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
struct snd_sof_ipc_msg *msg)
{ {
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
struct sof_ipc_cmd_hdr *hdr; struct sof_ipc_cmd_hdr *hdr;
...@@ -211,7 +210,7 @@ static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, ...@@ -211,7 +210,7 @@ static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
return 0; return 0;
} }
static void cnl_ipc_dump(struct snd_sof_dev *sdev) void cnl_ipc_dump(struct snd_sof_dev *sdev)
{ {
u32 hipcctl; u32 hipcctl;
u32 hipcida; u32 hipcida;
...@@ -369,22 +368,6 @@ const struct sof_intel_dsp_desc icl_chip_info = { ...@@ -369,22 +368,6 @@ const struct sof_intel_dsp_desc icl_chip_info = {
}; };
EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
const struct sof_intel_dsp_desc tgl_chip_info = {
/* Tigerlake */
.cores_num = 4,
.init_core_mask = 1,
.cores_mask = HDA_DSP_CORE_MASK(0),
.ipc_req = CNL_DSP_REG_HIPCIDR,
.ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
.ipc_ack = CNL_DSP_REG_HIPCIDA,
.ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
.ipc_ctl = CNL_DSP_REG_HIPCCTL,
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
};
EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
const struct sof_intel_dsp_desc ehl_chip_info = { const struct sof_intel_dsp_desc ehl_chip_info = {
/* Elkhartlake */ /* Elkhartlake */
.cores_num = 4, .cores_num = 4,
......
...@@ -48,4 +48,8 @@ ...@@ -48,4 +48,8 @@
#define HDA_PM_PG_STREAMING BIT(1) #define HDA_PM_PG_STREAMING BIT(1)
#define HDA_PM_PG_RSVD BIT(0) #define HDA_PM_PG_RSVD BIT(0)
irqreturn_t cnl_ipc_irq_thread(int irq, void *context);
int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg);
void cnl_ipc_dump(struct snd_sof_dev *sdev);
#endif #endif
...@@ -17,13 +17,15 @@ ...@@ -17,13 +17,15 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <sound/hdaudio_ext.h> #include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
#include <sound/sof.h> #include <sound/sof.h>
#include "../ops.h" #include "../ops.h"
#include "hda.h" #include "hda.h"
#define HDA_FW_BOOT_ATTEMPTS 3 #define HDA_FW_BOOT_ATTEMPTS 3
#define HDA_CL_STREAM_FORMAT 0x40
static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
unsigned int size, struct snd_dma_buffer *dmab, unsigned int size, struct snd_dma_buffer *dmab,
int direction) int direction)
{ {
...@@ -32,16 +34,11 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, ...@@ -32,16 +34,11 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
struct pci_dev *pci = to_pci_dev(sdev->dev); struct pci_dev *pci = to_pci_dev(sdev->dev);
int ret; int ret;
if (direction != SNDRV_PCM_STREAM_PLAYBACK) {
dev_err(sdev->dev, "error: code loading DMA is playback only\n");
return -EINVAL;
}
dsp_stream = hda_dsp_stream_get(sdev, direction); dsp_stream = hda_dsp_stream_get(sdev, direction);
if (!dsp_stream) { if (!dsp_stream) {
dev_err(sdev->dev, "error: no stream available\n"); dev_err(sdev->dev, "error: no stream available\n");
return -ENODEV; return ERR_PTR(-ENODEV);
} }
hstream = &dsp_stream->hstream; hstream = &dsp_stream->hstream;
hstream->substream = NULL; hstream->substream = NULL;
...@@ -57,20 +54,27 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, ...@@ -57,20 +54,27 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
hstream->format_val = format; hstream->format_val = format;
hstream->bufsize = size; hstream->bufsize = size;
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
ret = hda_dsp_iccmax_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) {
dev_err(sdev->dev, "error: iccmax stream prepare failed: %x\n", ret);
goto error;
}
} else {
ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL); ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) { if (ret < 0) {
dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret); dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
goto error; goto error;
} }
hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size); hda_dsp_stream_spib_config(sdev, dsp_stream, HDA_DSP_SPIB_ENABLE, size);
}
return hstream->stream_tag; return dsp_stream;
error: error:
hda_dsp_stream_put(sdev, direction, hstream->stream_tag); hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
snd_dma_free_pages(dmab); snd_dma_free_pages(dmab);
return ret; return ERR_PTR(ret);
} }
/* /*
...@@ -78,8 +82,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, ...@@ -78,8 +82,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
* status on core 1, so power up core 1 also momentarily, keep it in * status on core 1, so power up core 1 also momentarily, keep it in
* reset/stall and then turn it off * reset/stall and then turn it off
*/ */
static int cl_dsp_init(struct snd_sof_dev *sdev, const void *fwdata, static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, int iteration)
u32 fwsize, int stream_tag, int iteration)
{ {
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc; const struct sof_intel_dsp_desc *chip = hda->desc;
...@@ -205,34 +208,20 @@ static int cl_trigger(struct snd_sof_dev *sdev, ...@@ -205,34 +208,20 @@ static int cl_trigger(struct snd_sof_dev *sdev,
} }
} }
static struct hdac_ext_stream *get_stream_with_tag(struct snd_sof_dev *sdev,
int tag)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct hdac_stream *s;
/* get stream with tag */
list_for_each_entry(s, &bus->stream_list, list) {
if (s->direction == SNDRV_PCM_STREAM_PLAYBACK &&
s->stream_tag == tag) {
return stream_to_hdac_ext_stream(s);
}
}
return NULL;
}
static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
struct hdac_ext_stream *stream) struct hdac_ext_stream *stream)
{ {
struct hdac_stream *hstream = &stream->hstream; struct hdac_stream *hstream = &stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream); int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
int ret; int ret = 0;
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
ret = hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0); ret = hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0);
else
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
SOF_HDA_SD_CTL_DMA_START, 0);
hda_dsp_stream_put(sdev, SNDRV_PCM_STREAM_PLAYBACK, hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
hstream->stream_tag);
hstream->running = 0; hstream->running = 0;
hstream->substream = NULL; hstream->substream = NULL;
...@@ -290,6 +279,54 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) ...@@ -290,6 +279,54 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream)
return status; return status;
} }
int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *plat_data = sdev->pdata;
struct hdac_ext_stream *iccmax_stream;
struct hdac_bus *bus = sof_to_bus(sdev);
struct firmware stripped_firmware;
int ret, ret1;
u8 original_gb;
/* save the original LTRP guardband value */
original_gb = snd_hdac_chip_readb(bus, VS_LTRP) & HDA_VS_INTEL_LTRP_GB_MASK;
if (plat_data->fw->size <= plat_data->fw_offset) {
dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n");
return -EINVAL;
}
stripped_firmware.size = plat_data->fw->size - plat_data->fw_offset;
/* prepare capture stream for ICCMAX */
iccmax_stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream);
}
ret = hda_dsp_cl_boot_firmware(sdev);
/*
* Perform iccmax stream cleanup. This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
ret1 = cl_cleanup(sdev, &sdev->dmab_bdl, iccmax_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
/* set return value to indicate cleanup failure */
if (!ret)
ret = ret1;
}
/* restore the original guardband value after FW boot */
snd_hdac_chip_updateb(bus, VS_LTRP, HDA_VS_INTEL_LTRP_GB_MASK, original_gb);
return ret;
}
int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
{ {
struct snd_sof_pdata *plat_data = sdev->pdata; struct snd_sof_pdata *plat_data = sdev->pdata;
...@@ -297,7 +334,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -297,7 +334,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
const struct sof_intel_dsp_desc *chip_info; const struct sof_intel_dsp_desc *chip_info;
struct hdac_ext_stream *stream; struct hdac_ext_stream *stream;
struct firmware stripped_firmware; struct firmware stripped_firmware;
int ret, ret1, tag, i; int ret, ret1, i;
chip_info = desc->chip_info; chip_info = desc->chip_info;
...@@ -313,23 +350,11 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -313,23 +350,11 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
init_waitqueue_head(&sdev->boot_wait); init_waitqueue_head(&sdev->boot_wait);
/* prepare DMA for code loader stream */ /* prepare DMA for code loader stream */
tag = cl_stream_prepare(sdev, 0x40, stripped_firmware.size, stream = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab, SNDRV_PCM_STREAM_PLAYBACK); &sdev->dmab, SNDRV_PCM_STREAM_PLAYBACK);
if (IS_ERR(stream)) {
if (tag < 0) { dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
dev_err(sdev->dev, "error: dma prepare for fw loading err: %x\n", return PTR_ERR(stream);
tag);
return tag;
}
/* get stream with tag */
stream = get_stream_with_tag(sdev, tag);
if (!stream) {
dev_err(sdev->dev,
"error: could not get stream with stream tag %d\n",
tag);
ret = -ENODEV;
goto err;
} }
memcpy(sdev->dmab.area, stripped_firmware.data, memcpy(sdev->dmab.area, stripped_firmware.data,
...@@ -340,8 +365,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -340,8 +365,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, dev_dbg(sdev->dev,
"Attempting iteration %d of Core En/ROM load...\n", i); "Attempting iteration %d of Core En/ROM load...\n", i);
ret = cl_dsp_init(sdev, stripped_firmware.data, ret = cl_dsp_init(sdev, stream->hstream.stream_tag, i + 1);
stripped_firmware.size, tag, i + 1);
/* don't retry anymore if successful */ /* don't retry anymore if successful */
if (!ret) if (!ret)
...@@ -410,7 +434,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -410,7 +434,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
return chip_info->init_core_mask; return chip_info->init_core_mask;
/* dump dsp registers and disable DSP upon error */ /* dump dsp registers and disable DSP upon error */
err:
hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX); hda_dsp_dump(sdev, SOF_DBG_REGS | SOF_DBG_PCI | SOF_DBG_MBOX);
/* disable DSP */ /* disable DSP */
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "../sof-audio.h" #include "../sof-audio.h"
#include "hda.h" #include "hda.h"
#define HDA_LTRP_GB_VALUE_US 95
/* /*
* set up one of BDL entries for a stream * set up one of BDL entries for a stream
*/ */
...@@ -322,6 +324,73 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, ...@@ -322,6 +324,73 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
return 0; return 0;
} }
/* minimal recommended programming for ICCMAX stream */
int hda_dsp_iccmax_stream_hw_params(struct snd_sof_dev *sdev, 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;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
int ret;
u32 mask = 0x1 << hstream->index;
if (!stream) {
dev_err(sdev->dev, "error: no stream available\n");
return -ENODEV;
}
if (hstream->posbuf)
*hstream->posbuf = 0;
/* reset BDL address */
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL,
0x0);
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU,
0x0);
hstream->frags = 0;
ret = hda_dsp_stream_setup_bdl(sdev, dmab, hstream);
if (ret < 0) {
dev_err(sdev->dev, "error: set up of BDL failed\n");
return ret;
}
/* program BDL address */
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPL,
(u32)hstream->bdl.addr);
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_BDLPU,
upper_32_bits(hstream->bdl.addr));
/* program cyclic buffer length */
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_CBL,
hstream->bufsize);
/* program last valid index */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
sd_offset + SOF_HDA_ADSP_REG_CL_SD_LVI,
0xffff, (hstream->frags - 1));
/* decouple host and link DMA, enable DSP features */
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
mask, mask);
/* Follow HW recommendation to set the guardband value to 95us during FW boot */
snd_hdac_chip_updateb(bus, VS_LTRP, HDA_VS_INTEL_LTRP_GB_MASK, HDA_LTRP_GB_VALUE_US);
/* start DMA */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset,
SOF_HDA_SD_CTL_DMA_START, SOF_HDA_SD_CTL_DMA_START);
return 0;
}
/* /*
* prepare for common hdac registers settings, for both code loader * prepare for common hdac registers settings, for both code loader
* and normal stream. * and normal stream.
......
...@@ -246,6 +246,7 @@ ...@@ -246,6 +246,7 @@
/* Intel Vendor Specific Registers */ /* Intel Vendor Specific Registers */
#define HDA_VS_INTEL_EM2 0x1030 #define HDA_VS_INTEL_EM2 0x1030
#define HDA_VS_INTEL_EM2_L1SEN BIT(13) #define HDA_VS_INTEL_EM2_L1SEN BIT(13)
#define HDA_VS_INTEL_LTRP_GB_MASK 0x3F
/* HIPCI */ /* HIPCI */
#define HDA_DSP_REG_HIPCI_BUSY BIT(31) #define HDA_DSP_REG_HIPCI_BUSY BIT(31)
...@@ -546,6 +547,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, ...@@ -546,6 +547,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev,
struct hdac_ext_stream *stream, struct hdac_ext_stream *stream,
struct snd_dma_buffer *dmab, struct snd_dma_buffer *dmab,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
int hda_dsp_iccmax_stream_hw_params(struct snd_sof_dev *sdev, 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, int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
struct hdac_ext_stream *stream, int cmd); struct hdac_ext_stream *stream, int cmd);
irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context); irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context);
...@@ -608,6 +612,7 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); ...@@ -608,6 +612,7 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);
* DSP Code loader. * DSP Code loader.
*/ */
int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev); int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev); int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev);
/* pre and post fw run ops */ /* pre and post fw run ops */
...@@ -728,6 +733,7 @@ extern struct snd_soc_dai_driver skl_dai[]; ...@@ -728,6 +733,7 @@ extern struct snd_soc_dai_driver skl_dai[];
*/ */
extern const struct snd_sof_dsp_ops sof_apl_ops; extern const struct snd_sof_dsp_ops sof_apl_ops;
extern const struct snd_sof_dsp_ops sof_cnl_ops; extern const struct snd_sof_dsp_ops sof_cnl_ops;
extern const struct snd_sof_dsp_ops sof_tgl_ops;
extern const struct sof_intel_dsp_desc apl_chip_info; extern const struct sof_intel_dsp_desc apl_chip_info;
extern const struct sof_intel_dsp_desc cnl_chip_info; extern const struct sof_intel_dsp_desc cnl_chip_info;
......
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// Copyright(c) 2020 Intel Corporation. All rights reserved.
//
// Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
//
/*
* Hardware interface for audio DSP on Tigerlake.
*/
#include "../ops.h"
#include "hda.h"
#include "hda-ipc.h"
#include "../sof-audio.h"
static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
{"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
{"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
};
/* Tigerlake ops */
const struct snd_sof_dsp_ops sof_tgl_ops = {
/* probe and remove */
.probe = hda_dsp_probe,
.remove = hda_dsp_remove,
/* Register IO */
.write = sof_io_write,
.read = sof_io_read,
.write64 = sof_io_write64,
.read64 = sof_io_read64,
/* Block IO */
.block_read = sof_block_read,
.block_write = sof_block_write,
/* doorbell */
.irq_thread = cnl_ipc_irq_thread,
/* ipc */
.send_msg = cnl_ipc_send_msg,
.fw_ready = sof_fw_ready,
.get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset,
.get_window_offset = hda_dsp_ipc_get_window_offset,
.ipc_msg_data = hda_ipc_msg_data,
.ipc_pcm_params = hda_ipc_pcm_params,
/* machine driver */
.machine_select = hda_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
.set_mach_params = hda_set_mach_params,
/* debug */
.debug_map = tgl_dsp_debugfs,
.debug_map_count = ARRAY_SIZE(tgl_dsp_debugfs),
.dbg_dump = hda_dsp_dump,
.ipc_dump = cnl_ipc_dump,
/* stream callbacks */
.pcm_open = hda_dsp_pcm_open,
.pcm_close = hda_dsp_pcm_close,
.pcm_hw_params = hda_dsp_pcm_hw_params,
.pcm_hw_free = hda_dsp_stream_hw_free,
.pcm_trigger = hda_dsp_pcm_trigger,
.pcm_pointer = hda_dsp_pcm_pointer,
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
/* probe callbacks */
.probe_assign = hda_probe_compr_assign,
.probe_free = hda_probe_compr_free,
.probe_set_params = hda_probe_compr_set_params,
.probe_trigger = hda_probe_compr_trigger,
.probe_pointer = hda_probe_compr_pointer,
#endif
/* firmware loading */
.load_firmware = snd_sof_load_firmware_raw,
/* pre/post fw run */
.pre_fw_run = hda_dsp_pre_fw_run,
.post_fw_run = hda_dsp_post_fw_run,
/* dsp core power up/down */
.core_power_up = hda_dsp_enable_core,
.core_power_down = hda_dsp_core_reset_power_down,
/* firmware run */
.run = hda_dsp_cl_boot_firmware_iccmax,
/* trace callback */
.trace_init = hda_dsp_trace_init,
.trace_release = hda_dsp_trace_release,
.trace_trigger = hda_dsp_trace_trigger,
/* DAI drivers */
.drv = skl_dai,
.num_drv = SOF_SKL_NUM_DAIS,
/* PM */
.suspend = hda_dsp_suspend,
.resume = hda_dsp_resume,
.runtime_suspend = hda_dsp_runtime_suspend,
.runtime_resume = hda_dsp_runtime_resume,
.runtime_idle = hda_dsp_runtime_idle,
.set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume,
.set_power_state = hda_dsp_set_power_state,
/* ALSA HW info flags */
.hw_info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.arch_ops = &sof_xtensa_arch_ops,
};
EXPORT_SYMBOL_NS(sof_tgl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
const struct sof_intel_dsp_desc tgl_chip_info = {
/* Tigerlake */
.cores_num = 4,
.init_core_mask = 1,
.cores_mask = HDA_DSP_CORE_MASK(0),
.ipc_req = CNL_DSP_REG_HIPCIDR,
.ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
.ipc_ack = CNL_DSP_REG_HIPCIDA,
.ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
.ipc_ctl = CNL_DSP_REG_HIPCCTL,
.rom_init_timeout = 300,
.ssp_count = ICL_SSP_COUNT,
.ssp_base_offset = CNL_SSP_BASE_OFFSET,
};
EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
...@@ -221,7 +221,7 @@ static const struct sof_dev_desc tgl_desc = { ...@@ -221,7 +221,7 @@ static const struct sof_dev_desc tgl_desc = {
.default_tplg_path = "intel/sof-tplg", .default_tplg_path = "intel/sof-tplg",
.default_fw_filename = "sof-tgl.ri", .default_fw_filename = "sof-tgl.ri",
.nocodec_tplg_filename = "sof-tgl-nocodec.tplg", .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
.ops = &sof_cnl_ops, .ops = &sof_tgl_ops,
}; };
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment