ASoC: codecs: qcrg update for TX paths
Add qcrg updates for AMIC and DMIC register updates and modes. Change-Id: I7401b21cfffd2c40f456d985e2b3ea1988f4ba6c Signed-off-by: Karthikeyan Mani <kmani@codeaurora.org>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _WCD938X_INTERNAL_H
|
||||
@@ -17,6 +17,7 @@
|
||||
#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50)
|
||||
#define MAX_PORT 8
|
||||
#define MAX_CH_PER_PORT 8
|
||||
#define TX_ADC_MAX 4
|
||||
|
||||
enum {
|
||||
TX_HDR12 = 0,
|
||||
@@ -63,6 +64,7 @@ struct wcd938x_priv {
|
||||
struct wcd938x_mbhc *mbhc;
|
||||
|
||||
u32 hph_mode;
|
||||
u32 tx_mode[TX_ADC_MAX];
|
||||
bool comp1_enable;
|
||||
bool comp2_enable;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@@ -30,6 +30,27 @@
|
||||
#define WCD938X_VERSION_1_0 1
|
||||
#define WCD938X_VERSION_ENTRY_SIZE 32
|
||||
|
||||
#define ADC_MODE_VAL_HIFI 0x01
|
||||
#define ADC_MODE_VAL_LO_HIF 0x02
|
||||
#define ADC_MODE_VAL_NORMAL 0x03
|
||||
#define ADC_MODE_VAL_LP 0x05
|
||||
#define ADC_MODE_VAL_ULP1 0x09
|
||||
#define ADC_MODE_VAL_ULP2 0x0B
|
||||
|
||||
#define STRING(name) #name
|
||||
#define WCD_DAPM_ENUM(name, reg, offset, text) \
|
||||
static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
|
||||
static const struct snd_kcontrol_new name##_mux = \
|
||||
SOC_DAPM_ENUM(STRING(name), name##_enum)
|
||||
|
||||
#define WCD_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
|
||||
static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
|
||||
static const struct snd_kcontrol_new name##_mux = \
|
||||
SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
|
||||
|
||||
#define WCD_DAPM_MUX(name, shift, kctl) \
|
||||
SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
|
||||
|
||||
enum {
|
||||
WCD9380 = 0,
|
||||
WCD9385,
|
||||
@@ -47,6 +68,16 @@ enum {
|
||||
HPH_PA_DELAY,
|
||||
};
|
||||
|
||||
enum {
|
||||
ADC_MODE_INVALID = 0,
|
||||
ADC_MODE_HIFI,
|
||||
ADC_MODE_LO_HIF,
|
||||
ADC_MODE_NORMAL,
|
||||
ADC_MODE_LP,
|
||||
ADC_MODE_ULP1,
|
||||
ADC_MODE_ULP2,
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
|
||||
|
||||
@@ -311,8 +342,6 @@ static int wcd938x_rx_clk_enable(struct snd_soc_component *component)
|
||||
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (wcd938x->rx_clk_cnt == 0) {
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x08, 0x08);
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01);
|
||||
snd_soc_component_update_bits(component,
|
||||
@@ -945,17 +974,22 @@ static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
|
||||
case 0:
|
||||
case 1:
|
||||
dmic_clk_cnt = &(wcd938x->dmic_0_1_clk_cnt);
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_CTL;
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
dmic_clk_cnt = &(wcd938x->dmic_2_3_clk_cnt);
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
dmic_clk_cnt = &(wcd938x->dmic_4_5_clk_cnt);
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL;
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC3_CTL;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
dmic_clk_cnt = &(wcd938x->dmic_6_7_clk_cnt);
|
||||
dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC4_CTL;
|
||||
break;
|
||||
default:
|
||||
dev_err(component->dev, "%s: Invalid DMIC Selection\n",
|
||||
@@ -969,6 +1003,9 @@ static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80);
|
||||
/* enable clock scaling */
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_DMIC_CTL, 0x06, 0x06);
|
||||
snd_soc_component_update_bits(component,
|
||||
dmic_clk_reg, 0x07, 0x02);
|
||||
snd_soc_component_update_bits(component,
|
||||
@@ -1107,24 +1144,90 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcd938x_get_adc_mode(int val)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (val) {
|
||||
case ADC_MODE_INVALID:
|
||||
ret = ADC_MODE_VAL_NORMAL;
|
||||
break;
|
||||
case ADC_MODE_HIFI:
|
||||
ret = ADC_MODE_VAL_HIFI;
|
||||
break;
|
||||
case ADC_MODE_LO_HIF:
|
||||
ret = ADC_MODE_VAL_LO_HIF;
|
||||
break;
|
||||
case ADC_MODE_NORMAL:
|
||||
ret = ADC_MODE_VAL_NORMAL;
|
||||
break;
|
||||
case ADC_MODE_LP:
|
||||
ret = ADC_MODE_VAL_LP;
|
||||
break;
|
||||
case ADC_MODE_ULP1:
|
||||
ret = ADC_MODE_VAL_ULP1;
|
||||
break;
|
||||
case ADC_MODE_ULP2:
|
||||
ret = ADC_MODE_VAL_ULP2;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
pr_err("%s: invalid ADC mode value %d\n", __func__, val);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event){
|
||||
|
||||
int mode;
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
|
||||
|
||||
dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
|
||||
w->name, event);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
|
||||
if (mode < 0) {
|
||||
dev_info(component->dev,
|
||||
"%s: invalid mode, setting to normal mode\n",
|
||||
__func__);
|
||||
mode = ADC_MODE_VAL_NORMAL;
|
||||
}
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80);
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
|
||||
switch (w->shift) {
|
||||
case 0:
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0x0F,
|
||||
mode);
|
||||
break;
|
||||
case 1:
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0xF0,
|
||||
mode << 4);
|
||||
break;
|
||||
case 2:
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0x0F,
|
||||
mode);
|
||||
break;
|
||||
case 3:
|
||||
snd_soc_component_update_bits(component,
|
||||
WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0xF0,
|
||||
mode << 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wcd938x_tx_connect_port(component, ADC1 + (w->shift), true);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
@@ -1433,6 +1536,37 @@ static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
|
||||
return __wcd938x_codec_enable_micbias(w, event);
|
||||
}
|
||||
|
||||
static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget *widget =
|
||||
snd_soc_dapm_kcontrol_widget(kcontrol);
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
|
||||
|
||||
ucontrol->value.integer.value[0] = wcd938x->tx_mode[widget->shift];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dapm_widget *widget =
|
||||
snd_soc_dapm_kcontrol_widget(kcontrol);
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
|
||||
u32 mode_val;
|
||||
|
||||
mode_val = ucontrol->value.enumerated.item[0];
|
||||
|
||||
dev_dbg(component->dev, "%s: mode: %d\n", __func__, mode_val);
|
||||
|
||||
wcd938x->tx_mode[widget->shift] = mode_val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
@@ -1605,6 +1739,20 @@ static int wcd938x_tx_hdr_put(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const tx_mode_mux_text[] = {
|
||||
"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
|
||||
"ADC_ULP1", "ADC_ULP2",
|
||||
};
|
||||
|
||||
WCD_DAPM_ENUM_EXT(tx0_mode, SND_SOC_NOPM, 0, tx_mode_mux_text,
|
||||
wcd938x_tx_mode_get, wcd938x_tx_mode_put);
|
||||
WCD_DAPM_ENUM_EXT(tx1_mode, SND_SOC_NOPM, 1, tx_mode_mux_text,
|
||||
wcd938x_tx_mode_get, wcd938x_tx_mode_put);
|
||||
WCD_DAPM_ENUM_EXT(tx2_mode, SND_SOC_NOPM, 2, tx_mode_mux_text,
|
||||
wcd938x_tx_mode_get, wcd938x_tx_mode_put);
|
||||
WCD_DAPM_ENUM_EXT(tx3_mode, SND_SOC_NOPM, 3, tx_mode_mux_text,
|
||||
wcd938x_tx_mode_get, wcd938x_tx_mode_put);
|
||||
|
||||
static const char * const rx_hph_mode_mux_text[] = {
|
||||
"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
|
||||
"CLS_H_ULP", "CLS_AB_HIFI",
|
||||
@@ -1821,6 +1969,11 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0,
|
||||
&tx_adc4_mux),
|
||||
|
||||
WCD_DAPM_MUX("TX0 MODE", 0, tx0_mode),
|
||||
WCD_DAPM_MUX("TX1 MODE", 1, tx1_mode),
|
||||
WCD_DAPM_MUX("TX2 MODE", 2, tx2_mode),
|
||||
WCD_DAPM_MUX("TX3 MODE", 3, tx3_mode),
|
||||
|
||||
/*tx mixers*/
|
||||
SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0,
|
||||
adc1_switch, ARRAY_SIZE(adc1_switch),
|
||||
|
Reference in New Issue
Block a user