Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Merge up fixes as a dependency for future SOF work

New SOF changes require the current set of fixes.

+228 -86
+2
sound/soc/codecs/da7219-aad.c
··· 968 968 INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); 969 969 INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); 970 970 971 + mutex_init(&da7219_aad->jack_det_mutex); 972 + 971 973 ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread, 972 974 da7219_aad_irq_thread, 973 975 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+11
sound/soc/codecs/hdmi-codec.c
··· 428 428 { 429 429 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 430 430 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 431 + bool has_capture = !hcp->hcd.no_i2s_capture; 432 + bool has_playback = !hcp->hcd.no_i2s_playback; 431 433 int ret = 0; 434 + 435 + if (!((has_playback && tx) || (has_capture && !tx))) 436 + return 0; 432 437 433 438 mutex_lock(&hcp->lock); 434 439 if (hcp->busy) { ··· 473 468 struct snd_soc_dai *dai) 474 469 { 475 470 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 471 + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 472 + bool has_capture = !hcp->hcd.no_i2s_capture; 473 + bool has_playback = !hcp->hcd.no_i2s_playback; 474 + 475 + if (!((has_playback && tx) || (has_capture && !tx))) 476 + return; 476 477 477 478 hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; 478 479 hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
+6 -5
sound/soc/codecs/lpass-tx-macro.c
··· 242 242 243 243 struct tx_mute_work { 244 244 struct tx_macro *tx; 245 - u32 decimator; 245 + u8 decimator; 246 246 struct delayed_work dwork; 247 247 }; 248 248 ··· 635 635 return 0; 636 636 } 637 637 638 - static bool is_amic_enabled(struct snd_soc_component *component, int decimator) 638 + static bool is_amic_enabled(struct snd_soc_component *component, u8 decimator) 639 639 { 640 640 u16 adc_mux_reg, adc_reg, adc_n; 641 641 ··· 849 849 struct snd_kcontrol *kcontrol, int event) 850 850 { 851 851 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 852 - unsigned int decimator; 852 + u8 decimator; 853 853 u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg; 854 854 u8 hpf_cut_off_freq; 855 855 int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; ··· 1064 1064 struct snd_soc_dai *dai) 1065 1065 { 1066 1066 struct snd_soc_component *component = dai->component; 1067 - u32 decimator, sample_rate; 1067 + u32 sample_rate; 1068 + u8 decimator; 1068 1069 int tx_fs_rate; 1069 1070 struct tx_macro *tx = snd_soc_component_get_drvdata(component); 1070 1071 ··· 1129 1128 { 1130 1129 struct snd_soc_component *component = dai->component; 1131 1130 struct tx_macro *tx = snd_soc_component_get_drvdata(component); 1132 - u16 decimator; 1131 + u8 decimator; 1133 1132 1134 1133 /* active decimator not set yet */ 1135 1134 if (tx->active_decimator[dai->id] == -1)
+4
sound/soc/fsl/Kconfig
··· 303 303 Say Y if you want to add support for SoC audio on an i.MX board with 304 304 a sgtl5000 codec. 305 305 306 + Note that this is an old driver. Consider enabling 307 + SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer 308 + driver. 309 + 306 310 config SND_SOC_IMX_SPDIF 307 311 tristate "SoC Audio support for i.MX boards with S/PDIF" 308 312 select SND_SOC_IMX_PCM_DMA
+21
sound/soc/intel/avs/boards/da7219.c
··· 117 117 snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL); 118 118 } 119 119 120 + static int 121 + avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) 122 + { 123 + struct snd_interval *rate, *channels; 124 + struct snd_mask *fmt; 125 + 126 + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 127 + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 128 + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 129 + 130 + /* The ADSP will convert the FE rate to 48k, stereo */ 131 + rate->min = rate->max = 48000; 132 + channels->min = channels->max = 2; 133 + 134 + /* set SSP0 to 24 bit */ 135 + snd_mask_none(fmt); 136 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 137 + return 0; 138 + } 139 + 120 140 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, 121 141 struct snd_soc_dai_link **dai_link) 122 142 { ··· 168 148 dl->num_platforms = 1; 169 149 dl->id = 0; 170 150 dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; 151 + dl->be_hw_params_fixup = avs_da7219_be_fixup; 171 152 dl->init = avs_da7219_codec_init; 172 153 dl->exit = avs_da7219_codec_exit; 173 154 dl->nonatomic = 1;
+22
sound/soc/intel/avs/boards/max98357a.c
··· 8 8 9 9 #include <linux/module.h> 10 10 #include <linux/platform_device.h> 11 + #include <sound/pcm_params.h> 11 12 #include <sound/soc.h> 12 13 #include <sound/soc-acpi.h> 13 14 #include <sound/soc-dapm.h> ··· 24 23 static const struct snd_soc_dapm_route card_base_routes[] = { 25 24 { "Spk", NULL, "Speaker" }, 26 25 }; 26 + 27 + static int 28 + avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) 29 + { 30 + struct snd_interval *rate, *channels; 31 + struct snd_mask *fmt; 32 + 33 + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 34 + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 35 + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 36 + 37 + /* The ADSP will convert the FE rate to 48k, stereo */ 38 + rate->min = rate->max = 48000; 39 + channels->min = channels->max = 2; 40 + 41 + /* set SSP0 to 16 bit */ 42 + snd_mask_none(fmt); 43 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 44 + return 0; 45 + } 27 46 28 47 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, 29 48 struct snd_soc_dai_link **dai_link) ··· 76 55 dl->num_platforms = 1; 77 56 dl->id = 0; 78 57 dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; 58 + dl->be_hw_params_fixup = avs_max98357a_be_fixup; 79 59 dl->nonatomic = 1; 80 60 dl->no_pcm = 1; 81 61 dl->dpcm_playback = 1;
+7 -7
sound/soc/intel/avs/boards/nau8825.c
··· 33 33 return -EINVAL; 34 34 } 35 35 36 - if (!SND_SOC_DAPM_EVENT_ON(event)) { 36 + if (SND_SOC_DAPM_EVENT_ON(event)) 37 + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000, 38 + SND_SOC_CLOCK_IN); 39 + else 37 40 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); 38 - if (ret < 0) { 39 - dev_err(card->dev, "set sysclk err = %d\n", ret); 40 - return ret; 41 - } 42 - } 41 + if (ret < 0) 42 + dev_err(card->dev, "Set sysclk failed: %d\n", ret); 43 43 44 - return 0; 44 + return ret; 45 45 } 46 46 47 47 static const struct snd_kcontrol_new card_controls[] = {
+22
sound/soc/intel/avs/boards/rt5682.c
··· 169 169 .hw_params = avs_rt5682_hw_params, 170 170 }; 171 171 172 + static int 173 + avs_rt5682_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) 174 + { 175 + struct snd_interval *rate, *channels; 176 + struct snd_mask *fmt; 177 + 178 + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 179 + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 180 + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 181 + 182 + /* The ADSP will convert the FE rate to 48k, stereo */ 183 + rate->min = rate->max = 48000; 184 + channels->min = channels->max = 2; 185 + 186 + /* set SSPN to 24 bit */ 187 + snd_mask_none(fmt); 188 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 189 + 190 + return 0; 191 + } 192 + 172 193 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, 173 194 struct snd_soc_dai_link **dai_link) 174 195 { ··· 222 201 dl->id = 0; 223 202 dl->init = avs_rt5682_codec_init; 224 203 dl->exit = avs_rt5682_codec_exit; 204 + dl->be_hw_params_fixup = avs_rt5682_be_fixup; 225 205 dl->ops = &avs_rt5682_ops; 226 206 dl->nonatomic = 1; 227 207 dl->no_pcm = 1;
-31
sound/soc/intel/avs/boards/ssm4567.c
··· 15 15 #include <sound/soc-acpi.h> 16 16 #include "../../../codecs/nau8825.h" 17 17 18 - #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" 19 18 #define SKL_SSM_CODEC_DAI "ssm4567-hifi" 20 19 21 20 static struct snd_soc_codec_conf card_codec_conf[] = { ··· 33 34 SOC_DAPM_PIN_SWITCH("Right Speaker"), 34 35 }; 35 36 36 - static int 37 - platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) 38 - { 39 - struct snd_soc_dapm_context *dapm = w->dapm; 40 - struct snd_soc_card *card = dapm->card; 41 - struct snd_soc_dai *codec_dai; 42 - int ret; 43 - 44 - codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); 45 - if (!codec_dai) { 46 - dev_err(card->dev, "Codec dai not found\n"); 47 - return -EINVAL; 48 - } 49 - 50 - if (SND_SOC_DAPM_EVENT_ON(event)) { 51 - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000, 52 - SND_SOC_CLOCK_IN); 53 - if (ret < 0) 54 - dev_err(card->dev, "set sysclk err = %d\n", ret); 55 - } else { 56 - ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); 57 - if (ret < 0) 58 - dev_err(card->dev, "set sysclk err = %d\n", ret); 59 - } 60 - 61 - return ret; 62 - } 63 - 64 37 static const struct snd_soc_dapm_widget card_widgets[] = { 65 38 SND_SOC_DAPM_SPK("Left Speaker", NULL), 66 39 SND_SOC_DAPM_SPK("Right Speaker", NULL), 67 40 SND_SOC_DAPM_SPK("DP1", NULL), 68 41 SND_SOC_DAPM_SPK("DP2", NULL), 69 - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, 70 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 71 42 }; 72 43 73 44 static const struct snd_soc_dapm_route card_base_routes[] = {
+1 -1
sound/soc/intel/common/soc-acpi-intel-adl-match.c
··· 559 559 { 560 560 .comp_ids = &essx_83x6, 561 561 .drv_name = "sof-essx8336", 562 - .sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */ 562 + .sof_tplg_filename = "sof-adl-es8336", /* the tplg suffix is added at run time */ 563 563 .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER | 564 564 SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | 565 565 SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
+2 -2
sound/soc/qcom/qdsp6/q6prm.c
··· 184 184 unsigned int freq) 185 185 { 186 186 if (freq) 187 - return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq); 187 + return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_root, freq); 188 188 189 - return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq); 189 + return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_root, freq); 190 190 } 191 191 EXPORT_SYMBOL_GPL(q6prm_set_lpass_clock); 192 192
+3
sound/soc/sof/intel/hda-ctrl.c
··· 198 198 goto err; 199 199 } 200 200 201 + usleep_range(500, 1000); 202 + 201 203 /* exit HDA controller reset */ 202 204 ret = hda_dsp_ctrl_link_reset(sdev, false); 203 205 if (ret < 0) { 204 206 dev_err(sdev->dev, "error: failed to exit HDA controller reset\n"); 205 207 goto err; 206 208 } 209 + usleep_range(1000, 1200); 207 210 208 211 hda_codec_detect_mask(sdev); 209 212
+12
sound/soc/sof/intel/hda-dsp.c
··· 392 392 snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset, 393 393 SOF_HDA_VS_D0I3C_I3, value); 394 394 395 + /* 396 + * The value written to the D0I3C::I3 bit may not be taken into account immediately. 397 + * A delay is recommended before checking if D0I3C::CIP is cleared 398 + */ 399 + usleep_range(30, 40); 400 + 395 401 /* Wait for cmd in progress to be cleared before exiting the function */ 396 402 ret = hda_dsp_wait_d0i3c_done(sdev); 397 403 if (ret < 0) { ··· 406 400 } 407 401 408 402 reg = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset); 403 + /* Confirm d0i3 state changed with paranoia check */ 404 + if ((reg ^ value) & SOF_HDA_VS_D0I3C_I3) { 405 + dev_err(sdev->dev, "failed to update D0I3C!\n"); 406 + return -EIO; 407 + } 408 + 409 409 trace_sof_intel_D0I3C_updated(sdev, reg); 410 410 411 411 return 0;
+1
sound/soc/sof/intel/pci-apl.c
··· 78 78 .nocodec_tplg_filename = "sof-glk-nocodec.tplg", 79 79 .ops = &sof_apl_ops, 80 80 .ops_init = sof_apl_ops_init, 81 + .ops_free = hda_ops_free, 81 82 }; 82 83 83 84 /* PCI IDs */
+2
sound/soc/sof/intel/pci-cnl.c
··· 48 48 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 49 49 .ops = &sof_cnl_ops, 50 50 .ops_init = sof_cnl_ops_init, 51 + .ops_free = hda_ops_free, 51 52 }; 52 53 53 54 static const struct sof_dev_desc cfl_desc = { ··· 112 111 .nocodec_tplg_filename = "sof-cnl-nocodec.tplg", 113 112 .ops = &sof_cnl_ops, 114 113 .ops_init = sof_cnl_ops_init, 114 + .ops_free = hda_ops_free, 115 115 }; 116 116 117 117 /* PCI IDs */
+1
sound/soc/sof/intel/pci-icl.c
··· 79 79 .nocodec_tplg_filename = "sof-jsl-nocodec.tplg", 80 80 .ops = &sof_cnl_ops, 81 81 .ops_init = sof_cnl_ops_init, 82 + .ops_free = hda_ops_free, 82 83 }; 83 84 84 85 /* PCI IDs */
+1
sound/soc/sof/intel/pci-mtl.c
··· 46 46 .nocodec_tplg_filename = "sof-mtl-nocodec.tplg", 47 47 .ops = &sof_mtl_ops, 48 48 .ops_init = sof_mtl_ops_init, 49 + .ops_free = hda_ops_free, 49 50 }; 50 51 51 52 /* PCI IDs */
+2
sound/soc/sof/intel/pci-skl.c
··· 38 38 .nocodec_tplg_filename = "sof-skl-nocodec.tplg", 39 39 .ops = &sof_skl_ops, 40 40 .ops_init = sof_skl_ops_init, 41 + .ops_free = hda_ops_free, 41 42 }; 42 43 43 44 static struct sof_dev_desc kbl_desc = { ··· 62 61 .nocodec_tplg_filename = "sof-kbl-nocodec.tplg", 63 62 .ops = &sof_skl_ops, 64 63 .ops_init = sof_skl_ops_init, 64 + .ops_free = hda_ops_free, 65 65 }; 66 66 67 67 /* PCI IDs */
+7
sound/soc/sof/intel/pci-tgl.c
··· 48 48 .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", 49 49 .ops = &sof_tgl_ops, 50 50 .ops_init = sof_tgl_ops_init, 51 + .ops_free = hda_ops_free, 51 52 }; 52 53 53 54 static const struct sof_dev_desc tglh_desc = { ··· 111 110 .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", 112 111 .ops = &sof_tgl_ops, 113 112 .ops_init = sof_tgl_ops_init, 113 + .ops_free = hda_ops_free, 114 114 }; 115 115 116 116 static const struct sof_dev_desc adls_desc = { ··· 143 141 .nocodec_tplg_filename = "sof-adl-nocodec.tplg", 144 142 .ops = &sof_tgl_ops, 145 143 .ops_init = sof_tgl_ops_init, 144 + .ops_free = hda_ops_free, 146 145 }; 147 146 148 147 static const struct sof_dev_desc adl_desc = { ··· 175 172 .nocodec_tplg_filename = "sof-adl-nocodec.tplg", 176 173 .ops = &sof_tgl_ops, 177 174 .ops_init = sof_tgl_ops_init, 175 + .ops_free = hda_ops_free, 178 176 }; 179 177 180 178 static const struct sof_dev_desc adl_n_desc = { ··· 207 203 .nocodec_tplg_filename = "sof-adl-nocodec.tplg", 208 204 .ops = &sof_tgl_ops, 209 205 .ops_init = sof_tgl_ops_init, 206 + .ops_free = hda_ops_free, 210 207 }; 211 208 212 209 static const struct sof_dev_desc rpls_desc = { ··· 239 234 .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", 240 235 .ops = &sof_tgl_ops, 241 236 .ops_init = sof_tgl_ops_init, 237 + .ops_free = hda_ops_free, 242 238 }; 243 239 244 240 static const struct sof_dev_desc rpl_desc = { ··· 271 265 .nocodec_tplg_filename = "sof-rpl-nocodec.tplg", 272 266 .ops = &sof_tgl_ops, 273 267 .ops_init = sof_tgl_ops_init, 268 + .ops_free = hda_ops_free, 274 269 }; 275 270 276 271 /* PCI IDs */
+1 -5
sound/soc/sof/intel/pci-tng.c
··· 75 75 76 76 /* LPE base */ 77 77 base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET; 78 - size = pci_resource_len(pci, desc->resindex_lpe_base); 79 - if (size < PCI_BAR_SIZE) { 80 - dev_err(sdev->dev, "error: I/O region is too small.\n"); 81 - return -ENODEV; 82 - } 78 + size = PCI_BAR_SIZE; 83 79 84 80 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size); 85 81 sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+30 -2
sound/soc/sof/ipc3-topology.c
··· 2081 2081 break; 2082 2082 case SOF_DAI_INTEL_ALH: 2083 2083 if (data) { 2084 - config->dai_index = data->dai_index; 2084 + /* save the dai_index during hw_params and reuse it for hw_free */ 2085 + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) 2086 + config->dai_index = data->dai_index; 2085 2087 config->alh.stream_id = data->dai_data; 2086 2088 } 2087 2089 break; ··· 2091 2089 break; 2092 2090 } 2093 2091 2094 - config->flags = flags; 2092 + /* 2093 + * The dai_config op is invoked several times and the flags argument varies as below: 2094 + * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains 2095 + * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks 2096 + * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has 2097 + * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no 2098 + * quirks 2099 + * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to 2100 + * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks 2101 + * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to 2102 + * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks 2103 + * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to 2104 + * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks 2105 + * 2106 + * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE 2107 + * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks 2108 + * need to be preserved when assigning the flags before sending the IPC. 2109 + * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is. 2110 + */ 2111 + 2112 + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) 2113 + config->flags |= flags; 2114 + else 2115 + config->flags = flags; 2095 2116 2096 2117 /* only send the IPC if the widget is set up in the DSP */ 2097 2118 if (swidget->use_count > 0) { ··· 2122 2097 &reply, sizeof(reply)); 2123 2098 if (ret < 0) 2124 2099 dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); 2100 + 2101 + /* clear the flags once the IPC has been sent even if it fails */ 2102 + config->flags = SOF_DAI_CONFIG_FLAGS_NONE; 2125 2103 } 2126 2104 2127 2105 return ret;
+3 -2
sound/soc/sof/ipc3.c
··· 970 970 return; 971 971 } 972 972 973 - if (hdr.size < sizeof(hdr)) { 974 - dev_err(sdev->dev, "The received message size is invalid\n"); 973 + if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) { 974 + dev_err(sdev->dev, "The received message size is invalid: %u\n", 975 + hdr.size); 975 976 return; 976 977 } 977 978
+2 -1
sound/soc/sof/ipc4-control.c
··· 97 97 } 98 98 99 99 /* set curve type and duration from topology */ 100 - data.curve_duration = gain->data.curve_duration; 100 + data.curve_duration_l = gain->data.curve_duration_l; 101 + data.curve_duration_h = gain->data.curve_duration_h; 101 102 data.curve_type = gain->data.curve_type; 102 103 103 104 msg->data_ptr = &data;
+16 -5
sound/soc/sof/ipc4-topology.c
··· 111 111 get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)}, 112 112 {SOF_TKN_GAIN_RAMP_DURATION, 113 113 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 114 - offsetof(struct sof_ipc4_gain_data, curve_duration)}, 114 + offsetof(struct sof_ipc4_gain_data, curve_duration_l)}, 115 115 {SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD, 116 116 get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)}, 117 117 }; ··· 159 159 for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) { 160 160 fmt = ptr; 161 161 dev_dbg(dev, 162 - " #%d: %uKHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n", 162 + " #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n", 163 163 i, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, 164 164 fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg); 165 165 } ··· 715 715 716 716 dev_dbg(scomp->dev, 717 717 "pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x, cpc %d\n", 718 - swidget->widget->name, gain->data.curve_type, gain->data.curve_duration, 718 + swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l, 719 719 gain->data.init_val, gain->base_config.cpc); 720 720 721 721 ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg); ··· 1003 1003 1004 1004 ipc4_copier = dai->private; 1005 1005 if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { 1006 + struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data; 1006 1007 struct sof_ipc4_alh_configuration_blob *blob; 1007 1008 unsigned int group_id; 1008 1009 ··· 1013 1012 ALH_MULTI_GTW_BASE; 1014 1013 ida_free(&alh_group_ida, group_id); 1015 1014 } 1015 + 1016 + /* clear the node ID */ 1017 + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 1016 1018 } 1017 1019 } 1018 1020 ··· 1967 1963 pipeline->skip_during_fe_trigger = true; 1968 1964 fallthrough; 1969 1965 case SOF_DAI_INTEL_ALH: 1970 - copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 1971 - copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); 1966 + /* 1967 + * Do not clear the node ID when this op is invoked with 1968 + * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during 1969 + * unprepare. 1970 + */ 1971 + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { 1972 + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; 1973 + copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); 1974 + } 1972 1975 break; 1973 1976 case SOF_DAI_INTEL_DMIC: 1974 1977 case SOF_DAI_INTEL_SSP:
+5 -3
sound/soc/sof/ipc4-topology.h
··· 46 46 #define SOF_IPC4_NODE_INDEX_INTEL_SSP(x) (((x) & 0xf) << 4) 47 47 48 48 /* Node ID for DMIC type DAI copiers */ 49 - #define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) (((x) & 0x7) << 5) 49 + #define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) ((x) & 0x7) 50 50 51 51 #define SOF_IPC4_GAIN_ALL_CHANNELS_MASK 0xffffffff 52 52 #define SOF_IPC4_VOL_ZERO_DB 0x7fffffff ··· 279 279 * @init_val: Initial value 280 280 * @curve_type: Curve type 281 281 * @reserved: reserved for future use 282 - * @curve_duration: Curve duration 282 + * @curve_duration_l: Curve duration low part 283 + * @curve_duration_h: Curve duration high part 283 284 */ 284 285 struct sof_ipc4_gain_data { 285 286 uint32_t channels; 286 287 uint32_t init_val; 287 288 uint32_t curve_type; 288 289 uint32_t reserved; 289 - uint32_t curve_duration; 290 + uint32_t curve_duration_l; 291 + uint32_t curve_duration_h; 290 292 } __aligned(8); 291 293 292 294 /**
+27 -5
sound/soc/sof/sof-audio.c
··· 50 50 /* reset route setup status for all routes that contain this widget */ 51 51 sof_reset_route_setup_status(sdev, swidget); 52 52 53 + /* free DAI config and continue to free widget even if it fails */ 54 + if (WIDGET_IS_DAI(swidget->id)) { 55 + struct snd_sof_dai_config_data data; 56 + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE; 57 + 58 + data.dai_data = DMA_CHAN_INVALID; 59 + 60 + if (tplg_ops && tplg_ops->dai_config) { 61 + err = tplg_ops->dai_config(sdev, swidget, flags, &data); 62 + if (err < 0) 63 + dev_err(sdev->dev, "failed to free config for widget %s\n", 64 + swidget->widget->name); 65 + } 66 + } 67 + 53 68 /* continue to disable core even if IPC fails */ 54 - if (tplg_ops && tplg_ops->widget_free) 55 - err = tplg_ops->widget_free(sdev, swidget); 69 + if (tplg_ops && tplg_ops->widget_free) { 70 + ret = tplg_ops->widget_free(sdev, swidget); 71 + if (ret < 0 && !err) 72 + err = ret; 73 + } 56 74 57 75 /* 58 76 * disable widget core. continue to route setup status and complete flag ··· 169 151 170 152 /* send config for DAI components */ 171 153 if (WIDGET_IS_DAI(swidget->id)) { 172 - unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE; 154 + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 173 155 156 + /* 157 + * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does 158 + * not use the flags argument. 159 + */ 174 160 if (tplg_ops && tplg_ops->dai_config) { 175 161 ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); 176 162 if (ret < 0) ··· 610 588 ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 611 589 dir, SOF_WIDGET_SETUP); 612 590 if (ret < 0) { 613 - ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 614 - dir, SOF_WIDGET_UNPREPARE); 591 + sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 592 + dir, SOF_WIDGET_UNPREPARE); 615 593 return ret; 616 594 } 617 595
+17 -17
sound/soc/sof/topology.c
··· 1388 1388 if (ret < 0) { 1389 1389 dev_err(scomp->dev, "failed to parse component pin tokens for %s\n", 1390 1390 w->name); 1391 - return ret; 1391 + goto widget_free; 1392 1392 } 1393 1393 1394 1394 if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS || 1395 1395 swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) { 1396 1396 dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n", 1397 1397 swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins); 1398 - return -EINVAL; 1398 + ret = -EINVAL; 1399 + goto widget_free; 1399 1400 } 1400 1401 1401 1402 if (swidget->num_sink_pins > 1) { ··· 1405 1404 if (ret < 0) { 1406 1405 dev_err(scomp->dev, "failed to parse sink pin binding for %s\n", 1407 1406 w->name); 1408 - return ret; 1407 + goto widget_free; 1409 1408 } 1410 1409 } 1411 1410 ··· 1415 1414 if (ret < 0) { 1416 1415 dev_err(scomp->dev, "failed to parse source pin binding for %s\n", 1417 1416 w->name); 1418 - return ret; 1417 + goto widget_free; 1419 1418 } 1420 1419 } 1421 1420 ··· 1437 1436 case snd_soc_dapm_dai_out: 1438 1437 dai = kzalloc(sizeof(*dai), GFP_KERNEL); 1439 1438 if (!dai) { 1440 - kfree(swidget); 1441 - return -ENOMEM; 1442 - 1439 + ret = -ENOMEM; 1440 + goto widget_free; 1443 1441 } 1444 1442 1445 1443 ret = sof_widget_parse_tokens(scomp, swidget, tw, token_list, token_list_size); ··· 1496 1496 tw->shift, swidget->id, tw->name, 1497 1497 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 1498 1498 ? tw->sname : "none"); 1499 - kfree(swidget); 1500 - return ret; 1499 + goto widget_free; 1501 1500 } 1502 1501 1503 1502 if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { ··· 1517 1518 if (ret) { 1518 1519 dev_err(scomp->dev, "widget event binding failed for %s\n", 1519 1520 swidget->widget->name); 1520 - kfree(swidget->private); 1521 - kfree(swidget->tuples); 1522 - kfree(swidget); 1523 - return ret; 1521 + goto free; 1524 1522 } 1525 1523 } 1526 1524 } ··· 1528 1532 1529 1533 spipe = kzalloc(sizeof(*spipe), GFP_KERNEL); 1530 1534 if (!spipe) { 1531 - kfree(swidget->private); 1532 - kfree(swidget->tuples); 1533 - kfree(swidget); 1534 - return -ENOMEM; 1535 + ret = -ENOMEM; 1536 + goto free; 1535 1537 } 1536 1538 1537 1539 spipe->pipe_widget = swidget; ··· 1539 1545 1540 1546 w->dobj.private = swidget; 1541 1547 list_add(&swidget->list, &sdev->widget_list); 1548 + return ret; 1549 + free: 1550 + kfree(swidget->private); 1551 + kfree(swidget->tuples); 1552 + widget_free: 1553 + kfree(swidget); 1542 1554 return ret; 1543 1555 } 1544 1556