mirror of https://github.com/torvalds/linux.git
ASoC: codecs: add new pm4125 audio codec driver
The audio codec is found in Qualcomm PM2250/PM4125 PMICs and is used on platforms like Qualcomm QCM2290. It has soundwire interface and corresponding RX and TX slave devices. It has only two input channels: HPH left and right. The line output (LO) is linked to HPHL so the hardware has some limitations regarding concurrent playback via HPH and LO for instance. The codec driver also uses WCD MBCH framework. The MBHC functionality is implemented in a minimalistic way to enable IRQs and avoid different issues with IRQs. Co-developed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org> Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Tested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Link: https://patch.msgid.link/20250915-pm4125_audio_codec_v1-v4-3-b247b64eec52@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
f83ec76bf2
commit
8ad5294849
|
|
@ -192,6 +192,7 @@ config SND_SOC_ALL_CODECS
|
||||||
imply SND_SOC_PCM512x_SPI
|
imply SND_SOC_PCM512x_SPI
|
||||||
imply SND_SOC_PCM6240
|
imply SND_SOC_PCM6240
|
||||||
imply SND_SOC_PEB2466
|
imply SND_SOC_PEB2466
|
||||||
|
imply SND_SOC_PM4125_SDW
|
||||||
imply SND_SOC_RK3308
|
imply SND_SOC_RK3308
|
||||||
imply SND_SOC_RK3328
|
imply SND_SOC_RK3328
|
||||||
imply SND_SOC_RK817
|
imply SND_SOC_RK817
|
||||||
|
|
@ -1542,6 +1543,23 @@ config SND_SOC_PEB2466
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called snd-soc-peb2466.
|
will be called snd-soc-peb2466.
|
||||||
|
|
||||||
|
config SND_SOC_PM4125
|
||||||
|
depends on SND_SOC_PM4125_SDW
|
||||||
|
tristate
|
||||||
|
depends on SOUNDWIRE || !SOUNDWIRE
|
||||||
|
|
||||||
|
config SND_SOC_PM4125_SDW
|
||||||
|
tristate "PM4125 audio codec - SDW"
|
||||||
|
select SND_SOC_PM4125
|
||||||
|
select SND_SOC_WCD_MBHC
|
||||||
|
select REGMAP_IRQ
|
||||||
|
depends on SOUNDWIRE
|
||||||
|
select REGMAP_SOUNDWIRE
|
||||||
|
help
|
||||||
|
The PMIC PM4125 has an in-built audio codec IC used with SoCs
|
||||||
|
like QCM2290, and it is connected via soundwire and SPMI.
|
||||||
|
To compile this codec driver say Y or m.
|
||||||
|
|
||||||
config SND_SOC_RK3308
|
config SND_SOC_RK3308
|
||||||
tristate "Rockchip RK3308 audio CODEC"
|
tristate "Rockchip RK3308 audio CODEC"
|
||||||
depends on ARM64 || COMPILE_TEST
|
depends on ARM64 || COMPILE_TEST
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,8 @@ snd-soc-pcm512x-i2c-y := pcm512x-i2c.o
|
||||||
snd-soc-pcm512x-spi-y := pcm512x-spi.o
|
snd-soc-pcm512x-spi-y := pcm512x-spi.o
|
||||||
snd-soc-pcm6240-y := pcm6240.o
|
snd-soc-pcm6240-y := pcm6240.o
|
||||||
snd-soc-peb2466-y := peb2466.o
|
snd-soc-peb2466-y := peb2466.o
|
||||||
|
snd-soc-pm4125-y := pm4125.o
|
||||||
|
snd-soc-pm4125-sdw-y := pm4125-sdw.o
|
||||||
snd-soc-rk3308-y := rk3308_codec.o
|
snd-soc-rk3308-y := rk3308_codec.o
|
||||||
snd-soc-rk3328-y := rk3328_codec.o
|
snd-soc-rk3328-y := rk3328_codec.o
|
||||||
snd-soc-rk817-y := rk817_codec.o
|
snd-soc-rk817-y := rk817_codec.o
|
||||||
|
|
@ -642,6 +644,12 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
|
||||||
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
||||||
obj-$(CONFIG_SND_SOC_PCM6240) += snd-soc-pcm6240.o
|
obj-$(CONFIG_SND_SOC_PCM6240) += snd-soc-pcm6240.o
|
||||||
obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o
|
obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o
|
||||||
|
obj-$(CONFIG_SND_SOC_PM4125_SDW) += snd-soc-pm4125-sdw.o
|
||||||
|
obj-$(CONFIG_SND_SOC_PM4125) += snd-soc-pm4125.o
|
||||||
|
ifdef CONFIG_SND_SOC_PM4125_SDW
|
||||||
|
# avoid link failure by forcing sdw code built-in when needed
|
||||||
|
obj-$(CONFIG_SND_SOC_PM4125) += snd-soc-pm4125-sdw.o
|
||||||
|
endif
|
||||||
obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
|
obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
|
||||||
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
|
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
|
||||||
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
|
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,545 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
|
// Copyright, 2025 Linaro Ltd
|
||||||
|
|
||||||
|
#include <linux/component.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/irqdomain.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/soundwire/sdw.h>
|
||||||
|
#include <linux/soundwire/sdw_registers.h>
|
||||||
|
#include <linux/soundwire/sdw_type.h>
|
||||||
|
#include <sound/soc-dapm.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include "pm4125.h"
|
||||||
|
|
||||||
|
static struct pm4125_sdw_ch_info pm4125_sdw_rx_ch_info[] = {
|
||||||
|
WCD_SDW_CH(PM4125_HPH_L, PM4125_HPH_PORT, BIT(0)),
|
||||||
|
WCD_SDW_CH(PM4125_HPH_R, PM4125_HPH_PORT, BIT(1)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pm4125_sdw_ch_info pm4125_sdw_tx_ch_info[] = {
|
||||||
|
WCD_SDW_CH(PM4125_ADC1, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(0)),
|
||||||
|
WCD_SDW_CH(PM4125_ADC2, PM4125_ADC_1_2_DMIC1L_BCS_PORT, BIT(1)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sdw_dpn_prop pm4125_dpn_prop[PM4125_MAX_SWR_PORTS] = {
|
||||||
|
{
|
||||||
|
.num = 1,
|
||||||
|
.type = SDW_DPN_SIMPLE,
|
||||||
|
.min_ch = 1,
|
||||||
|
.max_ch = 8,
|
||||||
|
.simple_ch_prep_sm = true,
|
||||||
|
}, {
|
||||||
|
.num = 2,
|
||||||
|
.type = SDW_DPN_SIMPLE,
|
||||||
|
.min_ch = 1,
|
||||||
|
.max_ch = 4,
|
||||||
|
.simple_ch_prep_sm = true,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device *pm4125_sdw_device_get(struct device_node *np)
|
||||||
|
{
|
||||||
|
return bus_find_device_by_of_node(&sdw_bus_type, np);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm4125_sdw_device_get);
|
||||||
|
|
||||||
|
int pm4125_sdw_hw_params(struct pm4125_sdw_priv *priv, struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
struct sdw_port_config port_config[PM4125_MAX_SWR_PORTS];
|
||||||
|
unsigned long ch_mask;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
priv->sconfig.ch_count = 1;
|
||||||
|
priv->active_ports = 0;
|
||||||
|
for (i = 0; i < PM4125_MAX_SWR_PORTS; i++) {
|
||||||
|
ch_mask = priv->port_config[i].ch_mask;
|
||||||
|
if (!ch_mask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for_each_set_bit(j, &ch_mask, 4)
|
||||||
|
priv->sconfig.ch_count++;
|
||||||
|
|
||||||
|
port_config[priv->active_ports] = priv->port_config[i];
|
||||||
|
priv->active_ports++;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->sconfig.bps = 1;
|
||||||
|
priv->sconfig.frame_rate = params_rate(params);
|
||||||
|
priv->sconfig.direction = priv->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX;
|
||||||
|
priv->sconfig.type = SDW_STREAM_PCM;
|
||||||
|
|
||||||
|
return sdw_stream_add_slave(priv->sdev, &priv->sconfig, &port_config[0], priv->active_ports,
|
||||||
|
priv->sruntime);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm4125_sdw_hw_params);
|
||||||
|
|
||||||
|
static int pm4125_update_status(struct sdw_slave *slave, enum sdw_slave_status status)
|
||||||
|
{
|
||||||
|
struct pm4125_sdw_priv *priv = dev_get_drvdata(&slave->dev);
|
||||||
|
|
||||||
|
if (priv->regmap && status == SDW_SLAVE_ATTACHED) {
|
||||||
|
/* Write out any cached changes that happened between probe and attach */
|
||||||
|
regcache_cache_only(priv->regmap, false);
|
||||||
|
return regcache_sync(priv->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle Soundwire out-of-band interrupt event by triggering the first irq of the slave_irq
|
||||||
|
* irq domain, which then will be handled by the regmap_irq threaded irq.
|
||||||
|
* Looping is to ensure no interrupts were missed in the process.
|
||||||
|
*/
|
||||||
|
static int pm4125_interrupt_callback(struct sdw_slave *slave, struct sdw_slave_intr_status *status)
|
||||||
|
{
|
||||||
|
struct pm4125_sdw_priv *priv = dev_get_drvdata(&slave->dev);
|
||||||
|
struct irq_domain *slave_irq = priv->slave_irq;
|
||||||
|
u32 sts1, sts2, sts3;
|
||||||
|
|
||||||
|
do {
|
||||||
|
handle_nested_irq(irq_find_mapping(slave_irq, 0));
|
||||||
|
regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_0, &sts1);
|
||||||
|
regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_1, &sts2);
|
||||||
|
regmap_read(priv->regmap, PM4125_DIG_SWR_INTR_STATUS_2, &sts3);
|
||||||
|
|
||||||
|
} while (sts1 || sts2 || sts3);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct reg_default pm4125_defaults[] = {
|
||||||
|
{ PM4125_ANA_MICBIAS_MICB_1_2_EN, 0x01 },
|
||||||
|
{ PM4125_ANA_MICBIAS_MICB_3_EN, 0x00 },
|
||||||
|
{ PM4125_ANA_MICBIAS_LDO_1_SETTING, 0x21 },
|
||||||
|
{ PM4125_ANA_MICBIAS_LDO_1_CTRL, 0x01 },
|
||||||
|
{ PM4125_ANA_TX_AMIC1, 0x00 },
|
||||||
|
{ PM4125_ANA_TX_AMIC2, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_MECH, 0x39 },
|
||||||
|
{ PM4125_ANA_MBHC_ELECT, 0x08 },
|
||||||
|
{ PM4125_ANA_MBHC_ZDET, 0x10 },
|
||||||
|
{ PM4125_ANA_MBHC_RESULT_1, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_RESULT_2, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_RESULT_3, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_BTN0_ZDET_VREF1, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_BTN1_ZDET_VREF2, 0x10 },
|
||||||
|
{ PM4125_ANA_MBHC_BTN2_ZDET_VREF3, 0x20 },
|
||||||
|
{ PM4125_ANA_MBHC_BTN3_ZDET_DBG_400, 0x30 },
|
||||||
|
{ PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400, 0x40 },
|
||||||
|
{ PM4125_ANA_MBHC_MICB2_RAMP, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_CTL_1, 0x02 },
|
||||||
|
{ PM4125_ANA_MBHC_CTL_2, 0x05 },
|
||||||
|
{ PM4125_ANA_MBHC_PLUG_DETECT_CTL, 0xE9 },
|
||||||
|
{ PM4125_ANA_MBHC_ZDET_ANA_CTL, 0x0F },
|
||||||
|
{ PM4125_ANA_MBHC_ZDET_RAMP_CTL, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_FSM_STATUS, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_ADC_RESULT, 0x00 },
|
||||||
|
{ PM4125_ANA_MBHC_CTL_CLK, 0x30 },
|
||||||
|
{ PM4125_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 },
|
||||||
|
{ PM4125_ANA_NCP_EN, 0x00 },
|
||||||
|
{ PM4125_ANA_NCP_VCTRL, 0xA7 },
|
||||||
|
{ PM4125_ANA_HPHPA_CNP_CTL_1, 0x54 },
|
||||||
|
{ PM4125_ANA_HPHPA_CNP_CTL_2, 0x2B },
|
||||||
|
{ PM4125_ANA_HPHPA_PA_STATUS, 0x00 },
|
||||||
|
{ PM4125_ANA_HPHPA_FSM_CLK, 0x12 },
|
||||||
|
{ PM4125_ANA_HPHPA_L_GAIN, 0x00 },
|
||||||
|
{ PM4125_ANA_HPHPA_R_GAIN, 0x00 },
|
||||||
|
{ PM4125_SWR_HPHPA_HD2, 0x1B },
|
||||||
|
{ PM4125_ANA_HPHPA_SPARE_CTL, 0x02 },
|
||||||
|
{ PM4125_ANA_SURGE_EN, 0x38 },
|
||||||
|
{ PM4125_ANA_COMBOPA_CTL, 0x35 },
|
||||||
|
{ PM4125_ANA_COMBOPA_CTL_4, 0x84 },
|
||||||
|
{ PM4125_ANA_COMBOPA_CTL_5, 0x05 },
|
||||||
|
{ PM4125_ANA_RXLDO_CTL, 0x86 },
|
||||||
|
{ PM4125_ANA_MBIAS_EN, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CHIP_ID0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CHIP_ID1, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CHIP_ID2, 0x0C },
|
||||||
|
{ PM4125_DIG_SWR_CHIP_ID3, 0x01 },
|
||||||
|
{ PM4125_DIG_SWR_SWR_TX_CLK_RATE, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RST_CTL, 0x03 },
|
||||||
|
{ PM4125_DIG_SWR_TOP_CLK_CFG, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_CLK_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_TX_CLK_CTL, 0x33 },
|
||||||
|
{ PM4125_DIG_SWR_SWR_RST_EN, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_RST, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX0_CTL, 0xFC },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX1_CTL, 0xFC },
|
||||||
|
{ PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_COMP_CTL_0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_DELAY_CTL, 0x66 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_GAIN_0, 0x55 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_GAIN_1, 0xA9 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RX_GAIN_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_TX0_CTL, 0x68 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_TX1_CTL, 0x68 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_TX_RST, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_REQ0_CTL, 0x01 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_REQ1_CTL, 0x01 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_RST, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_AMIC_CTL, 0x02 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_DMIC_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_DMIC1_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_DMIC1_RATE, 0x01 },
|
||||||
|
{ PM4125_DIG_SWR_PDM_WD_CTL0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_PDM_WD_CTL1, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_MODE, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_MASK_0, 0xFF },
|
||||||
|
{ PM4125_DIG_SWR_INTR_MASK_1, 0x7F },
|
||||||
|
{ PM4125_DIG_SWR_INTR_MASK_2, 0x0C },
|
||||||
|
{ PM4125_DIG_SWR_INTR_STATUS_0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_STATUS_1, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_STATUS_2, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_CLEAR_0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_CLEAR_1, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_CLEAR_2, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_LEVEL_0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_INTR_LEVEL_1, 0x2A },
|
||||||
|
{ PM4125_DIG_SWR_INTR_LEVEL_2, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_CONN_RX0_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_CDC_CONN_RX1_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_LOOP_BACK_MODE, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_DRIVE_STRENGTH_0, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_DIG_DEBUG_CTL, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_DIG_DEBUG_EN, 0x00 },
|
||||||
|
{ PM4125_DIG_SWR_DEM_BYPASS_DATA0, 0x55 },
|
||||||
|
{ PM4125_DIG_SWR_DEM_BYPASS_DATA1, 0x55 },
|
||||||
|
{ PM4125_DIG_SWR_DEM_BYPASS_DATA2, 0x55 },
|
||||||
|
{ PM4125_DIG_SWR_DEM_BYPASS_DATA3, 0x01 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool pm4125_rdwr_register(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case PM4125_ANA_MICBIAS_MICB_1_2_EN:
|
||||||
|
case PM4125_ANA_MICBIAS_MICB_3_EN:
|
||||||
|
case PM4125_ANA_MICBIAS_LDO_1_SETTING:
|
||||||
|
case PM4125_ANA_MICBIAS_LDO_1_CTRL:
|
||||||
|
case PM4125_ANA_TX_AMIC1:
|
||||||
|
case PM4125_ANA_TX_AMIC2:
|
||||||
|
case PM4125_ANA_MBHC_MECH:
|
||||||
|
case PM4125_ANA_MBHC_ELECT:
|
||||||
|
case PM4125_ANA_MBHC_ZDET:
|
||||||
|
case PM4125_ANA_MBHC_BTN0_ZDET_VREF1:
|
||||||
|
case PM4125_ANA_MBHC_BTN1_ZDET_VREF2:
|
||||||
|
case PM4125_ANA_MBHC_BTN2_ZDET_VREF3:
|
||||||
|
case PM4125_ANA_MBHC_BTN3_ZDET_DBG_400:
|
||||||
|
case PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400:
|
||||||
|
case PM4125_ANA_MBHC_MICB2_RAMP:
|
||||||
|
case PM4125_ANA_MBHC_CTL_1:
|
||||||
|
case PM4125_ANA_MBHC_CTL_2:
|
||||||
|
case PM4125_ANA_MBHC_PLUG_DETECT_CTL:
|
||||||
|
case PM4125_ANA_MBHC_ZDET_ANA_CTL:
|
||||||
|
case PM4125_ANA_MBHC_ZDET_RAMP_CTL:
|
||||||
|
case PM4125_ANA_MBHC_CTL_CLK:
|
||||||
|
case PM4125_ANA_NCP_EN:
|
||||||
|
case PM4125_ANA_NCP_VCTRL:
|
||||||
|
case PM4125_ANA_HPHPA_CNP_CTL_1:
|
||||||
|
case PM4125_ANA_HPHPA_CNP_CTL_2:
|
||||||
|
case PM4125_ANA_HPHPA_FSM_CLK:
|
||||||
|
case PM4125_ANA_HPHPA_L_GAIN:
|
||||||
|
case PM4125_ANA_HPHPA_R_GAIN:
|
||||||
|
case PM4125_ANA_HPHPA_SPARE_CTL:
|
||||||
|
case PM4125_SWR_HPHPA_HD2:
|
||||||
|
case PM4125_ANA_SURGE_EN:
|
||||||
|
case PM4125_ANA_COMBOPA_CTL:
|
||||||
|
case PM4125_ANA_COMBOPA_CTL_4:
|
||||||
|
case PM4125_ANA_COMBOPA_CTL_5:
|
||||||
|
case PM4125_ANA_RXLDO_CTL:
|
||||||
|
case PM4125_ANA_MBIAS_EN:
|
||||||
|
case PM4125_DIG_SWR_SWR_TX_CLK_RATE:
|
||||||
|
case PM4125_DIG_SWR_CDC_RST_CTL:
|
||||||
|
case PM4125_DIG_SWR_TOP_CLK_CFG:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_CLK_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_TX_CLK_CTL:
|
||||||
|
case PM4125_DIG_SWR_SWR_RST_EN:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_RST:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX0_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX1_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1:
|
||||||
|
case PM4125_DIG_SWR_CDC_COMP_CTL_0:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_DELAY_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_GAIN_0:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_GAIN_1:
|
||||||
|
case PM4125_DIG_SWR_CDC_RX_GAIN_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_TX0_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_TX1_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_TX_RST:
|
||||||
|
case PM4125_DIG_SWR_CDC_REQ0_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_REQ1_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_RST:
|
||||||
|
case PM4125_DIG_SWR_CDC_AMIC_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_DMIC_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_DMIC1_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_DMIC1_RATE:
|
||||||
|
case PM4125_DIG_SWR_PDM_WD_CTL0:
|
||||||
|
case PM4125_DIG_SWR_PDM_WD_CTL1:
|
||||||
|
case PM4125_DIG_SWR_INTR_MODE:
|
||||||
|
case PM4125_DIG_SWR_INTR_MASK_0:
|
||||||
|
case PM4125_DIG_SWR_INTR_MASK_1:
|
||||||
|
case PM4125_DIG_SWR_INTR_MASK_2:
|
||||||
|
case PM4125_DIG_SWR_INTR_CLEAR_0:
|
||||||
|
case PM4125_DIG_SWR_INTR_CLEAR_1:
|
||||||
|
case PM4125_DIG_SWR_INTR_CLEAR_2:
|
||||||
|
case PM4125_DIG_SWR_INTR_LEVEL_0:
|
||||||
|
case PM4125_DIG_SWR_INTR_LEVEL_1:
|
||||||
|
case PM4125_DIG_SWR_INTR_LEVEL_2:
|
||||||
|
case PM4125_DIG_SWR_CDC_CONN_RX0_CTL:
|
||||||
|
case PM4125_DIG_SWR_CDC_CONN_RX1_CTL:
|
||||||
|
case PM4125_DIG_SWR_LOOP_BACK_MODE:
|
||||||
|
case PM4125_DIG_SWR_DRIVE_STRENGTH_0:
|
||||||
|
case PM4125_DIG_SWR_DIG_DEBUG_CTL:
|
||||||
|
case PM4125_DIG_SWR_DIG_DEBUG_EN:
|
||||||
|
case PM4125_DIG_SWR_DEM_BYPASS_DATA0:
|
||||||
|
case PM4125_DIG_SWR_DEM_BYPASS_DATA1:
|
||||||
|
case PM4125_DIG_SWR_DEM_BYPASS_DATA2:
|
||||||
|
case PM4125_DIG_SWR_DEM_BYPASS_DATA3:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pm4125_readable_register(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case PM4125_ANA_MBHC_RESULT_1:
|
||||||
|
case PM4125_ANA_MBHC_RESULT_2:
|
||||||
|
case PM4125_ANA_MBHC_RESULT_3:
|
||||||
|
case PM4125_ANA_MBHC_FSM_STATUS:
|
||||||
|
case PM4125_ANA_MBHC_ADC_RESULT:
|
||||||
|
case PM4125_ANA_MBHC_ZDET_CALIB_RESULT:
|
||||||
|
case PM4125_ANA_HPHPA_PA_STATUS:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID0:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID1:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID2:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID3:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_0:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_1:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_2:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return pm4125_rdwr_register(dev, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pm4125_volatile_register(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case PM4125_ANA_MBHC_RESULT_1:
|
||||||
|
case PM4125_ANA_MBHC_RESULT_2:
|
||||||
|
case PM4125_ANA_MBHC_RESULT_3:
|
||||||
|
case PM4125_ANA_MBHC_FSM_STATUS:
|
||||||
|
case PM4125_ANA_MBHC_ADC_RESULT:
|
||||||
|
case PM4125_ANA_MBHC_ZDET_CALIB_RESULT:
|
||||||
|
case PM4125_ANA_HPHPA_PA_STATUS:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID0:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID1:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID2:
|
||||||
|
case PM4125_DIG_SWR_CHIP_ID3:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_0:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_1:
|
||||||
|
case PM4125_DIG_SWR_INTR_STATUS_2:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config pm4125_regmap_config = {
|
||||||
|
.name = "pm4125_csr",
|
||||||
|
.reg_bits = 32,
|
||||||
|
.val_bits = 8,
|
||||||
|
.cache_type = REGCACHE_MAPLE,
|
||||||
|
.reg_defaults = pm4125_defaults,
|
||||||
|
.num_reg_defaults = ARRAY_SIZE(pm4125_defaults),
|
||||||
|
.max_register = PM4125_MAX_REGISTER,
|
||||||
|
.readable_reg = pm4125_readable_register,
|
||||||
|
.writeable_reg = pm4125_rdwr_register,
|
||||||
|
.volatile_reg = pm4125_volatile_register,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sdw_slave_ops pm4125_slave_ops = {
|
||||||
|
.update_status = pm4125_update_status,
|
||||||
|
.interrupt_callback = pm4125_interrupt_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pm4125_sdw_component_bind(struct device *dev, struct device *master, void *data)
|
||||||
|
{
|
||||||
|
pm_runtime_set_autosuspend_delay(dev, 3000);
|
||||||
|
pm_runtime_use_autosuspend(dev);
|
||||||
|
pm_runtime_set_active(dev);
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pm4125_sdw_component_unbind(struct device *dev, struct device *master, void *data)
|
||||||
|
{
|
||||||
|
pm_runtime_disable(dev);
|
||||||
|
pm_runtime_set_suspended(dev);
|
||||||
|
pm_runtime_dont_use_autosuspend(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct component_ops pm4125_sdw_component_ops = {
|
||||||
|
.bind = pm4125_sdw_component_bind,
|
||||||
|
.unbind = pm4125_sdw_component_unbind,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pm4125_probe(struct sdw_slave *pdev, const struct sdw_device_id *id)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct pm4125_sdw_priv *priv;
|
||||||
|
u8 master_ch_mask[PM4125_MAX_SWR_CH_IDS];
|
||||||
|
int master_ch_mask_size = 0;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Port map index starts at 0, however the data port for this codec starts at index 1 */
|
||||||
|
if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) {
|
||||||
|
priv->is_tx = true;
|
||||||
|
ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
|
||||||
|
&pdev->m_port_map[1], PM4125_MAX_TX_SWR_PORTS);
|
||||||
|
} else {
|
||||||
|
ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
|
||||||
|
&pdev->m_port_map[1], PM4125_MAX_SWR_PORTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
dev_info(dev, "Error getting static port mapping for %s (%d)\n",
|
||||||
|
priv->is_tx ? "TX" : "RX", ret);
|
||||||
|
|
||||||
|
priv->sdev = pdev;
|
||||||
|
dev_set_drvdata(dev, priv);
|
||||||
|
|
||||||
|
pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
|
||||||
|
SDW_SCP_INT1_BUS_CLASH |
|
||||||
|
SDW_SCP_INT1_PARITY;
|
||||||
|
pdev->prop.lane_control_support = true;
|
||||||
|
pdev->prop.simple_clk_stop_capable = true;
|
||||||
|
|
||||||
|
memset(master_ch_mask, 0, PM4125_MAX_SWR_CH_IDS);
|
||||||
|
|
||||||
|
if (priv->is_tx) {
|
||||||
|
master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
|
||||||
|
"qcom,tx-channel-mapping");
|
||||||
|
|
||||||
|
if (master_ch_mask_size)
|
||||||
|
ret = of_property_read_u8_array(dev->of_node, "qcom,tx-channel-mapping",
|
||||||
|
master_ch_mask, master_ch_mask_size);
|
||||||
|
} else {
|
||||||
|
master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
|
||||||
|
"qcom,rx-channel-mapping");
|
||||||
|
|
||||||
|
if (master_ch_mask_size)
|
||||||
|
ret = of_property_read_u8_array(dev->of_node, "qcom,rx-channel-mapping",
|
||||||
|
master_ch_mask, master_ch_mask_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
dev_info(dev, "Static channel mapping not specified using device channel maps\n");
|
||||||
|
|
||||||
|
if (priv->is_tx) {
|
||||||
|
pdev->prop.source_ports = GENMASK(PM4125_MAX_TX_SWR_PORTS, 0);
|
||||||
|
pdev->prop.src_dpn_prop = pm4125_dpn_prop;
|
||||||
|
priv->ch_info = &pm4125_sdw_tx_ch_info[0];
|
||||||
|
|
||||||
|
for (i = 0; i < master_ch_mask_size; i++)
|
||||||
|
priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]);
|
||||||
|
|
||||||
|
pdev->prop.wake_capable = true;
|
||||||
|
|
||||||
|
priv->regmap = devm_regmap_init_sdw(pdev, &pm4125_regmap_config);
|
||||||
|
if (IS_ERR(priv->regmap))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(priv->regmap), "regmap init failed\n");
|
||||||
|
|
||||||
|
/* Start in cache-only until device is enumerated */
|
||||||
|
regcache_cache_only(priv->regmap, true);
|
||||||
|
} else {
|
||||||
|
pdev->prop.sink_ports = GENMASK(PM4125_MAX_SWR_PORTS - 1, 0);
|
||||||
|
pdev->prop.sink_dpn_prop = pm4125_dpn_prop;
|
||||||
|
priv->ch_info = &pm4125_sdw_rx_ch_info[0];
|
||||||
|
|
||||||
|
for (i = 0; i < master_ch_mask_size; i++)
|
||||||
|
priv->ch_info[i].master_ch_mask = PM4125_SWRM_CH_MASK(master_ch_mask[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = component_add(dev, &pm4125_sdw_component_ops);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Set suspended until aggregate device is bind */
|
||||||
|
pm_runtime_set_suspended(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pm4125_remove(struct sdw_slave *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
|
component_del(dev, &pm4125_sdw_component_ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sdw_device_id pm4125_slave_id[] = {
|
||||||
|
SDW_SLAVE_ENTRY(0x0217, 0x10c, 0), /* Soundwire pm4125 RX/TX Device ID */
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(sdw, pm4125_slave_id);
|
||||||
|
|
||||||
|
static int __maybe_unused pm4125_sdw_runtime_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct pm4125_sdw_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (priv->regmap) {
|
||||||
|
regcache_cache_only(priv->regmap, true);
|
||||||
|
regcache_mark_dirty(priv->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused pm4125_sdw_runtime_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct pm4125_sdw_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (priv->regmap) {
|
||||||
|
regcache_cache_only(priv->regmap, false);
|
||||||
|
regcache_sync(priv->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops pm4125_sdw_pm_ops = {
|
||||||
|
SET_RUNTIME_PM_OPS(pm4125_sdw_runtime_suspend, pm4125_sdw_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sdw_driver pm4125_codec_driver = {
|
||||||
|
.probe = pm4125_probe,
|
||||||
|
.remove = pm4125_remove,
|
||||||
|
.ops = &pm4125_slave_ops,
|
||||||
|
.id_table = pm4125_slave_id,
|
||||||
|
.driver = {
|
||||||
|
.name = "pm4125-codec",
|
||||||
|
.pm = &pm4125_sdw_pm_ops,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
module_sdw_driver(pm4125_codec_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("PM4125 SDW codec driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,307 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PM4125_REGISTERS_H
|
||||||
|
#define _PM4125_REGISTERS_H
|
||||||
|
|
||||||
|
#include <linux/soundwire/sdw.h>
|
||||||
|
#include <linux/soundwire/sdw_type.h>
|
||||||
|
|
||||||
|
#define PM4125_ANA_BASE_ADDR 0x3000
|
||||||
|
#define PM4125_DIG_BASE_ADDR 0x3400
|
||||||
|
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB_1_2_EN (PM4125_ANA_BASE_ADDR+0x040)
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK BIT(5)
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK BIT(1)
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK BIT(0)
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB_PULL_ENABLE 1
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB_PULL_DISABLE 0
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB_3_EN (PM4125_ANA_BASE_ADDR+0x041)
|
||||||
|
#define PM4125_ANA_MICBIAS_LDO_1_SETTING (PM4125_ANA_BASE_ADDR+0x042)
|
||||||
|
#define PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK GENMASK(7, 3)
|
||||||
|
#define PM4125_ANA_MICBIAS_LDO_1_CTRL (PM4125_ANA_BASE_ADDR+0x043)
|
||||||
|
#define PM4125_ANA_TX_AMIC1 (PM4125_ANA_BASE_ADDR+0x047)
|
||||||
|
#define PM4125_ANA_TX_AMIC2 (PM4125_ANA_BASE_ADDR+0x048)
|
||||||
|
#define PM4125_ANA_MBHC_MECH (PM4125_ANA_BASE_ADDR+0x05A)
|
||||||
|
#define PM4125_ANA_MBHC_ELECT (PM4125_ANA_BASE_ADDR+0x05B)
|
||||||
|
#define PM4125_ANA_MBHC_ELECT_BIAS_EN_MASK BIT(0)
|
||||||
|
#define PM4125_ANA_MBHC_ELECT_BIAS_ENABLE 1
|
||||||
|
#define PM4125_ANA_MBHC_ELECT_BIAS_DISABLE 0
|
||||||
|
#define PM4125_ANA_MBHC_ZDET (PM4125_ANA_BASE_ADDR+0x05C)
|
||||||
|
#define PM4125_ANA_MBHC_RESULT_1 (PM4125_ANA_BASE_ADDR+0x05D)
|
||||||
|
#define PM4125_ANA_MBHC_RESULT_2 (PM4125_ANA_BASE_ADDR+0x05E)
|
||||||
|
#define PM4125_ANA_MBHC_RESULT_3 (PM4125_ANA_BASE_ADDR+0x05F)
|
||||||
|
#define PM4125_ANA_MBHC_BTN0_ZDET_VREF1 (PM4125_ANA_BASE_ADDR+0x060)
|
||||||
|
#define PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK GENMASK(7, 2)
|
||||||
|
#define PM4125_ANA_MBHC_BTN1_ZDET_VREF2 (PM4125_ANA_BASE_ADDR+0x061)
|
||||||
|
#define PM4125_ANA_MBHC_BTN2_ZDET_VREF3 (PM4125_ANA_BASE_ADDR+0x062)
|
||||||
|
#define PM4125_ANA_MBHC_BTN3_ZDET_DBG_400 (PM4125_ANA_BASE_ADDR+0x063)
|
||||||
|
#define PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400 (PM4125_ANA_BASE_ADDR+0x064)
|
||||||
|
#define PM4125_ANA_MBHC_MICB2_RAMP (PM4125_ANA_BASE_ADDR+0x065)
|
||||||
|
#define PM4125_ANA_MBHC_CTL_1 (PM4125_ANA_BASE_ADDR+0x066)
|
||||||
|
#define PM4125_ANA_MBHC_CTL_2 (PM4125_ANA_BASE_ADDR+0x067)
|
||||||
|
#define PM4125_ANA_MBHC_PLUG_DETECT_CTL (PM4125_ANA_BASE_ADDR+0x068)
|
||||||
|
#define PM4125_ANA_MBHC_ZDET_ANA_CTL (PM4125_ANA_BASE_ADDR+0x069)
|
||||||
|
#define PM4125_ANA_MBHC_ZDET_RAMP_CTL (PM4125_ANA_BASE_ADDR+0x06A)
|
||||||
|
#define PM4125_ANA_MBHC_FSM_STATUS (PM4125_ANA_BASE_ADDR+0x06B)
|
||||||
|
#define PM4125_ANA_MBHC_ADC_RESULT (PM4125_ANA_BASE_ADDR+0x06C)
|
||||||
|
#define PM4125_ANA_MBHC_CTL_CLK (PM4125_ANA_BASE_ADDR+0x06D)
|
||||||
|
#define PM4125_ANA_MBHC_ZDET_CALIB_RESULT (PM4125_ANA_BASE_ADDR+0x072)
|
||||||
|
#define PM4125_ANA_NCP_EN (PM4125_ANA_BASE_ADDR+0x077)
|
||||||
|
#define PM4125_ANA_NCP_ENABLE_MASK BIT(0)
|
||||||
|
#define PM4125_ANA_NCP_ENABLE 1
|
||||||
|
#define PM4125_ANA_NCP_DISABLE 0
|
||||||
|
#define PM4125_ANA_NCP_VCTRL (PM4125_ANA_BASE_ADDR+0x07C)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_CTL_1 (PM4125_ANA_BASE_ADDR+0x083)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK BIT(1)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_CTL_1_EN 1
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_CTL_2 (PM4125_ANA_BASE_ADDR+0x084)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_OCP_EN_L_MASK BIT(1)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_OCP_EN_R_MASK BIT(0)
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_OCP_ENABLE 1
|
||||||
|
#define PM4125_ANA_HPHPA_CNP_OCP_DISABLE 0
|
||||||
|
#define PM4125_ANA_HPHPA_PA_STATUS (PM4125_ANA_BASE_ADDR+0x087)
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_CLK (PM4125_ANA_BASE_ADDR+0x088)
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_CLK_DIV_EN_MASK BIT(7)
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_CLK_DIV_ENABLE 1
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_CLK_DIV_DISABLE 0
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_DIV_RATIO_MASK GENMASK(6, 0)
|
||||||
|
#define PM4125_ANA_HPHPA_FSM_DIV_RATIO_68 (0x11)
|
||||||
|
#define PM4125_ANA_HPHPA_L_GAIN (PM4125_ANA_BASE_ADDR+0x08B)
|
||||||
|
#define PM4125_ANA_HPHPA_R_GAIN (PM4125_ANA_BASE_ADDR+0x08C)
|
||||||
|
#define PM4125_ANA_HPHPA_SPARE_CTL (PM4125_ANA_BASE_ADDR+0x08E)
|
||||||
|
#define PM4125_SWR_HPHPA_HD2 (PM4125_ANA_BASE_ADDR+0x090)
|
||||||
|
#define PM4125_SWR_HPHPA_HD2_LEFT_MASK GENMASK(5, 3)
|
||||||
|
#define PM4125_SWR_HPHPA_HD2_RIGHT_MASK GENMASK(2, 0)
|
||||||
|
#define PM4125_SWR_HPHPA_HD2_ENABLE (BIT(2) | BIT(1) | BIT(0))
|
||||||
|
#define PM4125_ANA_SURGE_EN (PM4125_ANA_BASE_ADDR+0x097)
|
||||||
|
#define PM4125_ANA_SURGE_PROTECTION_HPHL_MASK BIT(7)
|
||||||
|
#define PM4125_ANA_SURGE_PROTECTION_HPHR_MASK BIT(6)
|
||||||
|
#define PM4125_ANA_SURGE_PROTECTION_ENABLE 1
|
||||||
|
#define PM4125_ANA_SURGE_PROTECTION_DISABLE 0
|
||||||
|
#define PM4125_ANA_COMBOPA_CTL (PM4125_ANA_BASE_ADDR+0x09B)
|
||||||
|
#define PM4125_ANA_COMBO_PA_SELECT_MASK BIT(6)
|
||||||
|
#define PM4125_ANA_COMBO_PA_SELECT_EAR 0
|
||||||
|
#define PM4125_ANA_COMBO_PA_SELECT_LO 1
|
||||||
|
#define PM4125_ANA_COMBOPA_CTL_4 (PM4125_ANA_BASE_ADDR+0x09F)
|
||||||
|
#define PM4125_ANA_COMBOPA_CTL_5 (PM4125_ANA_BASE_ADDR+0x0A0)
|
||||||
|
#define PM4125_ANA_RXLDO_CTL (PM4125_ANA_BASE_ADDR+0x0B2)
|
||||||
|
#define PM4125_ANA_MBIAS_EN (PM4125_ANA_BASE_ADDR+0x0B4)
|
||||||
|
#define PM4125_ANA_MBIAS_EN_GLOBAL_MASK BIT(5)
|
||||||
|
#define PM4125_ANA_MBIAS_EN_V2I_MASK BIT(4)
|
||||||
|
#define PM4125_ANA_MBIAS_EN_ENABLE 1
|
||||||
|
#define PM4125_ANA_MBIAS_EN_DISABLE 0
|
||||||
|
|
||||||
|
#define PM4125_DIG_SWR_CHIP_ID0 (PM4125_DIG_BASE_ADDR+0x001)
|
||||||
|
#define PM4125_DIG_SWR_CHIP_ID1 (PM4125_DIG_BASE_ADDR+0x002)
|
||||||
|
#define PM4125_DIG_SWR_CHIP_ID2 (PM4125_DIG_BASE_ADDR+0x003)
|
||||||
|
#define PM4125_DIG_SWR_CHIP_ID3 (PM4125_DIG_BASE_ADDR+0x004)
|
||||||
|
#define PM4125_DIG_SWR_SWR_TX_CLK_RATE (PM4125_DIG_BASE_ADDR+0x040)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RST_CTL (PM4125_DIG_BASE_ADDR+0x041)
|
||||||
|
#define PM4125_DIG_SWR_TOP_CLK_CFG (PM4125_DIG_BASE_ADDR+0x042)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_CLK_CTL (PM4125_DIG_BASE_ADDR+0x043)
|
||||||
|
#define PM4125_DIG_SWR_ANA_RX_DIV2_CLK_EN_MASK BIT(5)
|
||||||
|
#define PM4125_DIG_SWR_ANA_RX_CLK_EN_MASK BIT(4)
|
||||||
|
#define PM4125_DIG_SWR_RX1_CLK_EN_MASK BIT(1)
|
||||||
|
#define PM4125_DIG_SWR_RX0_CLK_EN_MASK BIT(0)
|
||||||
|
#define PM4125_DIG_SWR_RX_CLK_ENABLE 1
|
||||||
|
#define PM4125_DIG_SWR_RX_CLK_DISABLE 0
|
||||||
|
#define PM4125_DIG_SWR_CDC_TX_CLK_CTL (PM4125_DIG_BASE_ADDR+0x044)
|
||||||
|
#define PM4125_DIG_SWR_SWR_RST_EN (PM4125_DIG_BASE_ADDR+0x045)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_RST (PM4125_DIG_BASE_ADDR+0x047)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX0_CTL (PM4125_DIG_BASE_ADDR+0x048)
|
||||||
|
#define PM4125_DIG_SWR_DSM_DITHER_EN_MASK BIT(7)
|
||||||
|
#define PM4125_DIG_SWR_DSM_DITHER_DISABLE 0
|
||||||
|
#define PM4125_DIG_SWR_DSM_DITHER_ENABLE 1
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX1_CTL (PM4125_DIG_BASE_ADDR+0x049)
|
||||||
|
#define PM4125_DIG_SWR_CDC_TX_ANA_MODE_0_1 (PM4125_DIG_BASE_ADDR+0x04B)
|
||||||
|
#define PM4125_DIG_SWR_TX_ANA_TXD1_MODE_MASK GENMASK(7, 4)
|
||||||
|
#define PM4125_DIG_SWR_TX_ANA_TXD0_MODE_MASK GENMASK(3, 0)
|
||||||
|
#define PM4125_DIG_SWR_TXD_MODE_ULPI (0x9)
|
||||||
|
#define PM4125_DIG_SWR_TXD_MODE_NORMAL (0x3)
|
||||||
|
#define PM4125_DIG_SWR_CDC_COMP_CTL_0 (PM4125_DIG_BASE_ADDR+0x04F)
|
||||||
|
#define PM4125_DIG_SWR_COMP_HPHL_EN_MASK BIT(1)
|
||||||
|
#define PM4125_DIG_SWR_COMP_HPHR_EN_MASK BIT(0)
|
||||||
|
#define PM4125_DIG_SWR_COMP_ENABLE 1
|
||||||
|
#define PM4125_DIG_SWR_COMP_DISABLE 0
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_DELAY_CTL (PM4125_DIG_BASE_ADDR+0x052)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_GAIN_0 (PM4125_DIG_BASE_ADDR+0x053)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_GAIN_1 (PM4125_DIG_BASE_ADDR+0x054)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RX_GAIN_CTL (PM4125_DIG_BASE_ADDR+0x057)
|
||||||
|
#define PM4125_DIG_SWR_RX1_EN_MASK BIT(3)
|
||||||
|
#define PM4125_DIG_SWR_RX0_EN_MASK BIT(2)
|
||||||
|
#define PM4125_DIG_SWR_RX_INPUT_DISABLE 0
|
||||||
|
#define PM4125_DIG_SWR_RX_INPUT_ENABLE 1
|
||||||
|
#define PM4125_DIG_SWR_CDC_TX0_CTL (PM4125_DIG_BASE_ADDR+0x060)
|
||||||
|
#define PM4125_DIG_SWR_CDC_TX1_CTL (PM4125_DIG_BASE_ADDR+0x061)
|
||||||
|
#define PM4125_DIG_SWR_CDC_TX_RST (PM4125_DIG_BASE_ADDR+0x063)
|
||||||
|
#define PM4125_DIG_SWR_CDC_REQ0_CTL (PM4125_DIG_BASE_ADDR+0x064)
|
||||||
|
#define PM4125_DIG_SWR_CDC_REQ1_CTL (PM4125_DIG_BASE_ADDR+0x065)
|
||||||
|
#define PM4125_DIG_SWR_CDC_RST (PM4125_DIG_BASE_ADDR+0x067)
|
||||||
|
#define PM4125_DIG_SWR_CDC_AMIC_CTL (PM4125_DIG_BASE_ADDR+0x06A)
|
||||||
|
#define PM4125_DIG_SWR_AMIC_SELECT_MASK BIT(1)
|
||||||
|
#define PM4125_DIG_SWR_AMIC_SELECT_DMIC1 0
|
||||||
|
#define PM4125_DIG_SWR_AMIC_SELECT_AMIC3 1
|
||||||
|
#define PM4125_DIG_SWR_CDC_DMIC_CTL (PM4125_DIG_BASE_ADDR+0x06B)
|
||||||
|
#define PM4125_DIG_SWR_CDC_DMIC1_CTL (PM4125_DIG_BASE_ADDR+0x06C)
|
||||||
|
#define PM4125_DIG_SWR_DMIC1_CLK_EN_MASK BIT(3)
|
||||||
|
#define PM4125_DIG_SWR_DMIC1_CLK_ENABLE 1
|
||||||
|
#define PM4125_DIG_SWR_DMIC1_CLK_DISABLE 0
|
||||||
|
#define PM4125_DIG_SWR_CDC_DMIC1_RATE (PM4125_DIG_BASE_ADDR+0x06D)
|
||||||
|
#define PM4125_DIG_SWR_PDM_WD_CTL0 (PM4125_DIG_BASE_ADDR+0x070)
|
||||||
|
#define PM4125_WDT_ENABLE_MASK GENMASK(1, 0)
|
||||||
|
#define PM4125_WDT_ENABLE_RX0_L BIT(0)
|
||||||
|
#define PM4125_WDT_ENABLE_RX0_M BIT(1)
|
||||||
|
#define PM4125_DIG_SWR_PDM_WD_CTL1 (PM4125_DIG_BASE_ADDR+0x071)
|
||||||
|
#define PM4125_WDT_ENABLE_RX1_L BIT(0)
|
||||||
|
#define PM4125_WDT_ENABLE_RX1_M BIT(1)
|
||||||
|
#define PM4125_DIG_SWR_INTR_MODE (PM4125_DIG_BASE_ADDR+0x080)
|
||||||
|
#define PM4125_DIG_SWR_INTR_MASK_0 (PM4125_DIG_BASE_ADDR+0x081)
|
||||||
|
#define PM4125_DIG_SWR_INTR_MASK_1 (PM4125_DIG_BASE_ADDR+0x082)
|
||||||
|
#define PM4125_DIG_SWR_INTR_MASK_2 (PM4125_DIG_BASE_ADDR+0x083)
|
||||||
|
#define PM4125_DIG_SWR_INTR_STATUS_0 (PM4125_DIG_BASE_ADDR+0x084)
|
||||||
|
#define PM4125_DIG_SWR_INTR_STATUS_1 (PM4125_DIG_BASE_ADDR+0x085)
|
||||||
|
#define PM4125_DIG_SWR_INTR_STATUS_2 (PM4125_DIG_BASE_ADDR+0x086)
|
||||||
|
#define PM4125_DIG_SWR_INTR_CLEAR_0 (PM4125_DIG_BASE_ADDR+0x087)
|
||||||
|
#define PM4125_DIG_SWR_INTR_CLEAR_1 (PM4125_DIG_BASE_ADDR+0x088)
|
||||||
|
#define PM4125_DIG_SWR_INTR_CLEAR_2 (PM4125_DIG_BASE_ADDR+0x089)
|
||||||
|
#define PM4125_DIG_SWR_INTR_LEVEL_0 (PM4125_DIG_BASE_ADDR+0x08A)
|
||||||
|
#define PM4125_DIG_SWR_INTR_LEVEL_1 (PM4125_DIG_BASE_ADDR+0x08B)
|
||||||
|
#define PM4125_DIG_SWR_INTR_LEVEL_2 (PM4125_DIG_BASE_ADDR+0x08C)
|
||||||
|
#define PM4125_DIG_SWR_CDC_CONN_RX0_CTL (PM4125_DIG_BASE_ADDR+0x093)
|
||||||
|
#define PM4125_DIG_SWR_CDC_CONN_RX1_CTL (PM4125_DIG_BASE_ADDR+0x094)
|
||||||
|
#define PM4125_DIG_SWR_LOOP_BACK_MODE (PM4125_DIG_BASE_ADDR+0x097)
|
||||||
|
#define PM4125_DIG_SWR_DRIVE_STRENGTH_0 (PM4125_DIG_BASE_ADDR+0x0A0)
|
||||||
|
#define PM4125_DIG_SWR_DIG_DEBUG_CTL (PM4125_DIG_BASE_ADDR+0x0AB)
|
||||||
|
#define PM4125_DIG_SWR_DIG_DEBUG_EN (PM4125_DIG_BASE_ADDR+0x0AC)
|
||||||
|
#define PM4125_DIG_SWR_DEM_BYPASS_DATA0 (PM4125_DIG_BASE_ADDR+0x0B0)
|
||||||
|
#define PM4125_DIG_SWR_DEM_BYPASS_DATA1 (PM4125_DIG_BASE_ADDR+0x0B1)
|
||||||
|
#define PM4125_DIG_SWR_DEM_BYPASS_DATA2 (PM4125_DIG_BASE_ADDR+0x0B2)
|
||||||
|
#define PM4125_DIG_SWR_DEM_BYPASS_DATA3 (PM4125_DIG_BASE_ADDR+0x0B3)
|
||||||
|
|
||||||
|
#define PM4125_ANALOG_REGISTERS_MAX_SIZE (PM4125_ANA_BASE_ADDR+0x0B5)
|
||||||
|
#define PM4125_DIGITAL_REGISTERS_MAX_SIZE (PM4125_DIG_BASE_ADDR+0x0B4)
|
||||||
|
#define PM4125_ANALOG_MAX_REGISTER (PM4125_ANALOG_REGISTERS_MAX_SIZE - 1)
|
||||||
|
#define PM4125_DIGITAL_MAX_REGISTER (PM4125_DIGITAL_REGISTERS_MAX_SIZE - 1)
|
||||||
|
#define PM4125_MAX_REGISTER PM4125_DIGITAL_MAX_REGISTER
|
||||||
|
|
||||||
|
#define PM4125_MAX_MICBIAS 3
|
||||||
|
#define PM4125_MAX_SWR_CH_IDS 15
|
||||||
|
#define PM4125_SWRM_CH_MASK(ch_idx) BIT(ch_idx - 1)
|
||||||
|
|
||||||
|
enum pm4125_tx_sdw_ports {
|
||||||
|
PM4125_ADC_1_2_DMIC1L_BCS_PORT = 1,
|
||||||
|
PM4125_DMIC_1L_1R_ADC1_BCS_PORT,
|
||||||
|
PM4125_MAX_TX_SWR_PORTS = PM4125_DMIC_1L_1R_ADC1_BCS_PORT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pm4125_rx_sdw_ports {
|
||||||
|
PM4125_HPH_PORT = 1,
|
||||||
|
PM4125_COMP_PORT,
|
||||||
|
PM4125_MAX_SWR_PORTS = PM4125_COMP_PORT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pm4125_sdw_ch_info {
|
||||||
|
int port_num;
|
||||||
|
unsigned int ch_mask;
|
||||||
|
unsigned int master_ch_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WCD_SDW_CH(id, pn, cmask) \
|
||||||
|
[id] = { \
|
||||||
|
.port_num = pn, \
|
||||||
|
.ch_mask = cmask, \
|
||||||
|
.master_ch_mask = cmask, \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pm4125_priv;
|
||||||
|
struct pm4125_sdw_priv {
|
||||||
|
struct sdw_slave *sdev;
|
||||||
|
struct sdw_stream_config sconfig;
|
||||||
|
struct sdw_stream_runtime *sruntime;
|
||||||
|
struct sdw_port_config port_config[PM4125_MAX_SWR_PORTS];
|
||||||
|
struct pm4125_sdw_ch_info *ch_info;
|
||||||
|
bool port_enable[PM4125_MAX_SWR_CH_IDS];
|
||||||
|
unsigned int master_channel_map[SDW_MAX_PORTS];
|
||||||
|
int active_ports;
|
||||||
|
int num_ports;
|
||||||
|
bool is_tx;
|
||||||
|
struct pm4125_priv *pm4125;
|
||||||
|
struct irq_domain *slave_irq;
|
||||||
|
struct regmap *regmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_SND_SOC_PM4125_SDW)
|
||||||
|
int pm4125_sdw_free(struct pm4125_sdw_priv *pm4125, struct snd_pcm_substream *substream,
|
||||||
|
struct snd_soc_dai *dai);
|
||||||
|
int pm4125_sdw_set_sdw_stream(struct pm4125_sdw_priv *pm4125, struct snd_soc_dai *dai, void *stream,
|
||||||
|
int direction);
|
||||||
|
int pm4125_sdw_hw_params(struct pm4125_sdw_priv *pm4125, struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai);
|
||||||
|
|
||||||
|
struct device *pm4125_sdw_device_get(struct device_node *np);
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline int pm4125_sdw_free(struct pm4125_sdw_priv *pm4125,
|
||||||
|
struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pm4125_sdw_set_sdw_stream(struct pm4125_sdw_priv *pm4125,
|
||||||
|
struct snd_soc_dai *dai, void *stream, int direction)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pm4125_sdw_hw_params(struct pm4125_sdw_priv *pm4125,
|
||||||
|
struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/* INTR_CTRL_INT_MASK_0 */
|
||||||
|
PM4125_IRQ_MBHC_BUTTON_PRESS_DET = 0,
|
||||||
|
PM4125_IRQ_MBHC_BUTTON_RELEASE_DET,
|
||||||
|
PM4125_IRQ_MBHC_ELECT_INS_REM_DET,
|
||||||
|
PM4125_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
|
||||||
|
PM4125_IRQ_MBHC_SW_DET,
|
||||||
|
PM4125_IRQ_HPHR_OCP_INT,
|
||||||
|
PM4125_IRQ_HPHR_CNP_INT,
|
||||||
|
PM4125_IRQ_HPHL_OCP_INT,
|
||||||
|
|
||||||
|
/* INTR_CTRL_INT_MASK_1 */
|
||||||
|
PM4125_IRQ_HPHL_CNP_INT,
|
||||||
|
PM4125_IRQ_EAR_CNP_INT,
|
||||||
|
PM4125_IRQ_EAR_SCD_INT,
|
||||||
|
PM4125_IRQ_AUX_CNP_INT,
|
||||||
|
PM4125_IRQ_AUX_SCD_INT,
|
||||||
|
PM4125_IRQ_HPHL_PDM_WD_INT,
|
||||||
|
PM4125_IRQ_HPHR_PDM_WD_INT,
|
||||||
|
PM4125_IRQ_AUX_PDM_WD_INT,
|
||||||
|
|
||||||
|
/* INTR_CTRL_INT_MASK_2 */
|
||||||
|
PM4125_IRQ_LDORT_SCD_INT,
|
||||||
|
PM4125_IRQ_MBHC_MOISTURE_INT,
|
||||||
|
PM4125_IRQ_HPHL_SURGE_DET_INT,
|
||||||
|
PM4125_IRQ_HPHR_SURGE_DET_INT,
|
||||||
|
PM4125_NUM_IRQS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pm4125_tx_sdw_channels {
|
||||||
|
PM4125_ADC1,
|
||||||
|
PM4125_ADC2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pm4125_rx_sdw_channels {
|
||||||
|
PM4125_HPH_L,
|
||||||
|
PM4125_HPH_R,
|
||||||
|
PM4125_COMP_L,
|
||||||
|
PM4125_COMP_R,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _PM4125_REGISTERS_H */
|
||||||
Loading…
Reference in New Issue