TWL4030_REG_PRECKL_CTL);
reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- reg_val & (~TWL4030_PRECKL_GAIN),
+ reg_val & (~TWL4030_PRECKR_GAIN),
TWL4030_REG_PRECKR_CTL);
/* Disable PLL */
SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
/* Left analog microphone selection */
-static const char *twl4030_analoglmic_texts[] =
- {"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"};
-
-static const unsigned int twl4030_analoglmic_values[] =
- {0x0, 0x1, 0x2, 0x4, 0x8};
-
-static const struct soc_enum twl4030_analoglmic_enum =
- SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf,
- ARRAY_SIZE(twl4030_analoglmic_texts),
- twl4030_analoglmic_texts,
- twl4030_analoglmic_values);
-
-static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control =
-SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum);
+static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = {
+ SOC_DAPM_SINGLE("Main mic", TWL4030_REG_ANAMICL, 0, 1, 0),
+ SOC_DAPM_SINGLE("Headset mic", TWL4030_REG_ANAMICL, 1, 1, 0),
+ SOC_DAPM_SINGLE("AUXL", TWL4030_REG_ANAMICL, 2, 1, 0),
+ SOC_DAPM_SINGLE("Carkit mic", TWL4030_REG_ANAMICL, 3, 1, 0),
+};
/* Right analog microphone selection */
-static const char *twl4030_analogrmic_texts[] =
- {"Off", "Sub mic", "AUXR"};
-
-static const unsigned int twl4030_analogrmic_values[] =
- {0x0, 0x1, 0x4};
-
-static const struct soc_enum twl4030_analogrmic_enum =
- SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5,
- ARRAY_SIZE(twl4030_analogrmic_texts),
- twl4030_analogrmic_texts,
- twl4030_analogrmic_values);
-
-static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control =
-SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum);
+static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
+ SOC_DAPM_SINGLE("Sub mic", TWL4030_REG_ANAMICR, 0, 1, 0),
+ SOC_DAPM_SINGLE("AUXR", TWL4030_REG_ANAMICR, 2, 1, 0),
+};
/* TX1 L/R Analog/Digital microphone selection */
static const char *twl4030_micpathtx1_texts[] =
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
SND_SOC_DAPM_POST_REG),
- /* Analog input muxes with switch for the capture amplifiers */
- SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route",
- TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control),
- SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route",
- TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control),
+ /* Analog input mixers for the capture amplifiers */
+ SND_SOC_DAPM_MIXER("Analog Left Capture Route",
+ TWL4030_REG_ANAMICL, 4, 0,
+ &twl4030_dapm_analoglmic_controls[0],
+ ARRAY_SIZE(twl4030_dapm_analoglmic_controls)),
+ SND_SOC_DAPM_MIXER("Analog Right Capture Route",
+ TWL4030_REG_ANAMICR, 4, 0,
+ &twl4030_dapm_analogrmic_controls[0],
+ ARRAY_SIZE(twl4030_dapm_analogrmic_controls)),
SND_SOC_DAPM_PGA("ADC Physical Left",
TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0),
return 0;
}
+/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
+ * (VTXL, VTXR) for uplink has to be enabled/disabled. */
+static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
+ int enable)
+{
+ u8 reg, mask;
+
+ reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
+
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ mask = TWL4030_ARXL1_VRX_EN;
+ else
+ mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
+
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+
+ twl4030_write(codec, TWL4030_REG_OPTION, reg);
+}
+
static int twl4030_voice_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return 0;
}
+static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ /* Enable voice digital filters */
+ twl4030_voice_enable(codec, substream->stream, 0);
+}
+
static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = socdev->card->codec;
u8 old_mode, mode;
+ /* Enable voice digital filters */
+ twl4030_voice_enable(codec, substream->stream, 1);
+
/* bit rate */
old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
& ~(TWL4030_CODECPDZ);
static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
.startup = twl4030_voice_startup,
+ .shutdown = twl4030_voice_shutdown,
.hw_params = twl4030_voice_hw_params,
.set_sysclk = twl4030_voice_set_dai_sysclk,
.set_fmt = twl4030_voice_set_dai_fmt,