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

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: Intel: LunarLake preparation patches

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

This patchset adds the changes required for the hda-dai extension to
deal with SSSP/DMIC/SoundWire starting with LunarLake, as well as the
new TLV IPC to provide the DMA stream_tag to the DSP firmware.

LunarLake support for SSP/DMIC is ready but is gated by the patch
"ASoC: SOF: Intel: shim: add enum for ACE 2.0 IP used in LunarLake"
currently only present in the SoundWire tree.

+239 -66
+57 -1
sound/soc/sof/intel/hda-dai-ops.c
··· 175 175 snd_hdac_ext_stream_reset(hext_stream); 176 176 } 177 177 178 + static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev, 179 + struct snd_pcm_substream *substream, 180 + struct hdac_stream *hstream) 181 + { 182 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 183 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 184 + 185 + /* set the hdac_stream in the codec dai */ 186 + snd_soc_dai_set_stream(codec_dai, hstream, substream->stream); 187 + } 188 + 189 + static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev, 190 + struct snd_pcm_substream *substream, 191 + struct snd_pcm_hw_params *params) 192 + { 193 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 194 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 195 + unsigned int link_bps; 196 + unsigned int format_val; 197 + 198 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 199 + link_bps = codec_dai->driver->playback.sig_bits; 200 + else 201 + link_bps = codec_dai->driver->capture.sig_bits; 202 + 203 + format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), 204 + params_format(params), link_bps, 0); 205 + 206 + dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 207 + params_rate(params), params_channels(params), params_format(params)); 208 + 209 + return format_val; 210 + } 211 + 212 + static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev, 213 + struct snd_pcm_substream *substream) 214 + { 215 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 216 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 217 + struct hdac_bus *bus = sof_to_bus(sdev); 218 + 219 + return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 220 + } 221 + 178 222 static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 179 223 struct snd_pcm_substream *substream, int cmd) 180 224 { ··· 351 307 .reset_hext_stream = hda_reset_hext_stream, 352 308 .pre_trigger = hda_ipc4_pre_trigger, 353 309 .trigger = hda_trigger, 354 - .post_trigger = hda_ipc4_post_trigger 310 + .post_trigger = hda_ipc4_post_trigger, 311 + .codec_dai_set_stream = hda_codec_dai_set_stream, 312 + .calc_stream_format = hda_calc_stream_format, 313 + .get_hlink = hda_get_hlink, 355 314 }; 356 315 357 316 static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { ··· 364 317 .setup_hext_stream = hda_setup_hext_stream, 365 318 .reset_hext_stream = hda_reset_hext_stream, 366 319 .trigger = hda_trigger, 320 + .codec_dai_set_stream = hda_codec_dai_set_stream, 321 + .calc_stream_format = hda_calc_stream_format, 322 + .get_hlink = hda_get_hlink, 367 323 }; 368 324 369 325 static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, ··· 400 350 .reset_hext_stream = hda_reset_hext_stream, 401 351 .trigger = hda_trigger, 402 352 .post_trigger = hda_ipc3_post_trigger, 353 + .codec_dai_set_stream = hda_codec_dai_set_stream, 354 + .calc_stream_format = hda_calc_stream_format, 355 + .get_hlink = hda_get_hlink, 403 356 }; 404 357 405 358 static struct hdac_ext_stream * ··· 429 376 static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { 430 377 .get_hext_stream = hda_dspless_get_hext_stream, 431 378 .setup_hext_stream = hda_dspless_setup_hext_stream, 379 + .codec_dai_set_stream = hda_codec_dai_set_stream, 380 + .calc_stream_format = hda_calc_stream_format, 381 + .get_hlink = hda_get_hlink, 432 382 }; 433 383 434 384 #endif
+28 -38
sound/soc/sof/intel/hda-dai.c
··· 109 109 110 110 static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, 111 111 struct hdac_ext_stream *hext_stream, 112 - struct snd_soc_dai *cpu_dai, 113 - struct snd_soc_dai *codec_dai) 112 + struct snd_soc_dai *cpu_dai) 114 113 { 115 114 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 116 - struct hdac_stream *hstream = &hext_stream->hstream; 117 - struct hdac_bus *bus = hstream->bus; 118 115 struct sof_intel_hda_stream *hda_stream; 119 116 struct hdac_ext_link *hlink; 120 117 struct snd_sof_dev *sdev; 121 118 int stream_tag; 122 119 120 + if (!ops) { 121 + dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 122 + return -EINVAL; 123 + } 124 + 123 125 sdev = dai_to_sdev(substream, cpu_dai); 124 126 125 - hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 127 + hlink = ops->get_hlink(sdev, substream); 126 128 if (!hlink) 127 129 return -EINVAL; 128 130 ··· 149 147 struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) 150 148 { 151 149 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 152 - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 153 - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 154 150 struct hdac_ext_stream *hext_stream; 155 151 struct hdac_stream *hstream; 156 152 struct hdac_ext_link *hlink; 157 153 struct snd_sof_dev *sdev; 158 - struct hdac_bus *bus; 159 - unsigned int format_val; 160 - unsigned int link_bps; 161 154 int stream_tag; 162 155 163 - sdev = dai_to_sdev(substream, cpu_dai); 164 - bus = sof_to_bus(sdev); 156 + if (!ops) { 157 + dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 158 + return -EINVAL; 159 + } 165 160 166 - hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 161 + sdev = dai_to_sdev(substream, cpu_dai); 162 + 163 + hlink = ops->get_hlink(sdev, substream); 167 164 if (!hlink) 168 165 return -EINVAL; 169 166 ··· 183 182 snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag); 184 183 185 184 /* set the hdac_stream in the codec dai */ 186 - snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); 187 - 188 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 189 - link_bps = codec_dai->driver->playback.sig_bits; 190 - else 191 - link_bps = codec_dai->driver->capture.sig_bits; 185 + if (ops->codec_dai_set_stream) 186 + ops->codec_dai_set_stream(sdev, substream, hstream); 192 187 193 188 if (ops->reset_hext_stream) 194 189 ops->reset_hext_stream(sdev, hext_stream); 195 190 196 - format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), 197 - params_format(params), link_bps, 0); 191 + if (ops->calc_stream_format && ops->setup_hext_stream) { 192 + unsigned int format_val = ops->calc_stream_format(sdev, substream, params); 198 193 199 - dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 200 - params_rate(params), params_channels(params), params_format(params)); 201 - 202 - if (ops->setup_hext_stream) 203 194 ops->setup_hext_stream(sdev, hext_stream, format_val); 195 + } 204 196 205 197 hext_stream->link_prepared = 1; 206 198 ··· 204 210 struct snd_soc_dai *cpu_dai) 205 211 { 206 212 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 207 - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 208 - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 209 213 struct hdac_ext_stream *hext_stream; 210 214 struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai); 211 215 212 216 if (!ops) { 213 - dev_err(sdev->dev, "DAI widget ops not set\n"); 217 + dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 214 218 return -EINVAL; 215 219 } 216 220 ··· 216 224 if (!hext_stream) 217 225 return 0; 218 226 219 - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai); 227 + return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); 220 228 } 221 229 222 230 static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, ··· 261 269 { 262 270 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 263 271 struct hdac_ext_stream *hext_stream; 264 - struct snd_soc_pcm_runtime *rtd; 265 - struct snd_soc_dai *codec_dai; 266 272 struct snd_sof_dev *sdev; 267 273 int ret; 274 + 275 + if (!ops) { 276 + dev_err(dai->dev, "DAI widget ops not set\n"); 277 + return -EINVAL; 278 + } 268 279 269 280 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, 270 281 dai->name, substream->stream); ··· 277 282 hext_stream = ops->get_hext_stream(sdev, dai, substream); 278 283 if (!hext_stream) 279 284 return -EINVAL; 280 - 281 - rtd = asoc_substream_to_rtd(substream); 282 - codec_dai = asoc_rtd_to_codec(rtd, 0); 283 285 284 286 if (ops->pre_trigger) { 285 287 ret = ops->pre_trigger(sdev, dai, substream, cmd); ··· 298 306 299 307 switch (cmd) { 300 308 case SNDRV_PCM_TRIGGER_SUSPEND: 301 - ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); 309 + ret = hda_link_dma_cleanup(substream, hext_stream, dai); 302 310 if (ret < 0) { 303 311 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); 304 312 return ret; ··· 352 360 const struct hda_dai_widget_dma_ops *ops; 353 361 struct snd_sof_widget *swidget; 354 362 struct snd_soc_dapm_widget *w; 355 - struct snd_soc_dai *codec_dai; 356 363 struct snd_soc_dai *cpu_dai; 357 364 struct snd_sof_dev *sdev; 358 365 struct snd_sof_dai *sdai; 359 366 360 367 rtd = asoc_substream_to_rtd(hext_stream->link_substream); 361 368 cpu_dai = asoc_rtd_to_cpu(rtd, 0); 362 - codec_dai = asoc_rtd_to_codec(rtd, 0); 363 369 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 364 370 swidget = w->dobj.private; 365 371 sdev = widget_to_sdev(w); ··· 366 376 367 377 ret = hda_link_dma_cleanup(hext_stream->link_substream, 368 378 hext_stream, 369 - cpu_dai, codec_dai); 379 + cpu_dai); 370 380 if (ret < 0) 371 381 return ret; 372 382
+25
sound/soc/sof/intel/hda.c
··· 222 222 return 0; 223 223 } 224 224 225 + int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) 226 + { 227 + struct sof_intel_hda_dev *hdev; 228 + struct sdw_intel_ctx *ctx; 229 + struct hdac_bus *bus; 230 + u32 slcount; 231 + 232 + bus = sof_to_bus(sdev); 233 + 234 + hdev = sdev->pdata->hw_pdata; 235 + ctx = hdev->sdw; 236 + 237 + slcount = hdac_bus_eml_get_count(bus, true, AZX_REG_ML_LEPTR_ID_SDW); 238 + 239 + /* Check HW supported vs property value */ 240 + if (slcount < ctx->count) { 241 + dev_err(sdev->dev, 242 + "%s: BIOS master count %d is larger than hardware capabilities %d\n", 243 + __func__, ctx->count, slcount); 244 + return -EINVAL; 245 + } 246 + 247 + return 0; 248 + } 249 + 225 250 static int hda_sdw_check_lcount(struct snd_sof_dev *sdev) 226 251 { 227 252 const struct sof_intel_dsp_desc *chip;
+19
sound/soc/sof/intel/hda.h
··· 781 781 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 782 782 783 783 int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev); 784 + int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev); 784 785 int hda_sdw_startup(struct snd_sof_dev *sdev); 785 786 void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable); 786 787 void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable); ··· 791 790 #else 792 791 793 792 static inline int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) 793 + { 794 + return 0; 795 + } 796 + 797 + static inline int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) 794 798 { 795 799 return 0; 796 800 } ··· 925 919 * @pre_trigger: Function pointer for DAI DMA pre-trigger actions 926 920 * @trigger: Function pointer for DAI DMA trigger actions 927 921 * @post_trigger: Function pointer for DAI DMA post-trigger actions 922 + * @codec_dai_set_stream: Function pointer to set codec-side stream information 923 + * @calc_stream_format: Function pointer to determine stream format from hw_params and 924 + * for HDaudio codec DAI from the .sig bits 925 + * @get_hlink: Mandatory function pointer to retrieve hlink, mainly to program LOSIDV 926 + * for legacy HDaudio links or program HDaudio Extended Link registers. 928 927 */ 929 928 struct hda_dai_widget_dma_ops { 930 929 struct hdac_ext_stream *(*get_hext_stream)(struct snd_sof_dev *sdev, ··· 949 938 struct snd_pcm_substream *substream, int cmd); 950 939 int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 951 940 struct snd_pcm_substream *substream, int cmd); 941 + void (*codec_dai_set_stream)(struct snd_sof_dev *sdev, 942 + struct snd_pcm_substream *substream, 943 + struct hdac_stream *hstream); 944 + unsigned int (*calc_stream_format)(struct snd_sof_dev *sdev, 945 + struct snd_pcm_substream *substream, 946 + struct snd_pcm_hw_params *params); 947 + struct hdac_ext_link * (*get_hlink)(struct snd_sof_dev *sdev, 948 + struct snd_pcm_substream *substream); 952 949 }; 953 950 954 951 const struct hda_dai_widget_dma_ops *
+6 -6
sound/soc/sof/intel/mtl.c
··· 55 55 } 56 56 57 57 /* Check if an IPC IRQ occurred */ 58 - static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) 58 + bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) 59 59 { 60 60 u32 irq_status; 61 61 u32 hfintipptr; ··· 118 118 return 0; 119 119 } 120 120 121 - static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) 121 + void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) 122 122 { 123 123 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 124 124 const struct sof_intel_dsp_desc *chip = hda->desc; ··· 132 132 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE); 133 133 } 134 134 135 - static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) 135 + void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) 136 136 { 137 137 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 138 138 const struct sof_intel_dsp_desc *chip = hda->desc; ··· 173 173 enable ? "enable" : "disable"); 174 174 } 175 175 176 - static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) 176 + int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) 177 177 { 178 178 u32 hfintipptr; 179 179 u32 irqinten; ··· 394 394 return ret; 395 395 } 396 396 397 - static int mtl_power_down_dsp(struct snd_sof_dev *sdev) 397 + int mtl_power_down_dsp(struct snd_sof_dev *sdev) 398 398 { 399 399 u32 dsphfdsscs, cpa; 400 400 int ret; ··· 421 421 HDA_DSP_RESET_TIMEOUT_US); 422 422 } 423 423 424 - static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) 424 + int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) 425 425 { 426 426 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; 427 427 const struct sof_intel_dsp_desc *chip = hda->desc;
+7
sound/soc/sof/intel/mtl.h
··· 82 82 #define MTL_DSP_REG_HfIMRIS1 0x162088 83 83 #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0) 84 84 85 + void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev); 86 + void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev); 87 + bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev); 88 + 89 + int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable); 90 + int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); 91 + int mtl_power_down_dsp(struct snd_sof_dev *sdev);
+36 -8
sound/soc/sof/ipc4-topology.c
··· 559 559 strcmp(w->widget->sname, swidget->widget->sname)) 560 560 continue; 561 561 562 - blob->alh_cfg.count++; 562 + blob->alh_cfg.device_count++; 563 563 } 564 564 565 565 ipc4_copier->copier_config = (uint32_t *)blob; ··· 1225 1225 unsigned int group_id; 1226 1226 1227 1227 blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; 1228 - if (blob->alh_cfg.count > 1) { 1228 + if (blob->alh_cfg.device_count > 1) { 1229 1229 group_id = SOF_IPC4_NODE_INDEX(ipc4_copier->data.gtw_cfg.node_id) - 1230 1230 ALH_MULTI_GTW_BASE; 1231 1231 ida_free(&alh_group_ida, group_id); ··· 1383 1383 struct snd_sof_dai *dai; 1384 1384 struct snd_mask *fmt; 1385 1385 int out_sample_valid_bits; 1386 + u32 gtw_cfg_config_length; 1387 + u32 dma_config_tlv_size = 0; 1386 1388 void **ipc_config_data; 1387 1389 int *ipc_config_size; 1388 1390 u32 **data; ··· 1611 1609 ch_map >>= 4; 1612 1610 } 1613 1611 1614 - step = ch_count / blob->alh_cfg.count; 1612 + step = ch_count / blob->alh_cfg.device_count; 1615 1613 mask = GENMASK(step - 1, 0); 1616 1614 /* 1617 1615 * Set each gtw_cfg.node_id to blob->alh_cfg.mapping[] ··· 1626 1624 dai = w->private; 1627 1625 alh_copier = (struct sof_ipc4_copier *)dai->private; 1628 1626 alh_data = &alh_copier->data; 1629 - blob->alh_cfg.mapping[i].alh_id = alh_data->gtw_cfg.node_id; 1627 + blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id; 1630 1628 /* 1631 1629 * Set the same channel mask for playback as the audio data is 1632 1630 * duplicated for all speakers. For capture, split the channels ··· 1645 1643 1646 1644 i++; 1647 1645 } 1648 - if (blob->alh_cfg.count > 1) { 1646 + if (blob->alh_cfg.device_count > 1) { 1649 1647 int group_id; 1650 1648 1651 1649 group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1, ··· 1701 1699 ipc_config_data = &ipc4_copier->ipc_config_data; 1702 1700 1703 1701 /* config_length is DWORD based */ 1704 - ipc_size = sizeof(*copier_data) + copier_data->gtw_cfg.config_length * 4; 1702 + gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4; 1703 + ipc_size = sizeof(*copier_data) + gtw_cfg_config_length; 1704 + 1705 + if (ipc4_copier->dma_config_tlv.type == SOF_IPC4_GTW_DMA_CONFIG_ID && 1706 + ipc4_copier->dma_config_tlv.length) { 1707 + dma_config_tlv_size = sizeof(ipc4_copier->dma_config_tlv) + 1708 + ipc4_copier->dma_config_tlv.dma_config.dma_priv_config_size; 1709 + 1710 + /* paranoia check on TLV size/length */ 1711 + if (dma_config_tlv_size != ipc4_copier->dma_config_tlv.length + 1712 + sizeof(uint32_t) * 2) { 1713 + dev_err(sdev->dev, "Invalid configuration, TLV size %d length %d\n", 1714 + dma_config_tlv_size, ipc4_copier->dma_config_tlv.length); 1715 + return -EINVAL; 1716 + } 1717 + 1718 + ipc_size += dma_config_tlv_size; 1719 + 1720 + /* we also need to increase the size at the gtw level */ 1721 + copier_data->gtw_cfg.config_length += dma_config_tlv_size / 4; 1722 + } 1705 1723 1706 1724 dev_dbg(sdev->dev, "copier %s, IPC size is %d", swidget->widget->name, ipc_size); 1707 1725 ··· 1733 1711 1734 1712 /* copy IPC data */ 1735 1713 memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data)); 1736 - if (copier_data->gtw_cfg.config_length) 1714 + if (gtw_cfg_config_length) 1737 1715 memcpy(*ipc_config_data + sizeof(*copier_data), 1738 - *data, copier_data->gtw_cfg.config_length * 4); 1716 + *data, gtw_cfg_config_length); 1717 + 1718 + /* add DMA Config TLV, if configured */ 1719 + if (dma_config_tlv_size) 1720 + memcpy(*ipc_config_data + sizeof(*copier_data) + 1721 + gtw_cfg_config_length, 1722 + &ipc4_copier->dma_config_tlv, dma_config_tlv_size); 1739 1723 1740 1724 /* update pipeline memory usage */ 1741 1725 sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
+61 -13
sound/soc/sof/ipc4-topology.h
··· 55 55 #define SOF_IPC4_GAIN_ALL_CHANNELS_MASK 0xffffffff 56 56 #define SOF_IPC4_VOL_ZERO_DB 0x7fffffff 57 57 58 - #define ALH_MAX_NUMBER_OF_GTW 16 58 + #define SOF_IPC4_DMA_DEVICE_MAX_COUNT 16 59 59 60 60 #define SOF_IPC4_INVALID_NODE_ID 0xffffffff 61 61 ··· 220 220 uint32_t rsvd : 30; 221 221 }; 222 222 223 - /** struct sof_ipc4_alh_multi_gtw_cfg: ALH gateway cfg data 224 - * @count: Number of streams (valid items in mapping array) 225 - * @alh_id: ALH stream id of a single ALH stream aggregated 226 - * @channel_mask: Channel mask 227 - * @mapping: ALH streams 223 + /** 224 + * struct sof_ipc4_dma_device_stream_ch_map: abstract representation of 225 + * channel mapping to DMAs 226 + * @device: representation of hardware device address or FIFO 227 + * @channel_mask: channels handled by @device. Channels are expected to be 228 + * contiguous 228 229 */ 229 - struct sof_ipc4_alh_multi_gtw_cfg { 230 - uint32_t count; 231 - struct { 232 - uint32_t alh_id; 233 - uint32_t channel_mask; 234 - } mapping[ALH_MAX_NUMBER_OF_GTW]; 230 + struct sof_ipc4_dma_device_stream_ch_map { 231 + uint32_t device; 232 + uint32_t channel_mask; 233 + }; 234 + 235 + /** 236 + * struct sof_ipc4_dma_stream_ch_map: DMA configuration data 237 + * @device_count: Number valid items in mapping array 238 + * @mapping: device address and channel mask 239 + */ 240 + struct sof_ipc4_dma_stream_ch_map { 241 + uint32_t device_count; 242 + struct sof_ipc4_dma_device_stream_ch_map mapping[SOF_IPC4_DMA_DEVICE_MAX_COUNT]; 243 + } __packed; 244 + 245 + #define SOF_IPC4_DMA_METHOD_HDA 1 246 + #define SOF_IPC4_DMA_METHOD_GPDMA 2 /* defined for consistency but not used */ 247 + 248 + /** 249 + * struct sof_ipc4_dma_config: DMA configuration 250 + * @dma_method: HDAudio or GPDMA 251 + * @pre_allocated_by_host: 1 if host driver allocates DMA channels, 0 otherwise 252 + * @dma_channel_id: for HDaudio defined as @stream_id - 1 253 + * @stream_id: HDaudio stream tag 254 + * @dma_stream_channel_map: array of device/channel mappings 255 + * @dma_priv_config_size: currently not used 256 + * @dma_priv_config: currently not used 257 + */ 258 + struct sof_ipc4_dma_config { 259 + uint8_t dma_method; 260 + uint8_t pre_allocated_by_host; 261 + uint16_t rsvd; 262 + uint32_t dma_channel_id; 263 + uint32_t stream_id; 264 + struct sof_ipc4_dma_stream_ch_map dma_stream_channel_map; 265 + uint32_t dma_priv_config_size; 266 + uint8_t dma_priv_config[]; 267 + } __packed; 268 + 269 + #define SOF_IPC4_GTW_DMA_CONFIG_ID 0x1000 270 + 271 + /** 272 + * struct sof_ipc4_dma_config: DMA configuration 273 + * @type: set to SOF_IPC4_GTW_DMA_CONFIG_ID 274 + * @length: sizeof(struct sof_ipc4_dma_config) + dma_config.dma_priv_config_size 275 + * @dma_config: actual DMA configuration 276 + */ 277 + struct sof_ipc4_dma_config_tlv { 278 + uint32_t type; 279 + uint32_t length; 280 + struct sof_ipc4_dma_config dma_config; 235 281 } __packed; 236 282 237 283 /** struct sof_ipc4_alh_configuration_blob: ALH blob ··· 286 240 */ 287 241 struct sof_ipc4_alh_configuration_blob { 288 242 struct sof_ipc4_gtw_attributes gw_attr; 289 - struct sof_ipc4_alh_multi_gtw_cfg alh_cfg; 243 + struct sof_ipc4_dma_stream_ch_map alh_cfg; 290 244 }; 291 245 292 246 /** ··· 300 254 * @gtw_attr: Gateway attributes for copier blob 301 255 * @dai_type: DAI type 302 256 * @dai_index: DAI index 257 + * @dma_config_tlv: DMA configuration 303 258 */ 304 259 struct sof_ipc4_copier { 305 260 struct sof_ipc4_copier_data data; ··· 313 266 struct sof_ipc4_gtw_attributes *gtw_attr; 314 267 u32 dai_type; 315 268 int dai_index; 269 + struct sof_ipc4_dma_config_tlv dma_config_tlv; 316 270 }; 317 271 318 272 /**