RK3399 android7.1 耳机拔插ADC检测
rk3399_android7.1耳机拔插ADC检测 平仄散人
一.frameworks\base\services\core\java\com\android\server\WiredAccessoryManager.java
private static final String HEADSET_CONNECTION_NODE = "/sys/devices/virtual/switch/h2w/state"; public String getDevName() { return mDevName; } public String getDevPath() { return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName); } public String getSwitchStatePath() { return String.format(Locale.US, "/sys/class/switch/%s/state", mDevName); }
二.驱动解析
2.1.dts 配置
rockchip_headset { status = "okay"; compatible = "rockchip_headset"; io-channels = <&saradc 2>; io-channel-names = "headset"; headset_gpio = <&gpio0 8 GPIO_ACTIVE_LOW>; };
2.2.kernel\drivers\headset_observe\rockchip_headset_core.c
ret = of_get_named_gpio_flags(node, "headset_gpio", 0, &flags); //解析gpio
如果解析到gpio就devm_gpio_request //申请GPIO,gpio_direction_input//设置GPIO口为输入状态
of_get_named_gpio_flags(node, "hook_gpio", 0, &pdata->hook_gpio); //解析GPIO
如果解析不到GPIO就 pdata->chan = iio_channel_get(&pdev->dev, NULL); //获取ADC通道
static int rockchip_headset_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct rk_headset_pdata *pdata; int ret,i,val; //enum of_gpio_flags flags; pdata = kzalloc(sizeof(struct rk_headset_pdata), GFP_KERNEL); if (pdata == NULL) { printk("%s failed to allocate driver data\n",__FUNCTION__); return -ENOMEM; } memset(pdata,0,sizeof(struct rk_headset_pdata)); pdata_info = pdata; //headset ret = of_get_named_gpio(node, "headset_gpio", 0); if (ret < 0) { printk("%s() Can not read property headset_gpio\n", __FUNCTION__); goto err; } else { pdata->headset_gpio = ret; ret = devm_gpio_request(&pdev->dev, pdata->headset_gpio, "headset_gpio"); if(ret < 0){ printk("%s() devm_gpio_request headset_gpio request ERROR\n", __FUNCTION__); goto err; } ret = gpio_direction_input(pdata->headset_gpio); if(ret < 0){ printk("%s() gpio_direction_input headset_gpio set ERROR\n", __FUNCTION__); goto err; } pdata->headset_insert_type = HEADSET_IN_LOW; } pdata->chan = iio_channel_get(&pdev->dev, NULL); if (IS_ERR(pdata->chan)) { pdata->chan = NULL; printk("%s() have not set adc chan\n", __FUNCTION__); } set_headset_mic_power(1); for(i = 0;i < 5;i++){ ret = iio_read_channel_raw(pdata->chan, &val); if (ret < 0) { pr_err("timer_work_callback read adc channel() error: %d\n", ret); } msleep(100); } printk("eric 222 iio_read_channel_raw = %d \n",val); if(val > 5) { printk("%s() ZK-R39A V1.1\n",__FUNCTION__); ret = rk_headset_adc_probe(pdev,pdata); if(ret < 0) { goto err; } } else { printk("%s() ZK-R39A V1.0\n",__FUNCTION__); ret = rk_headset_probe(pdev,pdata); if(ret < 0) { goto err; } } return 0; err: kfree(pdata); return ret; }
2.3.kernel\drivers\headset_observe\rk_headset_irq_hook_adc.c
读取 AD 采集到的原始数据
int value,Vresult;
ret = iio_read_channel_raw(chan, &value);
调用 iio_read_channel_raw 函数读取 AD 采集的原始数据并存入value变量中
static void hook_once_work(struct work_struct *work) { int ret,val; #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(true); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(true); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(true); #endif ret = iio_read_channel_raw(headset_info->chan, &val); if (ret < 0) { pr_err("read hook_once_work adc channel() error: %d\n", ret); }else DBG("hook_once_work read adc value: %d\n",val); if(val >= 800 && val < 1000) { headset_info->isMic= 0;//No microphone #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(false); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(false); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(false); #endif } else if(val >= 550 && val < 750) { headset_info->isMic = 1;//four headseet in } else if(val >= 5 && val < 100) { headset_info->isMic = 1;//three headseet in } headset_info->cur_headset_status = headset_info->isMic ? 1:0; #if defined(CONFIG_SND_SOC_CX2072X) if (cx2072x_jack_report() != -1) headset_info->cur_headset_status = (cx2072x_jack_report() == 3) ? BIT_HEADSET : BIT_HEADSET_NO_MIC; #endif switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); DBG("%s notice android headset status = %d\n",__func__,headset_info->cur_headset_status); schedule_delayed_work(&headset_info->h_delayed_work[HOOK],msecs_to_jiffies(500)); }