static int hsw_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(rtd->platform); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; pcm_data = &pdata->pcm[rtd->cpu_dai->id]; mutex_lock(&pcm_data->mutex); snd_soc_pcm_set_drvdata(rtd, pcm_data); pcm_data->substream = substream; snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware); pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, hsw_notify_pointer, pcm_data); if (pcm_data->stream == NULL) { dev_err(rtd->dev, "error: failed to create stream\n"); mutex_unlock(&pcm_data->mutex); 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; }
static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); struct hsw_pcm_data *pcm_data; struct sst_hsw *hsw = pdata->hsw; u32 volume; int dai, stream; dai = mod_map[mc->reg].dai_id; stream = mod_map[mc->reg].stream; pcm_data = &pdata->pcm[dai][stream]; mutex_lock(&pcm_data->mutex); pm_runtime_get_sync(pdata->dev); if (!pcm_data->stream) { pcm_data->volume[0] = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); pcm_data->volume[1] = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); pm_runtime_mark_last_busy(pdata->dev); pm_runtime_put_autosuspend(pdata->dev); mutex_unlock(&pcm_data->mutex); return 0; } if (ucontrol->value.integer.value[0] == ucontrol->value.integer.value[1]) { volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); /* 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); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 1, volume); } pm_runtime_mark_last_busy(pdata->dev); pm_runtime_put_autosuspend(pdata->dev); mutex_unlock(&pcm_data->mutex); return 0; }
static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; struct sst_hsw *hsw = pdata->hsw; u32 volume; mutex_lock(&pcm_data->mutex); if (!pcm_data->stream) { pcm_data->volume[0] = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); pcm_data->volume[1] = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); mutex_unlock(&pcm_data->mutex); return 0; } 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); } else { volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume); volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 1, volume); } mutex_unlock(&pcm_data->mutex); return 0; }