ASoC: Intel: Fix stream volume set no effect issue on Broadwell
authorJie Yang <yang.jie@intel.com>
Tue, 25 Nov 2014 13:00:53 +0000 (21:00 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 25 Nov 2014 13:08:04 +0000 (13:08 +0000)
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>
sound/soc/intel/sst-haswell-ipc.c
sound/soc/intel/sst-haswell-ipc.h
sound/soc/intel/sst-haswell-pcm.c

index ffd5728..3f8c482 100644 (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);
 
-       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]) {
index 387511f..138e894 100644 (file)
@@ -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
index e7a3b6a..13c0100 100644 (file)
@@ -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;
 }