ASOC: msm8x60: support to device_mute is added.
Device mute control is added which can mute the
respective dev_id to volume zero.
msm_device_mute() in user space will use this
control.
CRs-Fixed: 295399
Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index b9436bf..133a065 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -64,4 +64,5 @@
int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
u32 rate);
int afe_port_stop_nowait(int port_id);
+int afe_apply_gain(u16 port_id, u16 gain);
#endif /* __Q6AFE_H__ */
diff --git a/sound/soc/msm/msm8x60.c b/sound/soc/msm/msm8x60.c
index 59597f9..7c34b22 100644
--- a/sound/soc/msm/msm8x60.c
+++ b/sound/soc/msm/msm8x60.c
@@ -911,7 +911,57 @@
}
return rc;
}
+static int msm_device_mute_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = msm_snddev_devcount();
+ return 0;
+}
+static int msm_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int msm_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int dev_id = ucontrol->value.integer.value[0];
+ int mute = ucontrol->value.integer.value[1];
+ struct msm_snddev_info *dev_info;
+ int rc = 0;
+ u16 gain = 0x2000;
+
+ dev_info = audio_dev_ctrl_find_dev(dev_id);
+ if (IS_ERR(dev_info)) {
+ rc = PTR_ERR(dev_info);
+ pr_err("%s: audio_dev_ctrl_find_dev failed. %ld\n",
+ __func__, PTR_ERR(dev_info));
+ return rc;
+ }
+ if (!(dev_info->capability & SNDDEV_CAP_TX)) {
+ rc = -EINVAL;
+ return rc;
+ }
+ if (mute)
+ gain = 0;
+
+ pr_debug("%s:dev_name = %s dev_id = %d, gain = %hX\n",
+ __func__, dev_info->name, dev_id, gain);
+ rc = afe_apply_gain(dev_info->copp_id, gain);
+ if (rc < 0) {
+ pr_err("%s : device %s not able to set device gain "
+ "control.", __func__, dev_info->name);
+ return rc;
+ }
+ pr_debug("Muting/Unmuting device id %d(%s)\n", dev_id, dev_info->name);
+
+ return rc;
+}
static struct snd_kcontrol_new snd_dev_controls[AUDIO_DEV_CTL_MAX_DEV];
static int snd_dev_ctl_index(int idx)
@@ -976,6 +1026,8 @@
MSM_EXT("Reset", msm_reset_info,
msm_reset_get, msm_reset_put, 0),
MSM_EXT("ANC", msm_anc_info, msm_anc_get, msm_anc_put, 0),
+ MSM_EXT("Device_Mute", msm_device_mute_info,
+ msm_device_mute_get, msm_device_mute_put, 0),
};
static struct snd_kcontrol_new snd_msm_secondary_controls[] = {
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 500ceb5..5c47159 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -72,6 +72,7 @@
case AFE_PORT_CMD_SET_PARAM:
case AFE_PSEUDOPORT_CMD_START:
case AFE_PSEUDOPORT_CMD_STOP:
+ case AFE_PORT_CMD_APPLY_GAIN:
atomic_set(&this_afe.state, 0);
wake_up(&this_afe.wait);
break;
@@ -488,6 +489,66 @@
return ret;
}
+int afe_apply_gain(u16 port_id, u16 gain)
+{
+ struct afe_port_gain_command set_gain;
+ int ret = 0;
+
+ if (this_afe.apr == NULL) {
+ pr_err("%s: AFE is not opened\n", __func__);
+ ret = -EPERM;
+ goto fail_cmd;
+ }
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ /* RX ports numbers are even .TX ports numbers are odd. */
+ if (port_id % 2 == 0) {
+ pr_err("%s: Failed : afe apply gain only for TX ports."
+ " port_id %d\n", __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ pr_debug("%s: %d %hX\n", __func__, port_id, gain);
+
+ set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ set_gain.hdr.pkt_size = sizeof(set_gain);
+ set_gain.hdr.src_port = 0;
+ set_gain.hdr.dest_port = 0;
+ set_gain.hdr.token = 0;
+ set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
+
+ set_gain.port_id = port_id;
+ set_gain.gain = gain;
+
+ atomic_set(&this_afe.state, 1);
+ ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
+ if (ret < 0) {
+ pr_err("%s: AFE Gain set failed for port %d\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ ret = wait_event_timeout(this_afe.wait,
+ (atomic_read(&this_afe.state) == 0),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (ret < 0) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return ret;
+}
int afe_start_pseudo_port(u16 port_id)
{
int ret = 0;