diff options
author | Jie Yang <yang.jie@intel.com> | 2014-11-25 16:00:53 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-25 16:08:04 +0300 |
commit | f1e5982546edf96e4537ba689cfad83b90b70143 (patch) | |
tree | 7caa8f271e12b3351f3afe63b17156d7be73b068 /sound/soc/intel | |
parent | 14cd7923122c7c4473848f7c737604bfe945b81b (diff) | |
download | linux-f1e5982546edf96e4537ba689cfad83b90b70143.tar.xz |
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>
Diffstat (limited to 'sound/soc/intel')
-rw-r--r-- | sound/soc/intel/sst-haswell-ipc.c | 35 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-ipc.h | 1 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-pcm.c | 21 |
3 files changed, 39 insertions, 18 deletions
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index ffd5728d55c3..3f8c48231364 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -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); - if (channel > 1) + if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL) return -EINVAL; - if (stream->mute[channel]) { - stream->mute_volume[channel] = volume; - return 0; - } - header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); 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); req = &stream->vol_req; - req->channel = channel; 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); if (ret < 0) { 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); + if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL) + return -EINVAL; + /* set both at same time ? */ - if (channel == 2) { + if (channel == SST_HSW_CHANNELS_ALL) { if (hsw->mute[0] && hsw->mute[1]) { hsw->mute_volume[0] = hsw->mute_volume[1] = volume; 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]) req.channel = 0; else - req.channel = 0xffffffff; + req.channel = SST_HSW_CHANNELS_ALL; } else { /* set only 1 channel */ if (hsw->mute[channel]) { diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h index 387511f12d85..138e894ab413 100644 --- a/sound/soc/intel/sst-haswell-ipc.h +++ b/sound/soc/intel/sst-haswell-ipc.h @@ -24,6 +24,7 @@ #define SST_HSW_NO_CHANNELS 4 #define SST_HSW_MAX_DX_REGIONS 14 #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_GLOBAL_LOG 15 diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index e7a3b6af87ba..13c01002994e 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -189,7 +189,8 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] == ucontrol->value.integer.value[1]) { 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 { volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); 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]) { 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 { 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); 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); if (ret < 0) @@ -632,12 +641,6 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream) 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); return 0; } |