Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 150
ICCMAX implementation for FW boot in TGL#2290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ccfd1ba8ae8ba6efe785de783ab5a9cfa951a0f659File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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, | ||
| @@ -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) { | ||
| @@ -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: | ||
| @@ -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) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo in commit message, should be ASoC: SOF: Intel. | ||
| { | ||
| 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; | ||
| } | ||
| @@ -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; | ||
| @@ -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; | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should you restore the guardband on errors? CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
| } | ||
ranj063 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /* | ||
| * 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; | ||
| @@ -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) { | ||
| @@ -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", | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.