Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5ce4b64 authored by Vidyakumar Athota's avatar Vidyakumar Athota
Browse files

ASoC: apq8084: Add Incall recording feature support



APQ8084 uses external modem for voice calls and is communicated
with modem through slimbus. Add incall recording support which
uses slimbus6 logical port to record.

Change-Id: I3e73121e79b5e6673e3933cd05b8367921a8e5e7
Signed-off-by: default avatarVidyakumar Athota <vathota@codeaurora.org>
parent a4c2acc4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ enum {
	IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
	IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
	IDX_VOICE2_PLAYBACK_TX = 44,
	IDX_SLIMBUS_6_RX = 45,
	IDX_SLIMBUS_6_TX = 46,
	IDX_GLOBAL_CFG,
	AFE_MAX_PORTS
};
+139 −3
Original line number Diff line number Diff line
@@ -191,9 +191,14 @@ enum {
	SLIM_3_RX_2 = 168, /* External echo-cancellation ref */
	SLIM_3_TX_1 = 169, /* HDMI RX */
	SLIM_3_TX_2 = 170, /* HDMI RX */
	SLIM_4_TX_1 = 163, /* In-call recording RX */
	SLIM_4_TX_2 = 164, /* In-call recording RX */
	SLIM_4_RX_1 = 165, /* In-call music delivery TX */
	SLIM_6_TX_1 = 163, /* In-call recording RX */
	SLIM_6_TX_2 = 164, /* In-call recording RX */
	SLIM_6_RX_1 = 165, /* In-call music delivery TX */
};

enum {
	INCALL_REC_MONO,
	INCALL_REC_STEREO,
};

static struct platform_device *spdev;
@@ -215,6 +220,7 @@ static int msm_slim_1_rate = SAMPLING_RATE_8KHZ;
static int msm_slim_1_rx_ch = 1;
static int msm_slim_1_tx_ch = 1;
static int msm_slim_3_rx_ch = 1;
static int rec_mode = INCALL_REC_MONO;

static struct mutex cdc_mclk_mutex;
static struct clk *codec_clk;
@@ -1392,6 +1398,45 @@ static int msm_slim_3_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
	return 0;
}

static int msm_slim_6_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
					    struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_RATE);

	struct snd_interval *channels = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_CHANNELS);

	pr_debug("%s()\n", __func__);

	rate->min = rate->max = 48000;
	if (rec_mode == INCALL_REC_STEREO)
		channels->min = channels->max = 2;
	else
		channels->min = channels->max = 1;

	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
		 channels->min, channels->max);
	return 0;
}

static int msm_slim_6_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
					    struct snd_pcm_hw_params *params)
{
	struct snd_interval *rate = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_RATE);

	struct snd_interval *channels = hw_param_interval(params,
						SNDRV_PCM_HW_PARAM_CHANNELS);

	rate->min = rate->max = 48000;
	channels->min = channels->max = 1;

	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
		 channels->min, channels->max);
	return 0;
}

static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
				  struct snd_pcm_hw_params *params)
{
@@ -1403,6 +1448,22 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
	return 0;
}

static int msm_incall_rec_mode_get(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	ucontrol->value.integer.value[0] = rec_mode;
	return 0;
}

static int msm_incall_rec_mode_put(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	rec_mode = ucontrol->value.integer.value[0];
	pr_debug("%s: rec_mode:%d\n", __func__, rec_mode);
	return 0;
}


static const struct soc_enum msm_snd_enum[] = {
	SOC_ENUM_SINGLE_EXT(2, spk_function),
	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
@@ -1444,6 +1505,8 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
			msm_slim_1_rate_get, msm_slim_1_rate_put),
	SOC_ENUM_EXT("SLIM_3_RX Channels", msm_snd_enum[10],
			msm_slim_3_rx_ch_get, msm_slim_3_rx_ch_put),
	SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
		msm_incall_rec_mode_get, msm_incall_rec_mode_put),
};

static bool apq8084_swap_gnd_mic(struct snd_soc_codec *codec)
@@ -2033,6 +2096,46 @@ end:
	return ret;
}

static int apq8084_slimbus_6_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	int ret = 0;
	unsigned int rx_ch = SLIM_6_RX_1, tx_ch[2];

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		pr_debug("%s: SLIMBUS_6_RX -> MDM TX shared ch %d\n",
			 __func__, rx_ch);

		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
		if (ret < 0) {
			pr_err("%s: Erorr %d setting SLIM_6 RX channel map\n",
				__func__, ret);
		}
	} else {
		if (rec_mode == INCALL_REC_STEREO) {
			tx_ch[0] = SLIM_6_TX_1;
			tx_ch[1] = SLIM_6_TX_2;
			ret = snd_soc_dai_set_channel_map(cpu_dai, 2,
							  tx_ch, 0, 0);
		} else {
			tx_ch[0] = SLIM_6_TX_1;
			ret = snd_soc_dai_set_channel_map(cpu_dai, 1,
							  tx_ch, 0, 0);
		}
		pr_debug("%s: Incall Record shared tx_ch[0]:%d, tx_ch[1]:%d\n",
			__func__, tx_ch[0], tx_ch[1]);

		if (ret < 0) {
			pr_err("%s: Erorr %d setting SLIM_6 TX channel map\n",
				__func__, ret);

		}
	}
	return ret;
}

static struct snd_soc_ops apq8084_slimbus_1_be_ops = {
	.startup = apq8084_slimbus_1_startup,
	.hw_params = apq8084_slimbus_1_hw_params,
@@ -2051,6 +2154,12 @@ static struct snd_soc_ops apq8084_slimbus_3_be_ops = {
	.shutdown = apq8084_snd_shudown,
};

static struct snd_soc_ops apq8084_slimbus_6_be_ops = {
	.startup = apq8084_snd_startup,
	.hw_params = apq8084_slimbus_6_hw_params,
	.shutdown = apq8084_snd_shudown,
};

/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link apq8084_common_dai_links[] = {
	/* FrontEnd DAI Links */
@@ -2716,6 +2825,33 @@ static struct snd_soc_dai_link apq8084_common_dai_links[] = {
		.ops = &apq8084_be_ops,
		.ignore_suspend = 1,
	},
	{
		.name = LPASS_BE_SLIMBUS_6_RX,
		.stream_name = "Slimbus6 Playback",
		.cpu_dai_name = "msm-dai-q6-dev.16396",
		.platform_name = "msm-pcm-routing",
		.codec_name     = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-rx",
		.no_pcm = 1,
		.be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
		.be_hw_params_fixup = msm_slim_6_rx_be_hw_params_fixup,
		.ops = &apq8084_slimbus_6_be_ops,
		.ignore_suspend = 1,
		.ignore_pmdown_time = 1,
	},
	{
		.name = LPASS_BE_SLIMBUS_6_TX,
		.stream_name = "Slimbus6 Capture",
		.cpu_dai_name = "msm-dai-q6-dev.16397",
		.platform_name = "msm-pcm-routing",
		.codec_name     = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-tx",
		.no_pcm = 1,
		.be_id = MSM_BACKEND_DAI_SLIMBUS_6_TX,
		.be_hw_params_fixup = msm_slim_6_tx_be_hw_params_fixup,
		.ops = &apq8084_slimbus_6_be_ops,
		.ignore_suspend = 1,
	},
};

static struct snd_soc_dai_link apq8084_hdmi_dai_link[] = {
+44 −0
Original line number Diff line number Diff line
@@ -778,12 +778,14 @@ static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
	case SLIMBUS_2_RX:
	case SLIMBUS_3_RX:
	case SLIMBUS_4_RX:
	case SLIMBUS_6_RX:
	case SLIMBUS_0_TX:
	case SLIMBUS_1_TX:
	case SLIMBUS_2_TX:
	case SLIMBUS_3_TX:
	case SLIMBUS_4_TX:
	case SLIMBUS_5_TX:
	case SLIMBUS_6_TX:
		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
				substream->stream);
		break;
@@ -889,6 +891,7 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
	case SLIMBUS_2_RX:
	case SLIMBUS_3_RX:
	case SLIMBUS_4_RX:
	case SLIMBUS_6_RX:
		/*
		 * channel number to be between 128 and 255.
		 * For RX port use channel numbers
@@ -916,6 +919,7 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
	case SLIMBUS_3_TX:
	case SLIMBUS_4_TX:
	case SLIMBUS_5_TX:
	case SLIMBUS_6_TX:
		/*
		 * channel number to be between 128 and 255.
		 * For TX port use channel numbers
@@ -1457,6 +1461,24 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai[] = {
		.probe = msm_dai_q6_dai_probe,
		.remove = msm_dai_q6_dai_remove,
	},
	{
		.playback = {
			.stream_name = "SLIM6_RX Playback",
			.aif_name = "SLIMBUS_6_RX",
			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
			SNDRV_PCM_RATE_192000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE |
			 SNDRV_PCM_FMTBIT_S24_LE,
			.channels_min = 1,
			.channels_max = 2,
			.rate_min = 8000,
			.rate_max = 192000,
		},
		.ops = &msm_dai_q6_ops,
		.probe = msm_dai_q6_dai_probe,
		.remove = msm_dai_q6_dai_remove,
	},
};

static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai[] = {
@@ -1559,6 +1581,22 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai[] = {
		.probe = msm_dai_q6_dai_probe,
		.remove = msm_dai_q6_dai_remove,
	},
	{
		.capture = {
			.stream_name = "SLIM6_TX Capture",
			.aif_name = "SLIMBUS_6_TX",
			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
			SNDRV_PCM_RATE_48000,
			.formats = SNDRV_PCM_FMTBIT_S16_LE,
			.channels_min = 1,
			.channels_max = 2,
			.rate_min = 8000,
			.rate_max = 48000,
		},
		.ops = &msm_dai_q6_ops,
		.probe = msm_dai_q6_dai_probe,
		.remove = msm_dai_q6_dai_remove,
	},
};

static int msm_dai_q6_mi2s_format_put(struct snd_kcontrol *kcontrol,
@@ -2367,6 +2405,9 @@ static int msm_dai_q6_dev_probe(struct platform_device *pdev)
		goto register_slim_playback;
	case SLIMBUS_4_RX:
		strlcpy(stream_name, "SLIM4_RX Playback", 80);
		goto register_slim_playback;
	case SLIMBUS_6_RX:
		strlcpy(stream_name, "SLIM6_RX Playback", 80);
register_slim_playback:
		rc = -ENODEV;
		len = strnlen(stream_name , 80);
@@ -2402,6 +2443,9 @@ register_slim_playback:
		goto register_slim_capture;
	case SLIMBUS_5_TX:
		strlcpy(stream_name, "SLIM5_TX Capture", 80);
		goto register_slim_capture;
	case SLIMBUS_6_TX:
		strlcpy(stream_name, "SLIM6_TX Capture", 80);
register_slim_capture:
		rc = -ENODEV;
		len = strnlen(stream_name , 80);
+26 −0
Original line number Diff line number Diff line
@@ -240,6 +240,8 @@ static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
	{ AUDIO_PORT_ID_I2S_RX,           0, 0, 0, 0, 0},
	{ AFE_PORT_ID_SECONDARY_PCM_RX,	  0, 0, 0, 0, 0},
	{ AFE_PORT_ID_SECONDARY_PCM_TX,   0, 0, 0, 0, 0},
	{ SLIMBUS_6_RX, 0, 0, 0, 0, 0},
	{ SLIMBUS_6_TX, 0, 0, 0, 0, 0},
};


@@ -1754,6 +1756,15 @@ static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
	msm_routing_put_audio_mixer),
};

static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = {
	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_6_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SLIMBUS_6_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
};

static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_BT_SCO_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1950,6 +1961,9 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
	SOC_SINGLE_EXT("SLIM_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX,
		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
		msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX,
		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
		msm_routing_put_audio_mixer),
};

static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
@@ -3255,6 +3269,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
	SND_SOC_DAPM_AIF_IN("STUB_1_TX", "Stub1 Capture", 0, 0, 0, 0),
	SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
	SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
	/* In- call recording */
	SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0 , 0),
	SND_SOC_DAPM_AIF_IN("SLIMBUS_6_TX", "Slimbus6 Capture", 0, 0, 0, 0),

	/* Switch Definitions */
	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
@@ -3321,6 +3338,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
	SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
	slimbus_4_rx_mixer_controls,
	ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
	SND_SOC_DAPM_MIXER("SLIMBUS_6_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
	slimbus_6_rx_mixer_controls,
	ARRAY_SIZE(slimbus_6_rx_mixer_controls)),
	/* Voice Mixer */
	SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
				SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
@@ -3490,12 +3510,16 @@ static const struct snd_soc_dapm_route intercon[] = {
	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
	{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
	{"SLIMBUS_6_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
	{"SLIMBUS_6_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
	{"SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Audio Mixer"},

	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
	{"MultiMedia4 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
	{"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
	{"MultiMedia1 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
	{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
	{"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
	{"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
@@ -3877,6 +3901,7 @@ static const struct snd_soc_dapm_route intercon[] = {
	{"BE_OUT", NULL, "SLIMBUS_1_RX"},
	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
	{"BE_OUT", NULL, "SLIMBUS_4_RX"},
	{"BE_OUT", NULL, "SLIMBUS_6_RX"},
	{"BE_OUT", NULL, "HDMI"},
	{"BE_OUT", NULL, "MI2S_RX"},
	{"BE_OUT", NULL, "QUAT_MI2S_RX"},
@@ -3909,6 +3934,7 @@ static const struct snd_soc_dapm_route intercon[] = {
	{"SLIMBUS_3_TX", NULL, "BE_IN" },
	{"SLIMBUS_4_TX", NULL, "BE_IN" },
	{"SLIMBUS_5_TX", NULL, "BE_IN" },
	{"SLIMBUS_6_TX", NULL, "BE_IN" },
	{"INT_BT_SCO_TX", NULL, "BE_IN"},
	{"INT_FM_TX", NULL, "BE_IN"},
	{"PCM_TX", NULL, "BE_IN"},
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@
#define LPASS_BE_SLIMBUS_4_RX "SLIMBUS_4_RX"
#define LPASS_BE_SLIMBUS_4_TX "SLIMBUS_4_TX"
#define LPASS_BE_SLIMBUS_5_TX "SLIMBUS_5_TX"
#define LPASS_BE_SLIMBUS_6_RX "SLIMBUS_6_RX"
#define LPASS_BE_SLIMBUS_6_TX "SLIMBUS_6_TX"

/* For multimedia front-ends, asm session is allocated dynamically.
 * Hence, asm session/multimedia front-end mapping has to be maintained.
@@ -130,6 +132,8 @@ enum {
	MSM_BACKEND_DAI_AUDIO_I2S_RX,
	MSM_BACKEND_DAI_SEC_AUXPCM_RX,
	MSM_BACKEND_DAI_SEC_AUXPCM_TX,
	MSM_BACKEND_DAI_SLIMBUS_6_RX,
	MSM_BACKEND_DAI_SLIMBUS_6_TX,
	MSM_BACKEND_DAI_MAX,
};

Loading