ASoC: WCD9335: important changes on tasha codec

Following commit ID's are propagated with this gerrit.

I3e3980e48ce19955b4230876887adfde5b44e8ea
I48b24d81e2047d4d4c299ca60cdbd299e172393e
Iae361cabf7b5194e12f5ddc8e32d60cf94bf28c3
I8b3271ee9af91b9e921957998e0fb074ffdebe86
I562f17363d7d38caece358a50d1e3f654d87491f

Change-Id: I1b8610f8333b91be5e2bf9ecacf916d4b25d3f54
Signed-off-by: Santosh Mardi <gsantosh@codeaurora.org>
This commit is contained in:
Santosh Mardi 2016-03-31 11:04:55 +05:30 committed by Gerrit - the friendly Code Review server
parent 2a015e8412
commit 6c21d6ca04
1 changed files with 197 additions and 4 deletions

View File

@ -113,7 +113,7 @@
/* Convert from vout ctl to micbias voltage in mV */
#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50)
#define TASHA_ZDET_NUM_MEASUREMENTS 60
#define TASHA_ZDET_NUM_MEASUREMENTS 150
#define TASHA_MBHC_GET_C1(c) ((c & 0xC000) >> 14)
#define TASHA_MBHC_GET_X1(x) (x & 0x3FFF)
/* z value compared in milliOhm */
@ -142,6 +142,12 @@ MODULE_PARM_DESC(tasha_cpe_debug_mode, "tasha boot cpe in debug mode");
#define TASHA_DIG_CORE_COLLAPSE_TIMER_MS (5 * 1000)
#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
"cdc-vdd-mic-bias",
};
enum {
POWER_COLLAPSE,
POWER_RESUME,
@ -346,6 +352,7 @@ enum {
AIF2_CAP,
AIF3_PB,
AIF3_CAP,
AIF4_PB,
AIF_MIX1_PB,
AIF4_MAD_TX,
AIF4_VIFEED,
@ -463,6 +470,7 @@ static const u32 vport_slim_check_table[NUM_CODEC_DAIS] = {
BIT(AIF1_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX), /* AIF2_CAP */
0, /* AIF3_PB */
BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF4_MAD_TX), /* AIF3_CAP */
0, /* AIF4_PB */
0, /* AIF_MIX1_PB */
BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF3_CAP), /* AIF4_MAD_TX */
};
@ -762,6 +770,8 @@ struct tasha_priv {
int power_active_ref;
int (*zdet_gpio_cb)(struct snd_soc_codec *codec, bool high);
struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
enum wcd9335_codec_event);
struct snd_info_entry *entry;
@ -1275,6 +1285,53 @@ static void tasha_mbhc_hph_l_pull_up_control(struct snd_soc_codec *codec,
0xC0, 0x40);
}
static int tasha_enable_ext_mb_source(struct snd_soc_codec *codec,
bool turn_on)
{
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
int ret = 0;
struct on_demand_supply *supply;
if (!tasha)
return -EINVAL;
supply = &tasha->on_demand_list[ON_DEMAND_MICBIAS];
if (!supply->supply) {
dev_dbg(codec->dev, "%s: warning supply not present ond for %s\n",
__func__, "onDemand Micbias");
return ret;
}
dev_dbg(codec->dev, "%s turn_on: %d count: %d\n", __func__, turn_on,
supply->ondemand_supply_count);
if (turn_on) {
if (!(supply->ondemand_supply_count)) {
ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
"MICBIAS_REGULATOR");
snd_soc_dapm_sync(&codec->dapm);
}
supply->ondemand_supply_count++;
} else {
if (supply->ondemand_supply_count > 0)
supply->ondemand_supply_count--;
if (!(supply->ondemand_supply_count)) {
ret = snd_soc_dapm_disable_pin(&codec->dapm,
"MICBIAS_REGULATOR");
snd_soc_dapm_sync(&codec->dapm);
}
}
if (ret)
dev_err(codec->dev, "%s: Failed to %s external micbias source\n",
__func__, turn_on ? "enable" : "disabled");
else
dev_dbg(codec->dev, "%s: %s external micbias source\n",
__func__, turn_on ? "Enabled" : "Disabled");
return ret;
}
static int tasha_micbias_control(struct snd_soc_codec *codec,
int micb_num,
int req, bool is_dapm)
@ -1548,11 +1605,15 @@ static inline void tasha_mbhc_get_result_params(struct wcd9xxx *wcd9xxx,
WCD9335_ANA_MBHC_ZDET, 0x20, 0x00);
x1 = TASHA_MBHC_GET_X1(val);
c1 = TASHA_MBHC_GET_C1(val);
/* If ramp is not complete, give additional 5ms */
if ((c1 < 2) && x1)
usleep_range(5000, 5050);
if (!c1 || !x1) {
dev_dbg(wcd9xxx->dev,
"%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
__func__, c1, x1);
return;
goto ramp_down;
}
d1 = d1_a[c1];
denom = (x1 * d1) - (1 << (14 - noff));
@ -1563,6 +1624,7 @@ static inline void tasha_mbhc_get_result_params(struct wcd9xxx *wcd9xxx,
dev_dbg(wcd9xxx->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
__func__, d1, c1, x1, *zdet);
ramp_down:
i = 0;
while (x1) {
wcd9xxx_bulk_read(&wcd9xxx->core_res,
@ -1677,7 +1739,7 @@ static void tasha_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
bool is_change = false;
struct tasha_mbhc_zdet_param zdet_param[] = {
{4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
{1, 0, 2, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
{2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
{1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
{1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
};
@ -1896,6 +1958,7 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.free_irq = tasha_mbhc_free_irq,
.clk_setup = tasha_mbhc_clk_setup,
.map_btn_code_to_num = tasha_mbhc_btn_to_num,
.enable_mb_source = tasha_enable_ext_mb_source,
.mbhc_bias = tasha_mbhc_mbhc_bias_control,
.set_btn_thr = tasha_mbhc_program_btn_thr,
.lock_sleep = tasha_mbhc_lock_sleep,
@ -2266,7 +2329,7 @@ static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
}
static const char *const slim_rx_mux_text[] = {
"ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF_MIX1_PB"
"ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB", "AIF_MIX1_PB"
};
static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
@ -2335,6 +2398,17 @@ static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
&tasha_p->dai[AIF3_PB].wcd9xxx_ch_list);
break;
case 4:
if (wcd9xxx_rx_vport_validation(port_id +
TASHA_RX_PORT_START_NUMBER,
&tasha_p->dai[AIF4_PB].wcd9xxx_ch_list)) {
dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
__func__, port_id);
goto rtn;
}
list_add_tail(&core->rx_chs[port_id].list,
&tasha_p->dai[AIF4_PB].wcd9xxx_ch_list);
break;
case 5:
if (wcd9xxx_rx_vport_validation(port_id +
TASHA_RX_PORT_START_NUMBER,
&tasha_p->dai[AIF_MIX1_PB].wcd9xxx_ch_list)) {
@ -4847,6 +4921,57 @@ static int tasha_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
return 0;
}
static int tasha_codec_enable_on_demand_supply(
struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
int ret = 0;
struct snd_soc_codec *codec = w->codec;
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
struct on_demand_supply *supply;
if (w->shift >= ON_DEMAND_SUPPLIES_MAX) {
dev_err(codec->dev, "%s: error index > MAX Demand supplies",
__func__);
ret = -EINVAL;
goto out;
}
dev_dbg(codec->dev, "%s: supply: %s event: %d\n",
__func__, on_demand_supply_name[w->shift], event);
supply = &tasha->on_demand_list[w->shift];
WARN_ONCE(!supply->supply, "%s isn't defined\n",
on_demand_supply_name[w->shift]);
if (!supply->supply) {
dev_err(codec->dev, "%s: err supply not present ond for %d",
__func__, w->shift);
goto out;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = regulator_enable(supply->supply);
if (ret)
dev_err(codec->dev, "%s: Failed to enable %s\n",
__func__,
on_demand_supply_name[w->shift]);
break;
case SND_SOC_DAPM_POST_PMD:
ret = regulator_disable(supply->supply);
if (ret)
dev_err(codec->dev, "%s: Failed to disable %s\n",
__func__,
on_demand_supply_name[w->shift]);
break;
default:
break;
};
out:
return ret;
}
static int tasha_codec_find_amic_input(struct snd_soc_codec *codec,
int adc_mux_n)
{
@ -6243,6 +6368,15 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
/* SLIM_MUX("AIF4_PB", "AIF4 PB"),*/
{"SLIM RX0 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX1 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX2 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX3 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX4 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX5 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX6 MUX", "AIF4_PB", "AIF4 PB"},
{"SLIM RX7 MUX", "AIF4_PB", "AIF4 PB"},
/* SLIM_MUX("AIF_MIX1_PB", "AIF MIX1 PB"),*/
{"SLIM RX0 MUX", "AIF_MIX1_PB", "AIF MIX1 PB"},
@ -8089,6 +8223,14 @@ static const struct snd_kcontrol_new tasha_analog_gain_controls[] = {
line_gain),
SOC_SINGLE_TLV("HPHR Volume", WCD9335_HPH_R_EN, 0, 20, 1,
line_gain),
SOC_SINGLE_TLV("LINEOUT1 Volume", WCD9335_DIFF_LO_LO1_COMPANDER,
3, 16, 1, line_gain),
SOC_SINGLE_TLV("LINEOUT2 Volume", WCD9335_DIFF_LO_LO2_COMPANDER,
3, 16, 1, line_gain),
SOC_SINGLE_TLV("LINEOUT3 Volume", WCD9335_SE_LO_LO3_GAIN, 0, 20, 1,
line_gain),
SOC_SINGLE_TLV("LINEOUT4 Volume", WCD9335_SE_LO_LO4_GAIN, 0, 20, 1,
line_gain),
SOC_SINGLE_TLV("ADC1 Volume", WCD9335_ANA_AMIC1, 0, 20, 0,
analog_gain),
@ -9296,6 +9438,9 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
AIF3_PB, 0, tasha_codec_enable_slimrx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
AIF4_PB, 0, tasha_codec_enable_slimrx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_AIF_IN_E("AIF MIX1 PB", "AIF Mix Playback", 0,
SND_SOC_NOPM, AIF_MIX1_PB, 0,
tasha_codec_enable_slimrx,
@ -9966,6 +10111,10 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("LINEOUT4"),
SND_SOC_DAPM_OUTPUT("ANC LINEOUT1"),
SND_SOC_DAPM_OUTPUT("ANC LINEOUT2"),
SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
ON_DEMAND_MICBIAS, 0,
tasha_codec_enable_on_demand_supply,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SWITCH("ADC US MUX0", WCD9335_CDC_TX0_TX_PATH_192_CTL, 0,
0, &adc_us_mux0_switch),
@ -10025,6 +10174,7 @@ static int tasha_get_channel_map(struct snd_soc_dai *dai,
case AIF1_PB:
case AIF2_PB:
case AIF3_PB:
case AIF4_PB:
case AIF_MIX1_PB:
if (!rx_slot || !rx_num) {
pr_err("%s: Invalid rx_slot %p or rx_num %p\n",
@ -10575,6 +10725,20 @@ static struct snd_soc_dai_driver tasha_dai[] = {
},
.ops = &tasha_dai_ops,
},
{
.name = "tasha_rx4",
.id = AIF4_PB,
.playback = {
.stream_name = "AIF4 Playback",
.rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK,
.formats = TASHA_FORMATS_S16_S24_LE,
.rate_min = 8000,
.rate_max = 192000,
.channels_min = 1,
.channels_max = 2,
},
.ops = &tasha_dai_ops,
},
{
.name = "tasha_mix_rx1",
.id = AIF_MIX1_PB,
@ -11998,6 +12162,26 @@ err:
return ret;
}
static struct regulator *tasha_codec_find_ondemand_regulator(
struct snd_soc_codec *codec, const char *name)
{
int i;
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
struct wcd9xxx *wcd9xxx = tasha->wcd9xxx;
struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
for (i = 0; i < wcd9xxx->num_of_supplies; ++i) {
if (pdata->regulator[i].ondemand &&
wcd9xxx->supplies[i].supply &&
!strcmp(wcd9xxx->supplies[i].supply, name))
return wcd9xxx->supplies[i].consumer;
}
dev_dbg(tasha->dev, "Warning: regulator not found:%s\n",
name);
return NULL;
}
static int tasha_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@ -12007,6 +12191,7 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int i, ret;
void *ptr = NULL;
struct regulator *supply;
control = dev_get_drvdata(codec->dev->parent);
codec->control_data = control->regmap;
@ -12060,6 +12245,14 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
goto err;
}
supply = tasha_codec_find_ondemand_regulator(codec,
on_demand_supply_name[ON_DEMAND_MICBIAS]);
if (supply) {
tasha->on_demand_list[ON_DEMAND_MICBIAS].supply = supply;
tasha->on_demand_list[ON_DEMAND_MICBIAS].ondemand_supply_count =
0;
}
tasha->fw_data = devm_kzalloc(codec->dev,
sizeof(*(tasha->fw_data)), GFP_KERNEL);
if (!tasha->fw_data) {