Repository navigation
Volume: Fix handling of mute and unmute control #2196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,6 +81,8 @@ static enum task_state vol_work(void *data) | |
| int again = 0; | ||
| int i; | ||
|
|
||
| cd->vol_ramp_active = true; | ||
|
|
||
| /* inc/dec each volume if it's not at target */ | ||
| for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { | ||
| /* skip if target reached */ | ||
|
|
@@ -96,6 +98,7 @@ static enum task_state vol_work(void *data) | |
| /* ramp up, check if ramp completed */ | ||
| if (vol >= cd->tvolume[i] || vol >= cd->vol_max) { | ||
| vol_update(cd, i); | ||
| cd->ramp_increment[i] = 0; | ||
| } else { | ||
| cd->volume[i] = vol; | ||
| again = 1; | ||
|
|
@@ -105,11 +108,13 @@ static enum task_state vol_work(void *data) | |
| if (vol <= 0) { | ||
| /* cannot ramp down below 0 */ | ||
| vol_update(cd, i); | ||
| cd->ramp_increment[i] = 0; | ||
| } else { | ||
| /* ramp completed ? */ | ||
| if (vol <= cd->tvolume[i] || | ||
| vol <= cd->vol_min) { | ||
| vol_update(cd, i); | ||
| cd->ramp_increment[i] = 0; | ||
| } else { | ||
| cd->volume[i] = vol; | ||
| again = 1; | ||
|
|
@@ -122,7 +127,11 @@ static enum task_state vol_work(void *data) | |
| } | ||
|
|
||
| /* do we need to continue ramping */ | ||
| return again ? SOF_TASK_STATE_RESCHEDULE : SOF_TASK_STATE_COMPLETED; | ||
| if (again) | ||
| return SOF_TASK_STATE_RESCHEDULE; | ||
|
|
||
| cd->vol_ramp_active = 0; | ||
| return SOF_TASK_STATE_COMPLETED; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -212,9 +221,12 @@ static struct comp_dev *volume_new(struct sof_ipc_comp *comp) | |
| for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { | ||
| cd->volume[i] = MAX(MIN(cd->vol_max, VOL_ZERO_DB), | ||
| cd->vol_min); | ||
| cd->tvolume[i] = cd->volume[i]; | ||
| cd->tvolume[i] = cd->volume[i]; | ||
| cd->mvolume[i] = cd->volume[i]; | ||
| cd->muted[i] = false; | ||
| } | ||
|
|
||
| cd->vol_ramp_active = false; | ||
| trace_volume_with_ids(dev, | ||
| "vol->initial_ramp = %d, vol->ramp = %d, " | ||
| "vol->min_value = %d, vol->max_value = %d", | ||
|
|
@@ -360,10 +372,11 @@ static inline void volume_set_chan_mute(struct comp_dev *dev, int chan) | |
| { | ||
| struct comp_data *cd = comp_get_drvdata(dev); | ||
|
|
||
| /* Check if not muted already */ | ||
| if (cd->volume[chan] != 0) | ||
| cd->mvolume[chan] = cd->volume[chan]; | ||
| cd->tvolume[chan] = 0; | ||
| if (!cd->muted[chan]) { | ||
| cd->mvolume[chan] = cd->tvolume[chan]; | ||
| volume_set_chan(dev, chan, 0); | ||
| cd->muted[chan] = true; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -375,9 +388,10 @@ static inline void volume_set_chan_unmute(struct comp_dev *dev, int chan) | |
| { | ||
| struct comp_data *cd = comp_get_drvdata(dev); | ||
|
|
||
| /* Check if muted */ | ||
| if (cd->volume[chan] == 0) | ||
| cd->tvolume[chan] = cd->mvolume[chan]; | ||
| if (cd->muted[chan]) { | ||
| cd->muted[chan] = false; | ||
| volume_set_chan(dev, chan, cd->mvolume[chan]); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -390,7 +404,8 @@ static int volume_ctrl_set_cmd(struct comp_dev *dev, | |
| struct sof_ipc_ctrl_data *cdata) | ||
| { | ||
| struct comp_data *cd = comp_get_drvdata(dev); | ||
| int i; | ||
| uint32_t val; | ||
| int ch; | ||
| int j; | ||
| int ret = 0; | ||
|
|
||
|
|
@@ -408,57 +423,56 @@ static int volume_ctrl_set_cmd(struct comp_dev *dev, | |
| "cdata->comp_id = %u", | ||
| cdata->comp_id); | ||
| for (j = 0; j < cdata->num_elems; j++) { | ||
| trace_volume_with_ids(dev, "volume_ctrl_set_cmd(), " | ||
| "SOF_CTRL_CMD_VOLUME, " | ||
| "channel = %u, value = %u", | ||
| cdata->chanv[j].channel, | ||
| cdata->chanv[j].value); | ||
| i = cdata->chanv[j].channel; | ||
| if (i >= 0 && i < SOF_IPC_MAX_CHANNELS) { | ||
| ret = volume_set_chan(dev, i, | ||
| cdata->chanv[j].value); | ||
| } else { | ||
| ch = cdata->chanv[j].channel; | ||
| val = cdata->chanv[j].value; | ||
| trace_volume_with_ids(dev, "volume_ctrl_set_cmd(), channel = %d" | ||
| ", value = %u", ch, val); | ||
| if (ch < 0 || ch >= SOF_IPC_MAX_CHANNELS) { | ||
| trace_volume_error_with_ids(dev, | ||
| "volume_ctrl_set_cmd() " | ||
| "error: " | ||
| "SOF_CTRL_CMD_VOLUME, " | ||
| "invalid i = %u", | ||
| i); | ||
| "volume_ctrl_set_cmd(), illegal channel = %d", | ||
| ch); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we need to error out in this case? If we do, I'd revert the test to do
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe some
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| return -EINVAL; | ||
| } | ||
|
|
||
| if (cd->muted[ch]) { | ||
| cd->mvolume[ch] = val; | ||
| } else { | ||
| ret = volume_set_chan(dev, ch, val); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also move the declaration here to make it clear that
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless I'm mistaken that's not done in SOF. I'll fix the typo any way, it's safe to change without need for me to re-test stuff.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| if (ret) | ||
| return ret; | ||
| } | ||
| if (ret) | ||
| return ret; | ||
| } | ||
|
|
||
| schedule_task(&cd->volwork, VOL_RAMP_UPDATE_US, | ||
| VOL_RAMP_UPDATE_US); | ||
| if (!cd->vol_ramp_active) | ||
| schedule_task(&cd->volwork, VOL_RAMP_UPDATE_US, | ||
| VOL_RAMP_UPDATE_US); | ||
| break; | ||
|
|
||
| case SOF_CTRL_CMD_SWITCH: | ||
| trace_volume_with_ids(dev, "volume_ctrl_set_cmd(), " | ||
| "SOF_CTRL_CMD_SWITCH, " | ||
| "cdata->comp_id = %u", cdata->comp_id); | ||
| for (j = 0; j < cdata->num_elems; j++) { | ||
| trace_volume_with_ids(dev, "volume_ctrl_set_cmd(), " | ||
| "SOF_CTRL_CMD_SWITCH, " | ||
| "channel = %u, value = %u", | ||
| cdata->chanv[j].channel, | ||
| cdata->chanv[j].value); | ||
| i = cdata->chanv[j].channel; | ||
| if (i >= 0 && i < SOF_IPC_MAX_CHANNELS) { | ||
| if (cdata->chanv[j].value) | ||
| volume_set_chan_unmute(dev, i); | ||
| else | ||
| volume_set_chan_mute(dev, i); | ||
| } else { | ||
| ch = cdata->chanv[j].channel; | ||
| val = cdata->chanv[j].value; | ||
| trace_volume_with_ids(dev, "volume_ctrl_set_cmd(), channel = %d" | ||
| ", value = %u", ch, val); | ||
| if (ch < 0 || ch >= SOF_IPC_MAX_CHANNELS) { | ||
| trace_volume_error_with_ids(dev, | ||
| "volume_ctrl_set_cmd() error: " | ||
| "SOF_CTRL_CMD_SWITCH, invalid i = %u", | ||
| i); | ||
| "volume_ctrl_set_cmd(), illegal channel = %d", | ||
| ch); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto for aborting and
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| return -EINVAL; | ||
| } | ||
|
|
||
| if (val) | ||
| volume_set_chan_unmute(dev, ch); | ||
| else | ||
| volume_set_chan_mute(dev, ch); | ||
| } | ||
|
|
||
| schedule_task(&cd->volwork, VOL_RAMP_UPDATE_US, | ||
| VOL_RAMP_UPDATE_US); | ||
| if (!cd->vol_ramp_active) | ||
| schedule_task(&cd->volwork, VOL_RAMP_UPDATE_US, | ||
| VOL_RAMP_UPDATE_US); | ||
| break; | ||
|
|
||
| default: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<rant> I find we use zero-initialising allocations (rzalloc()) exceedingly, sometimes also where they aren't really required, and then we also additionally initialise fields of the just allocated object with 0 or NULL of false... Seems strange to me </rant>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lyakh I'd find it safer than forgetting to zero-initialize where it's needed, for one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do whatever you recommend. I'm myself preferring to be explicit with things that need to be initialized. Let me know your preference.