Skip to content

Commit 260f795

Browse files
committed
Volume: Use min and max volume scale values from IPC
This patch adds feature to retrieve volume scale min and max from IPC if the parameters are set. Volume min and max are now used with ramp time parameter to compute gain ramp step to achieve constant rate ramps with any volume scale. If the min and max are zeros the previous FW operation is preserved. Previously the firmware did not know the volume range so the volume code uses in volume request a check to prevent exceeding ramp length specified in topology by step size re-adjust. It was done to prevent very long ramps to happen with volume scales with large gain. However the smaller transitions remained longer than necessary. This patch fixes that last remaining issue. The ramp length check code is preserved to be compatible with kernel versions those do not provide the min and max volume scale values. When provided the check code has no impact. The patch includes some cosmetic re-arranging of volume comp data struct fields in addition to adding new the fields vol_ramp_range, vol_min, and vol_max. Also error traces were added to notify if the volume min/max or request has been limited to fit to supported volume range. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent a2fa79f commit 260f795

2 files changed

Lines changed: 73 additions & 13 deletions

File tree

src/audio/volume/volume.c

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static uint64_t vol_work(void *data)
8383
vol += cd->ramp_increment[i];
8484
if (cd->volume[i] < cd->tvolume[i]) {
8585
/* ramp up, check if ramp completed */
86-
if (vol >= cd->tvolume[i] || vol >= VOL_MAX) {
86+
if (vol >= cd->tvolume[i] || vol >= cd->vol_max) {
8787
vol_update(cd, i);
8888
} else {
8989
cd->volume[i] = vol;
@@ -96,7 +96,8 @@ static uint64_t vol_work(void *data)
9696
vol_update(cd, i);
9797
} else {
9898
/* ramp completed ? */
99-
if (vol <= cd->tvolume[i] || vol <= VOL_MIN) {
99+
if (vol <= cd->tvolume[i] ||
100+
vol <= cd->vol_min) {
100101
vol_update(cd, i);
101102
} else {
102103
cd->volume[i] = vol;
@@ -157,14 +158,53 @@ static struct comp_dev *volume_new(struct sof_ipc_comp *comp)
157158
schedule_task_init(&cd->volwork, SOF_SCHEDULE_LL, SOF_TASK_PRI_MED,
158159
vol_work, dev, 0, 0);
159160

160-
/* set the default volumes */
161+
/* Set the default volumes. If IPC sets min_value or max_value to
162+
* not-zero, use them. Otherwise set to internal limits and notify
163+
* ramp step calculation about assumed range with the range set to
164+
* zero.
165+
*/
166+
if (vol->min_value || vol->max_value) {
167+
if (vol->min_value < VOL_MIN) {
168+
/* Use VOL_MIN instead, no need to stop new(). */
169+
cd->vol_min = VOL_MIN;
170+
trace_volume_error("volume_new(): vol->min_value "
171+
"was limited to VOL_MIN.");
172+
} else {
173+
cd->vol_min = vol->min_value;
174+
}
175+
176+
if (vol->max_value > VOL_MAX) {
177+
/* Use VOL_MAX instead, no need to stop new(). */
178+
cd->vol_max = VOL_MAX;
179+
trace_volume_error("volume_new(): vol->max_value "
180+
"was limited to VOL_MAX.");
181+
} else {
182+
cd->vol_max = vol->max_value;
183+
}
184+
185+
cd->vol_ramp_range = vol->max_value - vol->min_value;
186+
} else {
187+
/* Legacy mode, set the limits to firmware capability where
188+
* VOL_MAX is a very large gain to avoid restricting valid
189+
* requests. The default ramp rate will be computed based
190+
* on 0 - 1.0 gain range assumption when vol_ramp_range
191+
* is set to 0.
192+
*/
193+
cd->vol_min = VOL_MIN;
194+
cd->vol_max = VOL_MAX;
195+
cd->vol_ramp_range = 0;
196+
}
197+
161198
for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
162-
cd->volume[i] = MAX(MIN(VOL_MAX, VOL_ZERO_DB), VOL_MIN);
199+
cd->volume[i] = MAX(MIN(cd->vol_max, VOL_ZERO_DB),
200+
cd->vol_min);
163201
cd->tvolume[i] = cd->volume[i];
164202
}
165203

166-
trace_volume("vol->initial_ramp = %d, vol->ramp = %d",
167-
vol->initial_ramp, vol->ramp);
204+
trace_volume("vol->initial_ramp = %d, vol->ramp = %d, "
205+
"vol->min_value = %d, vol->max_value = %d",
206+
vol->initial_ramp, vol->ramp,
207+
vol->min_value, vol->max_value);
168208

169209
dev->state = COMP_STATE_READY;
170210
return dev;
@@ -220,11 +260,19 @@ static inline int volume_set_chan(struct comp_dev *dev, int chan, uint32_t vol)
220260
* multiplication overflow with the 32 bit value. Non-zero MIN option
221261
* can be useful to prevent totally muted small volume gain.
222262
*/
223-
if (v <= VOL_MIN)
263+
if (v <= VOL_MIN) {
264+
/* No need to fail, just trace the event. */
265+
trace_volume_error("volume_set_chan: Limited request %d to "
266+
"VOL_MIN.", v);
224267
v = VOL_MIN;
268+
}
225269

226-
if (v > VOL_MAX)
270+
if (v > VOL_MAX) {
271+
/* No need to fail, just trace the event. */
272+
trace_volume_error("volume_set_chan: Limited request %d to "
273+
"VOL_MAX.", v);
227274
v = VOL_MAX;
275+
}
228276

229277
cd->tvolume[chan] = v;
230278

@@ -242,6 +290,15 @@ static inline int volume_set_chan(struct comp_dev *dev, int chan, uint32_t vol)
242290
else
243291
inc = VOL_ZERO_DB;
244292

293+
/* Scale the increment with actual volume range if it was
294+
* passed via IPC.
295+
*/
296+
if (cd->vol_ramp_range)
297+
inc = q_multsr_32x32(inc, cd->vol_ramp_range,
298+
Q_SHIFT_BITS_32(VOL_QXY_Y,
299+
VOL_QXY_Y,
300+
VOL_QXY_Y));
301+
245302
delta = cd->tvolume[chan] - cd->volume[chan];
246303
delta_abs = ABS(delta);
247304

src/include/sof/audio/volume.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,20 @@
8585
* Gain amplitude value is between 0 (mute) ... 2^16 (0dB) ... 2^24 (~+48dB).
8686
*/
8787
struct comp_data {
88-
enum sof_ipc_frame source_format; /**< source frame format */
89-
enum sof_ipc_frame sink_format; /**< sink frame format */
88+
struct task volwork; /**< volume scheduled work function */
89+
struct sof_ipc_ctrl_value_chan *hvol; /**< host volume readback */
9090
int32_t volume[SOF_IPC_MAX_CHANNELS]; /**< current volume */
9191
int32_t tvolume[SOF_IPC_MAX_CHANNELS]; /**< target volume */
9292
int32_t mvolume[SOF_IPC_MAX_CHANNELS]; /**< mute volume */
93+
int32_t ramp_increment[SOF_IPC_MAX_CHANNELS]; /**< for linear ramp */
94+
int32_t vol_min; /**< minimum volume */
95+
int32_t vol_max; /**< maximum volume */
96+
int32_t vol_ramp_range; /**< max ramp transition */
97+
enum sof_ipc_frame source_format; /**< source frame format */
98+
enum sof_ipc_frame sink_format; /**< sink frame format */
9399
/**< volume processing function */
94100
void (*scale_vol)(struct comp_dev *dev, struct comp_buffer *sink,
95101
struct comp_buffer *source, uint32_t frames);
96-
struct task volwork; /**< volume scheduled work function */
97-
struct sof_ipc_ctrl_value_chan *hvol; /**< host volume readback */
98-
int32_t ramp_increment[SOF_IPC_MAX_CHANNELS]; /**< for linear ramp */
99102
};
100103

101104
/** \brief Volume processing functions map. */

0 commit comments

Comments
 (0)