一.硬件原理图
耳机输出硬件原理图:
耳机实物图:
耳机插入硬件原理:
耳机插入后HP_DET_L会连接耳机的GND,从而实现HP_DET_L叫从高到低的状态。
耳机插入软件原理:
软件需要在驱动里面定时的读取gpio的状态,实现实时检测耳机插入拔出的热插拔功能。
二.设备树DTS修改
目前需求在功放驱动里面添加耳机的插入检测, 功放为ad82584.
插入检测HP_DET_L(GPIO1_D2).
设备树DTS配置:
ad82584f_stereo: ad82584f-stereo@31 {
compatible = "ad82584f";
#sound-dai-cells = <0>;
reg = <0x31>;
spk-con-gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
+ earphone-det-gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
set_state_enable = <1>;
pinctrl-names = "default";
pinctrl-0 = <&earphone_det>;
status = "okay";
};
三.代码修改
在probe函数里面读取gpio:
ad82584f_probe:
data->earphone_det_gpio = devm_gpiod_get_optional(&client->dev,
"earphone-det",
GPIOD_IN);
if (IS_ERR(data->earphone_det_gpio)) {
dev_warn(dev, "get earphone_det_gpio failed\n");
return PTR_ERR(data->earphone_det_gpio);
}
在ad82584f_codec_probe添加定时检测gpio状态函数:
检测函数为:ad82584f_earphone_check_work。
INIT_DELAYED_WORK(&ad82584f->earphone_check_work, ad82584f_earphone_check_work);
schedule_delayed_work(&ad82584f->earphone_check_work,msecs_to_jiffies(5000));
static void ad82584f_earphone_check_work(struct work_struct *work)
{
struct ad82584f_data *ad82584f = container_of(work, struct ad82584f_data,
earphone_check_work.work);
if (ad82584f->earphone_det_gpio) {
bool curEarphone_plug_in = (gpiod_get_value(ad82584f->earphone_det_gpio) > 0) ? false:true; //检测耳机插入状态
if(curEarphone_plug_in != ad82584f->preEarphone_plug_in){
if(curEarphone_plug_in){
dev_info(ad82584f->dev, "%s: earphone plug in\n", __func__);
if(of_property_read_bool(ad82584f->dev->of_node, "set_state_enable")){ //使能耳机功能
extcon_set_state_sync(ad82584f->extcon, EXTCON_JACK_HEADPHONE, true);
extcon_set_state_sync(ad82584f->extcon, EXTCON_JACK_MICROPHONE, true);
}
ad82584f_enable_spk(ad82584f,0);
}else{
dev_info(ad82584f->dev, "%s: earphone plug out\n", __func__);
if(of_property_read_bool(ad82584f->dev->of_node, "set_state_enable")){
extcon_set_state_sync(ad82584f->extcon, EXTCON_JACK_HEADPHONE, false);
extcon_set_state_sync(ad82584f->extcon, EXTCON_JACK_MICROPHONE, false);
}
ad82584f_enable_spk(ad82584f,1);
//gpiod_set_value(ad82584f->spk_ctl_gpio, 0);
}
ad82584f->preEarphone_plug_in = curEarphone_plug_in;
}
}
schedule_delayed_work(&ad82584f->earphone_check_work,
msecs_to_jiffies(1000));
}