Skip to content

Commit 7be10ce

Browse files
committed
ASoC: soc-pcm: tidyup soc_pcm_pointer()'s delay update method
Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>: Current soc_pcm_pointer() is checking runtime->delay, but it might be updated silently by component's .point callback. It is strange and difficult to find/know the issue. This patch adds .delay callback for component, and solve the issue.
2 parents 679de7b + dd894f4 commit 7be10ce

8 files changed

Lines changed: 95 additions & 40 deletions

File tree

include/sound/soc-component.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ struct snd_soc_component_driver {
148148
struct vm_area_struct *vma);
149149
int (*ack)(struct snd_soc_component *component,
150150
struct snd_pcm_substream *substream);
151+
snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
152+
struct snd_pcm_substream *substream);
151153

152154
const struct snd_compress_ops *compress_ops;
153155

@@ -505,5 +507,7 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
505507
void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
506508
void *stream, int rollback);
507509
int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
510+
void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
511+
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
508512

509513
#endif /* __SOC_COMPONENT_H */

include/sound/soc-dai.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,6 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai,
208208
struct snd_pcm_substream *substream);
209209
void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
210210
struct snd_pcm_substream *substream, int rollback);
211-
snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai,
212-
struct snd_pcm_substream *substream);
213211
void snd_soc_dai_suspend(struct snd_soc_dai *dai);
214212
void snd_soc_dai_resume(struct snd_soc_dai *dai);
215213
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
@@ -238,6 +236,8 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
238236
int rollback);
239237
int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
240238
int cmd);
239+
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
240+
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
241241

242242
int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
243243
struct snd_compr_stream *cstream);

sound/soc/amd/acp-pcm-dma.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
10031003

10041004
struct snd_pcm_runtime *runtime = substream->runtime;
10051005
struct audio_substream_data *rtd = runtime->private_data;
1006+
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
10061007

10071008
if (!rtd)
10081009
return -EINVAL;
@@ -1023,7 +1024,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
10231024
}
10241025
if (bytescount > 0) {
10251026
delay = do_div(bytescount, period_bytes);
1026-
runtime->delay = bytes_to_frames(runtime, delay);
1027+
adata->delay += bytes_to_frames(runtime, delay);
10271028
}
10281029
} else {
10291030
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
@@ -1035,6 +1036,17 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
10351036
return bytes_to_frames(runtime, pos);
10361037
}
10371038

1039+
static snd_pcm_sframes_t acp_dma_delay(struct snd_soc_component *component,
1040+
struct snd_pcm_substream *substream)
1041+
{
1042+
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
1043+
snd_pcm_sframes_t delay = adata->delay;
1044+
1045+
adata->delay = 0;
1046+
1047+
return delay;
1048+
}
1049+
10381050
static int acp_dma_prepare(struct snd_soc_component *component,
10391051
struct snd_pcm_substream *substream)
10401052
{
@@ -1198,6 +1210,7 @@ static const struct snd_soc_component_driver acp_asoc_platform = {
11981210
.hw_params = acp_dma_hw_params,
11991211
.trigger = acp_dma_trigger,
12001212
.pointer = acp_dma_pointer,
1213+
.delay = acp_dma_delay,
12011214
.prepare = acp_dma_prepare,
12021215
.pcm_construct = acp_dma_new,
12031216
};

sound/soc/amd/acp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ struct audio_drv_data {
151151
struct snd_pcm_substream *capture_i2sbt_stream;
152152
void __iomem *acp_mmio;
153153
u32 asic_type;
154+
snd_pcm_sframes_t delay;
154155
};
155156

156157
/*

sound/soc/intel/atom/sst-mfld-platform-pcm.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,10 +653,21 @@ static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component,
653653
dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
654654
return ret_val;
655655
}
656-
substream->runtime->delay = str_info->pcm_delay;
657656
return str_info->buffer_ptr;
658657
}
659658

659+
static snd_pcm_sframes_t sst_soc_delay(struct snd_soc_component *component,
660+
struct snd_pcm_substream *substream)
661+
{
662+
struct sst_runtime_stream *stream = substream->runtime->private_data;
663+
struct pcm_stream_info *str_info = &stream->stream_info;
664+
665+
if (sst_get_stream_status(stream) == SST_PLATFORM_INIT)
666+
return 0;
667+
668+
return str_info->pcm_delay;
669+
}
670+
660671
static int sst_soc_pcm_new(struct snd_soc_component *component,
661672
struct snd_soc_pcm_runtime *rtd)
662673
{
@@ -695,6 +706,7 @@ static const struct snd_soc_component_driver sst_soc_platform_drv = {
695706
.open = sst_soc_open,
696707
.trigger = sst_soc_trigger,
697708
.pointer = sst_soc_pointer,
709+
.delay = sst_soc_delay,
698710
.compress_ops = &sst_platform_compress_ops,
699711
.pcm_construct = sst_soc_pcm_new,
700712
};

sound/soc/soc-component.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,34 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
932932
return 0;
933933
}
934934

935+
void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
936+
snd_pcm_sframes_t *cpu_delay,
937+
snd_pcm_sframes_t *codec_delay)
938+
{
939+
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
940+
struct snd_soc_component *component;
941+
snd_pcm_sframes_t delay;
942+
int i;
943+
944+
/*
945+
* We're looking for the delay through the full audio path so it needs to
946+
* be the maximum of the Components doing transmit and the maximum of the
947+
* Components doing receive (ie, all CPUs and all CODECs) rather than
948+
* just the maximum of all Components.
949+
*/
950+
for_each_rtd_components(rtd, i, component) {
951+
if (!component->driver->delay)
952+
continue;
953+
954+
delay = component->driver->delay(component, substream);
955+
956+
if (snd_soc_component_is_codec(component))
957+
*codec_delay = max(*codec_delay, delay);
958+
else
959+
*cpu_delay = max(*cpu_delay, delay);
960+
}
961+
}
962+
935963
int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
936964
unsigned int cmd, void *arg)
937965
{

sound/soc/soc-dai.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -453,18 +453,6 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
453453
soc_dai_mark_pop(dai, substream, startup);
454454
}
455455

456-
snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai,
457-
struct snd_pcm_substream *substream)
458-
{
459-
int delay = 0;
460-
461-
if (dai->driver->ops &&
462-
dai->driver->ops->delay)
463-
delay = dai->driver->ops->delay(substream, dai);
464-
465-
return delay;
466-
}
467-
468456
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
469457
struct snd_soc_pcm_runtime *rtd, int num)
470458
{
@@ -693,6 +681,34 @@ int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
693681
return 0;
694682
}
695683

684+
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
685+
snd_pcm_sframes_t *cpu_delay,
686+
snd_pcm_sframes_t *codec_delay)
687+
{
688+
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
689+
struct snd_soc_dai *dai;
690+
int i;
691+
692+
/*
693+
* We're looking for the delay through the full audio path so it needs to
694+
* be the maximum of the DAIs doing transmit and the maximum of the DAIs
695+
* doing receive (ie, all CPUs and all CODECs) rather than just the maximum
696+
* of all DAIs.
697+
*/
698+
699+
/* for CPU */
700+
for_each_rtd_cpu_dais(rtd, i, dai)
701+
if (dai->driver->ops &&
702+
dai->driver->ops->delay)
703+
*cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
704+
705+
/* for Codec */
706+
for_each_rtd_codec_dais(rtd, i, dai)
707+
if (dai->driver->ops &&
708+
dai->driver->ops->delay)
709+
*codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
710+
}
711+
696712
int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
697713
struct snd_compr_stream *cstream)
698714
{

sound/soc/soc-pcm.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,41 +1080,22 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
10801080
/*
10811081
* soc level wrapper for pointer callback
10821082
* If cpu_dai, codec_dai, component driver has the delay callback, then
1083-
* the runtime->delay will be updated accordingly.
1083+
* the runtime->delay will be updated via snd_soc_pcm_component/dai_delay().
10841084
*/
10851085
static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
10861086
{
1087-
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1088-
struct snd_soc_dai *cpu_dai;
1089-
struct snd_soc_dai *codec_dai;
10901087
struct snd_pcm_runtime *runtime = substream->runtime;
10911088
snd_pcm_uframes_t offset = 0;
1092-
snd_pcm_sframes_t delay = 0;
10931089
snd_pcm_sframes_t codec_delay = 0;
10941090
snd_pcm_sframes_t cpu_delay = 0;
1095-
int i;
1096-
1097-
/* clearing the previous total delay */
1098-
runtime->delay = 0;
10991091

11001092
offset = snd_soc_pcm_component_pointer(substream);
11011093

1102-
/* base delay if assigned in pointer callback */
1103-
delay = runtime->delay;
1104-
1105-
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
1106-
cpu_delay = max(cpu_delay,
1107-
snd_soc_dai_delay(cpu_dai, substream));
1108-
}
1109-
delay += cpu_delay;
1110-
1111-
for_each_rtd_codec_dais(rtd, i, codec_dai) {
1112-
codec_delay = max(codec_delay,
1113-
snd_soc_dai_delay(codec_dai, substream));
1114-
}
1115-
delay += codec_delay;
1094+
/* should be called *after* snd_soc_pcm_component_pointer() */
1095+
snd_soc_pcm_dai_delay(substream, &cpu_delay, &codec_delay);
1096+
snd_soc_pcm_component_delay(substream, &cpu_delay, &codec_delay);
11161097

1117-
runtime->delay = delay;
1098+
runtime->delay = cpu_delay + codec_delay;
11181099

11191100
return offset;
11201101
}

0 commit comments

Comments
 (0)