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

Merge tag 'sound-fix-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
"A few more small fixes for 6.18-rc1.

Most of changes are about ASoC Intel and SOF drivers, while a few
other device-specific fixes are found for HD-audio, USB-audio, ASoC
RT722VB and Meson"

* tag 'sound-fix-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ASoC: rt722: add settings for rt722VB
ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
ALSA: usb: fpc: replace kmalloc_array followed by copy_from_user with memdup_array_user
ALSA: hda/tas2781: Enable init_profile_id for device initialization
ALSA: emu10k1: Fix typo in docs
ALSA: hda/realtek: Add quirk for ASUS ROG Zephyrus Duo
ASoC: SOF: Intel: Read the LLP via the associated Link DMA channel
ASoC: SOF: ipc4-pcm: do not report invalid delay values
ASoC: SOF: sof-audio: add dev_dbg_ratelimited wrapper
ASoC: SOF: Intel: hda-pcm: Place the constraint on period time instead of buffer time
ASoC: SOF: ipc4-topology: Account for different ChainDMA host buffer size
ASoC: SOF: ipc4-topology: Correct the minimum host DMA buffer size
ASoC: SOF: ipc4-pcm: fix start offset calculation for chain DMA
ASoC: SOF: ipc4-pcm: fix delay calculation when DSP resamples
ASoC: SOF: ipc3-topology: Fix multi-core and static pipelines tear down
ALSA: hda/hdmi: Add pin fix for HP ProDesk model

+206 -55
+1 -1
Documentation/sound/cards/emu-mixer.rst
··· 66 66 67 67 name='Clock Source',index=0 68 68 --------------------------- 69 - This control allows switching the word clock between interally generated 69 + This control allows switching the word clock between internally generated 70 70 44.1 or 48 kHz, or a number of external sources. 71 71 72 72 Note: the sources for the 1616 CardBus card are unclear. Please report your
+1
sound/hda/codecs/hdmi/hdmi.c
··· 1549 1549 SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1), 1550 1550 SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1), 1551 1551 SND_PCI_QUIRK(0x103c, 0x845a, "HP EliteDesk 800 G4 DM 65W", 1), 1552 + SND_PCI_QUIRK(0x103c, 0x83f3, "HP ProDesk 400", 1), 1552 1553 SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), 1553 1554 SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), 1554 1555 SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
+10
sound/hda/codecs/realtek/alc269.c
··· 3735 3735 ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC, 3736 3736 ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1, 3737 3737 ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC, 3738 + ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK, 3738 3739 }; 3739 3740 3740 3741 /* A special fixup for Lenovo C940 and Yoga Duet 7; ··· 6165 6164 .chained = true, 6166 6165 .chain_id = ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE, 6167 6166 }, 6167 + [ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK] = { 6168 + .type = HDA_FIXUP_PINS, 6169 + .v.pins = (const struct hda_pintbl[]) { 6170 + { 0x17, 0x90170151 }, /* Internal Speaker LFE */ 6171 + { 0x1e, 0x90170150 }, /* Internal Speaker */ 6172 + { } 6173 + }, 6174 + } 6168 6175 }; 6169 6176 6170 6177 static const struct hda_quirk alc269_fixup_tbl[] = { ··· 6727 6718 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), 6728 6719 SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2), 6729 6720 SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC), 6721 + SND_PCI_QUIRK(0x1043, 0x1652, "ASUS ROG Zephyrus Do 15 SE", ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK), 6730 6722 SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), 6731 6723 SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), 6732 6724 SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
+12
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
··· 474 474 if (tas_priv->fmw->nr_configurations > 0) 475 475 tas_priv->cur_conf = 0; 476 476 477 + /* Init common setting for different audio profiles */ 478 + if (tas_priv->rcabin.init_profile_id >= 0) 479 + tasdevice_select_cfg_blk(tas_priv, 480 + tas_priv->rcabin.init_profile_id, 481 + TASDEVICE_BIN_BLK_PRE_POWER_UP); 482 + 477 483 /* If calibrated data occurs error, dsp will still works with default 478 484 * calibrated data inside algo. 479 485 */ ··· 775 769 } 776 770 tasdevice_reset(tas_hda->priv); 777 771 tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); 772 + 773 + /* Init common setting for different audio profiles */ 774 + if (tas_hda->priv->rcabin.init_profile_id >= 0) 775 + tasdevice_select_cfg_blk(tas_hda->priv, 776 + tas_hda->priv->rcabin.init_profile_id, 777 + TASDEVICE_BIN_BLK_PRE_POWER_UP); 778 778 779 779 if (tas_hda->priv->playback_started) 780 780 tasdevice_tuning_switch(tas_hda->priv, 0);
+1 -1
sound/soc/codecs/rt722-sdca-sdw.c
··· 21 21 switch (reg) { 22 22 case 0x2f01 ... 0x2f0a: 23 23 case 0x2f35 ... 0x2f36: 24 - case 0x2f50: 24 + case 0x2f50 ... 0x2f52: 25 25 case 0x2f54: 26 26 case 0x2f58 ... 0x2f5d: 27 27 case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0):
+14
sound/soc/codecs/rt722-sdca.c
··· 1378 1378 /* PHYtiming TDZ/TZD control */ 1379 1379 regmap_write(rt722->regmap, 0x2f03, 0x06); 1380 1380 1381 + if (rt722->hw_vid == RT722_VB) 1382 + regmap_write(rt722->regmap, 0x2f52, 0x00); 1383 + 1381 1384 /* clear flag */ 1382 1385 regmap_write(rt722->regmap, 1383 1386 SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0), ··· 1417 1414 regmap_write(rt722->regmap, 1418 1415 SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, 1419 1416 RT722_SDCA_CTL_VENDOR_DEF, CH_08), 0x04); 1417 + 1418 + if (rt722->hw_vid == RT722_VB) 1419 + regmap_write(rt722->regmap, 0x2f54, 0x00); 1420 1420 1421 1421 /* clear flag */ 1422 1422 regmap_write(rt722->regmap, ··· 1512 1506 rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4, 1513 1507 0x0010); 1514 1508 1509 + if (rt722->hw_vid == RT722_VB) 1510 + regmap_write(rt722->regmap, 0x2f51, 0x00); 1511 + 1515 1512 /* clear flag */ 1516 1513 regmap_write(rt722->regmap, 1517 1514 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT0, RT722_SDCA_CTL_FUNC_STATUS, 0), ··· 1525 1516 int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) 1526 1517 { 1527 1518 struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev); 1519 + unsigned int val; 1528 1520 1529 1521 rt722->disable_irq = false; 1530 1522 ··· 1554 1544 } 1555 1545 1556 1546 pm_runtime_get_noresume(&slave->dev); 1547 + 1548 + rt722_sdca_index_read(rt722, RT722_VENDOR_REG, RT722_JD_PRODUCT_NUM, &val); 1549 + rt722->hw_vid = (val & 0x0f00) >> 8; 1550 + dev_dbg(&slave->dev, "%s hw_vid=0x%x\n", __func__, rt722->hw_vid); 1557 1551 1558 1552 rt722_sdca_dmic_preset(rt722); 1559 1553 rt722_sdca_amp_preset(rt722);
+6
sound/soc/codecs/rt722-sdca.h
··· 39 39 /* For DMIC */ 40 40 bool fu1e_dapm_mute; 41 41 bool fu1e_mixer_mute[4]; 42 + int hw_vid; 42 43 }; 43 44 44 45 struct rt722_sdca_dmic_kctrl_priv { ··· 232 231 enum rt722_sdca_jd_src { 233 232 RT722_JD_NULL, 234 233 RT722_JD1, 234 + }; 235 + 236 + enum rt722_sdca_version { 237 + RT722_VA, 238 + RT722_VB, 235 239 }; 236 240 237 241 int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave);
+6 -3
sound/soc/meson/aiu-encoder-i2s.c
··· 236 236 inv == SND_SOC_DAIFMT_IB_IF) 237 237 val |= AIU_CLK_CTRL_LRCLK_INVERT; 238 238 239 - if (inv == SND_SOC_DAIFMT_IB_NF || 240 - inv == SND_SOC_DAIFMT_IB_IF) 239 + /* 240 + * The SoC changes data on the rising edge of the bitclock 241 + * so an inversion of the bitclock is required in normal mode 242 + */ 243 + if (inv == SND_SOC_DAIFMT_NB_NF || 244 + inv == SND_SOC_DAIFMT_NB_IF) 241 245 val |= AIU_CLK_CTRL_AOCLK_INVERT; 242 246 243 247 /* Signal skew */ ··· 332 328 .startup = aiu_encoder_i2s_startup, 333 329 .shutdown = aiu_encoder_i2s_shutdown, 334 330 }; 335 -
+21 -8
sound/soc/sof/intel/hda-pcm.c
··· 29 29 #define SDnFMT_BITS(x) ((x) << 4) 30 30 #define SDnFMT_CHAN(x) ((x) << 0) 31 31 32 + #define HDA_MAX_PERIOD_TIME_HEADROOM 10 33 + 32 34 static bool hda_always_enable_dmi_l1; 33 35 module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444); 34 36 MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1"); ··· 293 291 * On playback start the DMA will transfer dsp_max_burst_size_in_ms 294 292 * amount of data in one initial burst to fill up the host DMA buffer. 295 293 * Consequent DMA burst sizes are shorter and their length can vary. 296 - * To make sure that userspace allocate large enough ALSA buffer we need 297 - * to place a constraint on the buffer time. 294 + * To avoid immediate xrun by the initial burst we need to place 295 + * constraint on the period size (via PERIOD_TIME) to cover the size of 296 + * the host buffer. 297 + * We need to add headroom of max 10ms as the firmware needs time to 298 + * settle to the 1ms pacing and initially it can run faster for few 299 + * internal periods. 298 300 * 299 301 * On capture the DMA will transfer 1ms chunks. 300 - * 301 - * Exact dsp_max_burst_size_in_ms constraint is racy, so set the 302 - * constraint to a minimum of 2x dsp_max_burst_size_in_ms. 303 302 */ 304 - if (spcm->stream[direction].dsp_max_burst_size_in_ms) 303 + if (spcm->stream[direction].dsp_max_burst_size_in_ms) { 304 + unsigned int period_time = spcm->stream[direction].dsp_max_burst_size_in_ms; 305 + 306 + /* 307 + * add headroom over the maximum burst size to cover the time 308 + * needed for the DMA pace to settle. 309 + * Limit the headroom time to HDA_MAX_PERIOD_TIME_HEADROOM 310 + */ 311 + period_time += min(period_time, HDA_MAX_PERIOD_TIME_HEADROOM); 312 + 305 313 snd_pcm_hw_constraint_minmax(substream->runtime, 306 - SNDRV_PCM_HW_PARAM_BUFFER_TIME, 307 - spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2, 314 + SNDRV_PCM_HW_PARAM_PERIOD_TIME, 315 + period_time * USEC_PER_MSEC, 308 316 UINT_MAX); 317 + } 309 318 310 319 /* binding pcm substream to hda stream */ 311 320 substream->runtime->private_data = &dsp_stream->hstream;
+27 -2
sound/soc/sof/intel/hda-stream.c
··· 1129 1129 struct snd_soc_component *component, 1130 1130 struct snd_pcm_substream *substream) 1131 1131 { 1132 - struct hdac_stream *hstream = substream->runtime->private_data; 1133 - struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); 1132 + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 1133 + struct snd_soc_pcm_runtime *be_rtd = NULL; 1134 + struct hdac_ext_stream *hext_stream; 1135 + struct snd_soc_dai *cpu_dai; 1136 + struct snd_soc_dpcm *dpcm; 1134 1137 u32 llp_l, llp_u; 1138 + 1139 + /* 1140 + * The LLP needs to be read from the Link DMA used for this FE as it is 1141 + * allowed to use any combination of Link and Host channels 1142 + */ 1143 + for_each_dpcm_be(rtd, substream->stream, dpcm) { 1144 + if (dpcm->fe != rtd) 1145 + continue; 1146 + 1147 + be_rtd = dpcm->be; 1148 + } 1149 + 1150 + if (!be_rtd) 1151 + return 0; 1152 + 1153 + cpu_dai = snd_soc_rtd_to_cpu(be_rtd, 0); 1154 + if (!cpu_dai) 1155 + return 0; 1156 + 1157 + hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); 1158 + if (!hext_stream) 1159 + return 0; 1135 1160 1136 1161 /* 1137 1162 * The pplc_addr have been calculated during probe in
+5 -5
sound/soc/sof/ipc3-topology.c
··· 2473 2473 if (ret < 0) 2474 2474 return ret; 2475 2475 2476 - /* free all the scheduler widgets now */ 2477 - ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); 2478 - if (ret < 0) 2479 - return ret; 2480 - 2481 2476 /* 2482 2477 * Tear down all pipelines associated with PCMs that did not get suspended 2483 2478 * and unset the prepare flag so that they can be set up again during resume. ··· 2487 2492 return ret; 2488 2493 } 2489 2494 } 2495 + 2496 + /* free all the scheduler widgets now. This will also power down the secondary cores */ 2497 + ret = sof_ipc3_free_widgets_in_list(sdev, true, &dyn_widgets, verify); 2498 + if (ret < 0) 2499 + return ret; 2490 2500 2491 2501 list_for_each_entry(sroute, &sdev->route_list, list) 2492 2502 sroute->setup = false;
+80 -24
sound/soc/sof/ipc4-pcm.c
··· 19 19 * struct sof_ipc4_timestamp_info - IPC4 timestamp info 20 20 * @host_copier: the host copier of the pcm stream 21 21 * @dai_copier: the dai copier of the pcm stream 22 - * @stream_start_offset: reported by fw in memory window (converted to frames) 23 - * @stream_end_offset: reported by fw in memory window (converted to frames) 22 + * @stream_start_offset: reported by fw in memory window (converted to 23 + * frames at host_copier sampling rate) 24 + * @stream_end_offset: reported by fw in memory window (converted to 25 + * frames at host_copier sampling rate) 24 26 * @llp_offset: llp offset in memory window 25 - * @boundary: wrap boundary should be used for the LLP frame counter 26 27 * @delay: Calculated and stored in pointer callback. The stored value is 27 - * returned in the delay callback. 28 + * returned in the delay callback. Expressed in frames at host copier 29 + * sampling rate. 28 30 */ 29 31 struct sof_ipc4_timestamp_info { 30 32 struct sof_ipc4_copier *host_copier; ··· 35 33 u64 stream_end_offset; 36 34 u32 llp_offset; 37 35 38 - u64 boundary; 39 36 snd_pcm_sframes_t delay; 40 37 }; 41 38 ··· 48 47 49 48 bool chain_dma_allocated; 50 49 }; 50 + 51 + /* 52 + * Modulus to use to compare host and link position counters. The sampling 53 + * rates may be different, so the raw hardware counters will wrap 54 + * around at different times. To calculate differences, use 55 + * DELAY_BOUNDARY as a common modulus. This value must be smaller than 56 + * the wrap-around point of any hardware counter, and larger than any 57 + * valid delay measurement. 58 + */ 59 + #define DELAY_BOUNDARY U32_MAX 60 + 61 + #define DELAY_MAX (DELAY_BOUNDARY >> 1) 51 62 52 63 static inline struct sof_ipc4_timestamp_info * 53 64 sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps) ··· 1062 1049 return 0; 1063 1050 } 1064 1051 1052 + static u64 sof_ipc4_frames_dai_to_host(struct sof_ipc4_timestamp_info *time_info, u64 value) 1053 + { 1054 + u64 dai_rate, host_rate; 1055 + 1056 + if (!time_info->dai_copier || !time_info->host_copier) 1057 + return value; 1058 + 1059 + /* 1060 + * copiers do not change sampling rate, so we can use the 1061 + * out_format independently of stream direction 1062 + */ 1063 + dai_rate = time_info->dai_copier->data.out_format.sampling_frequency; 1064 + host_rate = time_info->host_copier->data.out_format.sampling_frequency; 1065 + 1066 + if (!dai_rate || !host_rate || dai_rate == host_rate) 1067 + return value; 1068 + 1069 + /* take care not to overflow u64, rates can be up to 768000 */ 1070 + if (value > U32_MAX) { 1071 + value = div64_u64(value, dai_rate); 1072 + value *= host_rate; 1073 + } else { 1074 + value *= host_rate; 1075 + value = div64_u64(value, dai_rate); 1076 + } 1077 + 1078 + return value; 1079 + } 1080 + 1065 1081 static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev, 1066 1082 struct snd_pcm_substream *substream, 1067 1083 struct snd_sof_pcm_stream *sps, ··· 1110 1068 return -EINVAL; 1111 1069 } else if (host_copier->data.gtw_cfg.node_id == SOF_IPC4_CHAIN_DMA_NODE_ID) { 1112 1070 /* 1113 - * While the firmware does not supports time_info reporting for 1071 + * While the firmware does not support time_info reporting for 1114 1072 * streams using ChainDMA, it is granted that ChainDMA can only 1115 1073 * be used on Host+Link pairs where the link position is 1116 1074 * accessible from the host side. ··· 1118 1076 * Enable delay calculation in case of ChainDMA via host 1119 1077 * accessible registers. 1120 1078 * 1121 - * The ChainDMA uses 2x 1ms ping-pong buffer, dai side starts 1122 - * when 1ms data is available 1079 + * The ChainDMA prefills the link DMA with a preamble 1080 + * of zero samples. Set the stream start offset based 1081 + * on size of the preamble (driver provided fifo size 1082 + * multiplied by 2.5). We add 1ms of margin as the FW 1083 + * will align the buffer size to DMA hardware 1084 + * alignment that is not known to host. 1123 1085 */ 1124 - time_info->stream_start_offset = substream->runtime->rate / MSEC_PER_SEC; 1086 + int pre_ms = SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * 5 / 2 + 1; 1087 + 1088 + time_info->stream_start_offset = pre_ms * substream->runtime->rate / MSEC_PER_SEC; 1125 1089 goto out; 1126 1090 } 1127 1091 ··· 1147 1099 time_info->stream_end_offset = ppl_reg.stream_end_offset; 1148 1100 do_div(time_info->stream_end_offset, dai_sample_size); 1149 1101 1102 + /* convert to host frame time */ 1103 + time_info->stream_start_offset = 1104 + sof_ipc4_frames_dai_to_host(time_info, time_info->stream_start_offset); 1105 + time_info->stream_end_offset = 1106 + sof_ipc4_frames_dai_to_host(time_info, time_info->stream_end_offset); 1107 + 1150 1108 out: 1151 - /* 1152 - * Calculate the wrap boundary need to be used for delay calculation 1153 - * The host counter is in bytes, it will wrap earlier than the frames 1154 - * based link counter. 1155 - */ 1156 - time_info->boundary = div64_u64(~((u64)0), 1157 - frames_to_bytes(substream->runtime, 1)); 1158 1109 /* Initialize the delay value to 0 (no delay) */ 1159 1110 time_info->delay = 0; 1160 1111 ··· 1196 1149 1197 1150 /* For delay calculation we need the host counter */ 1198 1151 host_cnt = snd_sof_pcm_get_host_byte_counter(sdev, component, substream); 1152 + 1153 + /* Store the original value to host_ptr */ 1199 1154 host_ptr = host_cnt; 1200 1155 1201 1156 /* convert the host_cnt to frames */ ··· 1216 1167 sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp)); 1217 1168 dai_cnt = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l; 1218 1169 } 1170 + 1171 + dai_cnt = sof_ipc4_frames_dai_to_host(time_info, dai_cnt); 1219 1172 dai_cnt += time_info->stream_end_offset; 1220 1173 1221 1174 /* In two cases dai dma counter is not accurate ··· 1251 1200 dai_cnt -= time_info->stream_start_offset; 1252 1201 } 1253 1202 1254 - /* Wrap the dai counter at the boundary where the host counter wraps */ 1255 - div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt); 1203 + /* Convert to a common base before comparisons */ 1204 + dai_cnt &= DELAY_BOUNDARY; 1205 + host_cnt &= DELAY_BOUNDARY; 1256 1206 1257 1207 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1258 1208 head_cnt = host_cnt; ··· 1263 1211 tail_cnt = host_cnt; 1264 1212 } 1265 1213 1266 - if (head_cnt < tail_cnt) { 1267 - time_info->delay = time_info->boundary - tail_cnt + head_cnt; 1268 - goto out; 1214 + if (unlikely(head_cnt < tail_cnt)) 1215 + time_info->delay = DELAY_BOUNDARY - tail_cnt + head_cnt; 1216 + else 1217 + time_info->delay = head_cnt - tail_cnt; 1218 + 1219 + if (time_info->delay > DELAY_MAX) { 1220 + spcm_dbg_ratelimited(spcm, substream->stream, 1221 + "inaccurate delay, host %llu dai_cnt %llu", 1222 + host_cnt, dai_cnt); 1223 + time_info->delay = 0; 1269 1224 } 1270 1225 1271 - time_info->delay = head_cnt - tail_cnt; 1272 - 1273 - out: 1274 1226 /* 1275 1227 * Convert the host byte counter to PCM pointer which wraps in buffer 1276 1228 * and it is in frames
+7 -3
sound/soc/sof/ipc4-topology.c
··· 33 33 34 34 #define SOF_IPC4_GAIN_PARAM_ID 0 35 35 #define SOF_IPC4_TPLG_ABI_SIZE 6 36 - #define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 37 36 38 37 static DEFINE_IDA(alh_group_ida); 39 38 static DEFINE_IDA(pipeline_ida); ··· 665 666 swidget->tuples, 666 667 swidget->num_tuples, sizeof(u32), 1); 667 668 /* Set default DMA buffer size if it is not specified in topology */ 668 - if (!sps->dsp_max_burst_size_in_ms) 669 - sps->dsp_max_burst_size_in_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE; 669 + if (!sps->dsp_max_burst_size_in_ms) { 670 + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 671 + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 672 + 673 + sps->dsp_max_burst_size_in_ms = pipeline->use_chain_dma ? 674 + SOF_IPC4_CHAIN_DMA_BUFFER_SIZE : SOF_IPC4_MIN_DMA_BUFFER_SIZE; 675 + } 670 676 } else { 671 677 /* Capture data is copied from DSP to host in 1ms bursts */ 672 678 spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
+7 -2
sound/soc/sof/ipc4-topology.h
··· 70 70 #define SOF_IPC4_CHAIN_DMA_NODE_ID 0x7fffffff 71 71 #define SOF_IPC4_INVALID_NODE_ID 0xffffffff 72 72 73 - /* FW requires minimum 2ms DMA buffer size */ 74 - #define SOF_IPC4_MIN_DMA_BUFFER_SIZE 2 73 + /* FW requires minimum 4ms DMA buffer size */ 74 + #define SOF_IPC4_MIN_DMA_BUFFER_SIZE 4 75 + 76 + /* ChainDMA in fw uses 5ms DMA buffer */ 77 + #define SOF_IPC4_CHAIN_DMA_BUFFER_SIZE 5 75 78 76 79 /* 77 80 * The base of multi-gateways. Multi-gateways addressing starts from ··· 265 262 266 263 #define SOF_IPC4_DMA_METHOD_HDA 1 267 264 #define SOF_IPC4_DMA_METHOD_GPDMA 2 /* defined for consistency but not used */ 265 + 266 + #define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 268 267 269 268 /** 270 269 * struct sof_ipc4_dma_config: DMA configuration
+5
sound/soc/sof/sof-audio.h
··· 629 629 (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \ 630 630 ##__VA_ARGS__) 631 631 632 + #define spcm_dbg_ratelimited(__spcm, __dir, __fmt, ...) \ 633 + dev_dbg_ratelimited((__spcm)->scomp->dev, "pcm%u (%s), dir %d: " __fmt, \ 634 + (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \ 635 + ##__VA_ARGS__) 636 + 632 637 #define spcm_err(__spcm, __dir, __fmt, ...) \ 633 638 dev_err((__spcm)->scomp->dev, "%s: pcm%u (%s), dir %d: " __fmt, \ 634 639 __func__, (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \
+3 -6
sound/usb/fcp.c
··· 641 641 return -EINVAL; 642 642 643 643 /* Allocate and copy the map data */ 644 - tmp_map = kmalloc_array(map.map_size, sizeof(s16), GFP_KERNEL); 645 - if (!tmp_map) 646 - return -ENOMEM; 647 - 648 - if (copy_from_user(tmp_map, arg->map, map.map_size * sizeof(s16))) 649 - return -EFAULT; 644 + tmp_map = memdup_array_user(arg->map, map.map_size, sizeof(s16)); 645 + if (IS_ERR(tmp_map)) 646 + return PTR_ERR(tmp_map); 650 647 651 648 err = validate_meter_map(tmp_map, map.map_size, map.meter_slots); 652 649 if (err < 0)