Explorar el Código

codecs: wcd9360: Add AQT based dais in WCD9360 codec driver

WCD9360 codec acts as an interface between AQT codec and
msmnile CPU DAI. Add AQT based playback and capture dais in
WCD9360 codec driver.

Change-Id: Ic780dd336a775dbb48a1d3ada90029763ac7a657
Signed-off-by: Sudheer Papothi <[email protected]>
Sudheer Papothi hace 7 años
padre
commit
e788b89d8b
Se han modificado 2 ficheros con 175 adiciones y 6 borrados
  1. 16 3
      asoc/codecs/wcd9360/wcd9360-routing.h
  2. 159 3
      asoc/codecs/wcd9360/wcd9360.c

+ 16 - 3
asoc/codecs/wcd9360/wcd9360-routing.h

@@ -75,8 +75,8 @@ const struct snd_soc_dapm_route pahu_slim_audio_map[] = {
 	{"SLIM TX7", NULL, "CDC_IF TX7 MUX"},
 	{"SLIM TX8", NULL, "CDC_IF TX8 MUX"},
 	{"SLIM TX9", NULL, "CDC_IF TX9 MUX"},
-	{"SLIM TX10", NULL, "CDC_IF TX10 MUX"},
-	{"SLIM TX11", NULL, "CDC_IF TX11 MUX"},
+	{"SLIM TX10", NULL, "CDC_IF TX10 MUX2"},
+	{"SLIM TX11", NULL, "CDC_IF TX11 MUX2"},
 	{"SLIM TX13", NULL, "CDC_IF TX13 MUX"},
 
 	{"SLIM RX0 MUX", "AIF1_PB", "AIF1 PB"},
@@ -138,7 +138,6 @@ const struct snd_soc_dapm_route pahu_slim_audio_map[] = {
 	{"AIF4_VI Mixer", "SPKR_VI_1", "VIINPUT"},
 	{"AIF4_VI Mixer", "SPKR_VI_2", "VIINPUT"},
 	{"AIF4 VI", NULL, "AIF4_VI Mixer"},
-
 };
 
 const struct snd_soc_dapm_route pahu_audio_map[] = {
@@ -266,7 +265,9 @@ const struct snd_soc_dapm_route pahu_audio_map[] = {
 	{"CDC_IF TX9 MUX", "DEC7_192", "ADC US MUX7"},
 	{"CDC_IF TX10 MUX", "DEC6", "ADC MUX6"},
 	{"CDC_IF TX10 MUX", "DEC6_192", "ADC US MUX6"},
+	{"CDC_IF TX10 MUX2", "TX10_MUX1", "CDC_IF TX10 MUX"},
 
+	{"CDC_IF TX11 MUX2", "TX11_MUX1", "CDC_IF TX11 MUX"},
 	{"CDC_IF TX11 MUX", "DEC_0_5", "CDC_IF TX11 INP1 MUX"},
 	{"CDC_IF TX11 MUX", "DEC_9_12", "CDC_IF TX11 INP1 MUX"},
 	{"CDC_IF TX11 INP1 MUX", "DEC0", "ADC MUX0"},
@@ -859,6 +860,18 @@ const struct snd_soc_dapm_route pahu_audio_map[] = {
 
 	{"ASRC3 MUX", "ASRC_IN_SPKR2", "RX INT8_2 INTERP"},
 	{"RX INT8 SEC MIX", NULL, "ASRC3 MUX"},
+
+	/* SLIMBUS-I2S Bridge interface */
+	{"I2S TX1_0 MUX", "AIF4_PB", "AIF4 PB"},
+	{"I2S TX1_1 MUX", "AIF4_PB", "AIF4 PB"},
+	{"I2S TX1 MIXER", NULL, "I2S TX1_0 MUX"},
+	{"I2S TX1 MIXER", NULL, "I2S TX1_1 MUX"},
+	{"I2S1 CAP", NULL, "I2S TX1 MIXER"},
+
+	{"CDC_IF TX10 MUX2", "I2SRX1_0_BRDG", "CDC_IF RX2 MUX"},
+	{"CDC_IF TX11 MUX2", "I2SRX1_1_BRDG", "CDC_IF RX3 MUX"},
+	{"CDC_IF RX2 MUX", "I2SRX1_0", "I2S1 PB"},
+	{"CDC_IF RX3 MUX", "I2SRX1_1", "I2S1 PB"},
 };
 
 #endif

+ 159 - 3
asoc/codecs/wcd9360/wcd9360.c

@@ -184,6 +184,8 @@ enum {
 	AIF4_PB,
 	AIF4_VIFEED,
 	AIF4_MAD_TX,
+	I2S1_PB,
+	I2S1_CAP,
 	NUM_CODEC_DAIS,
 };
 
@@ -601,6 +603,7 @@ struct pahu_priv {
 	struct platform_device *pdev_child_devices
 		[WCD9360_CHILD_DEVICES_MAX];
 	int child_count;
+	int i2s_ref_cnt;
 };
 
 static const struct pahu_reg_mask_val pahu_spkr_default[] = {
@@ -1540,6 +1543,71 @@ done:
 	return ret;
 }
 
+static void pahu_codec_enable_i2s(struct snd_soc_codec *codec, bool enable)
+{
+	struct pahu_priv *pahu = snd_soc_codec_get_drvdata(codec);
+
+	if (enable) {
+		if (++pahu->i2s_ref_cnt == 1)
+			snd_soc_update_bits(codec, WCD9360_DATA_HUB_I2S_1_CTL,
+					    0x01, 0x01);
+	} else {
+		if (--pahu->i2s_ref_cnt == 0)
+			snd_soc_update_bits(codec, WCD9360_DATA_HUB_I2S_1_CTL,
+					    0x01, 0x00);
+	}
+}
+
+static int pahu_i2s_aif_rx_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol,
+			      int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+	switch(event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		pahu_cdc_mclk_enable(codec, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		pahu_codec_enable_i2s(codec, true);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		pahu_codec_enable_i2s(codec, false);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		pahu_cdc_mclk_enable(codec, false);
+		break;
+	}
+
+	return 0;
+}
+
+static int pahu_i2s_aif_tx_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol,
+			      int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+	switch(event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		pahu_cdc_mclk_enable(codec, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		pahu_codec_enable_i2s(codec, true);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		pahu_codec_enable_i2s(codec, false);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		pahu_cdc_mclk_enable(codec, false);
+		break;
+	}
+
+	return 0;
+}
+
 static int pahu_codec_enable_ldo_rxtx(struct snd_soc_dapm_widget *w,
 				      struct snd_kcontrol *kcontrol, int event)
 {
@@ -4413,8 +4481,14 @@ static const char * const cdc_if_tx9_mux_text[] = {
 static const char * const cdc_if_tx10_mux_text[] = {
 	"ZERO", "DEC6", "DEC6_192"
 };
+static const char * const cdc_if_tx10_mux2_text[] = {
+	"TX10_MUX1", "I2SRX1_0_BRDG"
+};
+static const char * const cdc_if_tx11_mux2_text[] = {
+	"TX11_MUX1", "I2SRX1_1_BRDG", "SWR_PACKED_PDM"
+};
 static const char * const cdc_if_tx11_mux_text[] = {
-	"DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
+	"RDMA_TX11", "DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
 };
 static const char * const cdc_if_tx11_inp1_mux_text[] = {
 	"ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4",
@@ -4518,10 +4592,10 @@ static const char *const cdc_if_rx1_mux_text[] = {
 	"SLIM RX1", "I2S RX1"
 };
 static const char *const cdc_if_rx2_mux_text[] = {
-	"SLIM RX2", "I2S RX2"
+	"SLIM RX2", "I2SRX1_0", "I2SRX0_2"
 };
 static const char *const cdc_if_rx3_mux_text[] = {
-	"SLIM RX3", "I2S RX3"
+	"SLIM RX3", "I2SRX1_1", "I2SRX0_3"
 };
 static const char *const cdc_if_rx4_mux_text[] = {
 	"SLIM RX4", "I2S RX4"
@@ -4823,10 +4897,14 @@ WCD_DAPM_ENUM(cdc_if_tx9, WCD9360_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
 	cdc_if_tx9_mux_text);
 WCD_DAPM_ENUM(cdc_if_tx10, WCD9360_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
 	cdc_if_tx10_mux_text);
+WCD_DAPM_ENUM(cdc_if_tx10_inp2, WCD9360_DATA_HUB_SB_TX10_INP_CFG, 3,
+	cdc_if_tx10_mux2_text);
 WCD_DAPM_ENUM(cdc_if_tx11_inp1, WCD9360_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
 	cdc_if_tx11_inp1_mux_text);
 WCD_DAPM_ENUM(cdc_if_tx11, WCD9360_DATA_HUB_SB_TX11_INP_CFG, 0,
 	cdc_if_tx11_mux_text);
+WCD_DAPM_ENUM(cdc_if_tx11_inp2, WCD9360_DATA_HUB_SB_TX11_INP_CFG, 3,
+	cdc_if_tx11_mux2_text);
 WCD_DAPM_ENUM(cdc_if_tx13_inp1, WCD9360_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
 	cdc_if_tx13_inp1_mux_text);
 WCD_DAPM_ENUM(cdc_if_tx13, WCD9360_DATA_HUB_SB_TX13_INP_CFG, 0,
@@ -4974,6 +5052,17 @@ static const struct snd_kcontrol_new adc_us_mux8_switch =
 static const struct snd_kcontrol_new wdma3_onoff_switch =
 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
 
+static const char *const i2s_tx1_0_txt[] = {
+	"ZERO", "SB_TX8", "SB_RX2", "SB_TX12"
+};
+
+static const char *const i2s_tx1_1_txt[] = {
+	"ZERO", "SB_RX0", "SB_RX1", "SB_RX2", "SB_RX3", "SB_TX11"
+};
+
+WCD_DAPM_ENUM(i2s_tx1_0_inp, WCD9360_DATA_HUB_I2S_TX1_0_CFG, 0, i2s_tx1_0_txt);
+WCD_DAPM_ENUM(i2s_tx1_1_inp, WCD9360_DATA_HUB_I2S_TX1_1_CFG, 0, i2s_tx1_1_txt);
+
 static const struct snd_soc_dapm_widget pahu_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
 		AIF1_PB, 0, pahu_codec_enable_slimrx,
@@ -4988,6 +5077,11 @@ static const struct snd_soc_dapm_widget pahu_dapm_widgets[] = {
 		AIF4_PB, 0, pahu_codec_enable_slimrx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_AIF_IN_E("I2S1 PB", "I2S1 Playback", 0, SND_SOC_NOPM,
+		I2S1_PB, 0, pahu_i2s_aif_rx_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	WCD_DAPM_MUX("SLIM RX0 MUX", WCD9360_RX0, slim_rx0),
 	WCD_DAPM_MUX("SLIM RX1 MUX", WCD9360_RX1, slim_rx1),
 	WCD_DAPM_MUX("SLIM RX2 MUX", WCD9360_RX2, slim_rx2),
@@ -5104,6 +5198,8 @@ static const struct snd_soc_dapm_widget pahu_dapm_widgets[] = {
 	WCD_DAPM_MUX("CDC_IF TX11 INP1 MUX", WCD9360_TX11, cdc_if_tx11_inp1),
 	WCD_DAPM_MUX("CDC_IF TX13 MUX", WCD9360_TX13, cdc_if_tx13),
 	WCD_DAPM_MUX("CDC_IF TX13 INP1 MUX", WCD9360_TX13, cdc_if_tx13_inp1),
+	WCD_DAPM_MUX("CDC_IF TX10 MUX2", WCD9360_TX10, cdc_if_tx10_inp2),
+	WCD_DAPM_MUX("CDC_IF TX11 MUX2", WCD9360_TX11, cdc_if_tx11_inp2),
 
 	SND_SOC_DAPM_MUX_E("ADC MUX0", WCD9360_CDC_TX0_TX_PATH_CTL, 5, 0,
 		&tx_adc_mux0_mux, pahu_codec_enable_dec,
@@ -5234,6 +5330,16 @@ static const struct snd_soc_dapm_widget pahu_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
 		AIF3_CAP, 0, pahu_codec_enable_slimtx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	WCD_DAPM_MUX("I2S TX1_0 MUX", 0, i2s_tx1_0_inp),
+	WCD_DAPM_MUX("I2S TX1_1 MUX", 0, i2s_tx1_1_inp),
+	SND_SOC_DAPM_MIXER("I2S TX1 MIXER", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_AIF_OUT_E("I2S1 CAP", "I2S1 Capture", 0,
+		SND_SOC_NOPM, I2S1_CAP, 0, pahu_i2s_aif_tx_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
 		aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
 	SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
@@ -5956,6 +6062,22 @@ static int pahu_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static int pahu_i2s_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *params,
+			   struct snd_soc_dai *dai)
+{
+	struct pahu_priv *pahu = snd_soc_codec_get_drvdata(dai->codec);
+
+	dev_dbg(dai->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
+		 __func__, dai->name, dai->id, params_rate(params),
+		 params_channels(params));
+
+	pahu->dai[dai->id].rate = params_rate(params);
+	pahu->dai[dai->id].bit_width = params_width(params);
+
+	return 0;
+}
+
 static struct snd_soc_dai_ops pahu_dai_ops = {
 	.startup = pahu_startup,
 	.shutdown = pahu_shutdown,
@@ -5971,6 +6093,10 @@ static struct snd_soc_dai_ops pahu_vi_dai_ops = {
 	.get_channel_map = pahu_get_channel_map,
 };
 
+static struct snd_soc_dai_ops pahu_i2s_dai_ops = {
+	.hw_params = pahu_i2s_hw_params,
+};
+
 static struct snd_soc_dai_driver pahu_dai[] = {
 	{
 		.name = "pahu_rx1",
@@ -6098,6 +6224,34 @@ static struct snd_soc_dai_driver pahu_dai[] = {
 		},
 		.ops = &pahu_dai_ops,
 	},
+	{
+		.name = "pahu_i2s1_rx",
+		.id = I2S1_PB,
+		.playback = {
+			.stream_name = "I2S1 Playback",
+			.rates = WCD9360_RATES_MASK | WCD9360_FRAC_RATES_MASK,
+			.formats = WCD9360_FORMATS_S16_S24_S32_LE,
+			.rate_min = 8000,
+			.rate_max = 384000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &pahu_i2s_dai_ops,
+	},
+	{
+		.name = "pahu_i2s1_tx",
+		.id = I2S1_CAP,
+		.capture = {
+			.stream_name = "I2S1 Capture",
+			.rates = WCD9360_RATES_MASK | WCD9360_FRAC_RATES_MASK,
+			.formats = WCD9360_FORMATS_S16_S24_S32_LE,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &pahu_i2s_dai_ops,
+	},
 };
 
 static void pahu_codec_power_gate_digital_core(struct pahu_priv *pahu)
@@ -7205,6 +7359,8 @@ static int pahu_soc_codec_probe(struct snd_soc_codec *codec)
 	snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "AIF4 MAD TX");
 	snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
+	snd_soc_dapm_ignore_suspend(dapm, "I2S1 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "I2S1 Capture");
 
 	snd_soc_dapm_sync(dapm);