sound/soc/codecs/wcd-mbhc-v2.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/wcd-mbhc-v2.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/wcd-mbhc-v2.c
Extension
.c
Size
46183 bytes
Lines
1636
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 wcd_mbhc {
	struct device *dev;
	struct snd_soc_component *component;
	struct snd_soc_jack *jack;
	struct wcd_mbhc_config *cfg;
	const struct wcd_mbhc_cb *mbhc_cb;
	const struct wcd_mbhc_intr *intr_ids;
	const struct wcd_mbhc_field *fields;
	/* Delayed work to report long button press */
	struct delayed_work mbhc_btn_dwork;
	/* Work to handle plug report */
	struct work_struct mbhc_plug_detect_work;
	/* Work to correct accessory type */
	struct work_struct correct_plug_swch;
	struct mutex lock;
	int buttons_pressed;
	u32 hph_status; /* track headhpone status */
	u8 current_plug;
	unsigned int swap_thr;
	bool is_btn_press;
	bool in_swch_irq_handler;
	bool hs_detect_work_stop;
	bool is_hs_recording;
	bool extn_cable_hph_rem;
	bool force_linein;
	bool impedance_detect;
	unsigned long event_state;
	unsigned long jiffies_atreport;
	/* impedance of hphl and hphr */
	uint32_t zl, zr;
	/* Holds type of Headset - Mono/Stereo */
	enum wcd_mbhc_hph_type hph_type;
	/* Holds mbhc detection method - ADC/Legacy */
	int mbhc_detection_logic;
};

static inline int wcd_mbhc_write_field(const struct wcd_mbhc *mbhc,
				       int field, int val)
{
	if (!mbhc->fields[field].reg)
		return 0;

	return snd_soc_component_write_field(mbhc->component,
					     mbhc->fields[field].reg,
					     mbhc->fields[field].mask, val);
}

static inline int wcd_mbhc_read_field(const struct wcd_mbhc *mbhc, int field)
{
	if (!mbhc->fields[field].reg)
		return 0;

	return snd_soc_component_read_field(mbhc->component,
					    mbhc->fields[field].reg,
					    mbhc->fields[field].mask);
}

static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
{
	u32 reg_val = ((mbhc->cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);

	wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_VREF, reg_val);
}

static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
{
	struct snd_soc_component *component = mbhc->component;

	mbhc->mbhc_cb->set_btn_thr(component, mbhc->cfg->btn_low,
				   mbhc->cfg->btn_high,
				   mbhc->cfg->num_btn, micbias);
}

static void wcd_mbhc_curr_micbias_control(const struct wcd_mbhc *mbhc,
					  const enum wcd_mbhc_cs_mb_en_flag cs_mb_en)
{

	/*
	 * Some codecs handle micbias/pullup enablement in codec
	 * drivers itself and micbias is not needed for regular
	 * plug type detection. So if micbias_control callback function
	 * is defined, just return.
	 */
	if (mbhc->mbhc_cb->mbhc_micbias_control)
		return;

	switch (cs_mb_en) {
	case WCD_MBHC_EN_CS:
		wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
		wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);

Annotation

Implementation Notes