Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a27b0c32 authored by Karthikeyan Mani's avatar Karthikeyan Mani
Browse files

ASoC: codecs: qcrg update for TX paths



Add qcrg updates for AMIC and DMIC register updates
and modes.

Change-Id: I7401b21cfffd2c40f456d985e2b3ea1988f4ba6c
Signed-off-by: default avatarKarthikeyan Mani <kmani@codeaurora.org>
parent bde36b8f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
/* 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;

+160 −7
Original line number Diff line number Diff line
// 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),