高通耳机阻抗估算流程
程序员文章站
2022-06-10 09:58:41
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_co....
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;
}
根据不同的编解码器,用了不同的算法把阻抗值传到了相应的地址。至此阻抗估算的大体流程就结束了。
本文地址:https://blog.csdn.net/qq_36247447/article/details/108128965
推荐阅读
-
vivo发布TWS Earphone耳机:首发高通旗舰级双核芯片 999元起
-
高通7nm骁龙8cx芯片面积估算:快赶上Intel 14nm四核了
-
安卓版AirPods要来?vivo、高通携手打造真无线蓝牙耳机
-
高通msm8994启动流程简介
-
瑞银估算苹果向高通的和解费约60亿美元:未来iPhone单台抽9美元
-
vivo TWS Earphone耳机上手评测:首发高通旗舰级+“真”无线体验
-
高通耳机阻抗估算流程
-
vivo发布TWS Earphone耳机:首发高通旗舰级双核芯片 999元起
-
安卓版AirPods要来?vivo、高通携手打造真无线蓝牙耳机
-
瑞银估算苹果向高通的和解费约60亿美元:未来iPhone单台抽9美元