1. 程式人生 > >裝置樹學習之(十三)電容觸控式螢幕驅動

裝置樹學習之(十三)電容觸控式螢幕驅動

開發板:tiny4412SDK + S702 + 4GB Flash
要移植的核心版本:Linux-4.4.0 (支援device tree)
u-boot版本:友善之臂自帶的 U-Boot 2010.12
busybox版本:busybox 1.25

友善之臂提供的資料中,觸控式螢幕驅動採用的是一線觸控,但是保留了i2c介面,驅動晶片為FT5406,本文主要實現 i2c 介面的觸控式螢幕驅動。

首先,分析下 FT5406 的基本電路介面:
基本都是通用的介面,如 I2C 介面,INT,WAKE,RST。如圖:
這裡寫圖片描述
這裡寫圖片描述
以上可知,我們在驅動中必須定義一箇中斷口,來啟動接收觸控資料,一個gpio腳來複位FT5406。wake:主要靠cpu傳送一個喚醒指令給FT5406。
檢視tiny4412原理圖
這裡寫圖片描述


再次,需確認FT5406的從地址,以便於I2C訪問得到。這個可以根據FT5406資料手冊查詢到.
這裡寫圖片描述
可知從地址高位必須為:3,低位必須根據 i2ccon 設定的值來確定,這點很奇怪。
我這邊找到的從地址為:0x38
i2ccon 暫時未找到出處,可以用 i2c tools 探測一下

/mnt # ./i2cdetect -y 1                                            
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f                
00:          -- -- --
-- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50:
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

基本的東西確認好後,剩下的就是根據FT5406資料手冊上的指令,開始寫驅動了。
在此之前,我們先了解下驅動如何實現電容屏的多點觸控,其實很簡單,主要需要
觸控式螢幕IC FT5406 能夠捕獲多點資料,這點電容屏基本多能支援到捕獲2點以上,而FT5406 可以捕獲5個觸控點,編寫驅動時,只要去獲取這幾個點的資料,然後上報就行。格式如圖:
這裡寫圖片描述
這裡寫圖片描述
解釋:

  • 02h : 捕獲的觸控點個數
  • 03h- 1eh :對應每個點的x,y座標數值。
  • touch id 表示觸點編號,對應於typeB的slot

這裡寫圖片描述

驅動參考:Ft6236.c (drivers\input\touchscreen)

touch_demo{
    compatible = "tiny4412,touch_demo";
    interrupts = <6 0>;
        interrupt-parent = <&gpx1>;
        status = "okay";
};
&i2c_1{
        status = "okay";
        touch@38{
                compatible = "tiny4412,touch";
                reg = <0x38>;
        };
};
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/of_gpio.h>


#define uchar unsigned char

static void touch_read_handler(struct work_struct *work);
DECLARE_WORK(touch_read_work, touch_read_handler);


static struct i2c_client *touch_client;
static struct input_dev *touch_dev;
static int irq;


static void touch_read(unsigned char sAddr, unsigned char *buf, unsigned int len)
{
    struct i2c_msg msg[2];
    int i, ret;
    unsigned char address;
    for (i = 0; i < len; i++)
    {
        /* 先寫入要讀取的暫存器地址 */
        address = sAddr + i;
        msg[0].addr  = touch_client->addr;    /* 目的 */
        msg[0].buf   = &address;              /* 源 */
        msg[0].len   = 1;                     /* 地址=1 byte */
        msg[0].flags = 0;                     /* 表示寫 */

        /* 然後啟動讀操作 */
        msg[1].addr  = touch_client->addr;    /* 源 */
        msg[1].buf   = &buf[i];               /* 目的 */
        msg[1].len   = 1;                     /* 資料=1 byte */
        msg[1].flags = I2C_M_RD;              /* 表示讀 */
        ret = i2c_transfer(touch_client->adapter, msg, 2);
        if (ret < 0)
        {
            printk("i2c_transfer eror\n");
        }
        mdelay(10);
    }

}

static void touch_read_handler(struct work_struct *work)
{
    unsigned char buf[13];
    unsigned char touches, i, event, id;
    unsigned short x, y;
    bool act;
    /* read tp resister by i2c */
    touch_read(0x00, buf, 13);

    /* number of touch points */
    touches = buf[2] & 0x0f;
    //printk("point num %d\n", touches);

    if (touches > 2) {
        printk("%s touch read touches error\n",__func__);
        touches = 2;
    }

    for (i = 0; i < touches; i++) {
        y = ((buf[5 + i * 6] & 0x0f) << 8) | buf[6 + i * 6];
        x = ((buf[3 + i * 6] & 0x0f) << 8) | buf[4 + i * 6];
        //printk("%d point x:%08d y:%08d\n", i, x, y);
        event = buf[3 + i * 6] >> 6;    //event flags
        id = buf[5 + i * 6] >> 4;       //touch id
        //printk("event %d id %d\n", event, id);

        //down or contact
        act = (event == 0x00 || event == 0x02);

        input_mt_slot(touch_dev, id);
        input_mt_report_slot_state(touch_dev, MT_TOOL_FINGER, act);

        //if up return
        if (!act)
            continue;

        input_report_abs(touch_dev, ABS_MT_POSITION_X, x);
        input_report_abs(touch_dev, ABS_MT_POSITION_Y, y);  
    }

    input_mt_sync_frame(touch_dev);
    input_sync(touch_dev);

}

static irqreturn_t touch_isr(int irq, void *dev_id)
{
    schedule_work(&touch_read_work);

    return IRQ_HANDLED;
}

static int touch_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
{
    unsigned char buf;
    int ret;

    touch_client = client;
    printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

    touch_read(0xa3, &buf, 1);
    printk("Chip vendor ID  %x\n", buf);

    touch_read(0xa6, &buf, 1);
    printk("Firmware ID %x\n", buf);

    touch_read(0xa8, &buf, 1);
    printk("CTPM Vendor ID %x\n", buf);

    touch_read(0x00, &buf, 1);
    printk("DEVIDE_MODE %x\n", buf);

    touch_read(0x80, &buf, 1);
    printk("ID_G_THGROUP. %x\n", buf);

    touch_read(0x88, &buf, 1);
    printk("ID_G_PERIODACTIVE. %x\n", buf);

    touch_dev = input_allocate_device();
    if (touch_dev == NULL)
    {
        printk("%s, allocate input device, error\n", __func__);
        return -1;
    }

    //告訴input能夠支援哪些事件
    input_set_abs_params(touch_dev, ABS_MT_POSITION_X, 0, 800, 0, 0);
    input_set_abs_params(touch_dev, ABS_MT_POSITION_Y, 0, 480, 0, 0);
    ret = input_mt_init_slots(touch_dev, 2, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
    if (ret)
    {
        printk("%s, input_mt_init_slots error\n", __func__);
        return ret;
    }
    touch_dev->name = "touch";
    touch_dev->id.bustype = BUS_I2C;
    touch_dev->dev.parent = &(touch_client)->dev;
    ret = input_register_device(touch_dev);
    if (ret)
    {
        printk("%s, register input device, error\n", __func__);
        return ret;
    }

    printk("irq is %d\n", irq); 

    ret = devm_request_threaded_irq(&touch_client->dev, irq, touch_isr, NULL, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "touch1", NULL);

    if (ret < 0)
    {
        printk("failed to request_irq %d\n", ret);
    }

    return 0;
}

static int touch_remove(struct i2c_client *client)
{

    return 0;
}

static const struct i2c_device_id touch_id_table[] =
{
    { "touch", 0 },
    {}
};


/* 1. 分配/設定i2c_driver */
static struct i2c_driver touch_driver =
{
    .driver = {
        .name   = "touch",
        .owner  = THIS_MODULE,
    },
    .probe      = touch_probe,
    .remove     = touch_remove,
    .id_table   = touch_id_table,
};


static int int_demo_remove(struct platform_device *pdev) {

    printk("%s enter.\n", __func__);

    return 0;
}

static int int_demo_probe(struct platform_device *pdev) {
    irq = platform_get_irq(pdev, 0);
    printk("int_demo_probe %d\n", irq);
    return 0;
}

static const struct of_device_id touch_demo_dt_ids[] = {
    { .compatible = "tiny4412,touch_demo", },
    {},
};
MODULE_DEVICE_TABLE(of, touch_demo_dt_ids);
static struct platform_driver touch_demo_driver = {
    .driver        = {
        .name      = "touch_demo",
        .of_match_table    = of_match_ptr(touch_demo_dt_ids),
    },
    .probe         = int_demo_probe,
    .remove        = int_demo_remove,
};


static int touch_drv_init(void)
{
    int ret;
    /* 1.註冊平臺裝置驅動 */
    ret = platform_driver_register(&touch_demo_driver);
    if (ret)
        printk(KERN_ERR "int demo: probe failed: %d\n", ret);
    /* 2. 註冊i2c_driver */
    i2c_add_driver(&touch_driver);

    return 0;
}

static void touch_drv_exit(void)
{
    i2c_del_driver(&touch_driver);
    platform_driver_unregister(&touch_demo_driver);
}


module_init(touch_drv_init);
module_exit(touch_drv_exit);
MODULE_LICENSE("GPL");

相關推薦

裝置學習十三電容觸控式螢幕驅動

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:bu

裝置學習點燈

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy

裝置學習I2C裝置的註冊過程分析

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy

裝置學習SPI設備註冊過程

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy

裝置學習GPIO中斷

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busybox 1.25目標: 學習裝置樹中GP

裝置學習watchdog

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busybox 1.25 目標: 學習裝置樹中普通

裝置學習Clock

開發板:tiny4412SDK + S702 + 4GB Flash  要移植的核心版本:Linux-4.4.0 (支援device tree)  u-boot版本:友善之臂自帶的 U-Boot 2010.12  busybox版本:busybox 1.25 目標:

裝置學習spi flash

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy

裝置學習十二LCD驅動

開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy

Linux裝置學習日記裝置簡單介紹

一、linux裝置樹簡介1.    裝置樹是一種描述硬體的資料結構,它起源於openfirmware,採用裝置樹後,許多硬體的細節可以直接通過它傳遞給linux,而不需要在核心中進行大量冗餘編碼。2.    裝置樹由一系列被命名的節點(Node)和屬性(property)組成

《機器學習實戰》學習筆記十三利用SVD簡化資料

轉載請註明作者和出處:http://blog.csdn.net/john_bh/ 執行平臺: Windows Python版本: Python3.6 IDE: Sublime text3

從零開始學習html十三 CSS代碼縮寫,占用更少的帶寬

tin imp important 都是 -h 20px 帶寬 記得 樣式 一、盒模型代碼簡寫 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta http-equiv="Conten

如鵬網學習筆記十三EasyUI

bar -h 學習筆記 val datagrid center sheet 手機號 cti 一、EasyUI簡介   是一組基於JQuery的UI插件集合   主要作用:為JQuery對象提供新的方法,實現新的功能   可以快速創建出簡潔、友好、美觀的頁面,非常適合做

WorkerMan 入門學習基礎教程-Timer類的使用

timer類 定時 基礎教程 連接 worker loader 入門 入門學習 json 1、ServerTimer.php 代碼: <?php /** * 定時器學習 */ require_once __DIR__ . ‘/Workerman/Autoload

Python學習筆記十三

應該 成功 緩存 with open 文件 學習 編碼 打開 gbk 一、讀文件   file = open("文件路徑名","讀寫模式") # r :讀模式 、w :寫模式、a :追加模式   如果文件存在,則打開文件成功,如果文件不存在,則打開錯誤,會拋出一個IOEr

R語言學習筆記十三:時間序列

abs 以及 stat max 時間 aic air ror imp #生成時間序列對象 sales<-c(18,33,41,7,34,35,24,25,24,21,25,20,22,31,40,29,25,21,22,54,31,25,26,35) tsal

學習筆記十三——數據庫備份還原的知識點與註意事項

差異 並且 rom esc 每次 sel exe tor 參數 學習筆記(十三)——數據庫備份還原的知識點與註意事項 一、備份還原基本概念 1、 完整備份:完整備份因為需要備份的數據量大,所以需要在空閑時間進行,並且定期進行。 2、

day6-Python學習筆記十三redis數據庫

測試的 針對 def 時間 執行 原來 導入 style __main__ import redisr = redis.Redis(host=‘211.149.218.16‘,port=6379,password=‘123456‘,db=2)#連上redisprint(r.

Linux學習筆記十三 su 、sudo 、限制root遠程登陸

linux 中一 sudo ado type col tmp 如果 一個 一、su切換用戶su - username帶用戶環境切換用戶 su - -c "touch /tmp/123.txt" user1 以user1用戶創建/tmp/123.txt 文件 如果需要切換到

Android源代碼解析十三--&gt;apk安裝流程

solved 就是 activity 文章 空間不夠 orien gpo tpm systems 轉載請標明出處:一片楓葉的專欄 上一篇文章中給大家分析了一