ASoC: msm: Add mixer control to mute rx device
In answer machine use case, voice rx is muted and
the voice is recorded into file.
The mixer control command is added to mute the rx device.
CRs-Fixed: 338015
Change-Id: I1c71ed4129e8aa2fb7241e2f1fdb77db472235a8
Signed-off-by: Helen Zeng <xiaoyunz@codeaurora.org>
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 471284b..5a0f27a 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -217,6 +217,26 @@
return 0;
}
+static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ voc_get_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME));
+ return 0;
+}
+
+static int msm_voice_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME), mute);
+
+ return 0;
+}
+
static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
static const struct soc_enum msm_tty_mode_enum[] = {
SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -308,6 +328,9 @@
}
static struct snd_kcontrol_new msm_voice_controls[] = {
+ SOC_SINGLE_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice_rx_device_mute_get,
+ msm_voice_rx_device_mute_put),
SOC_SINGLE_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, 1, 0,
msm_voice_mute_get, msm_voice_mute_put),
SOC_SINGLE_EXT("Voice Rx Volume", SND_SOC_NOPM, 0, 5, 0,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index f0f833c..0376f34 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2282,6 +2282,51 @@
return -EINVAL;
}
+static int voice_send_rx_device_mute_cmd(struct voice_data *v)
+{
+ struct cvp_set_mute_cmd cvp_mute_cmd;
+ int ret = 0;
+ void *apr_cvp;
+ u16 cvp_handle;
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvp = common.apr_q6_cvp;
+
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ cvp_handle = voice_get_cvp_handle(v);
+
+ cvp_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_mute_cmd) - APR_HDR_SIZE);
+ cvp_mute_cmd.hdr.src_port = v->session_id;
+ cvp_mute_cmd.hdr.dest_port = cvp_handle;
+ cvp_mute_cmd.hdr.token = 0;
+ cvp_mute_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_MUTE;
+ cvp_mute_cmd.cvp_set_mute.direction = 1;
+ cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+ v->cvp_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_mute_cmd);
+ if (ret < 0) {
+ pr_err("Fail in sending RX device mute cmd\n");
+ return -EINVAL;
+ }
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int voice_send_vol_index_cmd(struct voice_data *v)
{
struct cvp_set_rx_volume_index_cmd cvp_vol_cmd;
@@ -2883,6 +2928,49 @@
return ret;
}
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ if (v == NULL) {
+ pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+
+ v->dev_rx.mute = mute;
+
+ if (v->voc_state == VOC_RUN)
+ ret = voice_send_rx_device_mute_cmd(v);
+
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
+int voc_get_rx_device_mute(uint16_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ if (v == NULL) {
+ pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+
+ ret = v->dev_rx.mute;
+
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
int voc_set_tty_mode(uint16_t session_id, uint8_t tty_mode)
{
struct voice_data *v = voice_get_session(session_id);
@@ -3571,6 +3659,7 @@
/* initialize dev_rx and dev_tx */
common.voice[i].dev_rx.volume = common.default_vol_val;
+ common.voice[i].dev_rx.mute = 0;
common.voice[i].dev_tx.mute = common.default_mute_val;
common.voice[i].dev_tx.port_id = 1;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 1a24b9c..0edf1c9 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -637,6 +637,8 @@
#define VSS_MEDIA_ID_G729 0x00010FD0
/* G.729AB (contains two 10ms vocoder frames. */
+#define VSS_IVOCPROC_CMD_SET_MUTE 0x000110EF
+
#define VOICE_CMD_SET_PARAM 0x00011006
#define VOICE_CMD_GET_PARAM 0x00011007
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
@@ -729,6 +731,22 @@
/* Size of the volume calibration table in bytes. */
} __packed;
+struct vss_ivocproc_cmd_set_mute_t {
+ uint16_t direction;
+ /*
+ * 0 : TX only.
+ * 1 : RX only.
+ * 2 : TX and Rx.
+ */
+ uint16_t mute_flag;
+ /*
+ * Mute, un-mute.
+ *
+ * 0 : Disable.
+ * 1 : Enable.
+ */
+} __packed;
+
struct cvp_create_full_ctl_session_cmd {
struct apr_hdr hdr;
struct vss_ivocproc_cmd_create_full_control_session_t cvp_session;
@@ -770,6 +788,11 @@
struct apr_hdr hdr;
} __packed;
+struct cvp_set_mute_cmd {
+ struct apr_hdr hdr;
+ struct vss_ivocproc_cmd_set_mute_t cvp_set_mute;
+} __packed;
+
/* CB for up-link packets. */
typedef void (*ul_cb_fn)(uint8_t *voc_pkt,
uint32_t pkt_len,
@@ -904,6 +927,8 @@
uint32_t dev_type);
int voc_set_rx_vol_index(uint16_t session_id, uint32_t dir, uint32_t voc_idx);
int voc_set_tx_mute(uint16_t session_id, uint32_t dir, uint32_t mute);
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute);
+int voc_get_rx_device_mute(uint16_t session_id);
int voc_disable_cvp(uint16_t session_id);
int voc_enable_cvp(uint16_t session_id);
int voc_set_route_flag(uint16_t session_id, uint8_t path_dir, uint8_t set);