ASoC: Intel: Fix stream volume set no effect issue on Broadwell

The volume setting control for capture stream doesn't take effect on intel
Broadwell platform. Root cause it at 2 points:
1. set stream volume with channel=2 is wrongly bapassed;
2. the saved stream volume should be restored after stream is commit.

Here correct these 2 items to fix the stream volume set issue.

Signed-off-by: Jie Yang <yang.jie@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Jie Yang 2014-11-25 21:00:53 +08:00 committed by Mark Brown
parent 14cd792312
commit f1e5982546
3 changed files with 39 additions and 18 deletions

View File

@ -1042,14 +1042,9 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
trace_ipc_request("set stream volume", stream->reply.stream_hw_id); trace_ipc_request("set stream volume", stream->reply.stream_hw_id);
if (channel > 1) if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL)
return -EINVAL; return -EINVAL;
if (stream->mute[channel]) {
stream->mute_volume[channel] = volume;
return 0;
}
header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE);
header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT);
@ -1057,9 +1052,28 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
header |= (stage_id << IPC_STG_ID_SHIFT); header |= (stage_id << IPC_STG_ID_SHIFT);
req = &stream->vol_req; req = &stream->vol_req;
req->channel = channel;
req->target_volume = volume; req->target_volume = volume;
/* set both at same time ? */
if (channel == SST_HSW_CHANNELS_ALL) {
if (hsw->mute[0] && hsw->mute[1]) {
hsw->mute_volume[0] = hsw->mute_volume[1] = volume;
return 0;
} else if (hsw->mute[0])
req->channel = 1;
else if (hsw->mute[1])
req->channel = 0;
else
req->channel = SST_HSW_CHANNELS_ALL;
} else {
/* set only 1 channel */
if (hsw->mute[channel]) {
hsw->mute_volume[channel] = volume;
return 0;
}
req->channel = channel;
}
ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0); ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0);
if (ret < 0) { if (ret < 0) {
dev_err(hsw->dev, "error: set stream volume failed\n"); dev_err(hsw->dev, "error: set stream volume failed\n");
@ -1138,8 +1152,11 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
trace_ipc_request("set mixer volume", volume); trace_ipc_request("set mixer volume", volume);
if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL)
return -EINVAL;
/* set both at same time ? */ /* set both at same time ? */
if (channel == 2) { if (channel == SST_HSW_CHANNELS_ALL) {
if (hsw->mute[0] && hsw->mute[1]) { if (hsw->mute[0] && hsw->mute[1]) {
hsw->mute_volume[0] = hsw->mute_volume[1] = volume; hsw->mute_volume[0] = hsw->mute_volume[1] = volume;
return 0; return 0;
@ -1148,7 +1165,7 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
else if (hsw->mute[1]) else if (hsw->mute[1])
req.channel = 0; req.channel = 0;
else else
req.channel = 0xffffffff; req.channel = SST_HSW_CHANNELS_ALL;
} else { } else {
/* set only 1 channel */ /* set only 1 channel */
if (hsw->mute[channel]) { if (hsw->mute[channel]) {

View File

@ -24,6 +24,7 @@
#define SST_HSW_NO_CHANNELS 4 #define SST_HSW_NO_CHANNELS 4
#define SST_HSW_MAX_DX_REGIONS 14 #define SST_HSW_MAX_DX_REGIONS 14
#define SST_HSW_DX_CONTEXT_SIZE (640 * 1024) #define SST_HSW_DX_CONTEXT_SIZE (640 * 1024)
#define SST_HSW_CHANNELS_ALL 0xffffffff
#define SST_HSW_FW_LOG_CONFIG_DWORDS 12 #define SST_HSW_FW_LOG_CONFIG_DWORDS 12
#define SST_HSW_GLOBAL_LOG 15 #define SST_HSW_GLOBAL_LOG 15

View File

@ -189,7 +189,8 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] == if (ucontrol->value.integer.value[0] ==
ucontrol->value.integer.value[1]) { ucontrol->value.integer.value[1]) {
volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]);
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 2, volume); /* apply volume value to all channels */
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, SST_HSW_CHANNELS_ALL, volume);
} else { } else {
volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]);
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume); sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume);
@ -255,7 +256,7 @@ static int hsw_volume_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[1]) { ucontrol->value.integer.value[1]) {
volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]);
sst_hsw_mixer_set_volume(hsw, 0, 2, volume); sst_hsw_mixer_set_volume(hsw, 0, SST_HSW_CHANNELS_ALL, volume);
} else { } else {
volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]);
@ -525,7 +526,15 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); dev_err(rtd->dev, "error: failed to commit stream %d\n", ret);
return ret; return ret;
} }
pcm_data->allocated = true;
if (!pcm_data->allocated) {
/* Set previous saved volume */
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0,
0, pcm_data->volume[0]);
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0,
1, pcm_data->volume[1]);
pcm_data->allocated = true;
}
ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1);
if (ret < 0) if (ret < 0)
@ -632,12 +641,6 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream)
return -EINVAL; return -EINVAL;
} }
/* Set previous saved volume */
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0,
0, pcm_data->volume[0]);
sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0,
1, pcm_data->volume[1]);
mutex_unlock(&pcm_data->mutex); mutex_unlock(&pcm_data->mutex);
return 0; return 0;
} }