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));
}

浙公网安备 33010602011771号