高通耳机阻抗估算流程

Msm-analog-cdc.c (vendor\qcom\opensource\audio-kernel\asoc\codecs\sdm660_cdc)  模拟编解码器驱动

static struct platform_driver msm_anlg_codec_driver = {
	.driver		= {
		.owner          = THIS_MODULE,
		.name           = DRV_NAME,
		.of_match_table = of_match_ptr(sdm660_codec_of_match)
	},
	.probe          = msm_anlg_cdc_probe,
	.remove         = msm_anlg_cdc_remove,
};

msm_anlg_cdc_probe()

static int msm_anlg_cdc_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct sdm660_cdc_priv *sdm660_cdc = NULL;
	struct sdm660_cdc_pdata *pdata;
	int adsp_state;
	const char *parent_dev = NULL;
	adsp_state = apr_get_subsys_state();
	if (adsp_state == APR_SUBSYS_DOWN ||
		!q6core_is_adsp_ready()) {
		dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
			adsp_state);
		return -EPROBE_DEFER;
	}
	device_init_wakeup(&pdev->dev, true);

	if (pdev->dev.of_node) {
		dev_dbg(&pdev->dev, "%s:Platform data from device tree\n",
			__func__);
		pdata = msm_anlg_cdc_populate_dt_pdata(&pdev->dev);
		pdev->dev.platform_data = pdata;
	} else {
		dev_dbg(&pdev->dev, "%s:Platform data from board file\n",
			__func__);
		pdata = pdev->dev.platform_data;
	}
	if (pdata == NULL) {
		dev_err(&pdev->dev, "%s:Platform data failed to populate\n",
			__func__);
		goto rtn;
	}
	sdm660_cdc = devm_kzalloc(&pdev->dev, sizeof(struct sdm660_cdc_priv),
				     GFP_KERNEL);
	if (sdm660_cdc == NULL) {
		ret = -ENOMEM;
		goto rtn;
	}

	sdm660_cdc->dev = &pdev->dev;
	ret = msm_anlg_cdc_init_supplies(sdm660_cdc, pdata);
	if (ret) {
		dev_err(&pdev->dev, "%s: Fail to enable Codec supplies\n",
			__func__);
		goto rtn;
	}
	ret = msm_anlg_cdc_enable_static_supplies(sdm660_cdc, pdata);
	if (ret) {
		dev_err(&pdev->dev,
			"%s: Fail to enable Codec pre-reset supplies\n",
			__func__);
		goto rtn;
	}
	/* Allow supplies to be ready */
	usleep_range(5, 6);

	wcd9xxx_spmi_set_dev(pdev, 0);
	wcd9xxx_spmi_set_dev(pdev, 1);
	if (wcd9xxx_spmi_irq_init()) {
		dev_err(&pdev->dev,
			"%s: irq initialization failed\n", __func__);
	} else {
		dev_dbg(&pdev->dev,
			"%s: irq initialization passed\n", __func__);
	}
	dev_set_drvdata(&pdev->dev, sdm660_cdc);

	ret = snd_soc_register_codec(&pdev->dev,
				     &soc_codec_dev_sdm660_cdc,
				     msm_anlg_cdc_i2s_dai,
				     ARRAY_SIZE(msm_anlg_cdc_i2s_dai));
	if (ret) {
		dev_err(&pdev->dev,
			"%s:snd_soc_register_codec failed with error %d\n",
			__func__, ret);
		goto err_supplies;
	}
	BLOCKING_INIT_NOTIFIER_HEAD(&sdm660_cdc->notifier);
	BLOCKING_INIT_NOTIFIER_HEAD(&sdm660_cdc->notifier_mbhc);

	sdm660_cdc->dig_plat_data.handle = (void *) sdm660_cdc;
	sdm660_cdc->dig_plat_data.set_compander_mode = set_compander_mode;
	sdm660_cdc->dig_plat_data.update_clkdiv = update_clkdiv;
	sdm660_cdc->dig_plat_data.get_cdc_version = get_cdc_version;
	sdm660_cdc->dig_plat_data.register_notifier =
					msm_anlg_cdc_dig_register_notifier;
	INIT_WORK(&sdm660_cdc->msm_anlg_add_child_devices_work,
		  msm_anlg_add_child_devices);
	schedule_work(&sdm660_cdc->msm_anlg_add_child_devices_work);
	parent_dev = pdev->dev.parent->of_node->full_name;
	if (parent_dev) {
		snprintf(sdm660_cdc->pmic_analog, PMIC_ANOLOG_SIZE, "spmi0-0%s",
			 parent_dev + strlen(parent_dev)-1);
		parent_dev = NULL;
	}
	return ret;
err_supplies:
	msm_anlg_cdc_disable_supplies(sdm660_cdc, pdata);
rtn:
	return ret;
}

ret = snd_soc_register_codec(&pdev->dev,
                     &soc_codec_dev_sdm660_cdc,
                     msm_anlg_cdc_i2s_dai,
                     ARRAY_SIZE(msm_anlg_cdc_i2s_dai));

static struct snd_soc_codec_driver soc_codec_dev_sdm660_cdc = {
	.probe	= msm_anlg_cdc_soc_probe,
	.remove	= msm_anlg_cdc_soc_remove,
	.suspend = msm_anlg_cdc_suspend,
	.resume = msm_anlg_cdc_resume,
	.reg_word_size = 1,
	.get_regmap = msm_anlg_get_regmap,
	.component_driver = {
		.controls = msm_anlg_cdc_snd_controls,
		.num_controls = ARRAY_SIZE(msm_anlg_cdc_snd_controls),
		.dapm_widgets = msm_anlg_cdc_dapm_widgets,
		.num_dapm_widgets = ARRAY_SIZE(msm_anlg_cdc_dapm_widgets),
		.dapm_routes = audio_map,
		.num_dapm_routes = ARRAY_SIZE(audio_map),
	},
};

msm_anlg_cdc_soc_probe()

wcd_mbhc_init(&sdm660_cdc->mbhc, codec, &mbhc_cb, &intr_ids,
		      wcd_mbhc_registers, true);
static const struct wcd_mbhc_cb mbhc_cb = {
	.enable_mb_source = msm_anlg_cdc_enable_ext_mb_source,
	.trim_btn_reg = msm_anlg_cdc_trim_btn_reg,
	.compute_impedance = msm_anlg_cdc_mbhc_calc_impedance,//估算阻抗
	.set_micbias_value = msm_anlg_cdc_set_micb_v,//设置mic偏置值
	.set_auto_zeroing = msm_anlg_cdc_set_auto_zeroing,//设置自动调零
	.get_hwdep_fw_cal = msm_anlg_cdc_get_hwdep_fw_cal,
	.set_cap_mode = msm_anlg_cdc_configure_cap,
	.register_notifier = msm_anlg_cdc_mbhc_register_notifier,//注册通知
	.request_irq = msm_anlg_cdc_request_irq,//请求中断
	.irq_control = wcd9xxx_spmi_irq_control,//中断控制
	.free_irq = msm_anlg_cdc_free_irq,
	.clk_setup = msm_anlg_cdc_mbhc_clk_setup,
	.map_btn_code_to_num = msm_anlg_cdc_mbhc_map_btn_code_to_num,
	.lock_sleep = msm_anlg_cdc_spmi_lock_sleep,
	.micbias_enable_status = msm_anlg_cdc_micb_en_status,
	.mbhc_bias = msm_anlg_cdc_enable_master_bias,
	.mbhc_common_micb_ctrl = msm_anlg_cdc_mbhc_common_micb_ctrl,
	.micb_internal = msm_anlg_cdc_mbhc_internal_micbias_ctrl,
	.hph_pa_on_status = msm_anlg_cdc_mbhc_hph_pa_on_status,
	.set_btn_thr = msm_anlg_cdc_mbhc_program_btn_thr,
	.extn_use_mb = msm_anlg_cdc_use_mb,
};

msm_anlg_cdc_mbhc_calc_impedance()计算阻抗值

static void msm_anlg_cdc_mbhc_calc_impedance(struct wcd_mbhc *mbhc,
					     uint32_t *zl, uint32_t *zr)
{
	struct snd_soc_codec *codec = mbhc->codec;
	struct sdm660_cdc_priv *sdm660_cdc =
					snd_soc_codec_get_drvdata(codec);
	s16 impedance_l, impedance_r;
	s16 impedance_l_fixed;
	s16 reg0, reg1, reg2, reg3, reg4;
	bool high = false;
	bool min_range_used =  false;

	WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
	reg0 = snd_soc_read(codec, MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER);
	reg1 = snd_soc_read(codec, MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL);
	reg2 = snd_soc_read(codec, MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2);
	reg3 = snd_soc_read(codec, MSM89XX_PMIC_ANALOG_MICB_2_EN);
	reg4 = snd_soc_read(codec, MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL);

	sdm660_cdc->imped_det_pin = WCD_MBHC_DET_BOTH;
	mbhc->hph_type = WCD_MBHC_HPH_NONE;

	/* 禁用FSM和micbias,启用上拉*/
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x80, 0x00);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MICB_2_EN,
			0xA5, 0x25);
	/*
	 * Enable legacy electrical detection current sources
	 * and disable fast ramp and enable manual switching
	 * of extra capacitance
	 */
	dev_dbg(codec->dev, "%s: Setup for impedance det\n", __func__);

	msm_anlg_cdc_set_ref_current(codec, I_h4_UA);

	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
			0x06, 0x02);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER,
			0x02, 0x02);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL,
			0x02, 0x00);

	dev_dbg(codec->dev, "%s: Start performing impedance detection\n",
		 __func__);
    //开始阻抗检测,进入此函数
	wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);

	if (impedance_l > 2 || impedance_r > 2) {
		high = true;
		if (!mbhc->mbhc_cfg->mono_stero_detection) {
			/* Set ZDET_CHG to 0  to discharge ramp */
			snd_soc_update_bits(codec,
					MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
					0x02, 0x00);
			/* wait 40ms for the discharge ramp to complete */
			usleep_range(40000, 40100);
			snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
				0x03, 0x00);
			sdm660_cdc->imped_det_pin = (impedance_l > 2 &&
						      impedance_r > 2) ?
						      WCD_MBHC_DET_NONE :
						      ((impedance_l > 2) ?
						      WCD_MBHC_DET_HPHR :
						      WCD_MBHC_DET_HPHL);
			if (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_NONE)
				goto exit;
		} else {
			if (get_codec_version(sdm660_cdc) >= CAJON) {
				if (impedance_l == 63 && impedance_r == 63) {
					dev_dbg(codec->dev,
						"%s: HPHL and HPHR are floating\n",
						 __func__);
					sdm660_cdc->imped_det_pin =
							WCD_MBHC_DET_NONE;
					mbhc->hph_type = WCD_MBHC_HPH_NONE;
				} else if (impedance_l == 63
					   && impedance_r < 63) {
					dev_dbg(codec->dev,
						"%s: Mono HS with HPHL floating\n",
						 __func__);
					sdm660_cdc->imped_det_pin =
							WCD_MBHC_DET_HPHR;
					mbhc->hph_type = WCD_MBHC_HPH_MONO;
				} else if (impedance_r == 63 &&
					   impedance_l < 63) {
					dev_dbg(codec->dev,
						"%s: Mono HS with HPHR floating\n",
						 __func__);
					sdm660_cdc->imped_det_pin =
							WCD_MBHC_DET_HPHL;
					mbhc->hph_type = WCD_MBHC_HPH_MONO;
				} else if (impedance_l > 3 && impedance_r > 3 &&
					(impedance_l == impedance_r)) {
					snd_soc_update_bits(codec,
					MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
					0x06, 0x06);
					wcd_mbhc_meas_imped(codec, &impedance_l,
							    &impedance_r);
					if (impedance_r == impedance_l)
						dev_dbg(codec->dev,
							"%s: Mono Headset\n",
							__func__);
						sdm660_cdc->imped_det_pin =
							WCD_MBHC_DET_NONE;
						mbhc->hph_type =
							WCD_MBHC_HPH_MONO;
				} else {
					dev_dbg(codec->dev,
						"%s: STEREO headset is found\n",
						 __func__);
					sdm660_cdc->imped_det_pin =
							WCD_MBHC_DET_BOTH;
					mbhc->hph_type = WCD_MBHC_HPH_STEREO;
				}
			}
		}
	}

	msm_anlg_cdc_set_ref_current(codec, I_pt5_UA);
	msm_anlg_cdc_set_ref_current(codec, I_14_UA);

	/* Enable RAMP_L , RAMP_R & ZDET_CHG*/
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
			0x03, 0x03);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x02, 0x02);
	/* wait for 50msec for the HW to apply ramp on HPHL and HPHR */
	usleep_range(50000, 50100);
	/* Enable ZDET_DISCHG_CAP_CTL  to add extra capacitance */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x01, 0x01);
	/* wait for 5msec for the voltage to get stable */
	usleep_range(5000, 5100);

	wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);

	min_range_used = msm_anlg_cdc_adj_ref_current(codec,
						&impedance_l, &impedance_r);
	if (!mbhc->mbhc_cfg->mono_stero_detection) {
		/* Set ZDET_CHG to 0  to discharge ramp */
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
				0x02, 0x00);
		/* wait for 40msec for the capacitor to discharge */
		usleep_range(40000, 40100);
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
				0x03, 0x00);
		goto exit;
	}

	/* we are setting ref current to the minimun range or the measured
	 * value larger than the minimum value, so min_range_used is true.
	 * If the headset is mono headset with either HPHL or HPHR floating
	 * then we have already done the mono stereo detection and do not
	 * need to continue further.
	 */

	if (!min_range_used ||
	    sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHL ||
	    sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHR)
		goto exit;


	/* Disable Set ZDET_CONN_RAMP_L and enable ZDET_CONN_FIXED_L */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
			0x02, 0x00);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
			0x02, 0x02);
	/* Set ZDET_CHG to 0  */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x02, 0x00);
	/* wait for 40msec for the capacitor to discharge */
	usleep_range(40000, 40100);

	/* Set ZDET_CONN_RAMP_R to 0  */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
			0x01, 0x00);
	/* Enable ZDET_L_MEAS_EN */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x08, 0x08);
	/* wait for 2msec for the HW to compute left inpedance value */
	usleep_range(2000, 2100);
	/* Read Left impedance value from Result1 */
	impedance_l_fixed = snd_soc_read(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
	/* Disable ZDET_L_MEAS_EN */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x08, 0x00);
	/*
	 * Assume impedance_l is L1, impedance_l_fixed is L2.
	 * If the following condition is met, we can take this
	 * headset as mono one with impedance of L2.
	 * Otherwise, take it as stereo with impedance of L1.
	 * Condition:
	 * abs[(L2-0.5L1)/(L2+0.5L1)] < abs [(L2-L1)/(L2+L1)]
	 */
	if ((abs(impedance_l_fixed - impedance_l/2) *
		(impedance_l_fixed + impedance_l)) >=
		(abs(impedance_l_fixed - impedance_l) *
		(impedance_l_fixed + impedance_l/2))) {
		dev_dbg(codec->dev,
			"%s: STEREO plug type detected\n",
			 __func__);
		mbhc->hph_type = WCD_MBHC_HPH_STEREO;
	} else {
		dev_dbg(codec->dev,
			"%s: MONO plug type detected\n",
			__func__);
		mbhc->hph_type = WCD_MBHC_HPH_MONO;
		impedance_l = impedance_l_fixed;
	}
	/* Enable ZDET_CHG  */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x02, 0x02);
	/* wait for 10msec for the capacitor to charge */
	usleep_range(10000, 10100);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
			0x02, 0x02);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
			0x02, 0x00);
	/* Set ZDET_CHG to 0  to discharge HPHL */
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
			0x02, 0x00);
	/* wait for 40msec for the capacitor to discharge */
	usleep_range(40000, 40100);
	snd_soc_update_bits(codec,
			MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
			0x02, 0x00);

exit:
	snd_soc_write(codec, MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, reg4);
	snd_soc_write(codec, MSM89XX_PMIC_ANALOG_MICB_2_EN, reg3);
	snd_soc_write(codec, MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL, reg1);
	snd_soc_write(codec, MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, reg0);
	snd_soc_write(codec, MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, reg2);
	msm_anlg_cdc_compute_impedance(codec, impedance_l, impedance_r,
				      zl, zr, high);

	dev_dbg(codec->dev, "%s: RL %d ohm, RR %d ohm\n", __func__, *zl, *zr);
	dev_dbg(codec->dev, "%s: Impedance detection completed\n", __func__);
}

wcd_mbhc_meas_imped()    阻抗检测

static void wcd_mbhc_meas_imped(struct snd_soc_codec *codec,
				s16 *impedance_l, s16 *impedance_r)
{
	struct sdm660_cdc_priv *sdm660_cdc =
					snd_soc_codec_get_drvdata(codec);

	if ((sdm660_cdc->imped_det_pin == WCD_MBHC_DET_BOTH) ||
	    (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHL)) {
		/* Enable ZDET_L_MEAS_EN */
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
				0x08, 0x08);
		/* Wait for 2ms for measurement to complete */
		usleep_range(2000, 2100);
		/* Read Left impedance value from Result1 */
		*impedance_l = snd_soc_read(codec,
				MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
		/* Enable ZDET_R_MEAS_EN */
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
				0x08, 0x00);
	}
	if ((sdm660_cdc->imped_det_pin == WCD_MBHC_DET_BOTH) ||
	    (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHR)) {
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
				0x04, 0x04);
		/* Wait for 2ms for measurement to complete */
		usleep_range(2000, 2100);
		/* Read Right impedance value from Result1 */
		*impedance_r = snd_soc_read(codec,
				MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
		snd_soc_update_bits(codec,
				MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
				0x04, 0x00);
	}
}

msm_anlg_cdc_compute_impedance()    估算阻抗

static void msm_anlg_cdc_compute_impedance(struct snd_soc_codec *codec, s16 l,
					   s16 r, uint32_t *zl, uint32_t *zr,
					   bool high)
{
	struct sdm660_cdc_priv *sdm660_cdc =
					snd_soc_codec_get_drvdata(codec);
	uint32_t rl = 0, rr = 0;
	struct wcd_imped_i_ref R = sdm660_cdc->imped_i_ref;
	int codec_ver = get_codec_version(sdm660_cdc);

	switch (codec_ver) {
	case TOMBAK_1_0:
	case TOMBAK_2_0:
	case CONGA:
		if (high) {
			dev_dbg(codec->dev,
				"%s: This plug has high range impedance\n",
				 __func__);
			rl = (uint32_t)(((100 * (l * 400 - 200))/96) - 230);
			rr = (uint32_t)(((100 * (r * 400 - 200))/96) - 230);
		} else {
			dev_dbg(codec->dev,
				"%s: This plug has low range impedance\n",
				 __func__);
			rl = (uint32_t)(((1000 * (l * 2 - 1))/1165) - (13/10));
			rr = (uint32_t)(((1000 * (r * 2 - 1))/1165) - (13/10));
		}
		break;
	case CAJON:
	case CAJON_2_0:
	case DIANGU:
	case DRAX_CDC:
		if (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHL) {
			rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
			   (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
			rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
			      - R.offset * R.gain_adj)/(R.gain_adj * 100));
		} else if (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_HPHR) {
			rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
			      - R.offset * R.gain_adj)/(R.gain_adj * 100));
			rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
			   (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
		} else if (sdm660_cdc->imped_det_pin == WCD_MBHC_DET_NONE) {
			rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
			   (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
			rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
			   (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
		} else {
			rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
			      - R.offset * R.gain_adj)/(R.gain_adj * 100));
			rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
			      - R.offset * R.gain_adj)/(R.gain_adj * 100));
		}
		break;
	default:
		dev_dbg(codec->dev, "%s: No codec mentioned\n", __func__);
		break;
	}
	*zl = rl;
	*zr = rr;
}

根据不同的编解码器,用了不同的算法把阻抗值传到了相应的地址。至此阻抗估算的大体流程就结束了。

猜你喜欢

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