sound/soc/codecs/msm8916-wcd-analog.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/msm8916-wcd-analog.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/msm8916-wcd-analog.c
Extension
.c
Size
42063 bytes
Lines
1281
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pm8916_wcd_analog_priv {
	u16 pmic_rev;
	u16 codec_version;
	bool	mbhc_btn_enabled;
	/* special event to detect accessory type */
	int	mbhc_btn0_released;
	bool	detect_accessory_type;
	struct clk *mclk;
	struct snd_soc_component *component;
	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
	struct snd_soc_jack *jack;
	bool hphl_jack_type_normally_open;
	bool gnd_jack_type_normally_open;
	/* Voltage threshold when internal current source of 100uA is used */
	u32 vref_btn_cs[MBHC_MAX_BUTTONS];
	/* Voltage threshold when microphone bias is ON */
	u32 vref_btn_micb[MBHC_MAX_BUTTONS];
	unsigned int micbias1_cap_mode;
	unsigned int micbias2_cap_mode;
	unsigned int micbias_mv;
};

static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
static const char *const rdac2_mux_text[] = { "RX1", "RX2" };
static const char *const hph_text[] = { "ZERO", "Switch", };

static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT(
					ARRAY_SIZE(hph_text), hph_text);

static const struct snd_kcontrol_new ear_mux = SOC_DAPM_ENUM("EAR_S", hph_enum);
static const struct snd_kcontrol_new hphl_mux = SOC_DAPM_ENUM("HPHL", hph_enum);
static const struct snd_kcontrol_new hphr_mux = SOC_DAPM_ENUM("HPHR", hph_enum);

/* ADC2 MUX */
static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT(
			ARRAY_SIZE(adc2_mux_text), adc2_mux_text);

/* RDAC2 MUX */
static const struct soc_enum rdac2_mux_enum = SOC_ENUM_SINGLE(
			CDC_D_CDC_CONN_HPHR_DAC_CTL, 0, 2, rdac2_mux_text);

static const struct snd_kcontrol_new spkr_switch[] = {
	SOC_DAPM_SINGLE("Switch", CDC_A_SPKR_DAC_CTL, 7, 1, 0)
};

static const struct snd_kcontrol_new rdac2_mux = SOC_DAPM_ENUM(
					"RDAC2 MUX Mux", rdac2_mux_enum);
static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM(
					"ADC2 MUX Mux", adc2_enum);

/* Analog Gain control 0 dB to +24 dB in 6 dB steps */
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 600, 0);

static const struct snd_kcontrol_new pm8916_wcd_analog_snd_controls[] = {
	SOC_SINGLE_TLV("ADC1 Volume", CDC_A_TX_1_EN, 3, 8, 0, analog_gain),
	SOC_SINGLE_TLV("ADC2 Volume", CDC_A_TX_2_EN, 3, 8, 0, analog_gain),
	SOC_SINGLE_TLV("ADC3 Volume", CDC_A_TX_3_EN, 3, 8, 0, analog_gain),
};

static void pm8916_wcd_analog_micbias_enable(struct snd_soc_component *component)
{
	struct pm8916_wcd_analog_priv *wcd = snd_soc_component_get_drvdata(component);

	snd_soc_component_update_bits(component, CDC_A_MICB_1_CTL,
			    MICB_1_CTL_EXT_PRECHARG_EN_MASK |
			    MICB_1_CTL_INT_PRECHARG_BYP_MASK,
			    MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL
			    | MICB_1_CTL_EXT_PRECHARG_EN_ENABLE);

	if (wcd->micbias_mv) {
		snd_soc_component_update_bits(component, CDC_A_MICB_1_VAL,
				    MICB_1_VAL_MICB_OUT_VAL_MASK,
				    MICB_VOLTAGE_REGVAL(wcd->micbias_mv));
		/*
		 * Special headset needs MICBIAS as 2.7V so wait for
		 * 50 msec for the MICBIAS to reach 2.7 volts.
		 */
		if (wcd->micbias_mv >= 2700)
			msleep(50);
	}

	snd_soc_component_update_bits(component, CDC_A_MICB_1_CTL,
			    MICB_1_CTL_EXT_PRECHARG_EN_MASK |
			    MICB_1_CTL_INT_PRECHARG_BYP_MASK, 0);

}

static int pm8916_wcd_analog_enable_micbias(struct snd_soc_component *component,
					    int event, unsigned int cap_mode)
{

Annotation

Implementation Notes