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

Enable timestamp support for SOF compress driver

Merge series from Daniel Baluta <daniel.baluta@oss.nxp.com>:

This patchseries computes pcm_io_frames from the DAI position reported
by SOF firmware. Using pcm_io_frames userspace applications can later
compute timestamps for compressed stream.

+40 -21
+33 -21
sound/soc/sof/compress.c
··· 11 11 #include "sof-priv.h" 12 12 #include "sof-utils.h" 13 13 14 - static void sof_set_transferred_bytes(struct snd_compr_tstamp *tstamp, 14 + static void sof_set_transferred_bytes(struct sof_compr_stream *sstream, 15 15 u64 host_pos, u64 buffer_size) 16 16 { 17 17 u64 prev_pos; 18 18 unsigned int copied; 19 19 20 - div64_u64_rem(tstamp->copied_total, buffer_size, &prev_pos); 20 + div64_u64_rem(sstream->copied_total, buffer_size, &prev_pos); 21 21 22 22 if (host_pos < prev_pos) 23 23 copied = (buffer_size - prev_pos) + host_pos; 24 24 else 25 25 copied = host_pos - prev_pos; 26 26 27 - tstamp->copied_total += copied; 27 + sstream->copied_total += copied; 28 28 } 29 29 30 30 static void snd_sof_compr_fragment_elapsed_work(struct work_struct *work) ··· 49 49 struct snd_soc_pcm_runtime *rtd; 50 50 struct snd_compr_runtime *crtd; 51 51 struct snd_soc_component *component; 52 - struct snd_compr_tstamp *tstamp; 52 + struct sof_compr_stream *sstream; 53 53 struct snd_sof_pcm *spcm; 54 54 55 55 if (!cstream) ··· 57 57 58 58 rtd = cstream->private_data; 59 59 crtd = cstream->runtime; 60 - tstamp = crtd->private_data; 60 + sstream = crtd->private_data; 61 61 component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 62 62 63 63 spcm = snd_sof_find_spcm_dai(component, rtd); ··· 67 67 return; 68 68 } 69 69 70 - sof_set_transferred_bytes(tstamp, spcm->stream[cstream->direction].posn.host_posn, 70 + sof_set_transferred_bytes(sstream, spcm->stream[cstream->direction].posn.host_posn, 71 71 crtd->buffer_size); 72 72 73 73 /* use the same workqueue-based solution as for PCM, cf. snd_sof_pcm_elapsed */ ··· 96 96 { 97 97 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 98 98 struct snd_compr_runtime *crtd = cstream->runtime; 99 - struct snd_compr_tstamp *tstamp; 99 + struct sof_compr_stream *sstream; 100 100 struct snd_sof_pcm *spcm; 101 101 int dir; 102 102 103 - tstamp = kzalloc(sizeof(*tstamp), GFP_KERNEL); 104 - if (!tstamp) 103 + sstream = kzalloc(sizeof(*sstream), GFP_KERNEL); 104 + if (!sstream) 105 105 return -ENOMEM; 106 106 107 107 spcm = snd_sof_find_spcm_dai(component, rtd); 108 108 if (!spcm) { 109 - kfree(tstamp); 109 + kfree(sstream); 110 110 return -EINVAL; 111 111 } 112 112 113 113 dir = cstream->direction; 114 114 115 115 if (spcm->stream[dir].cstream) { 116 - kfree(tstamp); 116 + kfree(sstream); 117 117 return -EBUSY; 118 118 } 119 119 ··· 122 122 spcm->stream[dir].posn.dai_posn = 0; 123 123 spcm->prepared[dir] = false; 124 124 125 - crtd->private_data = tstamp; 125 + crtd->private_data = sstream; 126 126 127 127 return 0; 128 128 } ··· 131 131 struct snd_compr_stream *cstream) 132 132 { 133 133 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 134 - struct snd_compr_tstamp *tstamp = cstream->runtime->private_data; 134 + struct sof_compr_stream *sstream = cstream->runtime->private_data; 135 135 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 136 136 struct sof_ipc_stream stream; 137 137 struct sof_ipc_reply reply; ··· 155 155 156 156 cancel_work_sync(&spcm->stream[cstream->direction].period_elapsed_work); 157 157 spcm->stream[cstream->direction].cstream = NULL; 158 - kfree(tstamp); 158 + kfree(sstream); 159 159 160 160 return ret; 161 161 } ··· 169 169 struct sof_ipc_pcm_params_reply ipc_params_reply; 170 170 struct sof_ipc_fw_ready *ready = &sdev->fw_ready; 171 171 struct sof_ipc_fw_version *v = &ready->version; 172 - struct snd_compr_tstamp *tstamp; 172 + struct sof_compr_stream *sstream; 173 173 struct sof_ipc_pcm_params *pcm; 174 174 struct snd_sof_pcm *spcm; 175 175 size_t ext_data_size; ··· 184 184 return -EINVAL; 185 185 } 186 186 187 - tstamp = crtd->private_data; 187 + sstream = crtd->private_data; 188 188 189 189 spcm = snd_sof_find_spcm_dai(component, rtd); 190 190 ··· 237 237 goto out; 238 238 } 239 239 240 - tstamp->byte_offset = sdev->stream_box.offset + ipc_params_reply.posn_offset; 241 - tstamp->sampling_rate = params->codec.sample_rate; 240 + sstream->sampling_rate = params->codec.sample_rate; 241 + sstream->channels = params->codec.ch_out; 242 + sstream->sample_container_bytes = pcm->params.sample_container_bytes; 242 243 243 244 spcm->prepared[cstream->direction] = true; 244 245 ··· 327 326 struct snd_compr_stream *cstream, 328 327 struct snd_compr_tstamp *tstamp) 329 328 { 330 - struct snd_compr_tstamp *pstamp = cstream->runtime->private_data; 329 + u64 dai_posn; 330 + struct snd_sof_pcm *spcm; 331 + struct snd_soc_pcm_runtime *rtd = cstream->private_data; 332 + struct sof_compr_stream *sstream = cstream->runtime->private_data; 331 333 332 - tstamp->sampling_rate = pstamp->sampling_rate; 333 - tstamp->copied_total = pstamp->copied_total; 334 + spcm = snd_sof_find_spcm_dai(component, rtd); 335 + if (!spcm) 336 + return -EINVAL; 337 + 338 + dai_posn = spcm->stream[cstream->direction].posn.dai_posn; 339 + 340 + tstamp->sampling_rate = sstream->sampling_rate; 341 + tstamp->copied_total = sstream->copied_total; 342 + tstamp->pcm_io_frames = div_u64(spcm->stream[cstream->direction].posn.dai_posn, 343 + sstream->channels * sstream->sample_container_bytes); 334 344 335 345 return 0; 336 346 }
+7
sound/soc/sof/sof-priv.h
··· 105 105 SOF_DEBUGFS_ACCESS_D0_ONLY, 106 106 }; 107 107 108 + struct sof_compr_stream { 109 + u64 copied_total; 110 + u32 sampling_rate; 111 + u16 channels; 112 + u16 sample_container_bytes; 113 + }; 114 + 108 115 struct snd_sof_dev; 109 116 struct snd_sof_ipc_msg; 110 117 struct snd_sof_ipc;