rk3399_android7.1耳機拔插ADC檢測

 2023-12-25 阅读 28 评论 0

摘要:我們這里以rk3399 android7.1平臺為例,淺析adc接口實現檢測耳機的拔插動作。 硬件原理部分:耳機插入把PHE_DET1處的彈片彈開,然后實現headphone_dect直接連通到1.8v,檢測端得到高電平1.8v;拔出耳機,彈片回去,只有0.159v電壓

我們這里以rk3399 android7.1平臺為例,淺析adc接口實現檢測耳機的拔插動作。

硬件原理部分:耳機插入把PHE_DET1處的彈片彈開,然后實現headphone_dect直接連通到1.8v,檢測端得到高電平1.8v;拔出耳機,彈片回去,只有0.159v電壓。所以實現了沒有耳機插入時這個“ADC_IN4”為低電位,插入耳機時這個“ADC_IN4”為高電位

在這里插入圖片描述
在這里插入圖片描述
耳機實物圖:
在這里插入圖片描述

軟件實現部分:
1、kernel

+ //dts配置
+       rockchip_headset {
+               compatible = "rockchip_headset";
+               io-channels = <&saradc 4>; //硬件上接的是adc4
+               io-channel-names = "headset";
+               status = "okay";
+       };

驅動:

drivers/headset_observe/rk_headset_irq_hook_adc.c
drivers/headset_observe/rockchip_headset_core.c

驅動代碼里probe首先注冊switch這個子類,并提供switch_dev_register這個注冊入口,對應的設備驅動調用switch_dev_register把自己注冊在switch這個子類中,ret = switch_dev_register(&switch_data_headset->sdev);然后在/sys/class/switch目錄中就會生成h2w這個子目錄,里面會有state,name等一些成員,然后初始化一個工作隊列,設置一個時間,循環去執行工作隊列去讀取ADC 的值,根據讀到的值調用switch_set_state函數改變state狀態值,然后上層通過讀取這個節點的值來相應切換狀態。

文件:./drivers/headset_observe/rockchip_headset_core.crockchip_headset_of_match的compatible跟dts的compatible匹配
--> 執行rockchip_headset_probe-->kzalloc(sizeof(struct rk_headset_pdata), GFP_KERNEL); //分配內存給私有結構體rk_headset_pdata-->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通道-->if(pdata->chan != NULL) //如果獲取到ADC channel就執行ADC檢測耳機拔插的probe探測函數-->ret = rk_headset_adc_probe(pdev,pdata);-->否則就執行ret = rk_headset_probe(pdev,pdata); //GPIO檢測耳機拔插模式的probe探測函數文件:drivers/headset_observe/rk_headset_irq_hook_adc.c
//宏定義上報給上層的state值
+#define BIT_HEADSET             (0 << 1) //no headphone insertion
+#define BIT_HEADSET_MIC         (1 << 0) //have mic headphone insertion
+#define BIT_HEADSET_NO_MIC      (1 << 1) //no mic headphone insertionrk_headset_adc_probe
->ret = switch_dev_register(&headset->sdev); //注冊switch這個子類->INIT_DELAYED_WORK(&headset->h_delayed_work[HOOK], hook_once_work);->iio_read_channel_raw(headset_info->chan, &val);->headset_info->cur_headset_status = headset_info->isMic ? BIT_HEADSET:BIT_HEADSET_NO_MIC;->switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);//這里設置耳機的狀態值->schedule_delayed_work(&headset_info->h_delayed_work[HOOK], msecs_to_jiffies(750));//循環750ms執行一次工作隊列

shell環境下通過執行cat sys/class/switch/h2w/state 查看耳機插入狀態(上層通過獲取這個state值去返回對應的狀態,顯示相應的圖標):

rk3399_all:/ #  cat sys/class/switch/h2w/state 
state <= 0 表示無耳機插入 
state = 1 表示帶 Mic 耳機插入 
state = 2 表示不帶 Mic 耳機插入

在system/media/brillo/audio/audioservice/audio_device_handler.cpp獲取狀態更新給上層調用,直接讀取sys/class/switch/h2w/中state值來獲取最新的狀態(以下為截取的部分代碼)。

static const char kH2WStateFile[] = "/sys/class/switch/h2w/state";63 void AudioDeviceHandler::GetInitialAudioDeviceState(64     const base::FilePath& path) {65   base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);66   if (!file.IsValid()) {67     LOG(WARNING) << "Kernel does not have wired headset support. Could not "68                  << "open " << path.value() << "( "69                  << base::File::ErrorToString(file.error_details()) << " ).";70     return;71   }72   int state = 0;73   int bytes_read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&state), 1);74   state -= '0';75   if (bytes_read == 0) {76     LOG(WARNING) << "Could not read from " << path.value();77     return;78   }79   VLOG(1) << "Initial audio jack state is " << state;80   static const int kHeadPhoneMask = 0x1;81   bool headphone = state & kHeadPhoneMask;82   static const int kMicrophoneMask = 0x2;83   bool microphone = (state & kMicrophoneMask) >> 1;8485   UpdateAudioSystem(headphone, microphone);86 }

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/194829.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息