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:
Karthikeyan Mani
2019-01-03 14:21:35 -08:00
parent bde36b8fc2
commit a27b0c32ea
2 changed files with 163 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #ifndef _WCD938X_INTERNAL_H
@@ -17,6 +17,7 @@
#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) #define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50)
#define MAX_PORT 8 #define MAX_PORT 8
#define MAX_CH_PER_PORT 8 #define MAX_CH_PER_PORT 8
#define TX_ADC_MAX 4
enum { enum {
TX_HDR12 = 0, TX_HDR12 = 0,
@@ -63,6 +64,7 @@ struct wcd938x_priv {
struct wcd938x_mbhc *mbhc; struct wcd938x_mbhc *mbhc;
u32 hph_mode; u32 hph_mode;
u32 tx_mode[TX_ADC_MAX];
bool comp1_enable; bool comp1_enable;
bool comp2_enable; bool comp2_enable;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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> #include <linux/module.h>
@@ -30,6 +30,27 @@
#define WCD938X_VERSION_1_0 1 #define WCD938X_VERSION_1_0 1
#define WCD938X_VERSION_ENTRY_SIZE 32 #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 { enum {
WCD9380 = 0, WCD9380 = 0,
WCD9385, WCD9385,
@@ -47,6 +68,16 @@ enum {
HPH_PA_DELAY, 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(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 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); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->rx_clk_cnt == 0) { 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, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01); WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01);
snd_soc_component_update_bits(component, 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 0:
case 1: case 1:
dmic_clk_cnt = &(wcd938x->dmic_0_1_clk_cnt); 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; break;
case 2: case 2:
case 3: case 3:
dmic_clk_cnt = &(wcd938x->dmic_2_3_clk_cnt); 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; break;
case 4: case 4:
case 5: case 5:
dmic_clk_cnt = &(wcd938x->dmic_4_5_clk_cnt); 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; break;
default: default:
dev_err(component->dev, "%s: Invalid DMIC Selection\n", 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: case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80); 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, snd_soc_component_update_bits(component,
dmic_clk_reg, 0x07, 0x02); dmic_clk_reg, 0x07, 0x02);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
@@ -1107,24 +1144,90 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
return ret; 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, static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, struct snd_kcontrol *kcontrol,
int event){ int event){
int mode;
struct snd_soc_component *component = struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm); 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__, dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
w->name, event); w->name, event);
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: 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, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80); WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08); WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10); 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); wcd938x_tx_connect_port(component, ADC1 + (w->shift), true);
break; break;
case SND_SOC_DAPM_POST_PMD: 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); 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, static int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
@@ -1605,6 +1739,20 @@ static int wcd938x_tx_hdr_put(struct snd_kcontrol *kcontrol,
return 0; 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[] = { 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_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
"CLS_H_ULP", "CLS_AB_HIFI", "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, SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0,
&tx_adc4_mux), &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*/ /*tx mixers*/
SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0,
adc1_switch, ARRAY_SIZE(adc1_switch), adc1_switch, ARRAY_SIZE(adc1_switch),