MT8788 Android11 tp 启动流程

环境:       
      MT8788 Android11 focaltech_touch HD720 5寸tp

log信息 分析步骤:

一 获取dts信息 和 添加驱动到内核
   
    1.获取dts设备树中配置的信息    2.将tp厂商的驱动文件注册添加到 tpd_driver_list[] 全局数组中

  1. 驱动注册加载流程:
  2. 执行tpd_driver_init()
  3.     1.tpd_get_dts_info();
  4.     2.tpd_driver_add(&tpd_device_driver);
  5.             static struct tpd_driver_t tpd_device_driver = {
  6.                     .tpd_device_name = FTS_DRIVER_NAME,
  7.                     .tpd_local_init = tpd_local_init,
  8.                     .suspend = tpd_suspend,
  9.                     .resume = tpd_resume,   };
复制代码



二 注册一个平台驱动driver 匹配后 tpd_probe执行
   


    1.模块入口函数,实现调用tpd_init_work_callback函数
        a.create_singlethread_workqueue用于创建workqueue工作队列,@name:workqueue名称

        b.初始化工作队列,调用tpd_init_work_callback函数用于注册一个对应的平台驱动,INIT_WORK只是定义了work和work对应的操作

        c.queue_work激活时,执行对应work,即执行tpd_init_work_callback函数

    2.执行tpd_init_work_callback函数
        a.调用platform_driver_register(&tpd_driver)注册一个平台驱动driver    平台驱动(platform driver)注册成功后,compatible相同匹配成功,就执行tpd_probe函数

  1. mtk_tpd的平台调用流程: kernel-4.14\drivers\input\touchscreen\mediatek\mtk_tpd.c
  2. 1. static int __init tpd_device_init(void)
  3.       a. tpd_init_workqueue = create_singlethread_workqueue("mtk-tpd");        
  4.       b. INIT_WORK(&tpd_init_work, tpd_init_work_callback);   
  5.       c. res = queue_work(tpd_init_workqueue, &tpd_init_work);      
  6.   
  7. 2. static void tpd_init_work_callback(struct work_struct *work)   
  8.     a. platform_driver_register(&tpd_driver) != 0)
复制代码


三 tpd_Probe函数执行(重点调用第三方驱动注册的 tpd_local_init 函数)
   

  1. kernel-4.14\drivers\input\touchscreen\mediatek\mtk_tpd.c  //内分析tpd_probe函数
  2. tpd_probe(struct platform_device *pdev)
  3. 1.注册杂项设备
  4.     static struct miscdevice tpd_misc_device = {
  5.             .minor = MISC_DYNAMIC_MINOR,
  6.             .name = "touch",
  7.             .fops = &tpd_fops,}
  8.             
  9. 2.获得 dts 相关引脚配置
  10.     pinctrltpd_get_gpio_info(pdev);
  11.    
  12. 3.分配 mtk 封装的 tp 数据结构
  13.     tpd = kmalloc(sizeof(struct tpd_device), GFP_KERNEL);
  14.    
  15. 4.分配输入子系统
  16.   tpd->dev = input_allocate_device();  
  17. 5.处理 touch panel 报点旋转
  18.   #ifdef CONFIG_MTK_LCM_PHYSICAL_ROTATION
  19.   if (strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "90", 2) == 0 || strncmp(CONFIG_MTK_LCM_PHYSICAL_ROTATION, "270", 3) == 0) {
  20. #ifdef CONFIG_MTK_FB
  21. /*Fix build errors,as some projects  cannot support these apis while bring up*/
  22.    TPD_RES_Y = DISP_GetScreenWidth();
  23.    TPD_RES_X = DISP_GetScreenHeight();
  24. #endif
  25. 6.相关报点参数设置
  26.     tpd_mode = TPD_MODE_NORMAL;
  27.         tpd_mode_axis = 0;
  28.         tpd_mode_min = TPD_RES_Y / 2;
  29.         tpd_mode_max = TPD_RES_Y;
  30.         tpd_mode_keypad_tolerance = TPD_RES_X * TPD_RES_X / 1600;
  31. 7.设置输入设备 TP 上报事件类型
  32.     set_bit(EV_ABS, tpd->dev->evbit);
  33.         set_bit(EV_KEY, tpd->dev->evbit);
  34.         set_bit(ABS_X, tpd->dev->absbit);
  35.         set_bit(ABS_Y, tpd->dev->absbit);
  36.         set_bit(ABS_PRESSURE, tpd->dev->absbit);
  37. 8.调用第三方驱动注册的的 init 函数
  38.     for (i = 1; i < TP_DRV_MAX_COUNT; i++){
  39.   /* add tpd driver into list */
  40.   if (tpd_driver_list[i].tpd_device_name != NULL) {   
  41.   
  42.   8.1.调用tpd_local_init()函数     
  43.    tpd_driver_list[i].tpd_local_init();
  44.    /* msleep(1); */
  45.    if (tpd_load_status == 1) {      
  46.     TPD_DMESG("tpd_probe, tpd_driver_name=%s\n",
  47.     tpd_driver_list[i].tpd_device_name);
  48.    
  49.      8.2.去执行具体的TP ic驱动
  50.     g_tpd_drv = &tpd_driver_list[i];
  51.     break;
  52.     }
  53.   }
  54. }
  55. 9.如果没有注册 tp 驱动,则调用默认的 R 电阻屏驱动
  56.   if (g_tpd_drv == NULL) {
  57.       if (tpd_driver_list[0].tpd_device_name != NULL) {
  58.        g_tpd_drv = &tpd_driver_list[0];
  59.        // touch_type:0: r-touch, 1: C-touch
  60.        touch_type = 0;
  61.        g_tpd_drv->tpd_local_init();               
  62.           }
  63.   }
  64. 10.调用当前使用的 tp 驱动的 resume() 函数
  65.     touch_resume_workqueue = create_singlethread_workqueue("touch_resume");
  66.         INIT_WORK(&touch_resume_work, touch_resume_workqueue_callback);
  67. 11.注册内核通知链,监听fb_notifier,应该会在相应的屏的驱动里面进行通知调用
  68.     11.1.在这里进行 TP 的唤醒和休眠操作
  69.         tpd_fb_notifier.notifier_call = tpd_fb_notifier_callback;
  70.         tpd_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
  71.     11.2.注册通知链
  72.         fb_register_client(&tpd_fb_notifier)
  73.         
  74.     11.3.设置输入设备 TP 上报事件
  75.         input_set_abs_params(tpd->dev, ABS_X, 0, TPD_RES_X, 0, 0);
  76.         input_set_abs_params(tpd->dev, ABS_Y, 0, TPD_RES_Y, 0, 0);
  77.         input_abs_set_res(tpd->dev, ABS_X, TPD_RES_X);
  78.         input_abs_set_res(tpd->dev, ABS_Y, TPD_RES_Y);
  79.         input_set_abs_params(tpd->dev, ABS_PRESSURE, 0, 255, 0, 0);
  80.         input_set_abs_params(tpd->dev, ABS_MT_TRACKING_ID, 0, 10, 0, 0);
  81.         
  82.     11.4.注册输入设备
  83.         if (input_register_device(tpd->dev))      
  84.            TPD_DMESG("input_register_device failed.(tpd)\n");
  85.         else
  86.            tpd_register_flag = 1;
  87.         if (g_tpd_drv->tpd_have_button)
  88.            tpd_button_init();        
  89.         if (g_tpd_drv->attrs.num)
  90.            tpd_create_attributes(&pdev->dev, &g_tpd_drv->attrs);
复制代码


四 tpd_local_init函数执行过程   



    1.调用i2c_add_driver(&tpd_i2c_driver),(有的驱动在这里上电)
        a.注册一个i2c设备驱动,并与注册的device name匹配,匹配一致后将执行tpd_device_driver里面的tpd_probe函数,成功的话就会将tpd_load_status变量置1



    2.设置按键



    3.i2c驱动probe函数执行
        a.创建工作队列(中断下半部)



        b.中断申请函数



        c.初始化 注册输入设备

  1. 目录:\kernel-4.14\drivers\input\touchscreen\mediatek\focaltech_touch\focaltech_core.c
  2.     1.tpd_local_init
  3.     1.1.-> fts_ts_driver_init()
  4.     1.2.-> i2c_add_driver(&fts_ts_driver);
  5.               
  6.     2.tpd_button_setting
  7.    
  8.     3.static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
  9.         -> ret = fts_ts_probe_entry(ts_data);
复制代码



五.申请中断
    1.获取触摸设备节点

    2.创建内核线程 touch_event_handler(重要函数)

    3.申请中断  fts_irq_handler为中断处理函数

  1. 目录:\kernel-4.14\drivers\input\touchscreen\mediatek\focaltech_touch\focaltech_core.c
  2. static int fts_irq_registration(struct fts_ts_data *ts_data)
  3. {
  4.     1.node = of_find_matching_node(node, touch_of_match);
  5.     2.ts_data->thread_tpd = kthread_run(touch_event_handler, 0, TPD_DEVICE);
  6.    
  7.     3.ret = request_irq(ts_data->irq, fts_irq_handler,
  8.               ts_data->pdata->irq_gpio_flags, FTS_DRIVER_NAME,
  9.               ts_data);
  10.     return ret;
  11. }
复制代码



4.中断处理函数
    a.(主动唤醒)当设备可以使用的时候就要唤醒进入休眠态的进程,wakr_up等待队列头中的所有进程都唤醒。

    b.1.除了主动唤醒以外,也可以设置等待队列等待某个事件,当这个事件满足以后就自动唤醒等待队列中的进程

    b.2.等待以waiter为等待队列头的等待队列被唤醒,前提是 condition 条件必须满足(为真),否则一直阻塞,允许被信号打断

注释: 第二个函数看的不是很懂猜测大概就是给当前正在运行的进程创建并初始化了一个等待队列项。


    c.重要函数 fts_irq_read_report() 调用 fts_input_report_b(ts_data)

  1. 目录:\kernel-4.14\drivers\input\touchscreen\mediatek\focaltech_touch\focaltech_core.c
  2. 1.static irqreturn_t fts_irq_handler(int irq, void *data)
  3.     wake_up_interruptible(&waiter);
  4.    
  5. 2. static int touch_event_handler(void *unused)
  6. {
  7.     struct sched_param param = {.sched_priority = RTPM_PRIO_TPD};
  8.     sched_setscheduler(current, SCHED_RR, ¶m);
  9.     do {
  10.         set_current_state(TASK_INTERRUPTIBLE);
  11.         wait_event_interruptible(waiter, tpd_flag != 0);
  12.         tpd_flag = 0;
  13.         set_current_state(TASK_RUNNING);
  14. #if FTS_PSENSOR_EN
  15.         if (fts_proximity_readdata(fts_data) == 0)
  16.             continue;
  17. #endif
  18. 3.        fts_irq_read_report();   
  19. //                -> fts_input_report_b(ts_data);
  20.     } while (!kthread_should_stop());
  21.     return 0;
  22. }
复制代码



    5.Linux 内核通过读取设备树中的中断属性信息来配置中断
        5.1.iic设备信息

        5.2. interrupt-parent 对应的是平台的中断控制器,里面应用的 pio对应的是mt6771.dtsi文件里面的中断控制器dts描述

        5.3.interrupts 的第一个参数对应的是中断号,第二个参数对应的是中断的触发方式,第三个参数是GPIO号,&pio内设置,第四个是GPIO口的电平

  1. //cust.dtsi设备树文件内
  2. 1.&i2c0 {
  3.       #address-cells = <1>;
  4.       #size-cells = <0>;
  5.       clock-frequency = <100000>;
  6.       mediatek,use-open-drain;
  7.       cap_touch_mtk:cap_touch@5D {
  8.        compatible = "mediatek,cap_touch";      
  9.        reg = <0x5D>;              
  10.        status = "okay";
  11.       };
  12.     };   
  13. &touch {
  14. 2.     interrupt-parent = <&pio>;      
  15. 3.     interrupts = <0 IRQ_TYPE_EDGE_FALLING 0 0>;
  16.       status = "okay";
  17. };
复制代码

六.最后就是fts_input_report_b(ts_data) 上报和同步读取到的坐标信息
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值