Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/sound/hda_register.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_VS_EM3U 0x103C
#define AZX_REG_VS_EM4L 0x1040
#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_PCE 0x104B
#define AZX_REG_VS_L2MAGC 0x1050
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/intel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.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-objs := hda-codec.o
Expand Down
23 changes: 3 additions & 20 deletions sound/soc/sof/intel/cnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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;
u32 hipci;
Expand Down Expand Up @@ -163,8 +163,7 @@ static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
return false;
}

static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
struct snd_sof_ipc_msg *msg)
int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
struct sof_ipc_cmd_hdr *hdr;
Expand Down Expand Up @@ -211,7 +210,7 @@ static int cnl_ipc_send_msg(struct snd_sof_dev *sdev,
return 0;
}

static void cnl_ipc_dump(struct snd_sof_dev *sdev)
void cnl_ipc_dump(struct snd_sof_dev *sdev)
{
u32 hipcctl;
u32 hipcida;
Expand Down Expand Up @@ -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);

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 = {
/* Elkhartlake */
.cores_num = 4,
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/sof/intel/hda-ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@
#define HDA_PM_PG_STREAMING BIT(1)
#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
106 changes: 83 additions & 23 deletions sound/soc/sof/intel/hda-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@

#include <linux/firmware.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
#include <sound/sof.h>
#include "../ops.h"
#include "hda.h"

#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,
unsigned int size, struct snd_dma_buffer *dmab,
Expand All @@ -32,11 +34,6 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
struct pci_dev *pci = to_pci_dev(sdev->dev);
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);

if (!dsp_stream) {
Expand All @@ -57,14 +54,21 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
hstream->format_val = format;
hstream->bufsize = size;

ret = hda_dsp_stream_hw_params(sdev, dsp_stream, dmab, NULL);
if (ret < 0) {
dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
goto error;
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);
if (ret < 0) {
dev_err(sdev->dev, "error: hdac prepare failed: %x\n", ret);
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;

error:
Expand Down Expand Up @@ -206,18 +210,15 @@ 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)
int tag, int direction)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in commit message, should be ASoC: SOF: Intel.
Maybe fix in sof-dev-rebase to avoid unnecessary reviews?

{
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) {
list_for_each_entry(s, &bus->stream_list, list)
if (s->direction == direction && s->stream_tag == tag)
return stream_to_hdac_ext_stream(s);
}
}

return NULL;
}
Expand All @@ -227,12 +228,15 @@ static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
{
struct hdac_stream *hstream = &stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
int ret;
int ret = 0;

ret = hda_dsp_stream_spib_config(sdev, stream, HDA_DSP_SPIB_DISABLE, 0);
if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK)
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,
hstream->stream_tag);
hda_dsp_stream_put(sdev, hstream->direction, hstream->stream_tag);
hstream->running = 0;
hstream->substream = NULL;

Expand Down Expand Up @@ -290,6 +294,62 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream)
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;
int iccmax_tag;
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_tag = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
if (iccmax_tag < 0) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX %x\n", iccmax_tag);
return iccmax_tag;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you restore the guardband on errors?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plbossart stream_prepare would fail only if the iccmax stream hw_params fails and in this case the guardband value wouldnt have been modified at all. So no need to restore here. But if get_stream_with_tag() fails, then we do need to restore which I do below.

}

/* get stream with tag */
iccmax_stream = get_stream_with_tag(sdev, iccmax_tag, SNDRV_PCM_STREAM_CAPTURE);
if (!iccmax_stream) {
dev_err(sdev->dev, "error: could not get stream with stream tag %d\n", iccmax_tag);
ret = -ENODEV;
} else {
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)
{
struct snd_sof_pdata *plat_data = sdev->pdata;
Expand All @@ -313,7 +373,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
init_waitqueue_head(&sdev->boot_wait);

/* prepare DMA for code loader stream */
tag = cl_stream_prepare(sdev, 0x40, stripped_firmware.size,
tag = cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size,
&sdev->dmab, SNDRV_PCM_STREAM_PLAYBACK);

if (tag < 0) {
Expand All @@ -323,7 +383,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
}

/* get stream with tag */
stream = get_stream_with_tag(sdev, tag);
stream = get_stream_with_tag(sdev, tag, SNDRV_PCM_STREAM_PLAYBACK);
if (!stream) {
dev_err(sdev->dev,
"error: could not get stream with stream tag %d\n",
Expand Down
69 changes: 69 additions & 0 deletions sound/soc/sof/intel/hda-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "../sof-audio.h"
#include "hda.h"

#define HDA_LTRP_GB_VALUE_US 95

/*
* set up one of BDL entries for a stream
*/
Expand Down Expand Up @@ -322,6 +324,73 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
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
* and normal stream.
Expand Down
6 changes: 6 additions & 0 deletions sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@
/* Intel Vendor Specific Registers */
#define HDA_VS_INTEL_EM2 0x1030
#define HDA_VS_INTEL_EM2_L1SEN BIT(13)
#define HDA_VS_INTEL_LTRP_GB_MASK 0x3F

/* HIPCI */
#define HDA_DSP_REG_HIPCI_BUSY BIT(31)
Expand Down Expand Up @@ -546,6 +547,9 @@ int hda_dsp_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_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,
struct hdac_ext_stream *stream, int cmd);
irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context);
Expand Down Expand Up @@ -608,6 +612,7 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);
* DSP Code loader.
*/
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);

/* pre and post fw run ops */
Expand Down Expand Up @@ -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_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 cnl_chip_info;
Expand Down
Loading