You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] IPC4 volume windows ramp was broken with latest sof-dev kernel and sof firmware #4026
Describe the bug
When volume change, volume ramp should take effect, however, from debug, never see ramp is happening, from sof side, finally find the cdata from kernel driver have random value, no the ramp time.
To Reproduce
build sof with ipc4 with logs inserted in volume ramp.
run it on test machine.
aplay a wav file.
enable mtrace and adjust volume with alsamixer, inserted log never come out.
Reproduction Rate
100%
Expected behavior
volume ramp should happen, and cdata should be right.
Impact
volume ramp missed, pop noise come when volume change.
Environment
Branch name and commit hash of the 2 repositories: sof (firmware/topology) and linux (kernel driver).
Kernel: latest
SOF: latest
Name of the topology file
Topology: cavs_sdw.tplg
Name of the platform(s) on which the bug is observed.
structsof_ipc4_gain_data {
uint32_tchannels;
uint32_tinit_val;
uint32_tcurve_type;
uint32_treserved;
uint32_tcurve_duration;
// compiler will allocate more u32 memory to aligned(8)
} __aligned(8);
But FW adopts a new version
structipc4_peak_volume_config {
uint32_tchannel_id;
uint32_ttarget_volume;
uint32_tcurve_type;
uint32_treserved;
/** * Curve duration in number of hundreds nanoseconds for format specified during * initialization. */uint64_tcurve_duration;
} __packed__aligned(8);
Change definition is simple but how to deal with token reader since the curve_duration is retrieved from topology. Current our get_token only support return value of int. And does topology support u64 token size ?
structsof_topology_token {
u32token;
u32type;
int (*get_token)(void*elem, void*object, u32offset);
u32offset;
};
Can we define u32 curve_duration_u and curve_duration_l in driver header file and also change topology definition ? then we don't have trouble with u64 in both topology and driver side ?
There is volume_check_levels.sh in sof-test for nocodec topologies. I've just set improvements PR to it to be more robust against control timing jitter. The driver changes have cause more delay to controls to happen vs. the time when I first developed the test. It would be great to get CI to run it.
There is volume_check_levels.sh in sof-test for nocodec topologies. I've just set improvements PR to it to be more robust against control timing jitter.
@RanderWang so is the problem that we retrieve a curve duration from topology as a u32, but the firmware expects a u64? In terms of endianess that should work.
Or that the firmware expects different definitions for the duration? I see this in the firmware commit message
- curve duration format is in hundred of ns (ipc4) and ms (ip3);
I don't know why anyone would want a ramp duration in ns... That's completely overkill. even micro-seconds would be too fine grained given the audio sampling rates.
A simple fix would be to multiple the curve duration by 10e6, e.g.
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 10189b6428c24..d8a4b00631191 100644
--- a/sound/soc/sof/ipc4-topology.c+++ b/sound/soc/sof/ipc4-topology.c@@ -680,6 +680,9 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
gain->data.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
gain->data.init_val = SOF_IPC4_VOL_ZERO_DB;
+ /* volume ramps are defined in 100 of nsec for IPC4 */+ gain->data.curve_duration *= (NSEC_PER_MSEC / 100);+
/* The out_audio_fmt in topology is ignored as it is not required to be sent to the FW */
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &gain->available_fmt, false);
if (ret)
The other parameters look identical to me or are overridden by the driver
@plbossart thanks for your feedback. so u32 is enough to support ramp feature. The key issue is caused by the set volume data.
(1) sizeof(struct sof_ipc4_gain_data data) = 6 * 32bits, one of 32bits is padded by compiler to align 8.
(2) currently we don't clear "struct sof_ipc4_gain_data data" to zero and only set curve_duration as 32bits, so the padded 32bits is full of garbage, 0xffffffff as I printed
(3) in fw curve_duration is 64bits data, so its value is 0xffffffff0000xxxx, so huge and result to panic
since u32 can support up to 100000ms and we can just clear "struct sof_ipc4_gain_data data" to zero in the sof_ipc4_set_volume_data function and only use u32 data.
structsof_ipc4_gain_data {
uint32_tchannels;
uint32_tinit_val;
uint32_tcurve_type;
uint32_treserved;
uint32_tcurve_duration;
} __aligned(8);
sof_ipc4_set_volume_data(structsnd_sof_dev*sdev, structsnd_sof_widget*swidget,
structsnd_sof_control*scontrol)
{
...
structsof_ipc4_gain_datadata;
...
for (i=0; i<scontrol->num_channels; i++) {
if (all_channels_equal) {
data.channels=SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
data.init_val=cdata->chanv[0].value;
} else {
data.channels=cdata->chanv[i].channel;
data.init_val=cdata->chanv[i].value;
}
/* set curve type and duration from topology */data.curve_duration=gain->data.curve_duration;
data.curve_type=gain->data.curve_type;
....
}
return0;
}
Activity
RanderWang commentedon Nov 18, 2022
good finding! we lack volume change test
RanderWang commentedon Nov 18, 2022
@plbossart @ujfalusi @ranj063. This issue is caused by driver used an old version of gain ipc msg.
But FW adopts a new version
Change definition is simple but how to deal with token reader since the curve_duration is retrieved from topology. Current our get_token only support return value of int. And does topology support u64 token size ?
Can we define u32 curve_duration_u and curve_duration_l in driver header file and also change topology definition ? then we don't have trouble with u64 in both topology and driver side ?
Welcome to give suggestion.
plbossart commentedon Nov 18, 2022
@RanderWang are we talking about the same functionality? the peak volume is typically to REPORT the volume level from the stream, not SET the gain.
RanderWang commentedon Nov 21, 2022
@plbossart Peak volume has two modes. The gain mode doesn't report volume level. Sof uses gain now.
singalsu commentedon Nov 25, 2022
There is volume_check_levels.sh in sof-test for nocodec topologies. I've just set improvements PR to it to be more robust against control timing jitter. The driver changes have cause more delay to controls to happen vs. the time when I first developed the test. It would be great to get CI to run it.
@marc-hb @aiChaoSONG
marc-hb commentedon Nov 28, 2022
I'm guessing thesofproject/sof-test#985
BTW there's another volume test fix that has been in review for a (too?) long time:
plbossart commentedon Nov 28, 2022
@RanderWang so is the problem that we retrieve a curve duration from topology as a u32, but the firmware expects a u64? In terms of endianess that should work.
Or that the firmware expects different definitions for the duration? I see this in the firmware commit message
I don't know why anyone would want a ramp duration in ns... That's completely overkill. even micro-seconds would be too fine grained given the audio sampling rates.
A simple fix would be to multiple the curve duration by 10e6, e.g.
The other parameters look identical to me or are overridden by the driver
RanderWang commentedon Nov 29, 2022
@plbossart thanks for your feedback. so u32 is enough to support ramp feature. The key issue is caused by the set volume data.
(1) sizeof(struct sof_ipc4_gain_data data) = 6 * 32bits, one of 32bits is padded by compiler to align 8.
(2) currently we don't clear "struct sof_ipc4_gain_data data" to zero and only set curve_duration as 32bits, so the padded 32bits is full of garbage, 0xffffffff as I printed
(3) in fw curve_duration is 64bits data, so its value is 0xffffffff0000xxxx, so huge and result to panic
since u32 can support up to 100000ms and we can just clear "struct sof_ipc4_gain_data data" to zero in the sof_ipc4_set_volume_data function and only use u32 data.
aiChaoSONG commentedon Nov 29, 2022
what about windows compatibility? I think windows driver will send a u64 value, right?
76 remaining items
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw
ASoC: SOF: IPC4: update gain ipc msg definition to align with fw