ASoC: msm: Add volume support for compressed and pcm driver
Add support for controlling pcm and compressed audio
volume from DSP. Add TLV mixer control to set the pcm
and compressed audio stream volume. Enable soft volume
and soft pause features in pcm and compressed driver.
Change-Id: Ifea8faca39a92127fa91e880b904c0e60c92f9d0
Signed-off-by: Krishnankutty Kolathappilly <kkolat@codeaurora.org>
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 7d99322..11ac330 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -32,6 +32,12 @@
#include "msm-compr-q6.h"
#include "msm-pcm-routing.h"
+struct snd_msm {
+ struct msm_audio *prtd;
+ unsigned volume;
+};
+static struct snd_msm compressed_audio = {NULL, 0x2000} ;
+
static struct audio_locks the_locks;
static struct snd_pcm_hardware msm_compr_hardware_playback = {
@@ -281,6 +287,17 @@
struct compr_audio *compr;
struct msm_audio *prtd;
int ret = 0;
+ struct asm_softpause_params softpause = {
+ .enable = SOFT_PAUSE_ENABLE,
+ .period = SOFT_PAUSE_PERIOD,
+ .step = SOFT_PAUSE_STEP,
+ .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
+ };
+ struct asm_softvolume_params softvol = {
+ .period = SOFT_VOLUME_PERIOD,
+ .step = SOFT_VOLUME_STEP,
+ .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
+ };
/* Capture path */
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -327,10 +344,40 @@
compr->codec = FORMAT_MP3;
populate_codec_list(compr, runtime);
runtime->private_data = compr;
+ compressed_audio.prtd = &compr->prtd;
+ ret = compressed_set_volume(compressed_audio.volume);
+ if (ret < 0)
+ pr_err("%s : Set Volume failed : %d", __func__, ret);
+
+ ret = q6asm_set_softpause(compressed_audio.prtd->audio_client,
+ &softpause);
+ if (ret < 0)
+ pr_err("%s: Send SoftPause Param failed ret=%d\n",
+ __func__, ret);
+ ret = q6asm_set_softvolume(compressed_audio.prtd->audio_client,
+ &softvol);
+ if (ret < 0)
+ pr_err("%s: Send SoftVolume Param failed ret=%d\n",
+ __func__, ret);
return 0;
}
+int compressed_set_volume(unsigned volume)
+{
+ int rc = 0;
+ if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
+ rc = q6asm_set_volume(compressed_audio.prtd->audio_client,
+ volume);
+ if (rc < 0) {
+ pr_err("%s: Send Volume command failed"
+ " rc=%d\n", __func__, rc);
+ }
+ }
+ compressed_audio.volume = volume;
+ return rc;
+}
+
static int msm_compr_playback_close(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -344,6 +391,7 @@
dir = IN;
atomic_set(&prtd->pending_buffer, 0);
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ compressed_audio.prtd = NULL;
q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 1dac5d2..0a8282c 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -39,6 +39,12 @@
struct snd_pcm *pcm;
};
+struct snd_msm_volume {
+ struct msm_audio *prtd;
+ unsigned volume;
+};
+static struct snd_msm_volume multi_ch_pcm_audio = {NULL, 0x2000};
+
#define PLAYBACK_NUM_PERIODS 8
#define PLAYBACK_PERIOD_SIZE 4032
#define CAPTURE_NUM_PERIODS 16
@@ -303,6 +309,17 @@
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct msm_audio *prtd;
int ret = 0;
+ struct asm_softpause_params softpause = {
+ .enable = SOFT_PAUSE_ENABLE,
+ .period = SOFT_PAUSE_PERIOD,
+ .step = SOFT_PAUSE_STEP,
+ .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
+ };
+ struct asm_softvolume_params softvol = {
+ .period = SOFT_VOLUME_PERIOD,
+ .step = SOFT_VOLUME_STEP,
+ .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
+ };
pr_debug("%s\n", __func__);
prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
@@ -363,10 +380,46 @@
prtd->dsp_cnt = 0;
runtime->private_data = prtd;
+ pr_debug("substream->pcm->device = %d\n", substream->pcm->device);
+ pr_debug("soc_prtd->dai_link->be_id = %d\n", soc_prtd->dai_link->be_id);
+ multi_ch_pcm_audio.prtd = prtd;
+ ret = multi_ch_pcm_set_volume(multi_ch_pcm_audio.volume);
+ if (ret < 0)
+ pr_err("%s : Set Volume failed : %d", __func__, ret);
+
+ ret = q6asm_set_softpause(multi_ch_pcm_audio.prtd->audio_client,
+ &softpause);
+ if (ret < 0)
+ pr_err("%s: Send SoftPause Param failed ret=%d\n",
+ __func__, ret);
+ ret = q6asm_set_softvolume(multi_ch_pcm_audio.prtd->audio_client,
+ &softvol);
+ if (ret < 0)
+ pr_err("%s: Send SoftVolume Param failed ret=%d\n",
+ __func__, ret);
return 0;
}
+int multi_ch_pcm_set_volume(unsigned volume)
+{
+ int rc = 0;
+ pr_err("multi_ch_pcm_set_volume\n");
+
+ if (multi_ch_pcm_audio.prtd && multi_ch_pcm_audio.prtd->audio_client) {
+ pr_err("%s q6asm_set_volume\n", __func__);
+ rc = q6asm_set_volume(multi_ch_pcm_audio.prtd->audio_client,
+ volume);
+ if (rc < 0) {
+ pr_err("%s: Send Volume command failed"
+ " rc=%d\n", __func__, rc);
+ }
+ }
+ multi_ch_pcm_audio.volume = volume;
+ return rc;
+}
+
+
static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
{
@@ -447,6 +500,7 @@
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
+ multi_ch_pcm_audio.prtd = NULL;
q6asm_audio_client_free(prtd->audio_client);
kfree(prtd);
return 0;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index bce1455..1d5060d 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -54,12 +54,22 @@
static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
INT_FM_RX_VOL_MAX_STEPS, 0);
-#define INT_LPA_RX_VOL_MAX_STEPS 100
-#define INT_LPA_RX_VOL_GAIN 0x2000
+#define INT_RX_VOL_MAX_STEPS 100
+#define INT_RX_VOL_GAIN 0x2000
static int msm_route_lpa_vol_control;
static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
- INT_LPA_RX_VOL_MAX_STEPS, 0);
+ INT_RX_VOL_MAX_STEPS, 0);
+
+static int msm_route_multimedia2_vol_control;
+static const DECLARE_TLV_DB_SCALE(multimedia2_rx_vol_gain, 0,
+ INT_RX_VOL_MAX_STEPS, 0);
+
+static int msm_route_compressed_vol_control;
+static const DECLARE_TLV_DB_SCALE(compressed_rx_vol_gain, 0,
+ INT_RX_VOL_MAX_STEPS, 0);
+
+
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
#define MAX_EQ_SESSIONS MSM_FRONTEND_DAI_CS_VOICE
@@ -622,6 +632,43 @@
return 0;
}
+static int msm_routing_get_multimedia2_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ ucontrol->value.integer.value[0] = msm_route_multimedia2_vol_control;
+ return 0;
+}
+
+static int msm_routing_set_multimedia2_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ if (!multi_ch_pcm_set_volume(ucontrol->value.integer.value[0]))
+ msm_route_multimedia2_vol_control =
+ ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
+static int msm_routing_get_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ ucontrol->value.integer.value[0] = msm_route_compressed_vol_control;
+ return 0;
+}
+
+static int msm_routing_set_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (!compressed_set_volume(ucontrol->value.integer.value[0]))
+ msm_route_compressed_vol_control =
+ ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
static void msm_send_eq_values(int eq_idx)
{
int result;
@@ -1107,10 +1154,22 @@
static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
- INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
};
+static const struct snd_kcontrol_new multimedia2_vol_mixer_controls[] = {
+ SOC_SINGLE_EXT_TLV("HIFI2 RX Volume", SND_SOC_NOPM, 0,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_multimedia2_vol_mixer,
+ msm_routing_set_multimedia2_vol_mixer, multimedia2_rx_vol_gain),
+};
+
+static const struct snd_kcontrol_new compressed_vol_mixer_controls[] = {
+ SOC_SINGLE_EXT_TLV("COMPRESSED RX Volume", SND_SOC_NOPM, 0,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_compressed_vol_mixer,
+ msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
+};
+
static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -1756,6 +1815,15 @@
snd_soc_add_platform_controls(platform,
eq_coeff_mixer_controls,
ARRAY_SIZE(eq_coeff_mixer_controls));
+
+ snd_soc_add_platform_controls(platform,
+ multimedia2_vol_mixer_controls,
+ ARRAY_SIZE(multimedia2_vol_mixer_controls));
+
+ snd_soc_add_platform_controls(platform,
+ compressed_vol_mixer_controls,
+ ARRAY_SIZE(compressed_vol_mixer_controls));
+
return 0;
}
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 423ff5f..eae2128 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -95,4 +95,9 @@
int lpa_set_volume(unsigned volume);
int msm_routing_check_backend_enabled(int fedai_id);
+
+int multi_ch_pcm_set_volume(unsigned volume);
+
+int compressed_set_volume(unsigned volume);
+
#endif /*_MSM_PCM_H*/