asoc: codecs: Update WSA2 Macro to Match WSA Macro

Propagate all changes to lpass-cdc-wsa-macro to
lpass-cdc-wsa2-macro. Leave get_channel_map alone
because it is wsa macro specific.

Change-Id: I46733a759490d488f46eda24b4006a1dec63c7cc
Signed-off-by: Matthew Rice <quic_mrice@quicinc.com>
This commit is contained in:
Matthew Rice
2022-05-06 19:26:42 -07:00
parent 68469d7946
commit c3cddd0b43
2 changed files with 560 additions and 95 deletions

View File

@@ -12,6 +12,7 @@
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include <soc/swr-common.h>
#include <soc/swr-wcd.h>
@@ -71,6 +72,9 @@ enum {
LPASS_CDC_WSA2_MACRO_RX_MIX1,
LPASS_CDC_WSA2_MACRO_RX4,
LPASS_CDC_WSA2_MACRO_RX5,
LPASS_CDC_WSA2_MACRO_RX6,
LPASS_CDC_WSA2_MACRO_RX7,
LPASS_CDC_WSA2_MACRO_RX8,
LPASS_CDC_WSA2_MACRO_RX_MAX,
};
@@ -106,6 +110,9 @@ enum {
INTn_1_INP_SEL_RX3,
INTn_1_INP_SEL_RX4,
INTn_1_INP_SEL_RX5,
INTn_1_INP_SEL_RX6,
INTn_1_INP_SEL_RX7,
INTn_1_INP_SEL_RX8,
INTn_1_INP_SEL_DEC0,
INTn_1_INP_SEL_DEC1,
};
@@ -118,23 +125,19 @@ enum {
INTn_2_INP_SEL_RX3,
INTn_2_INP_SEL_RX4,
INTn_2_INP_SEL_RX5,
INTn_2_INP_SEL_RX6,
INTn_2_INP_SEL_RX7,
INTn_2_INP_SEL_RX8,
};
enum {
WSA2_MODE_21DB,
WSA2_MODE_19P5DB,
WSA2_MODE_18DB,
WSA2_MODE_16P5DB,
WSA2_MODE_15DB,
WSA2_MODE_13P5DB,
WSA2_MODE_12DB,
WSA2_MODE_10P5DB,
WSA2_MODE_9DB,
WSA2_MODE_MAX
IDLE_DETECT,
NG1,
NG2,
NG3,
};
static struct lpass_cdc_comp_setting comp_setting_table[WSA2_MODE_MAX] =
{
static struct lpass_cdc_comp_setting comp_setting_table[G_MAX_DB] = {
{42, 0, 42},
{39, 0, 42},
{36, 0, 42},
@@ -189,6 +192,8 @@ static int lpass_cdc_wsa2_macro_get_channel_map(struct snd_soc_dai *dai,
unsigned int *tx_num, unsigned int *tx_slot,
unsigned int *rx_num, unsigned int *rx_slot);
static int lpass_cdc_wsa2_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
#define LPASS_CDC_WSA2_MACRO_VTH_TO_REG(vth) ((vth) == 0 ? 255 : (vth))
/* Hold instance to soundwire platform device */
struct lpass_cdc_wsa2_macro_swr_ctrl_data {
struct platform_device *wsa2_swr_pdev;
@@ -229,6 +234,7 @@ enum {
LPASS_CDC_WSA2_MACRO_MAX_DAIS,
};
#define LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX 3
/*
@@ -252,6 +258,9 @@ enum {
* @active_ch_cnt: channel count of all AIF DAIs
* @rx_port_value: mixer ctl value of WSA2 RX MUXes
* @wsa2_io_base: Base address of WSA2 macro addr space
* @wsa2_sys_gain System gain value, see wsa2 driver
* @wsa2_bat_cfg Battery Configuration value, see wsa2 driver
* @wsa2_rload Resistor load value for WSA2 Speaker, see wsa2 driver
*/
struct lpass_cdc_wsa2_macro_priv {
struct device *dev;
@@ -273,14 +282,17 @@ struct lpass_cdc_wsa2_macro_priv {
struct snd_soc_component *component;
int rx_0_count;
int rx_1_count;
int wsa_spkrrecv;
unsigned long active_ch_mask[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
unsigned long active_ch_cnt[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
u16 bit_width[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
int rx_port_value[LPASS_CDC_WSA2_MACRO_RX_MAX];
char __iomem *wsa2_io_base;
struct platform_device *pdev_child_devices
[LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX];
int child_count;
int wsa2_spkrrecv;
int spkr_gain_offset;
int spkr_mode;
int is_softclip_on[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
int softclip_clk_users[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
char __iomem *mclk_mode_muxsel;
@@ -293,17 +305,24 @@ struct lpass_cdc_wsa2_macro_priv {
uint32_t thermal_cur_state;
uint32_t thermal_max_state;
struct work_struct lpass_cdc_wsa2_macro_cooling_work;
bool pbr_enable;
u32 wsa2_sys_gain[2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1)];
u32 wsa2_bat_cfg[LPASS_CDC_WSA2_MACRO_RX1 + 1];
u32 wsa2_rload[LPASS_CDC_WSA2_MACRO_RX1 + 1];
u8 idle_detect_en;
int noise_gate_mode;
};
static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[];
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static const char *const rx_text[] = {
"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "DEC0", "DEC1"
"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4",
"RX5", "RX6", "RX7", "RX8", "DEC0", "DEC1"
};
static const char *const rx_mix_text[] = {
"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5",
"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8"
};
static const char *const rx_mix_ec_text[] = {
@@ -322,10 +341,6 @@ static const char * const lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text[] = {
"OFF", "ON"
};
static const char *const lpass_cdc_wsa2_macro_ear_spkrrecv_text[] = {
"OFF", "ON"
};
static const char * const lpass_cdc_wsa2_macro_comp_mode_text[] = {
"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
@@ -339,8 +354,7 @@ static const struct snd_kcontrol_new wsa2_int1_vbat_mix_switch[] = {
SOC_DAPM_SINGLE("WSA2 RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
};
static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
lpass_cdc_wsa2_macro_ear_spkrrecv_text);
static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text);
static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
@@ -349,19 +363,19 @@ static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
/* RX INT0 */
static const struct soc_enum rx0_prim_inp0_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
0, 9, rx_text);
0, 12, rx_text);
static const struct soc_enum rx0_prim_inp1_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
3, 9, rx_text);
3, 12, rx_text);
static const struct soc_enum rx0_prim_inp2_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
3, 9, rx_text);
3, 12, rx_text);
static const struct soc_enum rx0_mix_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
0, 7, rx_mix_text);
0, 10, rx_mix_text);
static const struct soc_enum rx0_sidetone_mix_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
@@ -384,19 +398,19 @@ static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
/* RX INT1 */
static const struct soc_enum rx1_prim_inp0_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
0, 9, rx_text);
0, 12, rx_text);
static const struct soc_enum rx1_prim_inp1_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
3, 9, rx_text);
3, 12, rx_text);
static const struct soc_enum rx1_prim_inp2_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
3, 9, rx_text);
3, 12, rx_text);
static const struct soc_enum rx1_mix_chain_enum =
SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
0, 7, rx_mix_text);
0, 10, rx_mix_text);
static const struct snd_kcontrol_new rx1_prim_inp0_mux =
SOC_DAPM_ENUM("WSA2_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
@@ -730,10 +744,37 @@ static int lpass_cdc_wsa2_macro_hw_params(struct snd_pcm_substream *substream,
__func__, params_rate(params));
return ret;
}
switch (params_width(params)) {
case 16:
wsa2_priv->bit_width[dai->id] = 16;
break;
case 24:
wsa2_priv->bit_width[dai->id] = 24;
break;
case 32:
wsa2_priv->bit_width[dai->id] = 32;
break;
default:
dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
__func__, params_width(params));
return -EINVAL;
}
break;
case SNDRV_PCM_STREAM_CAPTURE:
if (dai->id == LPASS_CDC_WSA2_MACRO_AIF_VI)
wsa2_priv->pcm_rate_vi = params_rate(params);
switch (params_width(params)) {
case 16:
wsa2_priv->bit_width[dai->id] = 16;
break;
case 24:
wsa2_priv->bit_width[dai->id] = 24;
break;
default:
dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
__func__, params_width(params));
return -EINVAL;
}
default:
break;
}
@@ -1019,16 +1060,16 @@ static int lpass_cdc_wsa2_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w
return -EINVAL;
switch (wsa2_priv->pcm_rate_vi) {
case 48000:
val = 0x04;
break;
case 24000:
val = 0x02;
break;
case 8000:
default:
val = 0x00;
break;
case 48000:
val = 0x04;
break;
case 24000:
val = 0x02;
break;
case 8000:
default:
val = 0x00;
break;
}
switch (event) {
@@ -1256,7 +1297,9 @@ static int lpass_cdc_wsa2_macro_config_compander(struct snd_soc_component *compo
u16 comp_ctl0_reg, comp_ctl8_reg, rx_path_cfg0_reg;
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
struct lpass_cdc_comp_setting *comp_settings = NULL;
u16 mode = 0;
int sys_gain, bat_cfg, sys_gain_int, upper_gain, lower_gain;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
@@ -1274,11 +1317,49 @@ static int lpass_cdc_wsa2_macro_config_compander(struct snd_soc_component *compo
(comp * LPASS_CDC_WSA2_MACRO_RX_COMP_OFFSET);
rx_path_cfg0_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG0 +
(comp * LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET);
comp_settings = &comp_setting_table[mode];
/* If System has battery configuration */
if (wsa2_priv->wsa2_bat_cfg[comp]) {
sys_gain = wsa2_priv->wsa2_sys_gain[comp * 2 + wsa2_priv->wsa2_spkrrecv];
bat_cfg = wsa2_priv->wsa2_bat_cfg[comp];
/* Convert enum to value and
* multiply all values by 10 to avoid float
*/
sys_gain_int = -15 * sys_gain + 210;
switch (bat_cfg) {
case CONFIG_1S:
case EXT_1S:
if (sys_gain > G_13P5_DB) {
upper_gain = sys_gain_int + 60;
lower_gain = 0;
} else {
upper_gain = 210;
lower_gain = 0;
}
break;
case CONFIG_3S:
case EXT_3S:
upper_gain = sys_gain_int;
lower_gain = 75;
case EXT_ABOVE_3S:
upper_gain = sys_gain_int;
lower_gain = 120;
break;
default:
upper_gain = sys_gain_int;
lower_gain = 0;
break;
}
/* Truncate after calculation */
comp_settings->lower_gain_int = (lower_gain * 2) / 10;
comp_settings->upper_gain_int = (upper_gain * 2) / 10;
}
if (SND_SOC_DAPM_EVENT_ON(event)) {
lpass_cdc_update_compander_setting(component,
comp_ctl8_reg,
&comp_setting_table[mode]);
comp_settings);
/* Enable Compander Clock */
snd_soc_component_update_bits(component, comp_ctl0_reg,
0x01, 0x01);
@@ -1386,6 +1467,63 @@ static int lpass_cdc_wsa2_macro_config_softclip(struct snd_soc_component *compon
return 0;
}
static int lpass_cdc_was_macro_config_pbr(struct snd_soc_component *component,
int path, int event)
{
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
u16 reg1 = 0, reg2 = 0, reg3 = 0;
int softclip_path = 0;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
if (path == LPASS_CDC_WSA2_MACRO_COMP1) {
reg1 = LPASS_CDC_WSA2_COMPANDER0_CTL0;
reg2 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
reg3 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG1;
softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP0;
} else if (path == LPASS_CDC_WSA2_MACRO_COMP2) {
reg1 = LPASS_CDC_WSA2_COMPANDER1_CTL0;
reg2 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
reg3 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG1;
softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP1;
}
if (!wsa2_priv->pbr_enable || wsa2_priv->wsa2_bat_cfg[path] >= EXT_1S ||
wsa2_priv->wsa2_sys_gain[path * 2] > G_12_DB ||
wsa2_priv->wsa2_spkrrecv || !reg1 || !reg2 || !reg3)
return 0;
if (SND_SOC_DAPM_EVENT_ON(event)) {
snd_soc_component_update_bits(component,
reg1, 0x08, 0x08);
snd_soc_component_update_bits(component,
reg2, 0x40, 0x40);
snd_soc_component_update_bits(component,
reg3, 0x80, 0x80);
lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
softclip_path, true);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_PBR_PATH_CTL,
0x01, 0x01);
}
if (SND_SOC_DAPM_EVENT_OFF(event)) {
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_PBR_PATH_CTL,
0x01, 0x00);
lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
softclip_path, false);
snd_soc_component_update_bits(component,
reg1, 0x08, 0x00);
snd_soc_component_update_bits(component,
reg2, 0x40, 0x00);
snd_soc_component_update_bits(component,
reg3, 0x80, 0x00);
}
return 0;
}
static bool lpass_cdc_wsa2_macro_adie_lb(struct snd_soc_component *component,
int interp_idx)
{
@@ -1524,6 +1662,57 @@ static int lpass_cdc_wsa2_macro_enable_prim_interpolator(
return 0;
}
static void lpass_cdc_macro_idle_detect_control(struct snd_soc_component *component,
struct lpass_cdc_wsa2_macro_priv *wsa2_priv,
int interp, int event)
{
int reg = 0, mask = 0, val = 0, source_reg = 0;
u16 mode = 0;
dev_dbg(component->dev, "%s: Idle_detect_en value: %d\n", __func__,
wsa2_priv->idle_detect_en);
if (!wsa2_priv->idle_detect_en)
return;
if (interp == LPASS_CDC_WSA2_MACRO_COMP1) {
source_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
mask = 0x01;
val = 0x01;
}
if (interp == LPASS_CDC_WSA2_MACRO_COMP2) {
source_reg = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
mask = 0x02;
val = 0x02;
}
mode = wsa2_priv->comp_mode[interp];
if ((wsa2_priv->noise_gate_mode == NG2 && mode >= G_13P5_DB) ||
wsa2_priv->noise_gate_mode == IDLE_DETECT || !wsa2_priv->pbr_enable ||
wsa2_priv->wsa2_spkrrecv) {
snd_soc_component_update_bits(component, source_reg, 0x80, 0x00);
dev_dbg(component->dev, "%s: Idle detect source: Legacy\n", __func__);
} else {
snd_soc_component_update_bits(component, source_reg, 0x80, 0x80);
dev_dbg(component->dev, "%s: Idle detect source: PRE-LA\n", __func__);
}
if (reg && SND_SOC_DAPM_EVENT_ON(event)) {
snd_soc_component_update_bits(component, reg, mask, val);
dev_dbg(component->dev, "%s: Idle detect clks ON\n", __func__);
}
if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
snd_soc_component_update_bits(component, reg, mask, 0x00);
snd_soc_component_write(component,
LPASS_CDC_WSA2_IDLE_DETECT_CFG3, 0x0);
dev_dbg(component->dev, "%s: Idle detect clks OFF\n", __func__);
}
}
static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -1588,8 +1777,11 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
}
lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
w->shift, event);
lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
if(wsa2_priv->wsa_spkrrecv)
lpass_cdc_was_macro_config_pbr(component, w->shift, event);
if (wsa2_priv->wsa2_spkrrecv)
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_RX0_RX_PATH_CFG1,
0x08, 0x00);
@@ -1598,7 +1790,10 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08);
lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
w->shift, event);
lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
lpass_cdc_was_macro_config_pbr(component, w->shift, event);
lpass_cdc_wsa2_macro_enable_prim_interpolator(component, reg, event);
break;
}
@@ -1733,24 +1928,24 @@ static int lpass_cdc_wsa2_macro_enable_vbat(struct snd_soc_dapm_widget *w,
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
0xFF, 0x00);
/* Enable CB decode block clock */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
/* Enable BCL path */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
/* Request for BCL data */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
/* Enable CB decode block clock */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
/* Enable BCL path */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
/* Request for BCL data */
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
snd_soc_component_update_bits(component, vbat_path_cfg,
0x80, 0x00);
snd_soc_component_update_bits(component,
@@ -2056,7 +2251,7 @@ static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
ucontrol->value.integer.value[0] = wsa2_priv->wsa_spkrrecv;
ucontrol->value.integer.value[0] = wsa2_priv->wsa2_spkrrecv;
dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
__func__, ucontrol->value.integer.value[0]);
@@ -2065,21 +2260,54 @@ static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
}
static int lpass_cdc_wsa2_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
wsa2_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
__func__, wsa2_priv->wsa_spkrrecv);
wsa2_priv->wsa2_spkrrecv = ucontrol->value.integer.value[0];
return 0;
dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
__func__, wsa2_priv->wsa2_spkrrecv);
return 0;
}
static int lpass_cdc_wsa2_macro_idle_detect_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
struct device *wsa2_dev = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
ucontrol->value.integer.value[0] = wsa2_priv->idle_detect_en;
return 0;
}
static int lpass_cdc_wsa2_macro_idle_detect_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
struct device *wsa2_dev = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
wsa2_priv->idle_detect_en = ucontrol->value.integer.value[0];
return 0;
}
static int lpass_cdc_wsa2_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
@@ -2292,10 +2520,41 @@ static int lpass_cdc_wsa2_macro_soft_clip_enable_put(struct snd_kcontrol *kcontr
return 0;
}
static int lpass_cdc_wsa2_macro_pbr_enable_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
ucontrol->value.integer.value[0] = wsa2_priv->pbr_enable;
return 0;
}
static int lpass_cdc_wsa2_macro_pbr_enable_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return -EINVAL;
wsa2_priv->pbr_enable = ucontrol->value.integer.value[0];
return 0;
}
static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
SOC_ENUM_EXT("WSA2 SPKRRECV", lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
lpass_cdc_wsa2_macro_ear_spkrrecv_get,
lpass_cdc_wsa2_macro_ear_spkrrecv_put),
SOC_ENUM_EXT("WSA2_GSM mode Enable", lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_get,
lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_put),
@@ -2305,6 +2564,12 @@ static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
SOC_ENUM_EXT("WSA2_RX1 comp_mode", lpass_cdc_wsa2_macro_comp_mode_enum,
lpass_cdc_wsa2_macro_comp_mode_get,
lpass_cdc_wsa2_macro_comp_mode_put),
SOC_SINGLE_EXT("WSA2 SPKRRECV", SND_SOC_NOPM, 0, 1, 0,
lpass_cdc_wsa2_macro_ear_spkrrecv_get,
lpass_cdc_wsa2_macro_ear_spkrrecv_put),
SOC_SINGLE_EXT("WSA2 Idle Detect", SND_SOC_NOPM, 0, 1,
0, lpass_cdc_wsa2_macro_idle_detect_get,
lpass_cdc_wsa2_macro_idle_detect_put),
SOC_SINGLE_EXT("WSA2_Softclip0 Enable", SND_SOC_NOPM,
LPASS_CDC_WSA2_MACRO_SOFTCLIP0, 1, 0,
lpass_cdc_wsa2_macro_soft_clip_enable_get,
@@ -2339,6 +2604,9 @@ static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
SOC_SINGLE_EXT("WSA2_RX1 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX1,
1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
SOC_SINGLE_EXT("WSA2 PBR Enable", SND_SOC_NOPM, 0, 1,
0, lpass_cdc_wsa2_macro_pbr_enable_get,
lpass_cdc_wsa2_macro_pbr_enable_put),
};
static const struct soc_enum rx_mux_enum =
@@ -2712,14 +2980,150 @@ static const struct snd_soc_dapm_route wsa2_audio_map[] = {
{"WSA2_SPK2 OUT", NULL, "WSA2_MCLK"},
};
static void lpass_cdc_wsa2_macro_init_pbr(struct snd_soc_component *component)
{
int sys_gain, bat_cfg, rload;
int vth1, vth2, vth3, vth4, vth5, vth6, vth7, vth8, vth9;
int vth10, vth11, vth12, vth13, vth14, vth15;
struct device *wsa2_dev = NULL;
struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
return;
/* RX0 */
sys_gain = wsa2_priv->wsa2_sys_gain[0];
bat_cfg = wsa2_priv->wsa2_bat_cfg[0];
rload = wsa2_priv->wsa2_rload[0];
/* ILIM */
switch (rload) {
case WSA_4_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x40);
break;
case WSA_6_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x80);
break;
case WSA_8_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xC0);
break;
case WSA_32_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xE0);
break;
default:
break;
}
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG1, 0x0F, sys_gain);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG9, 0xC0, (bat_cfg - 1) << 0x6);
/* Thesh */
vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1, vth1);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2, vth2);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3, vth3);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4, vth4);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5, vth5);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6, vth6);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7, vth7);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8, vth8);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9, vth9);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10, vth10);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11, vth11);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12, vth12);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13, vth13);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14, vth14);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15, vth15);
/* RX1 */
sys_gain = wsa2_priv->wsa2_sys_gain[2];
bat_cfg = wsa2_priv->wsa2_bat_cfg[1];
rload = wsa2_priv->wsa2_rload[1];
/* ILIM */
switch (rload) {
case WSA_4_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x40);
break;
case WSA_6_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x80);
break;
case WSA_8_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xC0);
break;
case WSA_32_OHMS:
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xE0);
break;
default:
break;
}
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG1_1, 0x0F, sys_gain);
snd_soc_component_update_bits(component,
LPASS_CDC_WSA2_ILIM_CFG9, 0x30, (bat_cfg - 1) << 0x4);
/* Thesh */
vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1_1, vth1);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2_1, vth2);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3_1, vth3);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4_1, vth4);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5_1, vth5);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6_1, vth6);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7_1, vth7);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8_1, vth8);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9_1, vth9);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10_1, vth10);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11_1, vth11);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12_1, vth12);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13_1, vth13);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14_1, vth14);
snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15_1, vth15);
}
static const struct lpass_cdc_wsa2_macro_reg_mask_val
lpass_cdc_wsa2_macro_reg_init[] = {
{LPASS_CDC_WSA2_BOOST0_BOOST_CFG1, 0x3F, 0x12},
{LPASS_CDC_WSA2_BOOST0_BOOST_CFG2, 0x1C, 0x08},
{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x1E, 0x18},
{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x3E, 0x2e},
{LPASS_CDC_WSA2_BOOST1_BOOST_CFG1, 0x3F, 0x12},
{LPASS_CDC_WSA2_BOOST1_BOOST_CFG2, 0x1C, 0x08},
{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x1E, 0x18},
{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x3E, 0x2e},
{LPASS_CDC_WSA2_BOOST0_BOOST_CTL, 0x70, 0x58},
{LPASS_CDC_WSA2_BOOST1_BOOST_CTL, 0x70, 0x58},
{LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08},
@@ -2730,12 +3134,28 @@ static const struct lpass_cdc_wsa2_macro_reg_mask_val
{LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
{LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
{LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x01, 0x01},
{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x01, 0x01},
{LPASS_CDC_WSA2_RX0_RX_PATH_CFG0, 0x01, 0x01},
{LPASS_CDC_WSA2_RX1_RX_PATH_CFG0, 0x01, 0x01},
{LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
{LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
{LPASS_CDC_WSA2_LA_CFG, 0x3F, 0xF},
{LPASS_CDC_WSA2_PBR_CFG16, 0xFF, 0x42},
{LPASS_CDC_WSA2_PBR_CFG19, 0xFF, 0xFC},
{LPASS_CDC_WSA2_PBR_CFG20, 0xF0, 0x60},
{LPASS_CDC_WSA2_ILIM_CFG1, 0x70, 0x40},
{LPASS_CDC_WSA2_ILIM_CFG0, 0x03, 0x01},
{LPASS_CDC_WSA2_ILIM_CFG3, 0x1F, 0x15},
{LPASS_CDC_WSA2_LA_CFG_1, 0x3F, 0x0F},
{LPASS_CDC_WSA2_PBR_CFG16_1, 0xFF, 0x42},
{LPASS_CDC_WSA2_PBR_CFG21, 0xFF, 0xFC},
{LPASS_CDC_WSA2_PBR_CFG22, 0xF0, 0x60},
{LPASS_CDC_WSA2_ILIM_CFG1_1, 0x70, 0x40},
{LPASS_CDC_WSA2_ILIM_CFG0_1, 0x03, 0x01},
{LPASS_CDC_WSA2_ILIM_CFG4, 0x1F, 0x15},
{LPASS_CDC_WSA2_ILIM_CFG2_1, 0xFF, 0x2A},
{LPASS_CDC_WSA2_ILIM_CFG2, 0x3F, 0x1B},
{LPASS_CDC_WSA2_ILIM_CFG9, 0x0F, 0x05},
{LPASS_CDC_WSA2_IDLE_DETECT_CFG1, 0xFF, 0x1D},
};
static void lpass_cdc_wsa2_macro_init_reg(struct snd_soc_component *component)
@@ -2747,6 +3167,7 @@ static void lpass_cdc_wsa2_macro_init_reg(struct snd_soc_component *component)
lpass_cdc_wsa2_macro_reg_init[i].reg,
lpass_cdc_wsa2_macro_reg_init[i].mask,
lpass_cdc_wsa2_macro_reg_init[i].val);
lpass_cdc_wsa2_macro_init_pbr(component);
}
static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
@@ -2768,6 +3189,7 @@ static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
pm_runtime_put_autosuspend(wsa2_priv->dev);
pm_runtime_mark_last_busy(wsa2_priv->dev);
}
return rc;
}
@@ -2952,9 +3374,8 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
return -EINVAL;
}
ret = snd_soc_dapm_new_controls(dapm,
lpass_cdc_wsa2_macro_dapm_widgets,
ARRAY_SIZE(lpass_cdc_wsa2_macro_dapm_widgets));
ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa2_macro_dapm_widgets,
ARRAY_SIZE(lpass_cdc_wsa2_macro_dapm_widgets));
if (ret < 0) {
dev_err(wsa2_dev, "%s: Failed to add controls\n", __func__);
return ret;
@@ -2973,9 +3394,8 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
return ret;
}
ret = snd_soc_add_component_controls(component,
lpass_cdc_wsa2_macro_snd_controls,
ARRAY_SIZE(lpass_cdc_wsa2_macro_snd_controls));
ret = snd_soc_add_component_controls(component, lpass_cdc_wsa2_macro_snd_controls,
ARRAY_SIZE(lpass_cdc_wsa2_macro_snd_controls));
if (ret < 0) {
dev_err(wsa2_dev, "%s: Failed to add snd_ctls\n", __func__);
return ret;
@@ -2993,6 +3413,7 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
snd_soc_dapm_sync(dapm);
wsa2_priv->component = component;
wsa2_priv->spkr_gain_offset = LPASS_CDC_WSA2_MACRO_GAIN_OFFSET_0_DB;
lpass_cdc_wsa2_macro_init_reg(component);
return 0;
@@ -3084,7 +3505,7 @@ static void lpass_cdc_wsa2_macro_add_child_devices(struct work_struct *work)
swr_ctrl_data[ctrl_num].wsa2_swr_pdev = pdev;
ctrl_num++;
dev_dbg(&pdev->dev,
"%s: Added soundwire ctrl device(s)\n",
"%s: Adding soundwire ctrl device(s)\n",
__func__);
wsa2_priv->swr_ctrl_data = swr_ctrl_data;
}
@@ -3120,12 +3541,12 @@ static void lpass_cdc_wsa2_macro_cooling_adjust_gain(struct work_struct *work)
wsa2_priv = container_of(work, struct lpass_cdc_wsa2_macro_priv,
lpass_cdc_wsa2_macro_cooling_work);
if (!wsa2_priv) {
pr_err_ratelimited("%s: priv is null for macro!\n",
pr_err("%s: priv is null for macro!\n",
__func__);
return;
}
if (!wsa2_priv->dev || !wsa2_priv->dev->of_node) {
dev_err_ratelimited(wsa2_priv->dev,
dev_err(wsa2_priv->dev,
"%s: DT node for wsa2_priv does not exist\n", __func__);
return;
}
@@ -3154,6 +3575,31 @@ static void lpass_cdc_wsa2_macro_cooling_adjust_gain(struct work_struct *work)
return;
}
static int lpass_cdc_wsa2_macro_read_array(struct platform_device *pdev,
const char *name, int num_values,
u32 *output)
{
u32 len, ret, size;
if (!of_find_property(pdev->dev.of_node, name, &size)) {
dev_info(&pdev->dev, "%s: missing %s\n", __func__, name);
return 0;
}
len = size / sizeof(u32);
if (len != num_values) {
dev_info(&pdev->dev, "%s: invalid number of %s\n", __func__, name);
return -EINVAL;
}
ret = of_property_read_u32_array(pdev->dev.of_node, name, output, len);
if (ret)
dev_info(&pdev->dev, "%s: Failed to read %s\n", __func__, name);
return 0;
}
static void lpass_cdc_wsa2_macro_init_ops(struct macro_ops *ops,
char __iomem *wsa2_io_base)
{
@@ -3175,6 +3621,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
char __iomem *wsa2_io_base;
int ret = 0;
u32 is_used_wsa2_swr_gpio = 1;
u32 noise_gate_mode;
const char *is_used_wsa2_swr_gpio_dt = "qcom,is-used-swr-gpio";
if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
@@ -3183,8 +3630,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
wsa2_priv = devm_kzalloc(&pdev->dev,
sizeof(struct lpass_cdc_wsa2_macro_priv),
wsa2_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_wsa2_macro_priv),
GFP_KERNEL);
if (!wsa2_priv)
return -ENOMEM;
@@ -3225,12 +3671,20 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
wsa2_priv->wsa2_swr_gpio_p, false);
wsa2_io_base = devm_ioremap(&pdev->dev,
wsa2_base_addr,
LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
wsa2_base_addr, LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
if (!wsa2_io_base) {
dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
return -EINVAL;
}
lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-rloads",
LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_rload);
lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-system-gains",
2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1), wsa2_priv->wsa2_sys_gain);
lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-bat-cfgs",
LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_bat_cfg);
wsa2_priv->wsa2_io_base = wsa2_io_base;
wsa2_priv->reset_swr = true;
INIT_WORK(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work,
@@ -3250,7 +3704,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
__func__, "qcom,mux0-clk-id");
default_clk_id = WSA_CORE_CLK;
default_clk_id = WSA2_CORE_CLK;
}
wsa2_priv->default_clk_id = default_clk_id;
@@ -3293,14 +3747,25 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
}
}
ret = of_property_read_u32(pdev->dev.of_node,
"qcom,noise-gate-mode", &noise_gate_mode);
if (ret) {
dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
__func__, "qcom,noise-gate-mode");
wsa2_priv->noise_gate_mode = IDLE_DETECT;
} else {
if (noise_gate_mode >= IDLE_DETECT && noise_gate_mode <= NG3)
wsa2_priv->noise_gate_mode = noise_gate_mode;
else
wsa2_priv->noise_gate_mode = IDLE_DETECT;
}
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_suspend_ignore_children(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
schedule_work(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work);
return ret;
reg_macro_fail:
mutex_destroy(&wsa2_priv->mclk_lock);