aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/sst-baytrail-pcm.c
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2014-05-08 09:07:21 -0400
committerMark Brown <broonie@linaro.org>2014-05-12 17:02:17 -0400
commitc83649e3cdb6e78cfbc3abda7207ff44ba7bea75 (patch)
tree8c422f3e44a74b3f896f903bec5c4c1b650d8b30 /sound/soc/intel/sst-baytrail-pcm.c
parentb9d4cf74b93e4255ac90d75f9bc3f85510a71378 (diff)
ASoC: Intel: Sample Baytrail DSP DMA pointer only after each period
This is for preparing suspend/resume support but can give also more safeguard against concurrent timestamp structure access between DSP firmware and host. Now DSP DMA pointer is sampled in each pcm pointer callback in sst_byt_pcm_pointer() but that is unneeded since DSP updates the timestamp period basis and can potentially be racy if sst_byt_pcm_pointer() is called when DSP is updating the timestamp. By taking DSP DMA pointer only after period elapsed IPC messages in byt_notify_pointer() and returning stored hw pointer in sst_byt_pcm_pointer() there is less risk for concurrent access. The same stored hw pointer can be also used in suspend/resume code for restarting the stream at the same position. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/intel/sst-baytrail-pcm.c')
-rw-r--r--sound/soc/intel/sst-baytrail-pcm.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c
index 6d101f3813b4..b8a89e9f753d 100644
--- a/sound/soc/intel/sst-baytrail-pcm.c
+++ b/sound/soc/intel/sst-baytrail-pcm.c
@@ -45,6 +45,9 @@ struct sst_byt_pcm_data {
45 struct sst_byt_stream *stream; 45 struct sst_byt_stream *stream;
46 struct snd_pcm_substream *substream; 46 struct snd_pcm_substream *substream;
47 struct mutex mutex; 47 struct mutex mutex;
48
49 /* latest DSP DMA hw pointer */
50 u32 hw_ptr;
48}; 51};
49 52
50/* private data for the driver */ 53/* private data for the driver */
@@ -168,13 +171,19 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data)
168 struct snd_pcm_substream *substream = pcm_data->substream; 171 struct snd_pcm_substream *substream = pcm_data->substream;
169 struct snd_pcm_runtime *runtime = substream->runtime; 172 struct snd_pcm_runtime *runtime = substream->runtime;
170 struct snd_soc_pcm_runtime *rtd = substream->private_data; 173 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171 u32 pos; 174 struct sst_byt_priv_data *pdata =
175 snd_soc_platform_get_drvdata(rtd->platform);
176 struct sst_byt *byt = pdata->byt;
177 u32 pos, hw_pos;
172 178
179 hw_pos = sst_byt_get_dsp_position(byt, pcm_data->stream,
180 snd_pcm_lib_buffer_bytes(substream));
181 pcm_data->hw_ptr = hw_pos;
173 pos = frames_to_bytes(runtime, 182 pos = frames_to_bytes(runtime,
174 (runtime->control->appl_ptr % 183 (runtime->control->appl_ptr %
175 runtime->buffer_size)); 184 runtime->buffer_size));
176 185
177 dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); 186 dev_dbg(rtd->dev, "PCM: App/DMA pointer %u/%u bytes\n", pos, hw_pos);
178 187
179 snd_pcm_period_elapsed(substream); 188 snd_pcm_period_elapsed(substream);
180 return pos; 189 return pos;
@@ -184,20 +193,11 @@ static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream
184{ 193{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data; 194 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_pcm_runtime *runtime = substream->runtime; 195 struct snd_pcm_runtime *runtime = substream->runtime;
187 struct sst_byt_priv_data *pdata =
188 snd_soc_platform_get_drvdata(rtd->platform);
189 struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); 196 struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
190 struct sst_byt *byt = pdata->byt;
191 snd_pcm_uframes_t offset;
192 int pos;
193 197
194 pos = sst_byt_get_dsp_position(byt, pcm_data->stream, 198 dev_dbg(rtd->dev, "PCM: DMA pointer %u bytes\n", pcm_data->hw_ptr);
195 snd_pcm_lib_buffer_bytes(substream));
196 offset = bytes_to_frames(runtime, pos);
197 199
198 dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", 200 return bytes_to_frames(runtime, pcm_data->hw_ptr);
199 frames_to_bytes(runtime, (u32)offset));
200 return offset;
201} 201}
202 202
203static int sst_byt_pcm_open(struct snd_pcm_substream *substream) 203static int sst_byt_pcm_open(struct snd_pcm_substream *substream)