高通平台根据阻抗值判断耳机类型

 入口函数:初始化MBHC ADC相关函数指针到MBHC结构

void wcd_mbhc_adc_init(struct wcd_mbhc *mbhc)
{
	if (!mbhc) {
		pr_err("%s: mbhc is NULL\n", __func__);
		return;
	}
	mbhc->mbhc_fn = &mbhc_fn;
	INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
}

 这里添加了一个工作队列wcd_correct_swch_plug,只有在使用的时候去激活它。

static struct wcd_mbhc_fn mbhc_fn = {
	.wcd_mbhc_hs_ins_irq = wcd_mbhc_adc_hs_ins_irq,
	.wcd_mbhc_hs_rem_irq = wcd_mbhc_adc_hs_rem_irq,
	.wcd_mbhc_detect_plug_type = wcd_mbhc_adc_detect_plug_type,
	.wcd_mbhc_detect_anc_plug_type = wcd_mbhc_adc_detect_anc_plug_type,
	.wcd_cancel_hs_detect_plug = wcd_cancel_hs_detect_plug,
};

wcd_mbhc_adc_detect_plug_type()    在获取编解码器资源锁时调用

static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
{
	struct snd_soc_codec *codec = mbhc->codec;

	pr_debug("%s: enter\n", __func__);
	WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);

	if (mbhc->mbhc_cb->hph_pull_down_ctrl)
		mbhc->mbhc_cb->hph_pull_down_ctrl(codec, false);

	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 0);

	if (mbhc->mbhc_cb->mbhc_micbias_control) {
		mbhc->mbhc_cb->mbhc_micbias_control(codec, MIC_BIAS_2,
						    MICB_ENABLE);
	} else {
		pr_err("%s: Mic Bias is not enabled\n", __func__);
		return;
	}

	/* Re-initialize button press completion object */
	reinit_completion(&mbhc->btn_press_compl);
	wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
	pr_debug("%s: leave\n", __func__);
}

wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);应该在保持挂起的中断上下文下调用

 wcd_correct_swch_plug()    开始类型的检测

    pr_debug("%s: enter\n", __func__);

	mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
	codec = mbhc->codec;

	WCD_MBHC_RSC_LOCK(mbhc);
	/* Mask ADC COMPLETE interrupt */
	wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
	WCD_MBHC_RSC_UNLOCK(mbhc);

	/* Check for cross connection */
	do {
		cross_conn = wcd_check_cross_conn(mbhc);
		try++;
	} while (try < mbhc->swap_thr);

	if (cross_conn > 0) {
		plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
		pr_debug("%s: cross connection found, Plug type %d\n",
			 __func__, plug_type);
		goto correct_plug_type;
	}
	/* Find plug type */
	output_mv = wcd_measure_adc_continuous(mbhc);
	plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);

	/*
	 * Report plug type if it is either headset or headphone
	 * else start the 3 sec loop
	 */
	if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
	     plug_type == MBHC_PLUG_TYPE_HEADPHONE) &&
	    (!wcd_swch_level_remove(mbhc))) {
		WCD_MBHC_RSC_LOCK(mbhc);
		wcd_mbhc_find_plug_and_report(mbhc, plug_type);
		WCD_MBHC_RSC_UNLOCK(mbhc);
	}

先看下mic和gnd有没有接反,接着检测插头类型,不是耳机则开始3秒的循环,是则上报耳机类型事件。

wcd_mbhc_get_plug_from_adc()    通过输出电压的大小得到耳机类型。

static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result)

{
	enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
	u32 hph_thr = 0, hs_thr = 0;

	if (mbhc->hs_thr)
		hs_thr = mbhc->hs_thr;
	else
		hs_thr = WCD_MBHC_ADC_HS_THRESHOLD_MV;

	if (mbhc->hph_thr)
		hph_thr = mbhc->hph_thr;
	else
		hph_thr = WCD_MBHC_ADC_HPH_THRESHOLD_MV;

	if (adc_result < hph_thr)
		plug_type = MBHC_PLUG_TYPE_HEADPHONE;
	else if (adc_result > hs_thr)
		plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
	else
		plug_type = MBHC_PLUG_TYPE_HEADSET;
	pr_debug("%s: plug type is %d found\n", __func__, plug_type);

	return plug_type;
}

 如果是高阻抗耳机,会一直往下走,直到最后上报耳机类型。

if (output_mv > WCD_MBHC_ADC_HS_THRESHOLD_MV) {
			pr_debug("%s: cable is extension cable\n", __func__);
			plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
			wrk_complete = true;
		}
。。。

if (!wrk_complete) {
		/*
		 * If plug_tye is headset, we might have already reported either
		 * in detect_plug-type or in above while loop, no need to report
		 * again
		 */
		if ((plug_type == MBHC_PLUG_TYPE_HEADSET) ||
		    (plug_type == MBHC_PLUG_TYPE_ANC_HEADPHONE)) {
			pr_debug("%s: plug_type:0x%x already reported\n",
				 __func__, mbhc->current_plug);
			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
			goto enable_supply;
		}
	}
	if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
		if (wcd_is_special_headset(mbhc)) {
			pr_debug("%s: Special headset found %d\n",
					__func__, plug_type);
			plug_type = MBHC_PLUG_TYPE_HEADSET;
		} else {
			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_ISRC_EN, 1);
		}
	}

report:
	if (wcd_swch_level_remove(mbhc)) {
		pr_debug("%s: Switch level is low\n", __func__);
		goto exit;
	}

	pr_debug("%s: Valid plug found, plug type %d wrk_cmpt %d btn_intr %d\n",
			__func__, plug_type, wrk_complete,
			mbhc->btn_press_intr);

	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);

	WCD_MBHC_RSC_LOCK(mbhc);
	wcd_mbhc_find_plug_and_report(mbhc, plug_type);
	WCD_MBHC_RSC_UNLOCK(mbhc);

至此,耳机类型判断完成。

猜你喜欢

转载自blog.csdn.net/qq_36247447/article/details/108146193