当前位置: 首页 > article >正文

RK3399 android7.1 话柄电话功能

实现功能:挂柄接IO口+GND控制话机听筒与系统喇叭的切换(抬起手柄声音由喇叭切换到听筒,挂到磁吸底座喇叭出声)
应用场景: 电子电话班牌,电话机等
硬件接线方式:

电话手柄:听筒接耳机座子<HRP,GND>,麦克风接<MIC+,MIC->
电话底座:磁吸座子接<IO2,GND>


一,IO(gpio)口为系统cpu直出

1.确认gpio引脚

例如(IO2+GND):

io2-gpio =<&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;

2.将需要对地控制的gpio引脚直接替换原生的耳机控制脚

一般dts中有描述:

rk_headset: rk-headset {
        compatible = "rockchip_headset";
        headset_gpio = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&hp_det>;
};

例如(IO2+GND):

diff --git a/kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi b/kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi
index 65a3266d09..e6a621adce 100644
--- a/kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi
+++ b/kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi
@@ -17,10 +17,9 @@


        rk_headset: rk-headset {
                compatible = "rockchip_headset";
-               headset_gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
+               headset_gpio = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&hp_det>;
-               io-channels = <&saradc 2>;
        };


        vcc2v5_sys: vcc2v5-ddr {
@@ -415,7 +414,7 @@
        };
        headphone {
                hp_det: hp-det {
-                       rockchip,pins = <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };

二,通过xrm117x驱动 i2c转外部扩展GPIO

1.添加gpio_key.c

代码路径kernel/drivers/char/gpio_key.c
代码功能:用于管理 GPIO 键,通过一个线程监控 GPIO 键的状态变化并相应地处理这些状态变化。

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/iio/consumer.h>
#include <dt-bindings/pinctrl/rk.h>

/* Debug */
#define DEBUG 0
#if DEBUG
#define DBG_GPIO(x...) printk(x)
#else
#define DBG_GPIO(x...) do { } while (0)
#endif

#define KETDELAY  50

enum  {
        SMDT_KEY_F1 = 96,
        SMDT_KEY_F2 = 97,
};
enum  {
        XRM117X_IO0 = 0,
        XRM117X_IO1 = 1,
        XRM117X_IO2 = 2,
        XRM117X_IO3 = 3,
        XRM117X_IO4 = 4,
        XRM117X_IO5 = 5,
        XRM117X_IO6 = 6,
        XRM117X_IO7 = 7,
};
/***************************************************************************************************************************/
extern int android_flag;

static struct task_struct * gpio_key_task;

extern void smdt_hp_det(char flag);
extern void smdt_gpiokey(int event);
extern int xrm117x_gpio_sw_cfg_set(int gpio_sw_cdev, int mul_cfg , int data);
extern int xrm117x_gpio_sw_data_get(int gpio_sw_cdev);
/***************************************************************************************************************************/

int read_gpio(void)
{
    static char gpio_status=1;
    static unsigned int count=0;
    int ret;
    int event=0;

        ret = xrm117x_gpio_sw_data_get(XRM117X_IO2); //控制脚为IO2,可根据需求自行切换
        if(ret < 0)
            return -1;
        DBG_GPIO("gpio1=%d\n",ret);

    if(ret == gpio_status)
    {
        count++;
    }
    else
    {
        gpio_status = ret;
        count = 0;
    }

    if(count == 3)
    {
        smdt_hp_det(gpio_status);
        DBG_GPIO("send event=%d\n",event);
    }
}

int gpio_key_run_thread(void *parg)
{
    msleep(15000);
    while(!android_flag)
        msleep(1000);

    printk("%s in\n",__func__);
    xrm117x_gpio_sw_cfg_set(XRM117X_IO2, 0, 0); //控制脚为IO2,可根据需求自行切换

    while(1)
    {
        msleep(KETDELAY);
        read_gpio();
    }

    return 0;
}

static int gpio_key_probe(struct platform_device *pdev)
{
    int ret;

    printk("%s in\n",__func__);

    gpio_key_task = kthread_create(gpio_key_run_thread, (void*)0, "gpio_key proc");
    if(IS_ERR(gpio_key_task))
    {
        printk(KERN_ERR "### [fy]:gpio_key_task Unable to start kernel thread %s.\n","gpio_key proc");
        gpio_key_task = NULL;    
    }
    if(gpio_key_task)
        wake_up_process(gpio_key_task);

    printk("%s ok\n",__func__);
    return 0;
}
/***************************************************************************************************************************/
static const struct of_device_id gpio_key_of_match[] = {
        { .compatible = "rockchip,rk3399-gpio-key", },
        {},
};
MODULE_DEVICE_TABLE(of, gpio_key_of_match);

static struct platform_driver gpio_key_driver = {
    .probe    = gpio_key_probe,
    .driver    = {
        .name    = "rk3399-gpio-key",
        .owner    = THIS_MODULE,
        .of_match_table = gpio_key_of_match,        
    },
};

module_platform_driver_probe(gpio_key_driver, gpio_key_probe);
MODULE_LICENSE("GPL");

2.Makefile 中添加gpio_key.o;

代码路径kernel/drivers/char/Makefile

obj-y       += gpio_key.o

3.xrm117x驱动中添加 对现有 GPIO 配置和数据检索函数包装;

代码路径kernel/drivers/tty/serial/xrm117x.c

diff --git a/kernel/drivers/tty/serial/xrm117x.c b/kernel/drivers/tty/serial/xrm117x.c
index d65df1f7c1..0b85f1fe90 100644
--- a/kernel/drivers/tty/serial/xrm117x.c
+++ b/kernel/drivers/tty/serial/xrm117x.c
@@ -1634,6 +1634,18 @@ static int gpio_sw_data_get(int gpio_sw_cdev)
        return xrm117x_gpio_get(smdt,gpio_sw_cdev);
}
+int xrm117x_gpio_sw_cfg_set(int gpio_sw_cdev, int mul_cfg , int data)
+{
+       return gpio_sw_cfg_set(gpio_sw_cdev, mul_cfg , data);
+}
+EXPORT_SYMBOL(xrm117x_gpio_sw_cfg_set);
+
+int xrm117x_gpio_sw_data_get(int gpio_sw_cdev)
+{
+       return gpio_sw_data_get(gpio_sw_cdev);
+}
+EXPORT_SYMBOL(xrm117x_gpio_sw_data_get);
+
static int gpio_sw_drv_get(int gpio_sw_cdev)
{
         int ret;

4.由于音频芯片使用的是es8388,需要到对应驱动中 处理耳机插入检测的中断;

代码路径kernel/sound/soc/codecs/es8388.c

diff --git a/kernel/sound/soc/codecs/es8388.c b/kernel/sound/soc/codecs/es8388.c
index dc4726bb1b..5079ecf507 100644
--- a/kernel/sound/soc/codecs/es8388.c
+++ b/kernel/sound/soc/codecs/es8388.c
@@ -123,8 +123,22 @@ static int es8388_set_gpio(int gpio, bool level)
     return 0;
}
+void smdt_hp_det(char flag)
+{
+        struct es8388_priv *es8388 = es8388_private;
+
+    if (flag != es8388->hp_det_level) //根据检测到的级别更新耳机插入状态
+        es8388->hp_inserted = 0;
+    else
+        es8388->hp_inserted = 1;
+        printk("--------hp_det_irq_handler hp_det_level=%d hp_inserted=%d\n",es8388->hp_det_level,es8388->hp_inserted);
+        switch_set_state(&es8388->sw_dev, es8388->hp_inserted ? head_havemic : 0);
+}
+EXPORT_SYMBOL(smdt_hp_det);
+
@@ -833,7 +848,7 @@ static int es8388_i2c_probe(struct i2c_client *i2c,
     }
     //fixbug:power on with headset
-    headset_det_gpio_val = gpio_get_value(es8388->hp_det_gpio);
+    headset_det_gpio_val = 0;//gpio_get_value(es8388->hp_det_gpio);
     if(headset_det_gpio_val == 1){
         //if headset in, set h2w 1. (default is headset and ignore 3/4)
         switch_set_state(&es8388->sw_dev, head_havemic);


http://www.kler.cn/a/298697.html

相关文章:

  • llms 文本分类的微调
  • 《论多源数据集成及应用》写作框架,软考高级系统架构设计师
  • 【Android】NestedScrollView的简单用法与滚动冲突、滑动冲突
  • 聚观早报 | 红魔电竞平板新品发布;台积电8月份营收
  • LabVIEW步进电机控制方式
  • node.js入门基础
  • Learn OpenGL In Qt之着色器
  • 【C++】 Vector
  • mysql mgr 集群部署 单主模式和多主模式
  • [论文笔记] t-SNE数据可视化
  • Java笔试面试题AI答之JDBC(3)
  • framebuffer
  • Android13修改Setting实现电量低于30%的话不可执行Rest操作
  • ubuntu配置tftp、nfs
  • 【编程基础知识】Spring过滤器、拦截器、AOP区别
  • 《JavaScript 中数据类型判断、转换技巧及应用实例》
  • GitHub每日最火火火项目(9.10)
  • 最新版 | SpringBoot3如何自定义starter(面试常考)
  • Java数组的定义及遍历
  • 【局域网投屏】sunshine和moonlight投屏/屏幕共享/扩展屏