Alsa-devel
Threads by month
- ----- 2024 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
December 2019
- 123 participants
- 370 discussions
[alsa-devel] [PATCH v14 2/7] ASoC: amd: Refactoring of DAI from DMA driver
by Ravulapati Vishnu vardhan rao 27 Dec '19
by Ravulapati Vishnu vardhan rao 27 Dec '19
27 Dec '19
ASoC: PCM DMA driver should only have dma ops.
So Removed all DAI related functionality.Refactoring
the PCM DMA diver code.Added new file containing only DAI ops
Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati(a)amd.com>
---
sound/soc/amd/raven/Makefile | 2 +
sound/soc/amd/raven/acp3x-i2s.c | 262 +++++++++++++++++++++++++++++++
sound/soc/amd/raven/acp3x-pcm-dma.c | 302 +++++++-----------------------------
sound/soc/amd/raven/acp3x.h | 43 +++++
4 files changed, 364 insertions(+), 245 deletions(-)
create mode 100644 sound/soc/amd/raven/acp3x-i2s.c
diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile
index 108d1ac..62c22b6 100644
--- a/sound/soc/amd/raven/Makefile
+++ b/sound/soc/amd/raven/Makefile
@@ -2,5 +2,7 @@
# Raven Ridge platform Support
snd-pci-acp3x-objs := pci-acp3x.o
snd-acp3x-pcm-dma-objs := acp3x-pcm-dma.o
+snd-acp3x-i2s-objs := acp3x-i2s.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-pci-acp3x.o
obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-pcm-dma.o
+obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-i2s.o
diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
new file mode 100644
index 0000000..cdc1c61
--- /dev/null
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// AMD ALSA SoC PCM Driver
+//
+//Copyright 2016 Advanced Micro Devices, Inc.
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "acp3x.h"
+
+#define DRV_NAME "acp3x-i2s"
+
+static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct i2s_dev_data *adata;
+ int mode;
+
+ adata = snd_soc_dai_get_drvdata(cpu_dai);
+ mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ switch (mode) {
+ case SND_SOC_DAIFMT_I2S:
+ adata->tdm_mode = false;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ adata->tdm_mode = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
+ u32 tx_mask, u32 rx_mask, int slots, int slot_width)
+{
+ struct i2s_dev_data *adata;
+ u32 val, reg_val, frmt_val, frm_len;
+ u16 slot_len;
+
+ adata = snd_soc_dai_get_drvdata(cpu_dai);
+
+ /* These values are as per Hardware Spec */
+ switch (slot_width) {
+ case SLOT_WIDTH_8:
+ slot_len = 8;
+ break;
+ case SLOT_WIDTH_16:
+ slot_len = 16;
+ break;
+ case SLOT_WIDTH_24:
+ slot_len = 24;
+ break;
+ case SLOT_WIDTH_32:
+ slot_len = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable I2S/BT channels TDM, respective TX/RX frame lengths.*/
+
+ frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
+ if (adata->substream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+ reg_val = mmACP_BTTDM_ITER;
+ frmt_val = mmACP_BTTDM_TXFRMT;
+ } else {
+ reg_val = mmACP_BTTDM_IRER;
+ frmt_val = mmACP_BTTDM_RXFRMT;
+ }
+ val = rv_readl(adata->acp3x_base + reg_val);
+ rv_writel(val | 0x2, adata->acp3x_base + reg_val);
+ rv_writel(frm_len, adata->acp3x_base + frmt_val);
+ adata->tdm_fmt = frm_len;
+ return 0;
+}
+
+static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct i2s_stream_instance *rtd;
+ u32 val;
+ u32 reg_val;
+
+ rtd = substream->runtime->private_data;
+
+ /* These values are as per Hardware Spec */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U8:
+ case SNDRV_PCM_FORMAT_S8:
+ rtd->xfer_resolution = 0x0;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ rtd->xfer_resolution = 0x02;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ rtd->xfer_resolution = 0x04;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ rtd->xfer_resolution = 0x05;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ reg_val = mmACP_BTTDM_ITER;
+ else
+ reg_val = mmACP_BTTDM_IRER;
+
+ val = rv_readl(rtd->acp3x_base + reg_val);
+ val = val | (rtd->xfer_resolution << 3);
+ rv_writel(val, rtd->acp3x_base + reg_val);
+ return 0;
+}
+
+static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct i2s_stream_instance *rtd;
+ u32 val, period_bytes;
+ int ret, reg_val;
+
+ rtd = substream->runtime->private_data;
+ period_bytes = frames_to_bytes(substream->runtime,
+ substream->runtime->period_size);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ rtd->bytescount = acp_get_byte_count(rtd,
+ substream->stream);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ reg_val = mmACP_BTTDM_ITER;
+ rv_writel(period_bytes, rtd->acp3x_base +
+ mmACP_BT_TX_INTR_WATERMARK_SIZE);
+ } else {
+ reg_val = mmACP_BTTDM_IRER;
+ rv_writel(period_bytes, rtd->acp3x_base +
+ mmACP_BT_RX_INTR_WATERMARK_SIZE);
+ }
+ val = rv_readl(rtd->acp3x_base + reg_val);
+ val = val | BIT(0);
+ rv_writel(val, rtd->acp3x_base + reg_val);
+ rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ reg_val = mmACP_BTTDM_ITER;
+ else
+ reg_val = mmACP_BTTDM_IRER;
+
+ val = rv_readl(rtd->acp3x_base + reg_val);
+ val = val & ~BIT(0);
+ rv_writel(val, rtd->acp3x_base + reg_val);
+ rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static struct snd_soc_dai_ops acp3x_i2s_dai_ops = {
+ .hw_params = acp3x_i2s_hwparams,
+ .trigger = acp3x_i2s_trigger,
+ .set_fmt = acp3x_i2s_set_fmt,
+ .set_tdm_slot = acp3x_i2s_set_tdm_slot,
+};
+
+static const struct snd_soc_component_driver acp3x_dai_component = {
+ .name = "acp3x-i2s",
+};
+
+static struct snd_soc_dai_driver acp3x_i2s_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ },
+ .capture = {
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &acp3x_i2s_dai_ops,
+};
+
+static int acp3x_dai_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct i2s_dev_data *adata;
+ int ret;
+
+ adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+ GFP_KERNEL);
+ if (!adata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+ return -ENOMEM;
+ }
+ adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (IS_ERR(adata->acp3x_base))
+ return PTR_ERR(adata->acp3x_base);
+
+ adata->i2s_irq = res->start;
+ dev_set_drvdata(&pdev->dev, adata);
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &acp3x_dai_component, &acp3x_i2s_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int acp3x_dai_remove(struct platform_device *pdev)
+{
+ /* As we use devm_ memory alloc there is nothing TBD here */
+
+ return 0;
+}
+
+static struct platform_driver acp3x_dai_driver = {
+ .probe = acp3x_dai_probe,
+ .remove = acp3x_dai_remove,
+ .driver = {
+ .name = "acp3x_i2s_playcap",
+ },
+};
+
+module_platform_driver(acp3x_dai_driver);
+
+MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati(a)amd.com");
+MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 60709e3..3150516 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -18,24 +18,6 @@
#define DRV_NAME "acp3x-i2s-audio"
-struct i2s_dev_data {
- bool tdm_mode;
- unsigned int i2s_irq;
- u32 tdm_fmt;
- void __iomem *acp3x_base;
- struct snd_pcm_substream *play_stream;
- struct snd_pcm_substream *capture_stream;
-};
-
-struct i2s_stream_instance {
- u16 num_pages;
- u16 channels;
- u32 xfer_resolution;
- u64 bytescount;
- dma_addr_t dma_addr;
- void __iomem *acp3x_base;
-};
-
static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -178,10 +160,11 @@ static int acp3x_deinit(void __iomem *acp3x_base)
static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
{
+ struct i2s_dev_data *rv_i2s_data;
u16 play_flag, cap_flag;
u32 val;
- struct i2s_dev_data *rv_i2s_data = dev_id;
+ rv_i2s_data = dev_id;
if (!rv_i2s_data)
return IRQ_NONE;
@@ -278,11 +261,17 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
static int acp3x_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- int ret = 0;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
- struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance),
- GFP_KERNEL);
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_pcm_runtime *prtd;
+ struct i2s_dev_data *adata;
+ struct i2s_stream_instance *i2s_data;
+ int ret;
+
+ runtime = substream->runtime;
+ prtd = substream->private_data;
+ component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+ adata = dev_get_drvdata(component->dev);
+ i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
if (!i2s_data)
return -EINVAL;
@@ -312,33 +301,18 @@ static int acp3x_dma_open(struct snd_soc_component *component,
return 0;
}
-static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction)
-{
- u64 byte_count;
-
- if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
- byte_count = rv_readl(rtd->acp3x_base +
- mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
- byte_count |= rv_readl(rtd->acp3x_base +
- mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
- } else {
- byte_count = rv_readl(rtd->acp3x_base +
- mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
- byte_count |= rv_readl(rtd->acp3x_base +
- mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
- }
- return byte_count;
-}
static int acp3x_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
+ struct snd_pcm_runtime *runtime;
+ struct i2s_stream_instance *rtd;
int status;
u64 size;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct i2s_stream_instance *rtd = runtime->private_data;
+ runtime = substream->runtime;
+ rtd = substream->private_data;
if (!rtd)
return -EINVAL;
@@ -362,12 +336,12 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component,
static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- u32 pos = 0;
- u32 buffersize = 0;
- u64 bytescount = 0;
- struct i2s_stream_instance *rtd =
- substream->runtime->private_data;
+ struct i2s_stream_instance *rtd;
+ u32 pos;
+ u32 buffersize;
+ u64 bytescount;
+ rtd = substream->runtime->private_data;
buffersize = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
bytescount = acp_get_byte_count(rtd, substream->stream);
@@ -380,7 +354,10 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
static int acp3x_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
- struct device *parent = component->dev->parent;
+ struct device *parent;
+
+ component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ parent = component->dev->parent;
snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
parent, MIN_BUFFER, MAX_BUFFER);
return 0;
@@ -402,8 +379,12 @@ static int acp3x_dma_mmap(struct snd_soc_component *component,
static int acp3x_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- struct i2s_stream_instance *rtd = substream->runtime->private_data;
- struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
+ struct snd_soc_pcm_runtime *prtd;
+ struct i2s_dev_data *adata;
+
+ prtd = substream->private_data;
+ component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
+ adata = dev_get_drvdata(component->dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
adata->play_stream = NULL;
@@ -415,186 +396,9 @@ static int acp3x_dma_close(struct snd_soc_component *component,
*/
if (!adata->play_stream && !adata->capture_stream)
rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
- kfree(rtd);
return 0;
}
-static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
-
- struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
-
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- adata->tdm_mode = false;
- break;
- case SND_SOC_DAIFMT_DSP_A:
- adata->tdm_mode = true;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int acp3x_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
- u32 rx_mask, int slots, int slot_width)
-{
- u32 val = 0;
- u16 slot_len;
-
- struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
-
- switch (slot_width) {
- case SLOT_WIDTH_8:
- slot_len = 8;
- break;
- case SLOT_WIDTH_16:
- slot_len = 16;
- break;
- case SLOT_WIDTH_24:
- slot_len = 24;
- break;
- case SLOT_WIDTH_32:
- slot_len = 0;
- break;
- default:
- return -EINVAL;
- }
-
- val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
- rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
- val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
- rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
-
- val = (FRM_LEN | (slots << 15) | (slot_len << 18));
- rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
- rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
-
- adata->tdm_fmt = val;
- return 0;
-}
-
-static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- u32 val = 0;
- struct i2s_stream_instance *rtd = substream->runtime->private_data;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_U8:
- case SNDRV_PCM_FORMAT_S8:
- rtd->xfer_resolution = 0x0;
- break;
- case SNDRV_PCM_FORMAT_S16_LE:
- rtd->xfer_resolution = 0x02;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- rtd->xfer_resolution = 0x04;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- rtd->xfer_resolution = 0x05;
- break;
- default:
- return -EINVAL;
- }
- val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
- val = val | (rtd->xfer_resolution << 3);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
- else
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
-
- return 0;
-}
-
-static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
-{
- int ret = 0;
- struct i2s_stream_instance *rtd = substream->runtime->private_data;
- u32 val, period_bytes;
-
- period_bytes = frames_to_bytes(substream->runtime,
- substream->runtime->period_size);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- rtd->bytescount = acp_get_byte_count(rtd, substream->stream);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- rv_writel(period_bytes, rtd->acp3x_base +
- mmACP_BT_TX_INTR_WATERMARK_SIZE);
- val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
- val = val | BIT(0);
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
- } else {
- rv_writel(period_bytes, rtd->acp3x_base +
- mmACP_BT_RX_INTR_WATERMARK_SIZE);
- val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
- val = val | BIT(0);
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
- }
- rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
- val = val & ~BIT(0);
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
- } else {
- val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
- val = val & ~BIT(0);
- rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
- }
- rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
- .hw_params = acp3x_dai_i2s_hwparams,
- .trigger = acp3x_dai_i2s_trigger,
- .set_fmt = acp3x_dai_i2s_set_fmt,
- .set_tdm_slot = acp3x_dai_set_tdm_slot,
-};
-
-static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
- .playback = {
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .channels_min = 2,
- .channels_max = 8,
-
- .rate_min = 8000,
- .rate_max = 96000,
- },
- .capture = {
- .rates = SNDRV_PCM_RATE_8000_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .channels_min = 2,
- .channels_max = 2,
- .rate_min = 8000,
- .rate_max = 48000,
- },
- .ops = &acp3x_dai_i2s_ops,
-};
-
static const struct snd_soc_component_driver acp3x_i2s_component = {
.name = DRV_NAME,
.open = acp3x_dma_open,
@@ -609,10 +413,10 @@ static const struct snd_soc_component_driver acp3x_i2s_component = {
static int acp3x_audio_probe(struct platform_device *pdev)
{
- int status;
struct resource *res;
struct i2s_dev_data *adata;
unsigned int irqflags;
+ int status, ret;
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "platform_data not retrieved\n");
@@ -622,7 +426,7 @@ static int acp3x_audio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+ dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
return -ENODEV;
}
@@ -632,6 +436,8 @@ static int acp3x_audio_probe(struct platform_device *pdev)
adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
+ if (!adata->acp3x_base)
+ return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
@@ -640,52 +446,54 @@ static int acp3x_audio_probe(struct platform_device *pdev)
}
adata->i2s_irq = res->start;
- adata->play_stream = NULL;
- adata->capture_stream = NULL;
dev_set_drvdata(&pdev->dev, adata);
/* Initialize ACP */
status = acp3x_init(adata->acp3x_base);
if (status)
return -ENODEV;
+
status = devm_snd_soc_register_component(&pdev->dev,
&acp3x_i2s_component,
- &acp3x_i2s_dai_driver, 1);
+ NULL, 0);
if (status) {
- dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+ dev_err(&pdev->dev, "Fail to register acp i2s component\n");
+ ret = -ENODEV;
goto dev_err;
}
status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
irqflags, "ACP3x_I2S_IRQ", adata);
if (status) {
dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
+ ret = -ENODEV;
goto dev_err;
}
- pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 5000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
+
dev_err:
status = acp3x_deinit(adata->acp3x_base);
if (status)
dev_err(&pdev->dev, "ACP de-init failed\n");
else
- dev_info(&pdev->dev, "ACP de-initialized\n");
- /*ignore device status and return driver probe error*/
- return -ENODEV;
+ dev_dbg(&pdev->dev, "ACP de-initialized\n");
+ return ret;
}
static int acp3x_audio_remove(struct platform_device *pdev)
{
+ struct i2s_dev_data *adata;
int ret;
- struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev);
+ adata = dev_get_drvdata(&pdev->dev);
ret = acp3x_deinit(adata->acp3x_base);
if (ret)
dev_err(&pdev->dev, "ACP de-init failed\n");
else
- dev_info(&pdev->dev, "ACP de-initialized\n");
+ dev_dbg(&pdev->dev, "ACP de-initialized\n");
pm_runtime_disable(&pdev->dev);
return 0;
@@ -693,10 +501,11 @@ static int acp3x_audio_remove(struct platform_device *pdev)
static int acp3x_resume(struct device *dev)
{
+ struct i2s_dev_data *adata;
int status;
u32 val;
- struct i2s_dev_data *adata = dev_get_drvdata(dev);
+ adata = dev_get_drvdata(dev);
status = acp3x_init(adata->acp3x_base);
if (status)
return -ENODEV;
@@ -738,14 +547,15 @@ static int acp3x_resume(struct device *dev)
static int acp3x_pcm_runtime_suspend(struct device *dev)
{
+ struct i2s_dev_data *adata;
int status;
- struct i2s_dev_data *adata = dev_get_drvdata(dev);
+ adata = dev_get_drvdata(dev);
status = acp3x_deinit(adata->acp3x_base);
if (status)
dev_err(dev, "ACP de-init failed\n");
else
- dev_info(dev, "ACP de-initialized\n");
+ dev_dbg(dev, "ACP de-initialized\n");
rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
@@ -754,8 +564,9 @@ static int acp3x_pcm_runtime_suspend(struct device *dev)
static int acp3x_pcm_runtime_resume(struct device *dev)
{
+ struct i2s_dev_data *adata;
int status;
- struct i2s_dev_data *adata = dev_get_drvdata(dev);
+ adata = dev_get_drvdata(dev);
status = acp3x_init(adata->acp3x_base);
if (status)
@@ -774,13 +585,14 @@ static struct platform_driver acp3x_dma_driver = {
.probe = acp3x_audio_probe,
.remove = acp3x_audio_remove,
.driver = {
- .name = "acp3x_rv_i2s",
+ .name = "acp3x_rv_i2s_dma",
.pm = &acp3x_pm_ops,
},
};
module_platform_driver(acp3x_dma_driver);
+MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati(a)amd.com");
MODULE_AUTHOR("Maruthi.Bayyavarapu(a)amd.com");
MODULE_AUTHOR("Vijendar.Mukunda(a)amd.com");
MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 2f15fe1..a6c6d63 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -51,6 +51,30 @@
#define SLOT_WIDTH_24 0x18
#define SLOT_WIDTH_32 0x20
+struct acp3x_platform_info {
+ u16 play_i2s_instance;
+ u16 cap_i2s_instance;
+ u16 capture_channel;
+};
+
+struct i2s_dev_data {
+ bool tdm_mode;
+ unsigned int i2s_irq;
+ u32 tdm_fmt;
+ u32 substream_type;
+ void __iomem *acp3x_base;
+ struct snd_pcm_substream *play_stream;
+ struct snd_pcm_substream *capture_stream;
+};
+
+struct i2s_stream_instance {
+ u16 num_pages;
+ u16 channels;
+ u32 xfer_resolution;
+ u64 bytescount;
+ dma_addr_t dma_addr;
+ void __iomem *acp3x_base;
+};
static inline u32 rv_readl(void __iomem *base_addr)
{
@@ -61,3 +85,22 @@ static inline void rv_writel(u32 val, void __iomem *base_addr)
{
writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS);
}
+
+static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,
+ int direction)
+{
+ u64 byte_count;
+
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ byte_count = rv_readl(rtd->acp3x_base +
+ mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
+ byte_count |= rv_readl(rtd->acp3x_base +
+ mmACP_BT_TX_LINEARPOSITIONCNTR_LOW);
+ } else {
+ byte_count = rv_readl(rtd->acp3x_base +
+ mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
+ byte_count |= rv_readl(rtd->acp3x_base +
+ mmACP_BT_RX_LINEARPOSITIONCNTR_LOW);
+ }
+ return byte_count;
+}
--
2.7.4
2
1
26 Dec '19
Dear Linux folks,
With
$ git describe --tags drm-tip/drm-tip
v5.5-rc3-1481-ga20d8cd6901a
the internal audio device is not available, and just a dummy device.
Running `alsa-info.sh` [1], the messages below are shown with the
problematic Linux kernel.
alsactl: get_controls:567: snd_ctl_open error: Sound protocol is
not compatible
cat: /tmp/alsa-info.ateDlDjrZX/alsactl.tmp: No such file or directory
Please find the output of `alsa-info.sh` with Linux 5.5-rc3 and drm-tip
attached.
Kind regards,
Paul
[1]: https://www.alsa-project.org/alsa-info.sh
2
3
[alsa-devel] broadwell-rt286: add support for hardware volume, conformance fixes
by GitHub pull_request - edited 26 Dec '19
by GitHub pull_request - edited 26 Dec '19
26 Dec '19
alsa-project/alsa-ucm-conf pull request #9 was edited from dpward:
This commit by @perexg fixes a regression on broadwell-rt286 which causes PulseAudio to abort on startup with:
`E: [pulseaudio] channelmap.c: Assertion 'pa_channels_valid(channels)' failed at pulse/channelmap.c:401, function pa_channel_map_init_extend(). Aborting.`
Request URL : https://github.com/alsa-project/alsa-ucm-conf/pull/9
Patch URL : https://github.com/alsa-project/alsa-ucm-conf/pull/9.patch
Repository URL: https://github.com/alsa-project/alsa-ucm-conf
1
0
[alsa-devel] broadwell-rt286: add support for hardware volume, conformance fixes
by GitHub pull_request - opened 26 Dec '19
by GitHub pull_request - opened 26 Dec '19
26 Dec '19
alsa-project/alsa-ucm-conf pull request #9 was opened from dpward:
This fixes a regression on broadwell-rt286.
Request URL : https://github.com/alsa-project/alsa-ucm-conf/pull/9
Patch URL : https://github.com/alsa-project/alsa-ucm-conf/pull/9.patch
Repository URL: https://github.com/alsa-project/alsa-ucm-conf
1
0
If SND_INTEL_DSP_CONFIG is m and SND_SOC_SOF_PCI is y,
building fails:
sound/soc/sof/sof-pci-dev.o: In function `sof_pci_probe':
sof-pci-dev.c:(.text+0xb4): undefined reference to `snd_intel_dsp_driver_probe'
Select SND_INTEL_DSP_CONFIG to fix this.
Reported-by: Hulk Robot <hulkci(a)huawei.com>
Fixes: 82d9d54a6c0e ("ALSA: hda: add Intel DSP configuration / probe code")
Signed-off-by: YueHaibing <yuehaibing(a)huawei.com>
---
sound/soc/sof/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 71a0fc0..e0b04b5 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -14,6 +14,7 @@ config SND_SOC_SOF_PCI
depends on PCI
select SND_SOC_SOF
select SND_SOC_ACPI if ACPI
+ select SND_INTEL_DSP_CONFIG
help
This adds support for PCI enumeration. This option is
required to enable Intel Skylake+ devices
--
2.7.4
2
2
26 Dec '19
From: Jeff Chang <jeff_chang(a)richtek.com>
The MT6660 is a boosted BTL class-D amplifier with V/I sensing.
A built-in DC-DC step-up converter is used to provide efficient
power for class-D amplifier with multi-level class-G operation.
The digital audio interface supports I2S, left-justified,
right-justified, TDM and DSP A/B format for audio in with a data
out used for chip information like voltage sense and current
sense, which are able to be monitored via DATAO through proper
Signed-off-by: Jeff Chang <jeff_chang(a)richtek.com>
---
Documentation/devicetree/bindings/sound/mt6660.txt | 53 ++
sound/soc/codecs/Kconfig | 11 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/mt6660.c | 628 +++++++++++++++++++++
sound/soc/codecs/mt6660.h | 75 +++
5 files changed, 769 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/mt6660.txt
create mode 100644 sound/soc/codecs/mt6660.c
create mode 100644 sound/soc/codecs/mt6660.h
changelogs between v4 & v3
- remove unnecessary kcontrols.
- modify copy right header.
- use dev_dbg instead of dev_info.
- add necessary debug message.
- add DT binding documentation.
- add space before } at every table.
changelogs between v3 & v2
- modify MT6660 Kconfig, remove unnecessary selection.
- remove my own debug io interface. use standard regmap for debugging.
- remove regmap volatile ops, we do not use cache.
- remove component io read/write function, use snd_soc_component_init_regmap.
- remove init setting write code. Using parsing dts to set them.
- remove unnecessary pr_info log message.
- remove mt6660_component_put_volsw. Using snd_soc_get_volsw.
diff --git a/Documentation/devicetree/bindings/sound/mt6660.txt b/Documentation/devicetree/bindings/sound/mt6660.txt
new file mode 100644
index 0000000..2a1736b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt6660.txt
@@ -0,0 +1,53 @@
+MT6660 MediaTek Speaker Amplifier
+
+This device supports I2C mode only.
+
+Required properties:
+
+ - compatible : "mediatek,mt6660"
+
+ - reg : The I2C slave address
+
+Optional properties:
+
+ - rt,init_setting_num : The initial register setting element number.
+
+ - rt,init_setting_addr : the addreses array for INIT Setting table.
+
+ - rt,init_setting_mask : the mask array for INIT Setting table.
+
+ - rt,init_setting_val : the value array for INIT Setting table.
+
+Example:
+
+ mt6660@34 {
+ status = "ok";
+ compatible = "mediatek,mt6660";
+ reg = <0x34>;
+ rt,init_setting_num = <26>;
+ rt,init_setting_addr =
+ <0x20 0x30 0x50 0xB1
+ 0xD3 0xE0 0x98 0xB9
+ 0xB7 0xB6 0x6B 0x07
+ 0xBB 0x69 0xBD 0x70
+ 0x7C 0x46 0x1A 0x1B
+ 0x51 0xA2 0x33 0x4C
+ 0x15 0x68>;
+ rt,init_setting_mask =
+ <0x80 0x01 0x1c 0x0c
+ 0x03 0x01 0x44 0xff
+ 0x7777 0x07 0xe0 0xff
+ 0xff 0xff 0xffff 0xff
+ 0xff 0xff 0xffffffff 0xffffffff
+ 0xff 0xff 0xffff 0xffff
+ 0x1800 0x1f>;
+ rt,init_setting_val =
+ <0x00 0x00 0x04 0x00
+ 0x03 0x00 0x04 0x82
+ 0x7273 0x03 0x20 0x70
+ 0x20 0x40 0x17f8 0x15
+ 0x00 0x1d 0x7fdb7ffe 0x7fdb7ffe
+ 0x58 0xce 0x7fff 0x0116
+ 0x0800 0x07>;
+ };
+
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 229cc89..f135fbb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -122,6 +122,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ML26124 if I2C
select SND_SOC_MT6351 if MTK_PMIC_WRAP
select SND_SOC_MT6358 if MTK_PMIC_WRAP
+ select SND_SOC_MT6660 if I2C
select SND_SOC_NAU8540 if I2C
select SND_SOC_NAU8810 if I2C
select SND_SOC_NAU8822 if I2C
@@ -1465,6 +1466,16 @@ config SND_SOC_MT6358
Enable support for the platform which uses MT6358 as
external codec device.
+config SND_SOC_MT6660
+ tristate "Mediatek MT6660 Speaker Amplifier"
+ depends on I2C
+ help
+ MediaTek MT6660 is a smart power amplifier which contain
+ speaker protection, multi-band DRC, equalizer functions.
+ Select N if you don't have MT6660 on board.
+ Select M to build this as module.
+
+
config SND_SOC_NAU8540
tristate "Nuvoton Technology Corporation NAU85L40 CODEC"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index c498373..2b6814c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -119,6 +119,7 @@ snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o
snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o
snd-soc-mt6351-objs := mt6351.o
snd-soc-mt6358-objs := mt6358.o
+snd-soc-mt6660-objs := mt6660.o
snd-soc-nau8540-objs := nau8540.o
snd-soc-nau8810-objs := nau8810.o
snd-soc-nau8822-objs := nau8822.o
@@ -403,6 +404,7 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o
obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o
obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o
obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o
+obj-$(CONFIG_SND_SOC_MT6660) += snd-soc-mt6660.o
obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o
obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o
obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
new file mode 100644
index 0000000..b8fc53b
--- /dev/null
+++ b/sound/soc/codecs/mt6660.c
@@ -0,0 +1,628 @@
+// SPDX-License-Identifier: GPL-2.0 //
+
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/pcm_params.h>
+#include <linux/debugfs.h>
+
+#include "mt6660.h"
+
+struct codec_reg_val {
+ u32 addr;
+ u32 mask;
+ u32 data;
+};
+
+struct reg_size_table {
+ u32 addr;
+ u8 size;
+};
+
+static const struct reg_size_table mt6660_reg_size_table[] = {
+ { MT6660_REG_HPF1_COEF, 4 },
+ { MT6660_REG_HPF2_COEF, 4 },
+ { MT6660_REG_TDM_CFG3, 2 },
+ { MT6660_REG_RESV17, 2 },
+ { MT6660_REG_RESV23, 2 },
+ { MT6660_REG_SIGMAX, 2 },
+ { MT6660_REG_DEVID, 2 },
+ { MT6660_REG_HCLIP_CTRL, 2 },
+ { MT6660_REG_DA_GAIN, 2 },
+};
+
+static int mt6660_get_reg_size(uint32_t addr)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mt6660_reg_size_table); i++) {
+ if (mt6660_reg_size_table[i].addr == addr)
+ return mt6660_reg_size_table[i].size;
+ }
+ return 1;
+}
+
+static int mt6660_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mt6660_chip *chip = context;
+ int size = mt6660_get_reg_size(reg);
+ u8 reg_data[4] = {0};
+ int i = 0, ret = 0;
+
+ for (i = 0; i < size; i++)
+ reg_data[size - i - 1] = (val >> (8 * i)) & 0xff;
+
+ ret = i2c_smbus_write_i2c_block_data(chip->i2c, reg, size, reg_data);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int mt6660_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mt6660_chip *chip = context;
+ int size = mt6660_get_reg_size(reg);
+ int i = 0, ret = 0;
+ u8 data[4] = {0};
+ u32 reg_data = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(chip->i2c, reg, size, data);
+ if (ret < 0)
+ return ret;
+ for (i = 0; i < size; i++) {
+ reg_data <<= 8;
+ reg_data |= data[i];
+ }
+ *val = reg_data;
+ return 0;
+}
+
+static struct regmap_config mt6660_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_write = mt6660_reg_write,
+ .reg_read = mt6660_reg_read,
+};
+
+static int mt6660_codec_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(1000, 1100);
+ break;
+ }
+ return 0;
+}
+
+static int mt6660_codec_classd_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_dbg(component->dev,
+ "%s: before classd turn on\n", __func__);
+ /* config to adaptive mode */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_BST_CTRL, 0x03, 0x03);
+ if (ret < 0) {
+ dev_err(component->dev, "config mode adaptive fail\n");
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* voltage sensing enable */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV7, 0x04, 0x04);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "enable voltage sensing fail\n");
+ return ret;
+ }
+ dev_dbg(component->dev, "Amp on\n");
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ dev_dbg(component->dev, "Amp off\n");
+ /* voltage sensing disable */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV7, 0x04, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "disable voltage sensing fail\n");
+ return ret;
+ }
+ /* pop-noise improvement 1 */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV10, 0x10, 0x10);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "pop-noise improvement 1 fail\n");
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_dbg(component->dev,
+ "%s: after classd turn off\n", __func__);
+ /* pop-noise improvement 2 */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_RESV10, 0x10, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "pop-noise improvement 2 fail\n");
+ return ret;
+ }
+ /* config to off mode */
+ ret = snd_soc_component_update_bits(component,
+ MT6660_REG_BST_CTRL, 0x03, 0x00);
+ if (ret < 0) {
+ dev_err(component->dev, "config mode off fail\n");
+ return ret;
+ }
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget mt6660_component_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC_E("DAC", NULL, MT6660_REG_PLL_CFG1,
+ 0, 1, mt6660_codec_dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC("VI ADC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV_E("ClassD", MT6660_REG_SYSTEM_CTRL, 2, 0,
+ NULL, 0, mt6660_codec_classd_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUTPUT("OUTP"),
+ SND_SOC_DAPM_OUTPUT("OUTN"),
+};
+
+static const struct snd_soc_dapm_route mt6660_component_dapm_routes[] = {
+ { "DAC", NULL, "aif_playback" },
+ { "PGA", NULL, "DAC" },
+ { "ClassD", NULL, "PGA" },
+ { "OUTP", NULL, "ClassD" },
+ { "OUTN", NULL, "ClassD" },
+ { "VI ADC", NULL, "ClassD" },
+ { "aif_capture", NULL, "VI ADC" },
+};
+
+static int mt6660_component_get_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct mt6660_chip *chip = (struct mt6660_chip *)
+ snd_soc_component_get_drvdata(component);
+ int ret = -EINVAL;
+
+ if (!strcmp(kcontrol->id.name, "Chip Rev")) {
+ ucontrol->value.integer.value[0] = chip->chip_rev & 0x0f;
+ ret = 0;
+ }
+ return ret;
+}
+
+static const DECLARE_TLV_DB_SCALE(vol_ctl_tlv, -1155, 5, 0);
+
+static const struct snd_kcontrol_new mt6660_component_snd_controls[] = {
+ SOC_SINGLE_TLV("Digital Volume", MT6660_REG_VOL_CTRL, 0, 255,
+ 1, vol_ctl_tlv),
+ SOC_SINGLE("Hard Clip Switch", MT6660_REG_HCLIP_CTRL, 8, 1, 0),
+ SOC_SINGLE("Clip Switch", MT6660_REG_SPS_CTRL, 0, 1, 0),
+ SOC_SINGLE("Boost Mode", MT6660_REG_BST_CTRL, 0, 3, 0),
+ SOC_SINGLE("DRE Switch", MT6660_REG_DRE_CTRL, 0, 1, 0),
+ SOC_SINGLE("DC Protect Switch", MT6660_REG_DC_PROTECT_CTRL, 3, 1, 0),
+ SOC_SINGLE("Data Output Left Channel Selection",
+ MT6660_REG_DATAO_SEL, 3, 7, 0),
+ SOC_SINGLE("Data Output Right Channel Selection",
+ MT6660_REG_DATAO_SEL, 0, 7, 0),
+ SOC_SINGLE_EXT("T0 SEL", MT6660_REG_CALI_T0, 0, 7, 0,
+ snd_soc_get_volsw, NULL),
+ SOC_SINGLE_EXT("Chip Rev", MT6660_REG_DEVID, 8, 15, 0,
+ mt6660_component_get_volsw, NULL),
+};
+
+static inline int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off)
+{
+ u8 reg_data = 0;
+ int ret = 0;
+
+ ret = i2c_smbus_read_byte_data(chip->i2c, MT6660_REG_SYSTEM_CTRL);
+ if (ret < 0)
+ return ret;
+ reg_data = (u8)ret;
+ if (on_off)
+ reg_data &= (~0x01);
+ else
+ reg_data |= 0x01;
+ return regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, reg_data);
+}
+
+static int mt6660_apply_plat_data(struct mt6660_chip *chip,
+ struct snd_soc_component *component)
+{
+ size_t i = 0;
+ int num = chip->plat_data.init_setting_num;
+ int ret = 0;
+
+ ret = _mt6660_chip_power_on(chip, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s power on failed\n", __func__);
+ return ret;
+ }
+
+ for (i = 0; i < num; i++) {
+ ret = snd_soc_component_update_bits(component,
+ chip->plat_data.init_setting_addr[i],
+ chip->plat_data.init_setting_mask[i],
+ chip->plat_data.init_setting_val[i]);
+ if (ret < 0)
+ return ret;
+ }
+ ret = _mt6660_chip_power_on(chip, 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "%s power on failed\n", __func__);
+ return ret;
+ }
+ return 0;
+}
+
+static int mt6660_component_probe(struct snd_soc_component *component)
+{
+ struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
+ int ret = 0;
+
+ dev_dbg(component->dev, "%s\n", __func__);
+ snd_soc_component_init_regmap(component, chip->regmap);
+
+ ret = mt6660_apply_plat_data(chip, component);
+ if (ret < 0)
+ dev_err(chip->dev, "mt6660 apply plat data failed\n");
+
+ return ret;
+}
+
+static void mt6660_component_remove(struct snd_soc_component *component)
+{
+ dev_dbg(component->dev, "%s\n", __func__);
+ snd_soc_component_exit_regmap(component);
+}
+
+static const struct snd_soc_component_driver mt6660_component_driver = {
+ .probe = mt6660_component_probe,
+ .remove = mt6660_component_remove,
+
+ .controls = mt6660_component_snd_controls,
+ .num_controls = ARRAY_SIZE(mt6660_component_snd_controls),
+ .dapm_widgets = mt6660_component_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt6660_component_dapm_widgets),
+ .dapm_routes = mt6660_component_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt6660_component_dapm_routes),
+
+ .idle_bias_on = false, /* idle_bias_off = true */
+};
+
+static int mt6660_component_aif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
+{
+ int word_len = params_physical_width(hw_params);
+ int aud_bit = params_width(hw_params);
+ u16 reg_data = 0;
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: ++\n", __func__);
+ dev_dbg(dai->dev, "format: 0x%08x\n", params_format(hw_params));
+ dev_dbg(dai->dev, "rate: 0x%08x\n", params_rate(hw_params));
+ dev_dbg(dai->dev, "word_len: %d, aud_bit: %d\n", word_len, aud_bit);
+ if (word_len > 32 || word_len < 16) {
+ dev_err(dai->dev, "not supported word length\n");
+ return -ENOTSUPP;
+ }
+ switch (aud_bit) {
+ case 16:
+ reg_data = 3;
+ break;
+ case 18:
+ reg_data = 2;
+ break;
+ case 20:
+ reg_data = 1;
+ break;
+ case 24:
+ case 32:
+ reg_data = 0;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ ret = snd_soc_component_update_bits(dai->component,
+ MT6660_REG_SERIAL_CFG1, 0xc0, (reg_data << 6));
+ if (ret < 0) {
+ dev_err(dai->dev, "config aud bit fail\n");
+ return ret;
+ }
+ ret = snd_soc_component_update_bits(dai->component,
+ MT6660_REG_TDM_CFG3, 0x3f0, word_len << 4);
+ if (ret < 0) {
+ dev_err(dai->dev, "config word len fail\n");
+ return ret;
+ }
+ dev_dbg(dai->dev, "%s: --\n", __func__);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mt6660_component_aif_ops = {
+ .hw_params = mt6660_component_aif_hw_params,
+};
+
+#define STUB_RATES SNDRV_PCM_RATE_8000_192000
+#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_U24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_U32_LE)
+
+static struct snd_soc_dai_driver mt6660_codec_dai = {
+ .name = "mt6660-aif",
+ .playback = {
+ .stream_name = "aif_playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = STUB_RATES,
+ .formats = STUB_FORMATS,
+ },
+ .capture = {
+ .stream_name = "aif_capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = STUB_RATES,
+ .formats = STUB_FORMATS,
+ },
+ /* dai properties */
+ .symmetric_rates = 1,
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+ /* dai operations */
+ .ops = &mt6660_component_aif_ops,
+};
+
+static inline int _mt6660_chip_id_check(struct mt6660_chip *chip)
+{
+ u8 id[2] = {0};
+ int ret = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(chip->i2c, MT6660_REG_DEVID, 2, id);
+ if (ret < 0)
+ return ret;
+ ret = (id[0] << 8) + id[1];
+ ret &= 0x0ff0;
+ if (ret != 0x00e0 && ret != 0x01e0) {
+ dev_err(chip->dev, "%s id(%x) not match\n", __func__, ret);
+ return -ENODEV;
+ }
+ return ret;
+}
+
+static inline int _mt6660_chip_sw_reset(struct mt6660_chip *chip)
+{
+ int ret;
+
+ /* turn on main pll first, then trigger reset */
+ ret = regmap_write(chip->regmap, 0x03, 0x00);
+ if (ret < 0)
+ return ret;
+ ret = regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, 0x80);
+ msleep(30);
+ return 0;
+}
+
+static inline int _mt6660_read_chip_revision(struct mt6660_chip *chip)
+{
+ u8 reg_data[2] = {0};
+ int ret = 0;
+
+ ret = i2c_smbus_read_i2c_block_data(
+ chip->i2c, MT6660_REG_DEVID, 2, reg_data);
+ if (ret < 0) {
+ dev_err(chip->dev, "get chip revision fail\n");
+ return ret;
+ }
+ chip->chip_rev = reg_data[1];
+ return 0;
+}
+
+static int mt6660_parse_dt(struct mt6660_chip *chip, struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ u32 val;
+ size_t i = 0;
+
+ if (!np) {
+ dev_err(dev, "no device node\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(np, "rt,init_setting_num", &val)) {
+ dev_err(dev, "no init setting\n");
+ chip->plat_data.init_setting_num = 0;
+ } else {
+ chip->plat_data.init_setting_num = val;
+ }
+
+ chip->plat_data.init_setting_addr =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+ chip->plat_data.init_setting_mask =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+ chip->plat_data.init_setting_val =
+ devm_kzalloc(dev, sizeof(u32) *
+ chip->plat_data.init_setting_num, GFP_KERNEL);
+
+ if (of_property_read_u32_array(np, "rt,init_setting_addr",
+ chip->plat_data.init_setting_addr,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+ if (of_property_read_u32_array(np, "rt,init_setting_mask",
+ chip->plat_data.init_setting_mask,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+ if (of_property_read_u32_array(np, "rt,init_setting_val",
+ chip->plat_data.init_setting_val,
+ chip->plat_data.init_setting_num)) {
+ dev_err(dev, "no init setting addr\n");
+ }
+
+ dev_dbg(dev, "%s, init stting table, num = %d\n", __func__,
+ chip->plat_data.init_setting_num);
+ for (i = 0; i < chip->plat_data.init_setting_num; i++) {
+ dev_dbg(dev, "0x%02x, 0x%08x, 0x%08x\n",
+ chip->plat_data.init_setting_addr[i],
+ chip->plat_data.init_setting_mask[i],
+ chip->plat_data.init_setting_val[i]);
+ }
+ return 0;
+}
+
+static int mt6660_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mt6660_chip *chip = NULL;
+ int ret = 0;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ chip->i2c = client;
+ chip->dev = &client->dev;
+ mutex_init(&chip->io_lock);
+ i2c_set_clientdata(client, chip);
+
+ ret = mt6660_parse_dt(chip, &client->dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "parsing dts failed\n");
+ return ret;
+ }
+
+ chip->regmap = devm_regmap_init(&client->dev,
+ NULL, chip, &mt6660_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ ret = PTR_ERR(chip->regmap);
+ dev_err(&client->dev, "failed to initialise regmap: %d\n", ret);
+ return ret;
+ }
+
+ /* chip reset first */
+ ret = _mt6660_chip_sw_reset(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip reset fail\n");
+ goto probe_fail;
+ }
+ /* chip power on */
+ ret = _mt6660_chip_power_on(chip, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip power on 2 fail\n");
+ goto probe_fail;
+ }
+ /* chip devid check */
+ ret = _mt6660_chip_id_check(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "chip id check fail\n");
+ goto probe_fail;
+ }
+ /* chip revision get */
+ ret = _mt6660_read_chip_revision(chip);
+ if (ret < 0) {
+ dev_err(chip->dev, "read chip revision fail\n");
+ goto probe_fail;
+ }
+ pm_runtime_set_active(chip->dev);
+ pm_runtime_enable(chip->dev);
+
+ ret = devm_snd_soc_register_component(chip->dev,
+ &mt6660_component_driver,
+ &mt6660_codec_dai, 1);
+ return ret;
+probe_fail:
+ _mt6660_chip_power_on(chip, 0);
+ mutex_destroy(&chip->io_lock);
+ return ret;
+}
+
+static int mt6660_i2c_remove(struct i2c_client *client)
+{
+ struct mt6660_chip *chip = i2c_get_clientdata(client);
+
+ pm_runtime_disable(chip->dev);
+ pm_runtime_set_suspended(chip->dev);
+ mutex_destroy(&chip->io_lock);
+ return 0;
+}
+
+static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev)
+{
+ struct mt6660_chip *chip = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "enter low power mode\n");
+ return regmap_update_bits(chip->regmap,
+ MT6660_REG_SYSTEM_CTRL, 0x01, 0x01);
+}
+
+static int __maybe_unused mt6660_i2c_runtime_resume(struct device *dev)
+{
+ struct mt6660_chip *chip = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "exit low power mode\n");
+ return regmap_update_bits(chip->regmap,
+ MT6660_REG_SYSTEM_CTRL, 0x01, 0x00);
+}
+
+static const struct dev_pm_ops mt6660_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(mt6660_i2c_runtime_suspend,
+ mt6660_i2c_runtime_resume, NULL)
+};
+
+static const struct of_device_id __maybe_unused mt6660_of_id[] = {
+ { .compatible = "mediatek,mt6660",},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt6660_of_id);
+
+static const struct i2c_device_id mt6660_i2c_id[] = {
+ {"mt6660", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id);
+
+static struct i2c_driver mt6660_i2c_driver = {
+ .driver = {
+ .name = "mt6660",
+ .of_match_table = of_match_ptr(mt6660_of_id),
+ .pm = &mt6660_dev_pm_ops,
+ },
+ .probe = mt6660_i2c_probe,
+ .remove = mt6660_i2c_remove,
+ .id_table = mt6660_i2c_id,
+};
+module_i2c_driver(mt6660_i2c_driver);
+
+MODULE_AUTHOR("Jeff Chang <jeff_chang(a)richtek.com>");
+MODULE_DESCRIPTION("MT6660 SPKAMP Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.7_G");
diff --git a/sound/soc/codecs/mt6660.h b/sound/soc/codecs/mt6660.h
new file mode 100644
index 0000000..6c40b40
--- /dev/null
+++ b/sound/soc/codecs/mt6660.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __SND_SOC_MT6660_H
+#define __SND_SOC_MT6660_H
+
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+struct mt6660_platform_data {
+ u8 init_setting_num;
+ u32 *init_setting_addr;
+ u32 *init_setting_mask;
+ u32 *init_setting_val;
+};
+
+struct mt6660_chip {
+ struct i2c_client *i2c;
+ struct device *dev;
+ struct platform_device *param_dev;
+ struct mt6660_platform_data plat_data;
+ struct mutex io_lock;
+ struct regmap *regmap;
+ u16 chip_rev;
+};
+
+#define MT6660_REG_DEVID (0x00)
+#define MT6660_REG_SYSTEM_CTRL (0x03)
+#define MT6660_REG_IRQ_STATUS1 (0x05)
+#define MT6660_REG_ADDA_CLOCK (0x07)
+#define MT6660_REG_SERIAL_CFG1 (0x10)
+#define MT6660_REG_DATAO_SEL (0x12)
+#define MT6660_REG_TDM_CFG3 (0x15)
+#define MT6660_REG_HPF_CTRL (0x18)
+#define MT6660_REG_HPF1_COEF (0x1A)
+#define MT6660_REG_HPF2_COEF (0x1B)
+#define MT6660_REG_PATH_BYPASS (0x1E)
+#define MT6660_REG_WDT_CTRL (0x20)
+#define MT6660_REG_HCLIP_CTRL (0x24)
+#define MT6660_REG_VOL_CTRL (0x29)
+#define MT6660_REG_SPS_CTRL (0x30)
+#define MT6660_REG_SIGMAX (0x33)
+#define MT6660_REG_CALI_T0 (0x3F)
+#define MT6660_REG_BST_CTRL (0x40)
+#define MT6660_REG_PROTECTION_CFG (0x46)
+#define MT6660_REG_DA_GAIN (0x4c)
+#define MT6660_REG_AUDIO_IN2_SEL (0x50)
+#define MT6660_REG_SIG_GAIN (0x51)
+#define MT6660_REG_PLL_CFG1 (0x60)
+#define MT6660_REG_DRE_CTRL (0x68)
+#define MT6660_REG_DRE_THDMODE (0x69)
+#define MT6660_REG_DRE_CORASE (0x6B)
+#define MT6660_REG_PWM_CTRL (0x70)
+#define MT6660_REG_DC_PROTECT_CTRL (0x74)
+#define MT6660_REG_ADC_USB_MODE (0x7c)
+#define MT6660_REG_INTERNAL_CFG (0x88)
+#define MT6660_REG_RESV0 (0x98)
+#define MT6660_REG_RESV1 (0x99)
+#define MT6660_REG_RESV2 (0x9A)
+#define MT6660_REG_RESV3 (0x9B)
+#define MT6660_REG_RESV6 (0xA2)
+#define MT6660_REG_RESV7 (0xA3)
+#define MT6660_REG_RESV10 (0xB0)
+#define MT6660_REG_RESV11 (0xB1)
+#define MT6660_REG_RESV16 (0xB6)
+#define MT6660_REG_RESV17 (0xB7)
+#define MT6660_REG_RESV19 (0xB9)
+#define MT6660_REG_RESV21 (0xBB)
+#define MT6660_REG_RESV23 (0xBD)
+#define MT6660_REG_RESV31 (0xD3)
+#define MT6660_REG_RESV40 (0xE0)
+
+#endif /* __SND_SOC_MT6660_H */
--
2.7.4
1
0
[alsa-devel] Applied "ASoC: dt-bindings: add dt bindings for WCD9340/WCD9341 audio codec" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: dt-bindings: add dt bindings for WCD9340/WCD9341 audio codec
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From a6b748713205242d1483a78662bf147b1aa7d90b Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:43 +0000
Subject: [PATCH] ASoC: dt-bindings: add dt bindings for WCD9340/WCD9341 audio
codec
This patch adds bindings for wcd9340/wcd9341 audio codec which can
support both SLIMbus and I2S/I2C interface.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Reviewed-by: Rob Herring <robh(a)kernel.org>
Link: https://lore.kernel.org/r/20191219103153.14875-2-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
.../bindings/sound/qcom,wcd934x.yaml | 175 ++++++++++++++++++
1 file changed, 175 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml
diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml
new file mode 100644
index 000000000000..38eaf0c028f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,wcd934x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bindings for Qualcomm WCD9340/WCD9341 Audio Codec
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
+
+description: |
+ Qualcomm WCD9340/WCD9341 Codec is a standalone Hi-Fi audio codec IC.
+ It has in-built Soundwire controller, pin controller, interrupt mux and
+ supports both I2S/I2C and SLIMbus audio interfaces.
+
+properties:
+ compatible:
+ const: slim217,250
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ description: GPIO spec for reset line to use
+ maxItems: 1
+
+ slim-ifc-dev: true
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: extclk
+
+ vdd-buck-supply:
+ description: A reference to the 1.8V buck supply
+
+ vdd-buck-sido-supply:
+ description: A reference to the 1.8V SIDO buck supply
+
+ vdd-rx-supply:
+ description: A reference to the 1.8V rx supply
+
+ vdd-tx-supply:
+ description: A reference to the 1.8V tx supply
+
+ vdd-vbat-supply:
+ description: A reference to the vbat supply
+
+ vdd-io-supply:
+ description: A reference to the 1.8V I/O supply
+
+ vdd-micbias-supply:
+ description: A reference to the micbias supply
+
+ qcom,micbias1-microvolt:
+ description: micbias1 voltage
+ minimum: 1800000
+ maximum: 2850000
+
+ qcom,micbias2-microvolt:
+ description: micbias2 voltage
+ minimum: 1800000
+ maximum: 2850000
+
+ qcom,micbias3-microvolt:
+ description: micbias3 voltage
+ minimum: 1800000
+ maximum: 2850000
+
+ qcom,micbias4-microvolt:
+ description: micbias4 voltage
+ minimum: 1800000
+ maximum: 2850000
+
+ clock-output-names:
+ const: mclk
+
+ clock-frequency:
+ description: Clock frequency of output clk in Hz
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 1
+
+ '#clock-cells':
+ const: 0
+
+ '#sound-dai-cells':
+ const: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ gpio@42:
+ type: object
+ allOf:
+ - $ref: ../gpio/qcom,wcd934x-gpio.yaml#
+
+patternProperties:
+ "^.*@[0-9a-f]+$":
+ type: object
+ description: |
+ WCD934x subnode for each slave devices. Bindings of each subnodes
+ depends on the specific driver providing the functionality and
+ documented in their respective bindings.
+
+ properties:
+ reg:
+ maxItems: 1
+
+ required:
+ - reg
+
+required:
+ - compatible
+ - reg
+ - reset-gpios
+ - slim-ifc-dev
+ - interrupts
+ - interrupt-controller
+ - clock-frequency
+ - clock-output-names
+ - qcom,micbias1-microvolt
+ - qcom,micbias2-microvolt
+ - qcom,micbias3-microvolt
+ - qcom,micbias4-microvolt
+ - "#interrupt-cells"
+ - "#clock-cells"
+ - "#sound-dai-cells"
+ - "#address-cells"
+ - "#size-cells"
+
+examples:
+ - |
+ codec@1,0{
+ compatible = "slim217,250";
+ reg = <1 0>;
+ reset-gpios = <&tlmm 64 0>;
+ slim-ifc-dev = <&wcd9340_ifd>;
+ #sound-dai-cells = <1>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <54 4>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ #clock-cells = <0>;
+ clock-frequency = <9600000>;
+ clock-output-names = "mclk";
+ qcom,micbias1-microvolt = <1800000>;
+ qcom,micbias2-microvolt = <1800000>;
+ qcom,micbias3-microvolt = <1800000>;
+ qcom,micbias4-microvolt = <1800000>;
+ clock-names = "extclk";
+ clocks = <&rpmhcc 2>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ gpio@42 {
+ compatible = "qcom,wcd9340-gpio";
+ reg = <0x42 0x2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+...
--
2.20.1
1
0
25 Dec '19
The patch
ASoC: wcd934x: add basic controls
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 1cde8b82233275a72db34a8c1efa4cf6cc8c894f Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:46 +0000
Subject: [PATCH] ASoC: wcd934x: add basic controls
This patch adds basic controls found in wcd934x codec.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-5-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 506 +++++++++++++++++++++++++++++++++++++
1 file changed, 506 insertions(+)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 825cf057e8b7..27a864f2ff77 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -120,6 +120,21 @@
#define WCD934X_DEF_MICBIAS_MV 1800
#define WCD934X_MAX_MICBIAS_MV 2850
+#define WCD_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX)
+
+#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = wcd934x_iir_filter_info, \
+ .get = wcd934x_get_iir_band_audio_mixer, \
+ .put = wcd934x_put_iir_band_audio_mixer, \
+ .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \
+ .iir_idx = iidx, \
+ .band_idx = bidx, \
+ .bytes_ext = {.max = WCD_IIR_FILTER_SIZE, }, \
+ } \
+}
+
enum {
SIDO_SOURCE_INTERNAL,
SIDO_SOURCE_RCO_BG,
@@ -217,6 +232,35 @@ static const struct wcd934x_slim_ch wcd934x_rx_chs[WCD934X_RX_MAX] = {
WCD934X_SLIM_RX_CH(12),
};
+/* Codec supports 2 IIR filters */
+enum {
+ IIR0 = 0,
+ IIR1,
+ IIR_MAX,
+};
+
+/* Each IIR has 5 Filter Stages */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+enum {
+ COMPANDER_1, /* HPH_L */
+ COMPANDER_2, /* HPH_R */
+ COMPANDER_3, /* LO1_DIFF */
+ COMPANDER_4, /* LO2_DIFF */
+ COMPANDER_5, /* LO3_SE - not used in Tavil */
+ COMPANDER_6, /* LO4_SE - not used in Tavil */
+ COMPANDER_7, /* SWR SPK CH1 */
+ COMPANDER_8, /* SWR SPK CH2 */
+ COMPANDER_MAX,
+};
+
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -335,12 +379,112 @@ struct wcd934x_codec {
int dmic_2_3_clk_cnt;
int dmic_4_5_clk_cnt;
int dmic_sample_rate;
+ int comp_enabled[COMPANDER_MAX];
int sysclk_users;
struct mutex sysclk_mutex;
};
#define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw)
+struct wcd_iir_filter_ctl {
+ unsigned int iir_idx;
+ unsigned int band_idx;
+ struct soc_bytes_ext bytes_ext;
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);
+
+/* Cutoff frequency for high pass filter */
+static const char * const cf_text[] = {
+ "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
+};
+
+static const char * const rx_cf_text[] = {
+ "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
+ "CF_NEG_3DB_0P48HZ"
+};
+
+static const char * const rx_hph_mode_mux_text[] = {
+ "Class H Invalid", "Class-H Hi-Fi", "Class-H Low Power", "Class-AB",
+ "Class-H Hi-Fi Low Power"
+};
+
+static const struct soc_enum cf_dec0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX1_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX2_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX3_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX4_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX5_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX6_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX7_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_dec8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX8_TX_PATH_CFG0, 5, 3, cf_text);
+
+static const struct soc_enum cf_int0_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX0_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD934X_CDC_RX0_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int1_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX1_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD934X_CDC_RX1_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int2_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX2_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD934X_CDC_RX2_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int3_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX3_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD934X_CDC_RX3_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int4_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX4_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD934X_CDC_RX4_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int7_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX7_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD934X_CDC_RX7_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum cf_int8_1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX8_RX_PATH_CFG2, 0, 4, rx_cf_text);
+
+static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD934X_CDC_RX8_RX_PATH_MIX_CFG, 2,
+ rx_cf_text);
+
+static const struct soc_enum rx_hph_mode_mux_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
+ rx_hph_mode_mux_text);
+
static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd,
int sido_src)
{
@@ -1479,10 +1623,372 @@ static int wcd934x_comp_set_sysclk(struct snd_soc_component *comp,
return clk_set_rate(wcd->extclk, freq);
}
+static uint32_t get_iir_band_coeff(struct snd_soc_component *component,
+ int iir_idx, int band_idx, int coeff_idx)
+{
+ u32 value = 0;
+ int reg, b2_reg;
+
+ /* Address does not automatically update if reading */
+ reg = WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+ b2_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx) *
+ sizeof(uint32_t)) & 0x7F);
+
+ value |= snd_soc_component_read32(component, b2_reg);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 1) & 0x7F);
+
+ value |= (snd_soc_component_read32(component, b2_reg) << 8);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 2) & 0x7F);
+
+ value |= (snd_soc_component_read32(component, b2_reg) << 16);
+ snd_soc_component_write(component, reg,
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 3) & 0x7F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ value |= (snd_soc_component_read32(component, b2_reg) << 24);
+ return value;
+}
+
+static void set_iir_band_coeff(struct snd_soc_component *component,
+ int iir_idx, int band_idx, uint32_t value)
+{
+ int reg = WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+ snd_soc_component_write(component, reg, (value & 0xFF));
+ snd_soc_component_write(component, reg, (value >> 8) & 0xFF);
+ snd_soc_component_write(component, reg, (value >> 16) & 0xFF);
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_component_write(component, reg, (value >> 24) & 0x3F);
+}
+
+static int wcd934x_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+ int iir_idx = ctl->iir_idx;
+ int band_idx = ctl->band_idx;
+ u32 coeff[BAND_MAX];
+ int reg = WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx;
+
+ memcpy(&coeff[0], ucontrol->value.bytes.data, params->max);
+
+ /* Mask top bit it is reserved */
+ /* Updates addr automatically for each B2 write */
+ snd_soc_component_write(component, reg, (band_idx * BAND_MAX *
+ sizeof(uint32_t)) & 0x7F);
+
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]);
+ set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]);
+
+ return 0;
+}
+
+static int wcd934x_get_iir_band_audio_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component =
+ snd_soc_kcontrol_component(kcontrol);
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+ int iir_idx = ctl->iir_idx;
+ int band_idx = ctl->band_idx;
+ u32 coeff[BAND_MAX];
+
+ coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0);
+ coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1);
+ coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2);
+ coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3);
+ coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4);
+
+ memcpy(ucontrol->value.bytes.data, &coeff[0], params->max);
+
+ return 0;
+}
+
+static int wcd934x_iir_filter_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *ucontrol)
+{
+ struct wcd_iir_filter_ctl *ctl =
+ (struct wcd_iir_filter_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+
+ ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ ucontrol->count = params->max;
+
+ return 0;
+}
+
+static int wcd934x_compander_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
+ int comp = ((struct soc_mixer_control *)kc->private_value)->shift;
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+
+ ucontrol->value.integer.value[0] = wcd->comp_enabled[comp];
+
+ return 0;
+}
+
+static int wcd934x_compander_set(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+ int comp = ((struct soc_mixer_control *)kc->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+ int sel;
+
+ wcd->comp_enabled[comp] = value;
+ sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER :
+ WCD934X_HPH_GAIN_SRC_SEL_REGISTER;
+
+ /* Any specific register configuration for compander */
+ switch (comp) {
+ case COMPANDER_1:
+ /* Set Gain Source Select based on compander enable/disable */
+ snd_soc_component_update_bits(component, WCD934X_HPH_L_EN,
+ WCD934X_HPH_GAIN_SRC_SEL_MASK,
+ sel);
+ break;
+ case COMPANDER_2:
+ snd_soc_component_update_bits(component, WCD934X_HPH_R_EN,
+ WCD934X_HPH_GAIN_SRC_SEL_MASK,
+ sel);
+ break;
+ case COMPANDER_3:
+ case COMPANDER_4:
+ case COMPANDER_7:
+ case COMPANDER_8:
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+
+ ucontrol->value.enumerated.item[0] = wcd->hph_mode;
+
+ return 0;
+}
+
+static int wcd934x_rx_hph_mode_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+ u32 mode_val;
+
+ mode_val = ucontrol->value.enumerated.item[0];
+
+ if (mode_val == 0) {
+ dev_err(wcd->dev, "Invalid HPH Mode, default to ClSH HiFi\n");
+ mode_val = CLS_H_LOHIFI;
+ }
+ wcd->hph_mode = mode_val;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
+ /* Gain Controls */
+ SOC_SINGLE_TLV("EAR PA Volume", WCD934X_ANA_EAR, 4, 4, 1, ear_pa_gain),
+ SOC_SINGLE_TLV("HPHL Volume", WCD934X_HPH_L_EN, 0, 24, 1, line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", WCD934X_HPH_R_EN, 0, 24, 1, line_gain),
+ SOC_SINGLE_TLV("LINEOUT1 Volume", WCD934X_DIFF_LO_LO1_COMPANDER,
+ 3, 16, 1, line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", WCD934X_DIFF_LO_LO2_COMPANDER,
+ 3, 16, 1, line_gain),
+
+ SOC_SINGLE_TLV("ADC1 Volume", WCD934X_ANA_AMIC1, 0, 20, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", WCD934X_ANA_AMIC2, 0, 20, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain),
+
+ SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL,
+ -84, 40, digital_gain), /* -84dB min - 40dB max */
+ SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume",
+ WCD934X_CDC_RX0_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume",
+ WCD934X_CDC_RX1_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume",
+ WCD934X_CDC_RX2_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume",
+ WCD934X_CDC_RX3_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume",
+ WCD934X_CDC_RX4_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume",
+ WCD934X_CDC_RX7_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume",
+ WCD934X_CDC_RX8_RX_VOL_MIX_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("IIR0 INP0 Volume",
+ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP1 Volume",
+ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP2 Volume",
+ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR0 INP3 Volume",
+ WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP0 Volume",
+ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+ WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40,
+ digital_gain),
+
+ SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+ SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+ SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+ SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+ SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+ SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+ SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
+
+ SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
+ SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
+ SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
+ SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
+ SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
+ SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
+ SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
+ SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
+ SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
+ SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
+ SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
+ SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
+ SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
+ SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
+
+ SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
+ wcd934x_rx_hph_mode_get, wcd934x_rx_hph_mode_put),
+
+ SOC_SINGLE("IIR1 Band1 Switch", WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,
+ 0, 1, 0),
+ SOC_SINGLE("IIR1 Band2 Switch", WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,
+ 1, 1, 0),
+ SOC_SINGLE("IIR1 Band3 Switch", WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,
+ 2, 1, 0),
+ SOC_SINGLE("IIR1 Band4 Switch", WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,
+ 3, 1, 0),
+ SOC_SINGLE("IIR1 Band5 Switch", WCD934X_CDC_SIDETONE_IIR0_IIR_CTL,
+ 4, 1, 0),
+ SOC_SINGLE("IIR2 Band1 Switch", WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,
+ 0, 1, 0),
+ SOC_SINGLE("IIR2 Band2 Switch", WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,
+ 1, 1, 0),
+ SOC_SINGLE("IIR2 Band3 Switch", WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,
+ 2, 1, 0),
+ SOC_SINGLE("IIR2 Band4 Switch", WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,
+ 3, 1, 0),
+ SOC_SINGLE("IIR2 Band5 Switch", WCD934X_CDC_SIDETONE_IIR1_IIR_CTL,
+ 4, 1, 0),
+ WCD_IIR_FILTER_CTL("IIR0 Band1", IIR0, BAND1),
+ WCD_IIR_FILTER_CTL("IIR0 Band2", IIR0, BAND2),
+ WCD_IIR_FILTER_CTL("IIR0 Band3", IIR0, BAND3),
+ WCD_IIR_FILTER_CTL("IIR0 Band4", IIR0, BAND4),
+ WCD_IIR_FILTER_CTL("IIR0 Band5", IIR0, BAND5),
+
+ WCD_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1),
+ WCD_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2),
+ WCD_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3),
+ WCD_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4),
+ WCD_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5),
+
+ SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+ SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+ SOC_SINGLE_EXT("COMP3 Switch", SND_SOC_NOPM, COMPANDER_3, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+ SOC_SINGLE_EXT("COMP4 Switch", SND_SOC_NOPM, COMPANDER_4, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+ SOC_SINGLE_EXT("COMP7 Switch", SND_SOC_NOPM, COMPANDER_7, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+ SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
+ wcd934x_compander_get, wcd934x_compander_set),
+};
+
static const struct snd_soc_component_driver wcd934x_component_drv = {
.probe = wcd934x_comp_probe,
.remove = wcd934x_comp_remove,
.set_sysclk = wcd934x_comp_set_sysclk,
+ .controls = wcd934x_snd_controls,
+ .num_controls = ARRAY_SIZE(wcd934x_snd_controls),
};
static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
--
2.20.1
1
0
[alsa-devel] Applied "ASoC: wcd934x: add playback dapm widgets" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: wcd934x: add playback dapm widgets
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From dd9eb19b567303e4b92747dcfb5deedb182af111 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:47 +0000
Subject: [PATCH] ASoC: wcd934x: add playback dapm widgets
This patch adds required dapm widgets for playback.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-6-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 1550 ++++++++++++++++++++++++++++++++++++
1 file changed, 1550 insertions(+)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 27a864f2ff77..556c051f7f99 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -412,6 +412,94 @@ static const char * const rx_hph_mode_mux_text[] = {
"Class-H Hi-Fi Low Power"
};
+static const char *const slim_rx_mux_text[] = {
+ "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB",
+};
+
+static const char * const rx_int0_7_mix_mux_text[] = {
+ "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
+ "RX6", "RX7", "PROXIMITY"
+};
+
+static const char * const rx_int_mix_mux_text[] = {
+ "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
+ "RX6", "RX7"
+};
+
+static const char * const rx_prim_mix_text[] = {
+ "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
+ "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const char * const rx_sidetone_mix_text[] = {
+ "ZERO", "SRC0", "SRC1", "SRC_SUM"
+};
+
+static const char * const iir_inp_mux_text[] = {
+ "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6",
+ "DEC7", "DEC8", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const char * const rx_int_dem_inp_mux_text[] = {
+ "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
+};
+
+static const char * const rx_int0_1_interp_mux_text[] = {
+ "ZERO", "RX INT0_1 MIX1",
+};
+
+static const char * const rx_int1_1_interp_mux_text[] = {
+ "ZERO", "RX INT1_1 MIX1",
+};
+
+static const char * const rx_int2_1_interp_mux_text[] = {
+ "ZERO", "RX INT2_1 MIX1",
+};
+
+static const char * const rx_int3_1_interp_mux_text[] = {
+ "ZERO", "RX INT3_1 MIX1",
+};
+
+static const char * const rx_int4_1_interp_mux_text[] = {
+ "ZERO", "RX INT4_1 MIX1",
+};
+
+static const char * const rx_int7_1_interp_mux_text[] = {
+ "ZERO", "RX INT7_1 MIX1",
+};
+
+static const char * const rx_int8_1_interp_mux_text[] = {
+ "ZERO", "RX INT8_1 MIX1",
+};
+
+static const char * const rx_int0_2_interp_mux_text[] = {
+ "ZERO", "RX INT0_2 MUX",
+};
+
+static const char * const rx_int1_2_interp_mux_text[] = {
+ "ZERO", "RX INT1_2 MUX",
+};
+
+static const char * const rx_int2_2_interp_mux_text[] = {
+ "ZERO", "RX INT2_2 MUX",
+};
+
+static const char * const rx_int3_2_interp_mux_text[] = {
+ "ZERO", "RX INT3_2 MUX",
+};
+
+static const char * const rx_int4_2_interp_mux_text[] = {
+ "ZERO", "RX INT4_2 MUX",
+};
+
+static const char * const rx_int7_2_interp_mux_text[] = {
+ "ZERO", "RX INT7_2 MUX",
+};
+
+static const char * const rx_int8_2_interp_mux_text[] = {
+ "ZERO", "RX INT8_2 MUX",
+};
+
static const struct soc_enum cf_dec0_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
@@ -485,6 +573,236 @@ static const struct soc_enum rx_hph_mode_mux_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
rx_hph_mode_mux_text);
+static const struct soc_enum slim_rx_mux_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
+
+static const struct soc_enum rx_int0_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 0, 10,
+ rx_int0_7_mix_mux_text);
+
+static const struct soc_enum rx_int1_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int2_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int3_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int4_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int7_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 0, 10,
+ rx_int0_7_mix_mux_text);
+
+static const struct soc_enum rx_int8_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int0_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int1_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int2_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int3_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int4_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int7_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum iir0_inp0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum rx_int0_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX0_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+
+static const struct soc_enum rx_int1_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX1_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+
+static const struct soc_enum rx_int2_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+static const struct soc_enum rx_int0_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int0_1_interp_mux_text);
+
+static const struct soc_enum rx_int1_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int1_1_interp_mux_text);
+
+static const struct soc_enum rx_int2_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int2_1_interp_mux_text);
+
+static const struct soc_enum rx_int3_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_1_interp_mux_text);
+
+static const struct soc_enum rx_int4_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_1_interp_mux_text);
+
+static const struct soc_enum rx_int7_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_1_interp_mux_text);
+
+static const struct soc_enum rx_int8_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_1_interp_mux_text);
+
+static const struct soc_enum rx_int0_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int0_2_interp_mux_text);
+
+static const struct soc_enum rx_int1_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int1_2_interp_mux_text);
+
+static const struct soc_enum rx_int2_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int2_2_interp_mux_text);
+
+static const struct soc_enum rx_int3_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_2_interp_mux_text);
+
+static const struct soc_enum rx_int4_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_2_interp_mux_text);
+
+static const struct soc_enum rx_int7_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_2_interp_mux_text);
+
+static const struct soc_enum rx_int8_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_2_interp_mux_text);
+
static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd,
int sido_src)
{
@@ -639,6 +957,22 @@ static int __wcd934x_cdc_mclk_enable(struct wcd934x_codec *wcd, bool enable)
return ret;
}
+static int wcd934x_codec_enable_mclk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return __wcd934x_cdc_mclk_enable(wcd, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return __wcd934x_cdc_mclk_enable(wcd, false);
+ }
+
+ return 0;
+}
+
static int wcd934x_get_version(struct wcd934x_codec *wcd)
{
int val1, val2, ver, ret;
@@ -1814,6 +2148,311 @@ static int wcd934x_rx_hph_mode_put(struct snd_kcontrol *kc,
return 0;
}
+static int slim_rx_mux_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(dapm->dev);
+
+ ucontrol->value.enumerated.item[0] = wcd->rx_port_value[w->shift];
+
+ return 0;
+}
+
+static int slim_rx_mux_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);
+ struct soc_enum *e = (struct soc_enum *)kc->private_value;
+ struct snd_soc_dapm_update *update = NULL;
+ u32 port_id = w->shift;
+
+ if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
+ return 0;
+
+ wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
+
+ switch (wcd->rx_port_value[port_id]) {
+ case 0:
+ list_del_init(&wcd->rx_chs[port_id].list);
+ break;
+ case 1:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF1_PB].slim_ch_list);
+ break;
+ case 2:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF2_PB].slim_ch_list);
+ break;
+ case 3:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF3_PB].slim_ch_list);
+ break;
+ case 4:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF4_PB].slim_ch_list);
+ break;
+ default:
+ dev_err(wcd->dev, "Unknown AIF %d\n",
+ wcd->rx_port_value[port_id]);
+ goto err;
+ }
+
+ snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],
+ e, update);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e = (struct soc_enum *)kc->private_value;
+ struct snd_soc_component *component;
+ int reg, val, ret;
+
+ component = snd_soc_dapm_kcontrol_component(kc);
+ val = ucontrol->value.enumerated.item[0];
+ if (e->reg == WCD934X_CDC_RX0_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
+ else if (e->reg == WCD934X_CDC_RX1_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
+ else if (e->reg == WCD934X_CDC_RX2_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
+ else
+ return -EINVAL;
+
+ /* Set Look Ahead Delay */
+ if (val)
+ snd_soc_component_update_bits(component, reg,
+ WCD934X_RX_DLY_ZN_EN_MASK,
+ WCD934X_RX_DLY_ZN_ENABLE);
+ else
+ snd_soc_component_update_bits(component, reg,
+ WCD934X_RX_DLY_ZN_EN_MASK,
+ WCD934X_RX_DLY_ZN_DISABLE);
+
+ ret = snd_soc_dapm_put_enum_double(kc, ucontrol);
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new rx_int0_2_mux =
+ SOC_DAPM_ENUM("RX INT0_2 MUX Mux", rx_int0_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_2_mux =
+ SOC_DAPM_ENUM("RX INT1_2 MUX Mux", rx_int1_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_2_mux =
+ SOC_DAPM_ENUM("RX INT2_2 MUX Mux", rx_int2_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_2_mux =
+ SOC_DAPM_ENUM("RX INT3_2 MUX Mux", rx_int3_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_2_mux =
+ SOC_DAPM_ENUM("RX INT4_2 MUX Mux", rx_int4_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_2_mux =
+ SOC_DAPM_ENUM("RX INT7_2 MUX Mux", rx_int7_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_2_mux =
+ SOC_DAPM_ENUM("RX INT8_2 MUX Mux", rx_int8_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP0 Mux", rx_int0_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP1 Mux", rx_int0_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP2 Mux", rx_int0_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP0 Mux", rx_int1_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP1 Mux", rx_int1_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP2 Mux", rx_int1_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP0 Mux", rx_int2_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP1 Mux", rx_int2_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP2 Mux", rx_int2_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP0 Mux", rx_int3_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP1 Mux", rx_int3_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP2 Mux", rx_int3_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP0 Mux", rx_int4_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP1 Mux", rx_int4_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP2 Mux", rx_int4_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP0 Mux", rx_int7_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP1 Mux", rx_int7_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP2 Mux", rx_int7_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP0 Mux", rx_int8_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP1 Mux", rx_int8_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP2 Mux", rx_int8_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT0 MIX2 INP Mux", rx_int0_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT1 MIX2 INP Mux", rx_int1_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT2 MIX2 INP Mux", rx_int2_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT3 MIX2 INP Mux", rx_int3_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT4 MIX2 INP Mux", rx_int4_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT7 MIX2 INP Mux", rx_int7_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new iir0_inp0_mux =
+ SOC_DAPM_ENUM("IIR0 INP0 Mux", iir0_inp0_mux_enum);
+static const struct snd_kcontrol_new iir0_inp1_mux =
+ SOC_DAPM_ENUM("IIR0 INP1 Mux", iir0_inp1_mux_enum);
+static const struct snd_kcontrol_new iir0_inp2_mux =
+ SOC_DAPM_ENUM("IIR0 INP2 Mux", iir0_inp2_mux_enum);
+static const struct snd_kcontrol_new iir0_inp3_mux =
+ SOC_DAPM_ENUM("IIR0 INP3 Mux", iir0_inp3_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp0_mux =
+ SOC_DAPM_ENUM("IIR1 INP0 Mux", iir1_inp0_mux_enum);
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+static const struct snd_kcontrol_new iir1_inp2_mux =
+ SOC_DAPM_ENUM("IIR1 INP2 Mux", iir1_inp2_mux_enum);
+static const struct snd_kcontrol_new iir1_inp3_mux =
+ SOC_DAPM_ENUM("IIR1 INP3 Mux", iir1_inp3_mux_enum);
+
+static const struct snd_kcontrol_new slim_rx_mux[WCD934X_RX_MAX] = {
+ SOC_DAPM_ENUM_EXT("SLIM RX0 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+};
+
+static const struct snd_kcontrol_new rx_int1_asrc_switch[] = {
+ SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int2_asrc_switch[] = {
+ SOC_DAPM_SINGLE("HPHR Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int3_asrc_switch[] = {
+ SOC_DAPM_SINGLE("LO1 Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int4_asrc_switch[] = {
+ SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int0_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT0 DEM MUX Mux", rx_int0_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int1_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT1 DEM MUX Mux", rx_int1_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int2_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT2 DEM MUX Mux", rx_int2_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int0_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT0_1 INTERP Mux", rx_int0_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT1_1 INTERP Mux", rx_int1_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT2_1 INTERP Mux", rx_int2_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT3_1 INTERP Mux", rx_int3_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT4_1 INTERP Mux", rx_int4_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT7_1 INTERP Mux", rx_int7_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT8_1 INTERP Mux", rx_int8_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int0_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT0_2 INTERP Mux", rx_int0_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT1_2 INTERP Mux", rx_int1_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT2_2 INTERP Mux", rx_int2_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT3_2 INTERP Mux", rx_int3_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT4_2 INTERP Mux", rx_int4_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT7_2 INTERP Mux", rx_int7_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int8_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT8_2 INTERP Mux", rx_int8_2_interp_mux_enum);
+
static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
/* Gain Controls */
SOC_SINGLE_TLV("EAR PA Volume", WCD934X_ANA_EAR, 4, 4, 1, ear_pa_gain),
@@ -1983,12 +2622,923 @@ static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
wcd934x_compander_get, wcd934x_compander_set),
};
+static void wcd934x_codec_enable_int_port(struct wcd_slim_codec_dai_data *dai,
+ struct snd_soc_component *component)
+{
+ int port_num = 0;
+ unsigned short reg = 0;
+ unsigned int val = 0;
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+ struct wcd934x_slim_ch *ch;
+
+ list_for_each_entry(ch, &dai->slim_ch_list, list) {
+ if (ch->port >= WCD934X_RX_START) {
+ port_num = ch->port - WCD934X_RX_START;
+ reg = WCD934X_SLIM_PGD_PORT_INT_EN0 + (port_num / 8);
+ } else {
+ port_num = ch->port;
+ reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
+ }
+
+ regmap_read(wcd->if_regmap, reg, &val);
+ if (!(val & BIT(port_num % 8)))
+ regmap_write(wcd->if_regmap, reg,
+ val | BIT(port_num % 8));
+ }
+}
+
+static int wcd934x_codec_enable_slim(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(comp);
+ struct wcd_slim_codec_dai_data *dai = &wcd->dai[w->shift];
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ wcd934x_codec_enable_int_port(dai, comp);
+ break;
+ }
+
+ return 0;
+}
+
+static void wcd934x_codec_hd2_control(struct snd_soc_component *component,
+ u16 interp_idx, int event)
+{
+ u16 hd2_scale_reg;
+ u16 hd2_enable_reg = 0;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hd2_scale_reg = WCD934X_CDC_RX1_RX_PATH_SEC3;
+ hd2_enable_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
+ break;
+ case INTERP_HPHR:
+ hd2_scale_reg = WCD934X_CDC_RX2_RX_PATH_SEC3;
+ hd2_enable_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
+ break;
+ default:
+ return;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_MASK,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P3125);
+ snd_soc_component_update_bits(component, hd2_enable_reg,
+ WCD934X_CDC_RX_PATH_CFG_HD2_EN_MASK,
+ WCD934X_CDC_RX_PATH_CFG_HD2_ENABLE);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_update_bits(component, hd2_enable_reg,
+ WCD934X_CDC_RX_PATH_CFG_HD2_EN_MASK,
+ WCD934X_CDC_RX_PATH_CFG_HD2_DISABLE);
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_MASK,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P0000);
+ }
+}
+
+static void wcd934x_codec_hphdelay_lutbypass(struct snd_soc_component *comp,
+ u16 interp_idx, int event)
+{
+ u8 hph_dly_mask;
+ u16 hph_lut_bypass_reg = 0;
+ u16 hph_comp_ctrl7 = 0;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hph_dly_mask = 1;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
+ break;
+ case INTERP_HPHR:
+ hph_dly_mask = 2;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
+ break;
+ default:
+ return;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_component_update_bits(comp, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, 0x0);
+ snd_soc_component_update_bits(comp, hph_lut_bypass_reg,
+ WCD934X_HPH_LUT_BYPASS_MASK,
+ WCD934X_HPH_LUT_BYPASS_ENABLE);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_update_bits(comp, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, hph_dly_mask);
+ snd_soc_component_update_bits(comp, hph_lut_bypass_reg,
+ WCD934X_HPH_LUT_BYPASS_MASK,
+ WCD934X_HPH_LUT_BYPASS_DISABLE);
+ }
+}
+
+static int wcd934x_config_compander(struct snd_soc_component *comp,
+ int interp_n, int event)
+{
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int compander;
+ u16 comp_ctl0_reg, rx_path_cfg0_reg;
+
+ /* EAR does not have compander */
+ if (!interp_n)
+ return 0;
+
+ compander = interp_n - 1;
+ if (!wcd->comp_enabled[compander])
+ return 0;
+
+ comp_ctl0_reg = WCD934X_CDC_COMPANDER1_CTL0 + (compander * 8);
+ rx_path_cfg0_reg = WCD934X_CDC_RX1_RX_PATH_CFG0 + (compander * 20);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Enable Compander Clock */
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_CLK_EN_MASK,
+ WCD934X_COMP_CLK_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_DISABLE);
+ snd_soc_component_update_bits(comp, rx_path_cfg0_reg,
+ WCD934X_HPH_CMP_EN_MASK,
+ WCD934X_HPH_CMP_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_update_bits(comp, rx_path_cfg0_reg,
+ WCD934X_HPH_CMP_EN_MASK,
+ WCD934X_HPH_CMP_DISABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_HALT_MASK,
+ WCD934X_COMP_HALT);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_DISABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_CLK_EN_MASK, 0x0);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK, 0x0);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_interp_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int interp_idx = w->shift;
+ u16 main_reg = WCD934X_CDC_RX0_RX_PATH_CTL + (interp_idx * 20);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Clk enable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_CLK_EN_MASK,
+ WCD934X_RX_CLK_ENABLE);
+ wcd934x_codec_hd2_control(comp, interp_idx, event);
+ wcd934x_codec_hphdelay_lutbypass(comp, interp_idx, event);
+ wcd934x_config_compander(comp, interp_idx, event);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd934x_config_compander(comp, interp_idx, event);
+ wcd934x_codec_hphdelay_lutbypass(comp, interp_idx, event);
+ wcd934x_codec_hd2_control(comp, interp_idx, event);
+ /* Clk Disable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_CLK_EN_MASK, 0);
+ /* Reset enable and disable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_RESET_MASK,
+ WCD934X_RX_RESET_ENABLE);
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_RESET_MASK,
+ WCD934X_RX_RESET_DISABLE);
+ /* Reset rate to 48K*/
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_PCM_RATE_MASK,
+ WCD934X_RX_PCM_RATE_F_48K);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int offset_val = 0;
+ u16 gain_reg, mix_reg;
+ int val = 0;
+
+ gain_reg = WCD934X_CDC_RX0_RX_VOL_MIX_CTL +
+ (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
+ mix_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
+ (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Clk enable */
+ snd_soc_component_update_bits(comp, mix_reg,
+ WCD934X_CDC_RX_MIX_CLK_EN_MASK,
+ WCD934X_CDC_RX_MIX_CLK_ENABLE);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ val = snd_soc_component_read32(comp, gain_reg);
+ val += offset_val;
+ snd_soc_component_write(comp, gain_reg, val);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int reg = w->reg;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* B1 GAIN */
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B2 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B3 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B4 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B5 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int wcd934x_codec_enable_main_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ u16 gain_reg;
+
+ gain_reg = WCD934X_CDC_RX0_RX_VOL_CTL + (w->shift *
+ WCD934X_RX_PATH_CTL_OFFSET);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_component_write(comp, gain_reg,
+ snd_soc_component_read32(comp, gain_reg));
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_EAR, CLS_H_NORMAL);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_EAR, CLS_H_NORMAL);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int hph_mode = wcd->hph_mode;
+ u8 dem_inp;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Read DEM INP Select */
+ dem_inp = snd_soc_component_read32(comp,
+ WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03;
+
+ if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+ (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+ return -EINVAL;
+ }
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control enable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK,
+ WCD934X_SIDO_RIPPLE_FREQ_ENABLE);
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_HPHL, hph_mode);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* 1000us required as per HW requirement */
+ usleep_range(1000, 1100);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_HPHL, hph_mode);
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control disable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK, 0x0);
+
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int hph_mode = wcd->hph_mode;
+ u8 dem_inp;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dem_inp = snd_soc_component_read32(comp,
+ WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03;
+ if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+ (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+ return -EINVAL;
+ }
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control enable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK,
+ WCD934X_SIDO_RIPPLE_FREQ_ENABLE);
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_HPHR,
+ hph_mode);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* 1000us required as per HW requirement */
+ usleep_range(1000, 1100);
+
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_HPHR, hph_mode);
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control disable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK, 0x0);
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_LO, CLS_AB);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_LO, CLS_AB);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * 7ms sleep is required after PA is enabled as per
+ * HW requirement. If compander is disabled, then
+ * 20ms delay is needed.
+ */
+ usleep_range(20000, 20100);
+
+ snd_soc_component_update_bits(comp, WCD934X_HPH_L_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_ENABLE);
+ /* Remove Mute on primary path */
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX1_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ 0);
+ /* Enable GM3 boost */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_CNP_WG_CTL,
+ WCD934X_HPH_GM3_BOOST_EN_MASK,
+ WCD934X_HPH_GM3_BOOST_ENABLE);
+ /* Enable AutoChop timer at the end of power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK,
+ WCD934X_HPH_AUTOCHOP_TIMER_ENABLE);
+ /* Remove mix path mute */
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Enable DSD Mute before PA disable */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_L_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_DISABLE);
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX1_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /*
+ * 5ms sleep is required after PA disable. If compander is
+ * disabled, then 20ms delay is needed after PA disable.
+ */
+ usleep_range(20000, 20100);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * 7ms sleep is required after PA is enabled as per
+ * HW requirement. If compander is disabled, then
+ * 20ms delay is needed.
+ */
+ usleep_range(20000, 20100);
+ snd_soc_component_update_bits(comp, WCD934X_HPH_R_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_ENABLE);
+ /* Remove mute */
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ 0);
+ /* Enable GM3 boost */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_CNP_WG_CTL,
+ WCD934X_HPH_GM3_BOOST_EN_MASK,
+ WCD934X_HPH_GM3_BOOST_ENABLE);
+ /* Enable AutoChop timer at the end of power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK,
+ WCD934X_HPH_AUTOCHOP_TIMER_ENABLE);
+ /* Remove mix path mute if it is enabled */
+ if ((snd_soc_component_read32(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & 0x10)
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK,
+ WCD934X_CDC_RX_PGA_MUTE_DISABLE);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_component_update_bits(comp, WCD934X_HPH_R_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_DISABLE);
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK,
+ WCD934X_CDC_RX_PGA_MUTE_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /*
+ * 5ms sleep is required after PA disable. If compander is
+ * disabled, then 20ms delay is needed after PA disable.
+ */
+ usleep_range(20000, 20100);
+ break;
+ };
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
+ /* Analog Outputs */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+ SND_SOC_DAPM_OUTPUT("HPHL"),
+ SND_SOC_DAPM_OUTPUT("HPHR"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
+ SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
+ SND_SOC_DAPM_OUTPUT("ANC EAR"),
+ SND_SOC_DAPM_OUTPUT("ANC HPHL"),
+ SND_SOC_DAPM_OUTPUT("ANC HPHR"),
+ SND_SOC_DAPM_OUTPUT("WDMA3_OUT"),
+ SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT1"),
+ SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT2"),
+ SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
+ AIF1_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
+ AIF2_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
+ AIF3_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
+ AIF4_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM RX0 MUX", SND_SOC_NOPM, WCD934X_RX0, 0,
+ &slim_rx_mux[WCD934X_RX0]),
+ SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, WCD934X_RX1, 0,
+ &slim_rx_mux[WCD934X_RX1]),
+ SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, WCD934X_RX2, 0,
+ &slim_rx_mux[WCD934X_RX2]),
+ SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, WCD934X_RX3, 0,
+ &slim_rx_mux[WCD934X_RX3]),
+ SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, WCD934X_RX4, 0,
+ &slim_rx_mux[WCD934X_RX4]),
+ SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, WCD934X_RX5, 0,
+ &slim_rx_mux[WCD934X_RX5]),
+ SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, WCD934X_RX6, 0,
+ &slim_rx_mux[WCD934X_RX6]),
+ SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, WCD934X_RX7, 0,
+ &slim_rx_mux[WCD934X_RX7]),
+
+ SND_SOC_DAPM_MIXER("SLIM RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_EAR, 0,
+ &rx_int0_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int1_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int2_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3_2 MUX", SND_SOC_NOPM, INTERP_LO1, 0,
+ &rx_int3_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4_2 MUX", SND_SOC_NOPM, INTERP_LO2, 0,
+ &rx_int4_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7_2 MUX", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ &rx_int7_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT8_2 MUX", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ &rx_int8_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp2_mux),
+ SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int1_asrc_switch,
+ ARRAY_SIZE(rx_int1_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int2_asrc_switch,
+ ARRAY_SIZE(rx_int2_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT3_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int3_asrc_switch,
+ ARRAY_SIZE(rx_int3_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT4_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int4_asrc_switch,
+ ARRAY_SIZE(rx_int4_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT7_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT7 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT8_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT8 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("RX INT7 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("RX INT7 CHAIN", SND_SOC_NOPM, 0, 0,
+ NULL, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("RX INT8 CHAIN", SND_SOC_NOPM, 0, 0,
+ NULL, 0, NULL, 0),
+ SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", WCD934X_CDC_RX0_RX_PATH_CFG0, 4,
+ 0, &rx_int0_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", WCD934X_CDC_RX1_RX_PATH_CFG0, 4,
+ 0, &rx_int1_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", WCD934X_CDC_RX2_RX_PATH_CFG0, 4,
+ 0, &rx_int2_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", WCD934X_CDC_RX3_RX_PATH_CFG0, 4,
+ 0, &rx_int3_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", WCD934X_CDC_RX4_RX_PATH_CFG0, 4,
+ 0, &rx_int4_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", WCD934X_CDC_RX7_RX_PATH_CFG0, 4,
+ 0, &rx_int7_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("IIR0 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp3_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux),
+
+ SND_SOC_DAPM_PGA_E("IIR0", WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+ 0, 0, NULL, 0, wcd934x_codec_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("IIR1", WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+ 1, 0, NULL, 0, wcd934x_codec_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER("SRC0", WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SRC1", WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int0_dem_inp_mux),
+ SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int1_dem_inp_mux),
+ SND_SOC_DAPM_MUX("RX INT2 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int2_dem_inp_mux),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_EAR, 0,
+ &rx_int0_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int1_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int2_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3_1 INTERP", SND_SOC_NOPM, INTERP_LO1, 0,
+ &rx_int3_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4_1 INTERP", SND_SOC_NOPM, INTERP_LO2, 0,
+ &rx_int4_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7_1 INTERP", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ &rx_int7_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT8_1 INTERP", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ &rx_int8_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int0_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT1_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int1_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT2_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int2_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT3_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int3_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT4_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int4_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT7_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int7_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT8_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int8_2_interp_mux),
+ SND_SOC_DAPM_DAC_E("RX INT0 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_ear_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT1 DAC", NULL, WCD934X_ANA_HPH,
+ 5, 0, wcd934x_codec_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT2 DAC", NULL, WCD934X_ANA_HPH,
+ 4, 0, wcd934x_codec_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT3 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT4 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("HPHL PA", WCD934X_ANA_HPH, 7, 0, NULL, 0,
+ wcd934x_codec_enable_hphl_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("HPHR PA", WCD934X_ANA_HPH, 6, 0, NULL, 0,
+ wcd934x_codec_enable_hphr_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", WCD934X_ANA_RX_SUPPLIES, 0, 0, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("SBOOST0", WCD934X_CDC_RX7_RX_PATH_CFG1,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST0_CLK", WCD934X_CDC_BOOST0_BOOST_PATH_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST1", WCD934X_CDC_RX8_RX_PATH_CFG1,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST1_CLK", WCD934X_CDC_BOOST1_BOOST_PATH_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("INT0_CLK", SND_SOC_NOPM, INTERP_EAR, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT1_CLK", SND_SOC_NOPM, INTERP_HPHL, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT2_CLK", SND_SOC_NOPM, INTERP_HPHR, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT3_CLK", SND_SOC_NOPM, INTERP_LO1, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT4_CLK", SND_SOC_NOPM, INTERP_LO2, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT7_CLK", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT8_CLK", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("DSMDEM0_CLK", WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM1_CLK", WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM2_CLK", WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM3_CLK", WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM4_CLK", WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM7_CLK", WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM8_CLK", WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_mclk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
static const struct snd_soc_component_driver wcd934x_component_drv = {
.probe = wcd934x_comp_probe,
.remove = wcd934x_comp_remove,
.set_sysclk = wcd934x_comp_set_sysclk,
.controls = wcd934x_snd_controls,
.num_controls = ARRAY_SIZE(wcd934x_snd_controls),
+ .dapm_widgets = wcd934x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wcd934x_dapm_widgets),
};
static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
--
2.20.1
1
0
[alsa-devel] Applied "ASoC: wcd934x: add capture dapm widgets" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: wcd934x: add capture dapm widgets
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From a70d9245759a48e57bb1dc9f63213dcf3017db32 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:48 +0000
Subject: [PATCH] ASoC: wcd934x: add capture dapm widgets
This patch adds required dapm widgets for capture path.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-7-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 1151 +++++++++++++++++++++++++++++++++++-
1 file changed, 1149 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 556c051f7f99..24f78a0b7f5a 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -135,6 +135,13 @@
} \
}
+enum {
+ MIC_BIAS_1 = 1,
+ MIC_BIAS_2,
+ MIC_BIAS_3,
+ MIC_BIAS_4
+};
+
enum {
SIDO_SOURCE_INTERNAL,
SIDO_SOURCE_RCO_BG,
@@ -500,6 +507,83 @@ static const char * const rx_int8_2_interp_mux_text[] = {
"ZERO", "RX INT8_2 MUX",
};
+static const char * const dmic_mux_text[] = {
+ "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5"
+};
+
+static const char * const amic_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4"
+};
+
+static const char * const amic4_5_sel_text[] = {
+ "AMIC4", "AMIC5"
+};
+
+static const char * const adc_mux_text[] = {
+ "DMIC", "AMIC", "ANC_FB_TUNE1", "ANC_FB_TUNE2"
+};
+
+static const char * const cdc_if_tx0_mux_text[] = {
+ "ZERO", "RX_MIX_TX0", "DEC0", "DEC0_192"
+};
+
+static const char * const cdc_if_tx1_mux_text[] = {
+ "ZERO", "RX_MIX_TX1", "DEC1", "DEC1_192"
+};
+
+static const char * const cdc_if_tx2_mux_text[] = {
+ "ZERO", "RX_MIX_TX2", "DEC2", "DEC2_192"
+};
+
+static const char * const cdc_if_tx3_mux_text[] = {
+ "ZERO", "RX_MIX_TX3", "DEC3", "DEC3_192"
+};
+
+static const char * const cdc_if_tx4_mux_text[] = {
+ "ZERO", "RX_MIX_TX4", "DEC4", "DEC4_192"
+};
+
+static const char * const cdc_if_tx5_mux_text[] = {
+ "ZERO", "RX_MIX_TX5", "DEC5", "DEC5_192"
+};
+
+static const char * const cdc_if_tx6_mux_text[] = {
+ "ZERO", "RX_MIX_TX6", "DEC6", "DEC6_192"
+};
+
+static const char * const cdc_if_tx7_mux_text[] = {
+ "ZERO", "RX_MIX_TX7", "DEC7", "DEC7_192"
+};
+
+static const char * const cdc_if_tx8_mux_text[] = {
+ "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
+};
+
+static const char * const cdc_if_tx9_mux_text[] = {
+ "ZERO", "DEC7", "DEC7_192"
+};
+
+static const char * const cdc_if_tx10_mux_text[] = {
+ "ZERO", "DEC6", "DEC6_192"
+};
+
+static const char * const cdc_if_tx11_mux_text[] = {
+ "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",
+ "DEC5", "RX_MIX_TX5", "DEC9_10", "DEC11_12"
+};
+
+static const char * const cdc_if_tx13_mux_text[] = {
+ "CDC_DEC_5", "MAD_BRDCST"
+};
+
+static const char * const cdc_if_tx13_inp1_mux_text[] = {
+ "ZERO", "DEC5", "DEC5_192"
+};
+
static const struct soc_enum cf_dec0_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
@@ -758,6 +842,35 @@ static const struct soc_enum rx_int2_dem_inp_mux_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
ARRAY_SIZE(rx_int_dem_inp_mux_text),
rx_int_dem_inp_mux_text);
+
+static const struct soc_enum tx_adc_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+
static const struct soc_enum rx_int0_1_interp_mux_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
rx_int0_1_interp_mux_text);
@@ -803,8 +916,122 @@ static const struct soc_enum rx_int7_2_interp_mux_enum =
static const struct soc_enum rx_int8_2_interp_mux_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_2_interp_mux_text);
-static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd,
- int sido_src)
+static const struct soc_enum tx_dmic_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_amic_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0, 5,
+ amic_mux_text);
+
+static const struct soc_enum tx_amic4_5_enum =
+ SOC_ENUM_SINGLE(WCD934X_TX_NEW_AMIC_4_5_SEL, 7, 2, amic4_5_sel_text);
+
+static const struct soc_enum cdc_if_tx0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
+ ARRAY_SIZE(cdc_if_tx0_mux_text), cdc_if_tx0_mux_text);
+static const struct soc_enum cdc_if_tx1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
+ ARRAY_SIZE(cdc_if_tx1_mux_text), cdc_if_tx1_mux_text);
+static const struct soc_enum cdc_if_tx2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
+ ARRAY_SIZE(cdc_if_tx2_mux_text), cdc_if_tx2_mux_text);
+static const struct soc_enum cdc_if_tx3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
+ ARRAY_SIZE(cdc_if_tx3_mux_text), cdc_if_tx3_mux_text);
+static const struct soc_enum cdc_if_tx4_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
+ ARRAY_SIZE(cdc_if_tx4_mux_text), cdc_if_tx4_mux_text);
+static const struct soc_enum cdc_if_tx5_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
+ ARRAY_SIZE(cdc_if_tx5_mux_text), cdc_if_tx5_mux_text);
+static const struct soc_enum cdc_if_tx6_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
+ ARRAY_SIZE(cdc_if_tx6_mux_text), cdc_if_tx6_mux_text);
+static const struct soc_enum cdc_if_tx7_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
+ ARRAY_SIZE(cdc_if_tx7_mux_text), cdc_if_tx7_mux_text);
+static const struct soc_enum cdc_if_tx8_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
+ ARRAY_SIZE(cdc_if_tx8_mux_text), cdc_if_tx8_mux_text);
+static const struct soc_enum cdc_if_tx9_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
+ ARRAY_SIZE(cdc_if_tx9_mux_text), cdc_if_tx9_mux_text);
+static const struct soc_enum cdc_if_tx10_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
+ ARRAY_SIZE(cdc_if_tx10_mux_text), cdc_if_tx10_mux_text);
+static const struct soc_enum cdc_if_tx11_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
+ ARRAY_SIZE(cdc_if_tx11_inp1_mux_text),
+ cdc_if_tx11_inp1_mux_text);
+static const struct soc_enum cdc_if_tx11_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
+ ARRAY_SIZE(cdc_if_tx11_mux_text), cdc_if_tx11_mux_text);
+static const struct soc_enum cdc_if_tx13_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
+ ARRAY_SIZE(cdc_if_tx13_inp1_mux_text),
+ cdc_if_tx13_inp1_mux_text);
+static const struct soc_enum cdc_if_tx13_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
+ ARRAY_SIZE(cdc_if_tx13_mux_text), cdc_if_tx13_mux_text);
+
+static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
{
if (sido_src == wcd->sido_input_src)
return 0;
@@ -2241,6 +2468,63 @@ static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,
return ret;
}
+static int wcd934x_dec_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp;
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int val;
+ u16 mic_sel_reg = 0;
+ u8 mic_sel;
+
+ comp = snd_soc_dapm_kcontrol_component(kcontrol);
+
+ val = ucontrol->value.enumerated.item[0];
+ if (val > e->items - 1)
+ return -EINVAL;
+
+ switch (e->reg) {
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX0_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX4_TX_PATH_CFG0;
+ else if (e->shift_l == 4)
+ mic_sel_reg = WCD934X_CDC_TX8_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX1_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX5_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX2_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX6_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX3_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX7_TX_PATH_CFG0;
+ break;
+ default:
+ dev_err(comp->dev, "%s: e->reg: 0x%x not expected\n",
+ __func__, e->reg);
+ return -EINVAL;
+ }
+
+ /* ADC: 0, DMIC: 1 */
+ mic_sel = val ? 0x0 : 0x1;
+ if (mic_sel_reg)
+ snd_soc_component_update_bits(comp, mic_sel_reg, BIT(7),
+ mic_sel << 7);
+
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
static const struct snd_kcontrol_new rx_int0_2_mux =
SOC_DAPM_ENUM("RX INT0_2 MUX Mux", rx_int0_2_mux_chain_enum);
@@ -2453,6 +2737,252 @@ static const struct snd_kcontrol_new rx_int7_2_interp_mux =
static const struct snd_kcontrol_new rx_int8_2_interp_mux =
SOC_DAPM_ENUM("RX INT8_2 INTERP Mux", rx_int8_2_interp_mux_enum);
+static const struct snd_kcontrol_new tx_dmic_mux0 =
+ SOC_DAPM_ENUM("DMIC MUX0 Mux", tx_dmic_mux0_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux1 =
+ SOC_DAPM_ENUM("DMIC MUX1 Mux", tx_dmic_mux1_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux2 =
+ SOC_DAPM_ENUM("DMIC MUX2 Mux", tx_dmic_mux2_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux3 =
+ SOC_DAPM_ENUM("DMIC MUX3 Mux", tx_dmic_mux3_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux4 =
+ SOC_DAPM_ENUM("DMIC MUX4 Mux", tx_dmic_mux4_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux5 =
+ SOC_DAPM_ENUM("DMIC MUX5 Mux", tx_dmic_mux5_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux6 =
+ SOC_DAPM_ENUM("DMIC MUX6 Mux", tx_dmic_mux6_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux7 =
+ SOC_DAPM_ENUM("DMIC MUX7 Mux", tx_dmic_mux7_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux8 =
+ SOC_DAPM_ENUM("DMIC MUX8 Mux", tx_dmic_mux8_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux0 =
+ SOC_DAPM_ENUM("AMIC MUX0 Mux", tx_amic_mux0_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux1 =
+ SOC_DAPM_ENUM("AMIC MUX1 Mux", tx_amic_mux1_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux2 =
+ SOC_DAPM_ENUM("AMIC MUX2 Mux", tx_amic_mux2_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux3 =
+ SOC_DAPM_ENUM("AMIC MUX3 Mux", tx_amic_mux3_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux4 =
+ SOC_DAPM_ENUM("AMIC MUX4 Mux", tx_amic_mux4_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux5 =
+ SOC_DAPM_ENUM("AMIC MUX5 Mux", tx_amic_mux5_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux6 =
+ SOC_DAPM_ENUM("AMIC MUX6 Mux", tx_amic_mux6_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux7 =
+ SOC_DAPM_ENUM("AMIC MUX7 Mux", tx_amic_mux7_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux8 =
+ SOC_DAPM_ENUM("AMIC MUX8 Mux", tx_amic_mux8_enum);
+
+static const struct snd_kcontrol_new tx_amic4_5 =
+ SOC_DAPM_ENUM("AMIC4_5 SEL Mux", tx_amic4_5_enum);
+
+static const struct snd_kcontrol_new tx_adc_mux0_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX0 Mux", tx_adc_mux0_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux1_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX1 Mux", tx_adc_mux1_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux2_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX2 Mux", tx_adc_mux2_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux3_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX3 Mux", tx_adc_mux3_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux4_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX4 Mux", tx_adc_mux4_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux5_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX5 Mux", tx_adc_mux5_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux6_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX6 Mux", tx_adc_mux6_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux7_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX7 Mux", tx_adc_mux7_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux8_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX8 Mux", tx_adc_mux8_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+
+static const struct snd_kcontrol_new cdc_if_tx0_mux =
+ SOC_DAPM_ENUM("CDC_IF TX0 MUX Mux", cdc_if_tx0_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX1 MUX Mux", cdc_if_tx1_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx2_mux =
+ SOC_DAPM_ENUM("CDC_IF TX2 MUX Mux", cdc_if_tx2_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx3_mux =
+ SOC_DAPM_ENUM("CDC_IF TX3 MUX Mux", cdc_if_tx3_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx4_mux =
+ SOC_DAPM_ENUM("CDC_IF TX4 MUX Mux", cdc_if_tx4_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx5_mux =
+ SOC_DAPM_ENUM("CDC_IF TX5 MUX Mux", cdc_if_tx5_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx6_mux =
+ SOC_DAPM_ENUM("CDC_IF TX6 MUX Mux", cdc_if_tx6_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx7_mux =
+ SOC_DAPM_ENUM("CDC_IF TX7 MUX Mux", cdc_if_tx7_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx8_mux =
+ SOC_DAPM_ENUM("CDC_IF TX8 MUX Mux", cdc_if_tx8_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx9_mux =
+ SOC_DAPM_ENUM("CDC_IF TX9 MUX Mux", cdc_if_tx9_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx10_mux =
+ SOC_DAPM_ENUM("CDC_IF TX10 MUX Mux", cdc_if_tx10_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx11_mux =
+ SOC_DAPM_ENUM("CDC_IF TX11 MUX Mux", cdc_if_tx11_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx11_inp1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX11 INP1 MUX Mux", cdc_if_tx11_inp1_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx13_mux =
+ SOC_DAPM_ENUM("CDC_IF TX13 MUX Mux", cdc_if_tx13_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx13_inp1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX13 INP1 MUX Mux", cdc_if_tx13_inp1_mux_enum);
+
+static int slim_tx_mixer_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(dapm->dev);
+ struct soc_mixer_control *mixer =
+ (struct soc_mixer_control *)kc->private_value;
+ int port_id = mixer->shift;
+
+ ucontrol->value.integer.value[0] = wcd->tx_port_value[port_id];
+
+ return 0;
+}
+
+static int slim_tx_mixer_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(widget->dapm->dev);
+ struct snd_soc_dapm_update *update = NULL;
+ struct soc_mixer_control *mixer =
+ (struct soc_mixer_control *)kc->private_value;
+ int enable = ucontrol->value.integer.value[0];
+ int dai_id = widget->shift;
+ int port_id = mixer->shift;
+
+ /* only add to the list if value not set */
+ if (enable == wcd->tx_port_value[port_id])
+ return 0;
+
+ wcd->tx_port_value[port_id] = enable;
+
+ if (enable)
+ list_add_tail(&wcd->tx_chs[port_id].list,
+ &wcd->dai[dai_id].slim_ch_list);
+ else
+ list_del_init(&wcd->tx_chs[port_id].list);
+
+ snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new aif2_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new aif3_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
/* Gain Controls */
SOC_SINGLE_TLV("EAR PA Volume", WCD934X_ANA_EAR, 4, 4, 1, ear_pa_gain),
@@ -3193,6 +3723,455 @@ static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
return 0;
}
+static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp,
+ unsigned int dmic,
+ struct wcd934x_codec *wcd)
+{
+ u8 tx_stream_fs;
+ u8 adc_mux_index = 0, adc_mux_sel = 0;
+ bool dec_found = false;
+ u16 adc_mux_ctl_reg, tx_fs_reg;
+ u32 dmic_fs;
+
+ while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) {
+ if (adc_mux_index < 4) {
+ adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ (adc_mux_index * 2);
+ } else if (adc_mux_index < WCD934X_INVALID_ADC_MUX) {
+ adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_index - 4;
+ } else if (adc_mux_index == WCD934X_INVALID_ADC_MUX) {
+ ++adc_mux_index;
+ continue;
+ }
+ adc_mux_sel = ((snd_soc_component_read32(comp, adc_mux_ctl_reg)
+ & 0xF8) >> 3) - 1;
+
+ if (adc_mux_sel == dmic) {
+ dec_found = true;
+ break;
+ }
+
+ ++adc_mux_index;
+ }
+
+ if (dec_found && adc_mux_index <= 8) {
+ tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index);
+ tx_stream_fs = snd_soc_component_read32(comp, tx_fs_reg) & 0x0F;
+ if (tx_stream_fs <= 4) {
+ if (wcd->dmic_sample_rate <=
+ WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ)
+ dmic_fs = wcd->dmic_sample_rate;
+ else
+ dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ;
+ } else
+ dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
+ } else {
+ dmic_fs = wcd->dmic_sample_rate;
+ }
+
+ return dmic_fs;
+}
+
+static u8 wcd934x_get_dmic_clk_val(struct snd_soc_component *comp,
+ u32 mclk_rate, u32 dmic_clk_rate)
+{
+ u32 div_factor;
+ u8 dmic_ctl_val;
+
+ /* Default value to return in case of error */
+ if (mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
+ else
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
+
+ if (dmic_clk_rate == 0) {
+ dev_err(comp->dev,
+ "%s: dmic_sample_rate cannot be 0\n",
+ __func__);
+ goto done;
+ }
+
+ div_factor = mclk_rate / dmic_clk_rate;
+ switch (div_factor) {
+ case 2:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
+ break;
+ case 3:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
+ break;
+ case 4:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_4;
+ break;
+ case 6:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_6;
+ break;
+ case 8:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_8;
+ break;
+ case 16:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_16;
+ break;
+ default:
+ dev_err(comp->dev,
+ "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
+ __func__, div_factor, mclk_rate, dmic_clk_rate);
+ break;
+ }
+
+done:
+ return dmic_ctl_val;
+}
+
+static int wcd934x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ u8 dmic_clk_en = 0x01;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ u8 dmic_rate_val, dmic_rate_shift = 1;
+ unsigned int dmic;
+ u32 dmic_sample_rate;
+ int ret;
+ char *wname;
+
+ wname = strpbrk(w->name, "012345");
+ if (!wname) {
+ dev_err(comp->dev, "%s: widget not found\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = kstrtouint(wname, 10, &dmic);
+ if (ret < 0) {
+ dev_err(comp->dev, "%s: Invalid DMIC line on the codec\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 0:
+ case 1:
+ dmic_clk_cnt = &wcd->dmic_0_1_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC0_CTL;
+ break;
+ case 2:
+ case 3:
+ dmic_clk_cnt = &wcd->dmic_2_3_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC1_CTL;
+ break;
+ case 4:
+ case 5:
+ dmic_clk_cnt = &wcd->dmic_4_5_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC2_CTL;
+ break;
+ default:
+ dev_err(comp->dev, "%s: Invalid DMIC Selection\n",
+ __func__);
+ return -EINVAL;
+ };
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dmic_sample_rate = wcd934x_get_dmic_sample_rate(comp, dmic,
+ wcd);
+ dmic_rate_val = wcd934x_get_dmic_clk_val(comp, wcd->rate,
+ dmic_sample_rate);
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1) {
+ dmic_rate_val = dmic_rate_val << dmic_rate_shift;
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ WCD934X_DMIC_RATE_MASK,
+ dmic_rate_val);
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+ }
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_find_amic_input(struct snd_soc_component *comp,
+ int adc_mux_n)
+{
+ u16 mask, shift, adc_mux_in_reg;
+ u16 amic_mux_sel_reg;
+ bool is_amic;
+
+ if (adc_mux_n < 0 || adc_mux_n > WCD934X_MAX_VALID_ADC_MUX ||
+ adc_mux_n == WCD934X_INVALID_ADC_MUX)
+ return 0;
+
+ if (adc_mux_n < 3) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ adc_mux_n;
+ mask = 0x03;
+ shift = 0;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ 2 * adc_mux_n;
+ } else if (adc_mux_n < 4) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x03;
+ shift = 0;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ 2 * adc_mux_n;
+ } else if (adc_mux_n < 7) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ (adc_mux_n - 4);
+ mask = 0x0C;
+ shift = 2;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 8) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x0C;
+ shift = 2;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 12) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ ((adc_mux_n == 8) ? (adc_mux_n - 8) :
+ (adc_mux_n - 9));
+ mask = 0x30;
+ shift = 4;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 13) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x30;
+ shift = 4;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1;
+ mask = 0xC0;
+ shift = 6;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ }
+
+ is_amic = (((snd_soc_component_read32(comp, adc_mux_in_reg)
+ & mask) >> shift) == 1);
+ if (!is_amic)
+ return 0;
+
+ return snd_soc_component_read32(comp, amic_mux_sel_reg) & 0x07;
+}
+
+static u16 wcd934x_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp,
+ int amic)
+{
+ u16 pwr_level_reg = 0;
+
+ switch (amic) {
+ case 1:
+ case 2:
+ pwr_level_reg = WCD934X_ANA_AMIC1;
+ break;
+
+ case 3:
+ case 4:
+ pwr_level_reg = WCD934X_ANA_AMIC3;
+ break;
+ default:
+ break;
+ }
+
+ return pwr_level_reg;
+}
+
+static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ unsigned int decimator;
+ char *dec_adc_mux_name = NULL;
+ char *widget_name = NULL;
+ char *wname;
+ int ret = 0, amic_n;
+ u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
+ u16 tx_gain_ctl_reg;
+ char *dec;
+ u8 hpf_coff_freq;
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+
+ wname = widget_name;
+ dec_adc_mux_name = strsep(&widget_name, " ");
+ if (!dec_adc_mux_name) {
+ dev_err(comp->dev, "%s: Invalid decimator = %s\n",
+ __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ dec_adc_mux_name = widget_name;
+
+ dec = strpbrk(dec_adc_mux_name, "012345678");
+ if (!dec) {
+ dev_err(comp->dev, "%s: decimator index not found\n",
+ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec, 10, &decimator);
+ if (ret < 0) {
+ dev_err(comp->dev, "%s: Invalid decimator = %s\n",
+ __func__, wname);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator;
+ hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
+ dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
+ tx_gain_ctl_reg = WCD934X_CDC_TX0_TX_VOL_CTL + 16 * decimator;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ amic_n = wcd934x_codec_find_amic_input(comp, decimator);
+ if (amic_n)
+ pwr_level_reg = wcd934x_codec_get_amic_pwlvl_reg(comp,
+ amic_n);
+
+ if (!pwr_level_reg)
+ break;
+
+ switch ((snd_soc_component_read32(comp, pwr_level_reg) &
+ WCD934X_AMIC_PWR_LVL_MASK) >>
+ WCD934X_AMIC_PWR_LVL_SHIFT) {
+ case WCD934X_AMIC_PWR_LEVEL_LP:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_LP);
+ break;
+ case WCD934X_AMIC_PWR_LEVEL_HP:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_HP);
+ break;
+ case WCD934X_AMIC_PWR_LEVEL_DEFAULT:
+ case WCD934X_AMIC_PWR_LEVEL_HYBRID:
+ default:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_DF);
+ break;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) &
+ TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+ if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ TX_HPF_CUT_OFF_FREQ_MASK,
+ CF_MIN_3DB_150HZ << 5);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ 0);
+ }
+ /* apply gain after decimator is enabled */
+ snd_soc_component_write(comp, tx_gain_ctl_reg,
+ snd_soc_component_read32(comp,
+ tx_gain_ctl_reg));
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) &
+ TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+
+ if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ TX_HPF_CUT_OFF_FREQ_MASK,
+ hpf_coff_freq << 5);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ 0);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_update_bits(comp, tx_vol_ctl_reg,
+ 0x10, 0x00);
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_DF);
+ break;
+ };
+out:
+ kfree(wname);
+ return ret;
+}
+
+static void wcd934x_codec_set_tx_hold(struct snd_soc_component *comp,
+ u16 amic_reg, bool set)
+{
+ u8 mask = 0x20;
+ u8 val;
+
+ if (amic_reg == WCD934X_ANA_AMIC1 ||
+ amic_reg == WCD934X_ANA_AMIC3)
+ mask = 0x40;
+
+ val = set ? mask : 0x00;
+
+ switch (amic_reg) {
+ case WCD934X_ANA_AMIC1:
+ case WCD934X_ANA_AMIC2:
+ snd_soc_component_update_bits(comp, WCD934X_ANA_AMIC2,
+ mask, val);
+ break;
+ case WCD934X_ANA_AMIC3:
+ case WCD934X_ANA_AMIC4:
+ snd_soc_component_update_bits(comp, WCD934X_ANA_AMIC4,
+ mask, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static int wcd934x_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd934x_codec_set_tx_hold(comp, w->reg, true);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
/* Analog Outputs */
SND_SOC_DAPM_OUTPUT("EAR"),
@@ -3529,6 +4508,174 @@ static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
wcd934x_codec_enable_mclk,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_INPUT("AMIC3"),
+ SND_SOC_DAPM_INPUT("AMIC4"),
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_INPUT("DMIC0 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC1 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC2 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC3 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC4 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC5 Pin"),
+
+ SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
+ AIF1_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
+ AIF2_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
+ AIF3_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX7", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX8", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX9", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX10", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX11", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX13", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX("DMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_dmic_mux0),
+ SND_SOC_DAPM_MUX("DMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_dmic_mux1),
+ SND_SOC_DAPM_MUX("DMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_dmic_mux2),
+ SND_SOC_DAPM_MUX("DMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_dmic_mux3),
+ SND_SOC_DAPM_MUX("DMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_dmic_mux4),
+ SND_SOC_DAPM_MUX("DMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_dmic_mux5),
+ SND_SOC_DAPM_MUX("DMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_dmic_mux6),
+ SND_SOC_DAPM_MUX("DMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_dmic_mux7),
+ SND_SOC_DAPM_MUX("DMIC MUX8", SND_SOC_NOPM, 0, 0, &tx_dmic_mux8),
+ SND_SOC_DAPM_MUX("AMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_amic_mux0),
+ SND_SOC_DAPM_MUX("AMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_amic_mux1),
+ SND_SOC_DAPM_MUX("AMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_amic_mux2),
+ SND_SOC_DAPM_MUX("AMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_amic_mux3),
+ SND_SOC_DAPM_MUX("AMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_amic_mux4),
+ SND_SOC_DAPM_MUX("AMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_amic_mux5),
+ SND_SOC_DAPM_MUX("AMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_amic_mux6),
+ SND_SOC_DAPM_MUX("AMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_amic_mux7),
+ SND_SOC_DAPM_MUX("AMIC MUX8", SND_SOC_NOPM, 0, 0, &tx_amic_mux8),
+ SND_SOC_DAPM_MUX_E("ADC MUX0", WCD934X_CDC_TX0_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux0_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX1", WCD934X_CDC_TX1_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux1_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX2", WCD934X_CDC_TX2_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux2_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX3", WCD934X_CDC_TX3_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux3_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX4", WCD934X_CDC_TX4_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux4_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX5", WCD934X_CDC_TX5_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux5_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX6", WCD934X_CDC_TX6_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux6_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX7", WCD934X_CDC_TX7_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux7_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX8", WCD934X_CDC_TX8_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux8_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, WCD934X_ANA_AMIC1, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, WCD934X_ANA_AMIC2, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC3", NULL, WCD934X_ANA_AMIC3, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC4", NULL, WCD934X_ANA_AMIC4, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS1", WCD934X_ANA_MICB1, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS2", WCD934X_ANA_MICB2, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS3", WCD934X_ANA_MICB3, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS4", WCD934X_ANA_MICB4, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("AMIC4_5 SEL", SND_SOC_NOPM, 0, 0, &tx_amic4_5),
+ SND_SOC_DAPM_MUX("CDC_IF TX0 MUX", SND_SOC_NOPM, WCD934X_TX0, 0,
+ &cdc_if_tx0_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX1 MUX", SND_SOC_NOPM, WCD934X_TX1, 0,
+ &cdc_if_tx1_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX2 MUX", SND_SOC_NOPM, WCD934X_TX2, 0,
+ &cdc_if_tx2_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX3 MUX", SND_SOC_NOPM, WCD934X_TX3, 0,
+ &cdc_if_tx3_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX4 MUX", SND_SOC_NOPM, WCD934X_TX4, 0,
+ &cdc_if_tx4_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX5 MUX", SND_SOC_NOPM, WCD934X_TX5, 0,
+ &cdc_if_tx5_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX6 MUX", SND_SOC_NOPM, WCD934X_TX6, 0,
+ &cdc_if_tx6_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX7 MUX", SND_SOC_NOPM, WCD934X_TX7, 0,
+ &cdc_if_tx7_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX8 MUX", SND_SOC_NOPM, WCD934X_TX8, 0,
+ &cdc_if_tx8_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX9 MUX", SND_SOC_NOPM, WCD934X_TX9, 0,
+ &cdc_if_tx9_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX10 MUX", SND_SOC_NOPM, WCD934X_TX10, 0,
+ &cdc_if_tx10_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX11 MUX", SND_SOC_NOPM, WCD934X_TX11, 0,
+ &cdc_if_tx11_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX11 INP1 MUX", SND_SOC_NOPM, WCD934X_TX11, 0,
+ &cdc_if_tx11_inp1_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX13 MUX", SND_SOC_NOPM, WCD934X_TX13, 0,
+ &cdc_if_tx13_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX13 INP1 MUX", SND_SOC_NOPM, WCD934X_TX13, 0,
+ &cdc_if_tx13_inp1_mux),
+ SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+ aif1_slim_cap_mixer,
+ ARRAY_SIZE(aif1_slim_cap_mixer)),
+ SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
+ aif2_slim_cap_mixer,
+ ARRAY_SIZE(aif2_slim_cap_mixer)),
+ SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
+ aif3_slim_cap_mixer,
+ ARRAY_SIZE(aif3_slim_cap_mixer)),
};
static const struct snd_soc_component_driver wcd934x_component_drv = {
--
2.20.1
1
0