ASoC: wcd: change classh settings as per impedance value

Depending on the impedance across HPHL and HPHR, set classh
configurations so as to avoid false OCP events.
Move wcd9xxx_registers.h to uapi folder, as this header
file is used by userspace for wdc9330 codec.

CRs-Fixed: 963843
Change-Id: Ie2fb4b75b7f74013580bd3912372c64ddefc734e
Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
Signed-off-by: Neema Shetty <nshetty@codeaurora.org>
This commit is contained in:
Neema Shetty 2016-07-27 19:51:44 -07:00 committed by Yeleswarapu Nagaradhesh
parent 7eb20e5733
commit 2f2c350993
5 changed files with 193 additions and 2 deletions

View file

@ -1 +1,2 @@
header-y += wcd9xxx_registers.h
header-y += wcd9320_registers.h

View file

@ -341,4 +341,13 @@
#define WCD9XXX_CDC_RX2_RX_PATH_CTL (0xB69)
#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL (0xD41)
#define WCD9XXX_CLASSH_CTRL_CCL_1 (0x69C)
/* RX Gain control registers of codecs from and above WCD9335 */
#define WCD9XXX_CDC_RX1_RX_VOL_CTL (0xB59)
#define WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL (0xB5C)
#define WCD9XXX_CDC_RX1_RX_PATH_SEC1 (0xB5E)
#define WCD9XXX_CDC_RX2_RX_VOL_CTL (0xB6D)
#define WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL (0xB70)
#define WCD9XXX_CDC_RX2_RX_PATH_SEC1 (0xB72)
#endif

View file

@ -355,6 +355,7 @@ enum {
ANC_MIC_AMIC4,
ANC_MIC_AMIC5,
ANC_MIC_AMIC6,
CLASSH_CONFIG,
};
enum {
@ -4461,6 +4462,7 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
int hph_mode = tasha->hph_mode;
u8 dem_inp;
int ret = 0;
uint32_t impedl = 0, impedr = 0;
dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
w->name, event, hph_mode);
@ -4494,6 +4496,16 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec,
WCD9335_CDC_RX1_RX_PATH_CFG0, 0x10, 0x10);
ret = wcd_mbhc_get_impedance(&tasha->mbhc,
&impedl, &impedr);
if (!ret) {
wcd_clsh_imped_config(codec, impedl, false);
set_bit(CLASSH_CONFIG, &tasha->status_mask);
} else
dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
__func__, ret);
break;
case SND_SOC_DAPM_POST_PMU:
/* 1000us required as per HW requirement */
@ -4523,6 +4535,15 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
WCD_CLSH_STATE_HPHL,
((hph_mode == CLS_H_LOHIFI) ?
CLS_H_HIFI : hph_mode));
if (test_bit(CLASSH_CONFIG, &tasha->status_mask)) {
wcd_clsh_imped_config(codec, impedl, true);
clear_bit(CLASSH_CONFIG, &tasha->status_mask);
} else
dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
__func__, ret);
break;
};
@ -11888,7 +11909,7 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_val_2_0[] = {
{WCD9335_RCO_CTRL_2, 0x0F, 0x08},
{WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10},
{WCD9335_FLYBACK_CTRL_1, 0x20, 0x20},
{WCD9335_HPH_OCP_CTL, 0xFF, 0x5A},
{WCD9335_HPH_OCP_CTL, 0xFF, 0x7A},
{WCD9335_HPH_L_TEST, 0x01, 0x01},
{WCD9335_HPH_R_TEST, 0x01, 0x01},
{WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},

View file

@ -21,6 +21,7 @@
#include "wcd9xxx-common-v2.h"
#define WCD_USLEEP_RANGE 50
#define MAX_IMPED_PARAMS 6
enum {
DAC_GAIN_0DB = 0,
@ -49,10 +50,161 @@ enum {
DELTA_I_50MA,
};
struct wcd_imped_val {
u32 imped_val;
u8 index;
};
static const struct wcd_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf5},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf5},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf5},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf5},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf7},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf7},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf7},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf9},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x0},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf9},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf9},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x0},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfa},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfa},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfa},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfb},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfb},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfb},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfc},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfc},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfc},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfd},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfd},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfd},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfe},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfe},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfe},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfe},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
},
{
{WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xff},
{WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xff},
{WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
{WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xff},
{WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xff},
{WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
},
};
static const struct wcd_imped_val imped_index[] = {
{4, 0},
{5, 1},
{6, 2},
{7, 3},
{8, 4},
{9, 5},
{10, 6},
{11, 7},
{12, 8},
{13, 9},
};
static void (*clsh_state_fp[NUM_CLSH_STATES_V2])(struct snd_soc_codec *,
struct wcd_clsh_cdc_data *,
u8 req_state, bool en, int mode);
static int get_impedance_index(int imped)
{
int i = 0;
if (imped < imped_index[i].imped_val) {
pr_debug("%s, detected impedance is less than 4 Ohm\n",
__func__);
i = 0;
goto ret;
}
if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
pr_debug("%s, detected impedance is greater than 12 Ohm\n",
__func__);
i = ARRAY_SIZE(imped_index) - 1;
goto ret;
}
for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
if (imped >= imped_index[i].imped_val &&
imped < imped_index[i + 1].imped_val)
break;
}
ret:
pr_debug("%s: selected impedance index = %d\n",
__func__, imped_index[i].index);
return imped_index[i].index;
}
/*
* Function: wcd_clsh_imped_config
* Params: codec, imped, reset
* Description:
* This function updates HPHL and HPHR gain settings
* according to the impedance value.
*/
void wcd_clsh_imped_config(struct snd_soc_codec *codec, int imped, bool reset)
{
int i;
int index = 0;
/* reset = 1, which means request is to reset the register values */
if (reset) {
for (i = 0; i < MAX_IMPED_PARAMS; i++)
snd_soc_update_bits(codec, imped_table[index][i].reg,
imped_table[index][i].mask, 0);
return;
}
index = get_impedance_index(imped);
if (index >= (ARRAY_SIZE(imped_index) - 1)) {
pr_debug("%s, impedance not in range = %d\n", __func__, imped);
return;
}
for (i = 0; i < MAX_IMPED_PARAMS; i++)
snd_soc_update_bits(codec, imped_table[index][i].reg,
imped_table[index][i].mask,
imped_table[index][i].val);
}
EXPORT_SYMBOL(wcd_clsh_imped_config);
static bool is_native_44_1_active(struct snd_soc_codec *codec)
{
bool native_active = false;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -136,6 +136,12 @@ struct vbat_monitor_reg {
u32 writes[MAX_VBAT_MONITOR_WRITES];
} __packed;
struct wcd_reg_mask_val {
u16 reg;
u8 mask;
u8 val;
};
extern void wcd_clsh_fsm(struct snd_soc_codec *codec,
struct wcd_clsh_cdc_data *cdc_clsh_d,
u8 clsh_event, u8 req_state,
@ -143,6 +149,8 @@ extern void wcd_clsh_fsm(struct snd_soc_codec *codec,
extern void wcd_clsh_init(struct wcd_clsh_cdc_data *clsh);
extern int wcd_clsh_get_clsh_state(struct wcd_clsh_cdc_data *clsh);
extern void wcd_clsh_imped_config(struct snd_soc_codec *codec, int imped,
bool reset);
enum {
RESERVED = 0,