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

Commit 3457de2a authored by Josh Kirsch's avatar Josh Kirsch
Browse files

ASoC: msm: set default I2S SR to 48Khz on APQ8096 I2C



Set default I2S sampling rate to 48khz on APQ8096 I2C.
This is required for super wideband testing. Add mixer
control to set sample rate.

CRs-Fixed: 1113633
Change-Id: I5dbde6d6fbe0d1e522ef99aed7f2bc8bde2fe04a
Signed-off-by: default avatarJosh Kirsch <jkirsch@codeaurora.org>
parent ae5da9c9
Loading
Loading
Loading
Loading
+144 −23
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016 The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@

#define SAMPLING_RATE_8KHZ      8000
#define SAMPLING_RATE_16KHZ     16000
#define SAMPLING_RATE_24KHZ     24000
#define SAMPLING_RATE_32KHZ     32000
#define SAMPLING_RATE_48KHZ     48000
#define SAMPLING_RATE_96KHZ     96000
@@ -55,6 +56,8 @@
#define MI2S_SLAVE_SEL 1
#define MI2S_SLAVE_SEL_OFFSET 0

#define APQ8096_I2C_BPS 16

struct pinctrl_info {
	struct pinctrl *pinctrl;
	struct pinctrl_state *sleep;
@@ -70,6 +73,9 @@ static struct platform_device *spdev;
static int apq_mi2s_rx_ch = 2;
static int apq_mi2s_tx_ch = 1;

static int apq8096_i2c_tert_rate = SAMPLING_RATE_48KHZ;
static int apq8096_i2c_quat_rate = SAMPLING_RATE_48KHZ;

static const char *const pin_states[] = {"Disable", "active"};

static const char *const auxpcm_rate_text[] = {"8000", "16000"};
@@ -77,10 +83,24 @@ static const struct soc_enum apq8096_i2c_auxpcm_enum[] = {
		SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
};

static const char *const tert_i2c_rate_text[] = {"8000", "16000",
						 "24000", "48000"};
static const struct soc_enum apq8096_i2c_tert_enum[] = {
		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tert_i2c_rate_text),
				    tert_i2c_rate_text),
};

static const char *const quat_i2c_rate_text[] = {"8000", "16000",
						 "24000", "48000"};
static const struct soc_enum apq8096_i2c_quat_enum[] = {
		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(quat_i2c_rate_text),
				    quat_i2c_rate_text),
};

static struct afe_clk_set ter_mi2s_clk = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
	Q6AFE_LPASS_IBIT_CLK_256_KHZ,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	0,
@@ -89,7 +109,7 @@ static struct afe_clk_set ter_mi2s_clk = {
static struct afe_clk_set quad_mi2s_clk = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT,
	Q6AFE_LPASS_IBIT_CLK_256_KHZ,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	0,
@@ -205,7 +225,22 @@ static int apq8096_i2c_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
	return 0;
}

static int apq_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int apq_auxpcm_be_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 = apq8096_i2c_auxpcm_rate;
	channels->min = channels->max = 1;

	return 0;
}

static int apq_mi2s_tert_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,
@@ -213,28 +248,44 @@ static int apq_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
	struct snd_interval *channels = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_CHANNELS);

	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_rx_ch);
	rate->min = rate->max = SAMPLING_RATE_8KHZ;
	rate->min = rate->max = apq8096_i2c_tert_rate;
	pr_debug("%s: rate:%d\n", __func__, apq8096_i2c_tert_rate);
	channels->min = channels->max = apq_mi2s_rx_ch;
	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_rx_ch);
	return 0;
}

static int apq_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int apq_mi2s_tert_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 *rate = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_RATE);
	struct snd_interval *channels = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_CHANNELS);

	struct snd_interval *channels =
	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
	rate->min = rate->max = apq8096_i2c_tert_rate;
	pr_debug("%s: rate:%d\n", __func__, apq8096_i2c_tert_rate);
	channels->min = channels->max = apq_mi2s_tx_ch;
	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_tx_ch);
	return 0;
}

	rate->min = rate->max = apq8096_i2c_auxpcm_rate;
	channels->min = channels->max = 1;
static int apq_mi2s_quat_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 = apq8096_i2c_quat_rate;
	pr_debug("%s: rate:%d\n", __func__, apq8096_i2c_quat_rate);
	channels->min = channels->max = apq_mi2s_rx_ch;
	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_rx_ch);
	return 0;
}

static int apq_mi2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int apq_mi2s_quat_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,
@@ -242,9 +293,10 @@ static int apq_mi2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
	struct snd_interval *channels = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_CHANNELS);

	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_tx_ch);
	rate->min = rate->max = SAMPLING_RATE_8KHZ;
	rate->min = rate->max = apq8096_i2c_quat_rate;
	pr_err("%s: rate:%d\n", __func__, apq8096_i2c_quat_rate);
	channels->min = channels->max = apq_mi2s_tx_ch;
	pr_debug("%s: channel:%d\n", __func__, apq_mi2s_tx_ch);
	return 0;
}

@@ -258,6 +310,10 @@ static int apq8096_i2c_ter_mi2s_snd_startup(struct snd_pcm_substream *substream)
		 substream->name, substream->stream);

	ter_mi2s_clk.enable = 1;
	ter_mi2s_clk.clk_freq_in_hz = apq8096_i2c_tert_rate*
				      apq_mi2s_rx_ch*
				      APQ8096_I2C_BPS;

	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_TERTIARY_MI2S_TX,
				&ter_mi2s_clk);
	if (ret < 0) {
@@ -309,6 +365,9 @@ static int apq8096_i2c_quad_mi2s_snd_startup(
		 substream->name, substream->stream);

	quad_mi2s_clk.enable = 1;
	quad_mi2s_clk.clk_freq_in_hz = apq8096_i2c_quat_rate*
				       apq_mi2s_rx_ch*
				       APQ8096_I2C_BPS;

	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_QUATERNARY_MI2S_TX,
				&quad_mi2s_clk);
@@ -400,6 +459,62 @@ static const struct soc_enum apq_snd_enum[] = {
	SOC_ENUM_SINGLE_EXT(2, mi2s_tx_ch_text),
};

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

static int apq8096_i2c_tert_rate_put(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	switch (ucontrol->value.integer.value[0]) {
	case 0:
		apq8096_i2c_tert_rate = SAMPLING_RATE_8KHZ;
		break;
	case 1:
		apq8096_i2c_tert_rate = SAMPLING_RATE_16KHZ;
		break;
	case 2:
		apq8096_i2c_tert_rate = SAMPLING_RATE_24KHZ;
		break;
	case 3:
	default:
		apq8096_i2c_tert_rate = SAMPLING_RATE_48KHZ;
		break;
	}
	return 0;
}

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

static int apq8096_i2c_quat_rate_put(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	switch (ucontrol->value.integer.value[0]) {
	case 0:
		apq8096_i2c_quat_rate = SAMPLING_RATE_8KHZ;
		break;
	case 1:
		apq8096_i2c_quat_rate = SAMPLING_RATE_16KHZ;
		break;
	case 2:
		apq8096_i2c_quat_rate = SAMPLING_RATE_24KHZ;
		break;
	case 3:
	default:
		apq8096_i2c_quat_rate = SAMPLING_RATE_48KHZ;
		break;
	}
	return 0;
}

static const struct snd_kcontrol_new msm_snd_controls[] = {
	SOC_ENUM_EXT("AUX PCM SampleRate", apq8096_i2c_auxpcm_enum[0],
			apq8096_i2c_auxpcm_rate_get,
@@ -410,6 +525,12 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
	SOC_ENUM_EXT("MI2S_TX Channels",   apq_snd_enum[1],
				 apq_mi2s_tx_ch_get,
				 apq_mi2s_tx_ch_put),
	SOC_ENUM_EXT("TERT I2S SampleRate", apq8096_i2c_tert_enum[0],
			apq8096_i2c_tert_rate_get,
			apq8096_i2c_tert_rate_put),
	SOC_ENUM_EXT("QUAT I2S SampleRate", apq8096_i2c_quat_enum[0],
			apq8096_i2c_quat_rate_get,
			apq8096_i2c_quat_rate_put),
};

static int apq_mi2s_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -581,7 +702,7 @@ static struct snd_soc_dai_link apq8096_i2c_dai[] = {
		.no_pcm = 1,
		.dpcm_capture = 1,
		.be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
		.be_hw_params_fixup = apq_mi2s_tx_be_hw_params_fixup,
		.be_hw_params_fixup = apq_mi2s_tert_tx_be_hw_params_fixup,
		.ops = &apq8096_i2c_ter_mi2s_be_ops,
		.ignore_suspend = 1,
	},
@@ -595,7 +716,7 @@ static struct snd_soc_dai_link apq8096_i2c_dai[] = {
		.no_pcm = 1,
		.dpcm_playback = 1,
		.be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
		.be_hw_params_fixup = apq_mi2s_rx_be_hw_params_fixup,
		.be_hw_params_fixup = apq_mi2s_tert_rx_be_hw_params_fixup,
		.ops = &apq8096_i2c_ter_mi2s_be_ops,
		.ignore_suspend = 1,
	},
@@ -609,7 +730,7 @@ static struct snd_soc_dai_link apq8096_i2c_dai[] = {
		.no_pcm = 1,
		.dpcm_capture = 1,
		.be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
		.be_hw_params_fixup = apq_mi2s_tx_be_hw_params_fixup,
		.be_hw_params_fixup = apq_mi2s_quat_tx_be_hw_params_fixup,
		.ops = &apq8096_i2c_quad_mi2s_be_ops,
		.ignore_suspend = 1,
	},
@@ -624,7 +745,7 @@ static struct snd_soc_dai_link apq8096_i2c_dai[] = {
		.dpcm_playback = 1,
		.be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
		.init  = &apq_mi2s_audrx_init,
		.be_hw_params_fixup = apq_mi2s_rx_be_hw_params_fixup,
		.be_hw_params_fixup = apq_mi2s_quat_rx_be_hw_params_fixup,
		.ops = &apq8096_i2c_quad_mi2s_be_ops,
		.ignore_suspend = 1,
	},