aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cpcap.c
diff options
context:
space:
mode:
authorLinus Torvalds <[email protected]>2021-02-21 14:21:35 -0800
committerLinus Torvalds <[email protected]>2021-02-21 14:21:35 -0800
commit10e2ec8edece2566b40f69bae035a555ece71ab4 (patch)
tree27eed009a4817948623bbc31a83911c5ace7a4b0 /sound/soc/codecs/cpcap.c
parentde1617578849acab8e16c9ffdce39b91fb50639d (diff)
parentc4294d7f057d05053412ebd0d5700228d0f2588d (diff)
Merge tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "A relatively calm release at this time, and no massive code changes are found in the stats, while a wide range of code refactoring and cleanup have been done. Note that this update includes the tree-wide trivial changes for dropping the return value from ISA remove callbacks, too. Below lists up some highlight: ALSA Core: - Support for the software jack injection via debugfs - Fixes for sync_stop PCM operations HD-audio and USB-audio: - A few usual HD-audio device quirks - Updates for Tegra HD-audio - More quirks for Pioneer and other USB-audio devices - Stricter state checks at USB-audio disconnection ASoC: - Continued code refactoring, cleanup and fixes in ASoC core API - A KUnit testsuite for the topology code - Lots of ASoC Intel driver Realtek codec updates, quirk additions and fixes - Support for Ingenic JZ4760(B), Intel AlderLake-P, DT configured nVidia cards, Qualcomm lpass-rx-macro and lpass-tx-macro - Removal of obsolete SIRF prima/atlas, Txx9 and ZTE zx drivers Others: - Drop return value from ISA driver remove callback - Cleanup with DIV_ROUND_UP() macro - FireWire updates, HDSP output loopback support" * tag 'sound-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (322 commits) ALSA: hda: intel-dsp-config: add Alder Lake support ASoC: soc-pcm: fix hw param limits calculation for multi-DAI ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R tablet ASoC: soc-pcm: fix hwparams min/max init for dpcm ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10 ALSA: hda: Add another CometLake-H PCI ID ASoC: soc-pcm: add soc_pcm_hw_update_format() ASoC: soc-pcm: add soc_pcm_hw_update_chan() ASoC: soc-pcm: add soc_pcm_hw_update_rate() ASoC: wm_adsp: Remove unused control callback structure ASoC: SOF: relax ABI checks and avoid unnecessary warnings ASoC: codecs: lpass-tx-macro: add dapm widgets and route ASoC: codecs: lpass-tx-macro: add support for lpass tx macro ASoC: qcom: dt-bindings: add bindings for lpass tx macro codec ASoC: codecs: lpass-rx-macro: add iir widgets ASoC: codecs: lpass-rx-macro: add dapm widgets and route ...
Diffstat (limited to 'sound/soc/codecs/cpcap.c')
-rw-r--r--sound/soc/codecs/cpcap.c139
1 files changed, 131 insertions, 8 deletions
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index f046987ee4cd..05bbacd0d174 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -16,6 +16,14 @@
#include <sound/soc.h>
#include <sound/tlv.h>
+/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */
+#define CPCAP_BIT_AUDIO_LOW_PWR 6
+#define CPCAP_BIT_AUD_LOWPWR_SPEED 5
+#define CPCAP_BIT_VAUDIOPRISTBY 4
+#define CPCAP_BIT_VAUDIO_MODE1 2
+#define CPCAP_BIT_VAUDIO_MODE0 1
+#define CPCAP_BIT_V_AUDIO_EN 0
+
/* Register 513 CPCAP_REG_CC --- CODEC */
#define CPCAP_BIT_CDC_CLK2 15
#define CPCAP_BIT_CDC_CLK1 14
@@ -221,6 +229,7 @@ struct cpcap_reg_info {
};
static const struct cpcap_reg_info cpcap_default_regs[] = {
+ { CPCAP_REG_VAUDIOC, 0x003F, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },
@@ -1264,12 +1273,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
if (direction == SNDRV_PCM_STREAM_CAPTURE) {
mask = 0x0000;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1;
- mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2;
- mask |= CPCAP_BIT_MIC2_TIMESLOT0;
- mask |= CPCAP_BIT_MIC2_TIMESLOT1;
- mask |= CPCAP_BIT_MIC2_TIMESLOT2;
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);
+ mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);
val = 0x0000;
if (channels >= 2)
val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
@@ -1371,8 +1380,121 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-static int cpcap_voice_set_mute(struct snd_soc_dai *dai,
- int mute, int direction)
+
+/*
+ * Configure codec for voice call if requested.
+ *
+ * We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt()
+ * and snd_soc_dai_set_tdm_slot(). This function configures the rest of the
+ * cpcap related hardware as CPU is not involved in the voice call.
+ */
+static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai,
+ bool voice_call)
+{
+ int mask, err;
+
+ /* Modem to codec VAUDIO_MODE1 */
+ mask = BIT(CPCAP_BIT_VAUDIO_MODE1);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Clear MIC1_MUX for call */
+ mask = BIT(CPCAP_BIT_MIC1_MUX);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+ mask, voice_call ? 0 : mask);
+ if (err)
+ return err;
+
+ /* Set MIC2_MUX for call */
+ mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) |
+ BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable LDSP for call */
+ mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable CPCAP_BIT_PGA_CDC_EN for call */
+ mask = BIT(CPCAP_BIT_PGA_CDC_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Unmute voice for call */
+ if (dai) {
+ err = snd_soc_dai_digital_mute(dai, !voice_call,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (err)
+ return err;
+ }
+
+ /* Set modem to codec mic CDC and HPF for call */
+ mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) |
+ BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) |
+ BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC,
+ mask, voice_call ? mask : 0);
+ if (err)
+ return err;
+
+ /* Enable modem to codec CDC for call*/
+ mask = BIT(CPCAP_BIT_CDC_CLK_EN);
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+ mask, voice_call ? mask : 0);
+
+ return err;
+}
+
+static int cpcap_voice_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_component *component = dai->component;
+ struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
+ int err, ts_mask, mask;
+ bool voice_call;
+
+ /*
+ * Primitive test for voice call, probably needs more checks
+ * later on for 16-bit calls detected, Bluetooth headset etc.
+ */
+ if (tx_mask == 0 && rx_mask == 1 && slot_width == 8)
+ voice_call = true;
+ else
+ voice_call = false;
+
+ ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0;
+ ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+ mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0;
+ mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0;
+
+ err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
+ ts_mask, mask);
+ if (err)
+ return err;
+
+ err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000);
+ if (err)
+ return err;
+
+ err = cpcap_voice_call(cpcap, dai, voice_call);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction)
{
struct snd_soc_component *component = dai->component;
struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
@@ -1393,6 +1515,7 @@ static const struct snd_soc_dai_ops cpcap_dai_voice_ops = {
.hw_params = cpcap_voice_hw_params,
.set_sysclk = cpcap_voice_set_dai_sysclk,
.set_fmt = cpcap_voice_set_dai_fmt,
+ .set_tdm_slot = cpcap_voice_set_tdm_slot,
.mute_stream = cpcap_voice_set_mute,
.no_capture_mute = 1,
};