5
回答
触摸屏 驱动
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

俺是刚刚接触驱动,看了好几天也不知道,也不是很理解。大侠来帮忙解释一下,各个结构体代表什么?函数是什么功能?

static int mXT224_probe(struct i2c_client *client, const struct i2c_device_id *id);
static int mXT224_remove(struct i2c_client *client);

#ifdef FEATURE_CFG_DUMP
static int total_size = 0;
static u8 *cfg_dmup;
#endif
static const struct i2c_device_id mXT224_ts_id[] = {
    { "mXT224_touch", 0 },
    { }
};
#endif
    .id_table = mXT224_ts_id,
    .driver   = {
        .name = "mXT224_touch",
    },
};


#define ID_INFORMATION_SIZE        0x7
#define OBJECT_TABLE_ELEMENT_SIZE  0x6
#define CRC_SIZE                   0x3
#define TABLE_SIZE_ADDR            ID_INFORMATION_SIZE-1
#define MESSAGE_T5                 0x5

不知道下面结构体是定义什么?
struct mxt224_id_info{
    u8   family_id;
    u8   variant_id;
    u8   version;
    u8   build;
    u8   matrix_x_size;
    u8   matrix_y_size;
    u8   object_num;
}__packed;

不知道下面结构体是定义什么?
struct mxt224_table_info{
    u8   obj_type;
    u8   start_addr_lsb;
    u8   start_addr_msb;
    u8   size;
    u8   instance;
    u8   report_id;
}__packed;

#define CFGERR_MASK (0x01<<3)

不知道下面结构体是定义什么?
union msg_body{
    u8 msg[7];
    struct{
        u8  status;
        u32 checksum:24;
    }t6;
    struct{
        u8  status;
        u8  x_msb;
        u8  y_msb;
        u8  xy_poslisb;
        u8  area;
        u8  tchamplitude;
        u8  tchvector;
    }t9;
}__packed;

 

不知道下面结构体是定义什么?
struct message_t5{
    u8 report_id;
    union msg_body body;
    u8 checksum;
}__packed;
struct message_t5 msg_t5;

struct mxt224_obj{
    struct mxt224_id_info    *id_info;
    u8                       *table_info_byte;
    struct mxt224_table_info *table_info;
    u8                        table_size;
    u16                       msg_t5_addr;
    u32                       info_crc;
};

struct mXT224_info {
    int int_gpio;
    int reset_gpio;
    int cfg_delay;
    struct hrtimer timer;
    struct i2c_client *client;
    struct input_dev *input_dev;
    int (*power)(int on);
    /* Object table relation */
    struct mxt224_obj obj;
};

static struct mXT224_info ts_data = {
    .int_gpio = 124,//MSM_GPIO_TO_INT(124),
    .reset_gpio = 117,
    .cfg_delay = 0,
};


struct mxt224_cfg{
    u8 type;
    const u8* data;
    int size;
};
#if 0
const u8 T7[] =  {0xff, 0xff, 0x32};
const u8 T8[] =  {0x08, 0x05, 0x14, 0x14, 0x00, 0x00, 0x0a, 0x0f,};
const u8 T9[] =  {0x83, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x11, 0x28,
                  0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x0a, 0x0a,
                  0x0a, 0x0a, 0x5a, 0x01, 0xef, 0x00, 0x19, 0x19,
                  0x1e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 T15[] = {0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x41, 0x1e,
                  0x02, 0x00, 0x00, };
const u8 T18[] = {0x00, 0x00 };
const u8 T19[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
const u8 T20[] = {0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00,};
const u8 T22[] = {0x15, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04,
                  0x32, 0x00, 0x01, 0x0a, 0x0f, 0x14, 0x19, 0x1e,
                  0x04};
const u8 T23[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
const u8 T25[] = {0x00, 0x00, 0xe0, 0x2e, 0x58, 0x1b, 0xb0, 0x36,
                  0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00,};
const u8 T28[] = {0x00, 0x00, 0x02, 0x04, 0x08, 0xf6,};
const u8 T38[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#else
/* New config from Ver18 */
const u8 T7[] =  {0xff, 0xff, 0x32};
const u8 T8[] =  {0x08, 0x05, 0x14, 0x14, 0x00, 0x00, 0x0a, 0x0f,};
const u8 T9[] =  {0x83, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x11, 0x28,
                  0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x0a, 0x0a,
                  0x0a, 0x0a, 0x5a, 0x01, 0xef, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x83, 0x0d, 0x0a, 0x03, 0x03, 0x00, 0x31, 0x14,
                  0x02, 0x03, 0x00, 0x01, 0x01, 0x00, 0x0a, 0x0a,
                  0x0a, 0x0a, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const u8 T15[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, };
const u8 T18[] = {0x00, 0x00 };
const u8 T19[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
const u8 T20[] = {0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00,};
const u8 T22[] = {0x15, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04,
                  0x32, 0x00, 0x01, 0x0a, 0x0f, 0x14, 0x19, 0x1e,
                  0x04};
const u8 T23[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
const u8 T25[] = {0x00, 0x00, 0xe0, 0x2e, 0x58, 0x1b, 0xb0, 0x36,
                  0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00,};
const u8 T28[] = {0x00, 0x00, 0x00, 0x04, 0x08, 0xf6,};
const u8 T38[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
const struct mxt224_cfg cfg_table[] = {
    {7,  T7,  sizeof(T7)},
    {8,  T8,  sizeof(T8)},
    {9,  T9,  sizeof(T9)},
    {15, T15, sizeof(T15)},
    {18, T18, sizeof(T18)},
    {19, T19, sizeof(T19)},
    {20, T20, sizeof(T20)},
    {22, T22, sizeof(T22)},
    {23, T23, sizeof(T23)},
    {25, T25, sizeof(T25)},
    {28, T28, sizeof(T28)},
    {38, T38, sizeof(T38)}
};

struct mxt224_key_info{
    u32  start;
    u32  end;
    u32  code;
};
const struct mxt224_key_info key_info[] = {
    {0,   60,  KEY_MENU},
    {60,  120, KEY_HOME},
    {120, 180, KEY_BACK},
    {180, 240, KEY_SEARCH},
};
#define FETURE_SECOND_T9_INSTANCE
#ifdef  FETURE_SECOND_T9_INSTANCE

#endif
#if 0
const u8 T7[] =  {0xff, 0xff, 0x32};
const u8 T8[] =  {0x08, 0x05, 0x14, 0x14, 0x00, 0x00, 0x0a, 0x0f};
const u8 T9[] =  {0x83, 0x00, 0x00, 0x0D, 0x0A, 0x00, 0x11, 0x28,
                  0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x0A,
                  0x0A, 0x0A, 0x01, 0x5A, 0x00, 0xEF, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  ///////////////////////////////////////
                  //0x83, 0x0D, 0x0A, 0x03, 0x03, 0x00, 0x11, 0x28,
                  //0x02, 0x03, 0x00, 0x01, 0x01, 0x00, 0x0A, 0x0A,
                  //0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  //0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  };
const u8 T15[] = {0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x41, 0x1E,
                  0x02, 0x00, 0x00 };
const u8 T18[] = {0x00, 0x00 };
const u8 T19[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const u8 T20[] = {0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00 };
const u8 T22[] = {0x15, 0x00, 0x00, 0x00, 0x19, 0xFF, 0xE7, 0x04,
                  0x32, 0x00, 0x01, 0x0A, 0x0F, 0x14, 0x19, 0x1E,
                  0x04,
                  /////////////////////////////////////
                  //0x15, 0x00, 0x00, 0x00, 0x19, 0xff, 0xe7, 0x04,
                  //0x32, 0x00, 0x01, 0x0a, 0x0f, 0x14, 0x19, 0x1e,
                  //0x04,
                  };
const u8 T23[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x00, 0x00, 0x00 };
const u8 T24[] = {0x03, 0x04, 0x03, 0xFF, 0x00, 0x64, 0x64, 0x01,
                  0x0A, 0x14, 0x28, 0x00, 0x4B, 0x00, 0x02, 0x00,
                  0x64, 0x00, 0x19 };
const u8 T25[] = {0x00, 0x00, 0x2E, 0xE0, 0x1B, 0x58, 0x36, 0xB0,
                  0x01, 0xF4, 0x00, 0x00, 0x00, 0x00 };
const u8 T27[] = {0x03, 0x02, 0x00, 0xE0, 0x03, 0x00, 0x23};
const u8 T28[] = {0x00, 0x00, 0x00, 0x04, 0x08, 0xF6 };
const u8 T38[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const struct mxt224_cfg cfg_table[] = {
    {7,  T7,  sizeof(T7)},
    {8,  T8,  sizeof(T8)},
    {9,  T9,  sizeof(T9)},
    {15, T15, sizeof(T15)},
    {18, T18, sizeof(T18)},
    {19, T19, sizeof(T19)},
    {20, T20, sizeof(T20)},
    {22, T22, sizeof(T22)},
    {23, T23, sizeof(T23)},
    {24, T24, sizeof(T24)},
    {25, T25, sizeof(T25)},
    {27, T27, sizeof(T27)},
    {28, T28, sizeof(T28)},
    {38, T38, sizeof(T38)}
};
#endif

static struct workqueue_struct *mxt224_wq;
struct work_struct work;
wait_queue_head_t wait;

u32 static crc24(u32 crc, u8 firstbyte, u8 secondbyte)
{
    const u32 crcpoly = 0x80001b;
    u32 result;
    u16 data_word;

    data_word = (u16)((u16)(secondbyte<<8u)|firstbyte);
    result = ((crc<<1u)^(u32)data_word);
    if(result & 0x1000000){
        result ^= crcpoly;
    }
    return result;
}

u32 static get_crc24(const u8* src, int cnt)
{
    int index = 0;
    u32 crc = 0;

    while(index < (cnt-1)){
        crc = crc24(crc, *(src+index), *(src+index+1));
        index += 2;
    }
    //1 TODO:
    if(index != cnt){
        crc = crc24(crc, *(src+index), 0);
    }
    crc = (crc & 0x00ffffff);
    return crc;
}

static u32 mXT224_cfg_crc(void)
{
    int index;
    int sub_index = 0;
    u32 crc = 0;

    /* Remove T38 */
    for(index=0; index<((sizeof(cfg_table)/sizeof(cfg_table[0]))-1); index++){
        const u8* data = cfg_table[index].data;
        while(sub_index <(cfg_table[index].size-1)){
            crc = crc24(crc, *(data+sub_index), *(data+sub_index+1));
            sub_index += 2;
        }
        if(sub_index != cfg_table[index].size){
            if(index == ((sizeof(cfg_table)/sizeof(cfg_table[0]))-1)){
                crc = crc24(crc, *(data+sub_index), 0);
            }else{
                const u8* next_data = cfg_table[index+1].data;
                crc = crc24(crc, *(data+sub_index), *(next_data));
                crc = (crc & 0x00ffffff);
                sub_index = 1;
                continue;
            }           
        }
        sub_index = 0;
        crc = (crc & 0x00ffffff);
    }
    //1 TODO:
    //crc = crc24(crc, 0, 0);
    crc = (crc & 0x00ffffff);
    return crc;
}

static void mxt224_mem_dbg(const void *src, int cnt)
{
    int index;
    const u8* disp = (u8*)src;
    printk(KERN_INFO "%s: start...\n", __func__);
    for(index=0; index        printk(KERN_INFO "0x%2x  ", disp[index]);
    }
    printk(KERN_INFO "\n%s: ...end\n", __func__);
}


#ifndef FEATURE_CFG_DUMP
static irqreturn_t mXT224_ts_interrupt(int irq, void *dev_id)
{
    queue_work(mxt224_wq, &work);
    return IRQ_HANDLED;
}
#endif

static u16 mXT224_get_obj_addr(u8 type, struct mxt224_table_info *info, u8 info_size)
{
    int index;
    u16 addr = 0;

    for(index=0; index        if(type == info[index].obj_type){
            addr = info[index].start_addr_msb;
            addr <<= 8;
            addr |= info[index].start_addr_lsb;
            return addr;
        }
    }
    return addr;
}

struct report_id_table{
    u8 report_start;
    u8 report_end;
    u8 obj_type;
};

static struct report_id_table* id_table = NULL;


static struct report_id_table* mXT224_build_report_id_table(
        struct mxt224_table_info *info, u8 info_size)
{
    int index;
    int write_index;
    u8  offset = 0;
    id_table = (struct report_id_table*)kzalloc(info_size*sizeof(struct report_id_table), GFP_KERNEL);
   
    if(!id_table){
        printk(KERN_INFO "%s: Can't get memory!\n", __func__);
        return NULL;
    }
   
    write_index = 0;
   
    for(index = 0; index        #ifdef FEATURE_CFG_DUMP
        total_size += ((info[index].size+1)*(info[index].instance+1));
        #endif
        if(info[index].obj_type == 0x5)
            continue;
        if(info[index].report_id == 0x00)
            continue;
       
        id_table[write_index].obj_type = info[index].obj_type;
        id_table[write_index].report_start = (offset+1);
        id_table[write_index].report_end = id_table[write_index].report_start+
                                                info[index].report_id*(info[index].instance+1)-1;
       
        offset = id_table[write_index].report_end;
        write_index++;
    }
   
    #ifdef FEATURE_CFG_DUMP
    for(index = 0; index        printk(KERN_INFO "%s: Object type:%d, size:[%d]\n", __func__,
                            info[index].obj_type, info[index].size+1);
    }
    #endif
   
    return id_table;
}


enum mXT224_type{
    MSG_T6 = 1,
    MSG_T9_FIRST_1,
    MSG_T9_FIRST_2,
    MSG_T9_FIRST_3,
    MSG_T9_SECOND,
};


#define MXT224_SECOND_T9_OFFSET 8

static u8 mXT224_get_obj_type(u8 id, struct report_id_table* table, u8 table_size)
{
    int index;

    for(index=0; index        //printk(KERN_INFO "%s: ID:%d, start:[%d], end:[%d]\n", __func__,
        //                 id, table[index].report_start, table[index].report_end);
        if(id>=table[index].report_start && id<=table[index].report_end){
            break;
        }
    }
   
    switch(table[index].obj_type){
        case 6:
            return MSG_T6;
           
        case 9:
        {
            int t9_offset = id-table[index].report_start;
            if(t9_offset < MXT224_SECOND_T9_OFFSET){
                return MSG_T9_FIRST_1+t9_offset;
            }else if(t9_offset == MXT224_SECOND_T9_OFFSET){
                return MSG_T9_SECOND;
            }else{
                return 0;
            }
        }  
       
        default:
            return 0;
    }
}


#define TS_POLL_PERIOD 10000*1000

 

static void mXT224_load_cfg(void)
{
    int index;
    u8  buf[6] = {0};
    u16 addr;
    int rc;
   
    //printk(KERN_INFO "%s\n", __func__);

    if(ts_data.cfg_delay){
        return;
    }
    ts_data.cfg_delay = 1;
   
    hrtimer_start(&ts_data.timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL);
   
    for(index=0; index<(sizeof(cfg_table)/sizeof(cfg_table[0])); index++){

        const u8* data = cfg_table[index].data;
        u16 addr = mXT224_get_obj_addr(cfg_table[index].type, ts_data.obj.table_info,
                                                              ts_data.obj.table_size);
        rc = mxt224_i2c_write(ts_data.client, addr, data, cfg_table[index].size);
        if(rc){
            printk(KERN_INFO "%s: Load mXT224 config failed, addr: 0x%x!\n", __func__, addr);
        }
    }
   
    addr = mXT224_get_obj_addr(6, ts_data.obj.table_info, ts_data.obj.table_size);
   
    //buf[0] = 0x05;
    buf[1] = 0x55;
   
    rc = mxt224_i2c_write(ts_data.client, addr, buf, 6);
   
    if(rc){
        printk(KERN_INFO "%s: Back up NV failed!\n", __func__);
    }
   
    /* Reset mXT224 */
    msleep(5);
   
    gpio_set_value(ts_data.reset_gpio, 0);
    msleep(1);
   
    gpio_set_value(ts_data.reset_gpio, 1);
    msleep(50);
   
}


#define MXT224_LCD_X    240
#define MXT224_LCD_Y    370
#define MXT224_TOUCH_X  930
#define MXT224_TOUCH_Y  1530

#define DETECT_MASK     (0x01<<7)
#define RELEASE_MASK    (0x01<<5)
#define MOVE_MASK       (0x01<<4)

#ifndef FEATURE_CFG_DUMP

 

static void mXT224_report_abs_key(u32 abs_x, u32 abs_y, u8 status)
{
    u32 x, y;

    x = (abs_x*MXT224_LCD_X)/MXT224_TOUCH_X;
    y = (abs_y*MXT224_LCD_Y)/MXT224_TOUCH_Y;
   
    //printk(KERN_INFO "%s: X[%d], Y[%d], Raw data: x[%d], y[%d]\n", __func__, x, y, abs_x, abs_y);
   
    if(y>320)
    {
        int index;
       
        for(index=0; index<(sizeof(key_info)/sizeof(key_info[0])); index++)
          {
            if(x>key_info[index].start && x              {
                input_report_key(ts_data.input_dev, key_info[index].code, (status&DETECT_MASK));
                break;
              }
          }
    }

    else
    {
        input_report_abs(ts_data.input_dev, ABS_X, x);
        input_report_abs(ts_data.input_dev, ABS_Y, y);
        input_report_abs(ts_data.input_dev, ABS_PRESSURE, (status&DETECT_MASK));
        input_report_key(ts_data.input_dev, BTN_TOUCH, (status&DETECT_MASK));
    }

   
    input_sync(ts_data.input_dev);
   
}

#endif
static u32 cfg_crc;


static int mXT224_process_msg(u8 id, u8 *msg)
{

#ifndef FEATURE_CFG_DUMP
    switch(id){
        case MSG_T6:
        {
            u32 checksum = ((union msg_body*)msg)->t6.checksum;
           
            u8  status = ((union msg_body*)msg)->t6.status;
           
            if(status & CFGERR_MASK){
                //printk(KERN_INFO "%s: Process mXT224 cfg error!\n", __func__);
                mXT224_load_cfg();
            }
           
            if(checksum!=cfg_crc){
               // printk(KERN_INFO "%s: Process mXT224 cfg CRC error!\n", __func__);
                //printk(KERN_INFO "%s: Read CRC:[0x%x], Our CRC:[0x%x]\n", __func__, checksum, cfg_crc);
                mXT224_load_cfg();
            }
           
            break;
        }
       
        case MSG_T9_FIRST_1:
         
        case MSG_T9_FIRST_2:
         
        case MSG_T9_FIRST_3:
        {
            u32 x, y;
            x = ((union msg_body*)msg)->t9.x_msb;
            x <<= 4;
            x |= (((union msg_body*)msg)->t9.xy_poslisb>>4);

            y = ((union msg_body*)msg)->t9.y_msb;
            y <<= 4;
            ((union msg_body*)msg)->t9.xy_poslisb &= 0x0f;
           
            y |= ((union msg_body*)msg)->t9.xy_poslisb;
           
            //printk(KERN_INFO "%s: X[%d], Y[%d]\n", __func__, x, y);
           
            mXT224_report_abs_key(x, y, ((union msg_body*)msg)->t9.status);
           
            break;
        }

       
        case MSG_T9_SECOND:
        {
            u32 y;
            y = ((union msg_body*)msg)->t9.y_msb;
            y <<= 4;
           
            ((union msg_body*)msg)->t9.xy_poslisb &= 0x0f;
           
            y |= ((union msg_body*)msg)->t9.xy_poslisb;

            y = (y*30)/432;
           
            printk(KERN_INFO "%s: Rel Y[%d]\n", __func__, y);
           
            input_report_rel(ts_data.input_dev, REL_Y, y);
           
            input_sync(ts_data.input_dev);
           
            break;
        }


        default:
            printk(KERN_INFO "%s: Default id[0x%x]\n", __func__, id);
           
            break;
    }
   
#endif
    return 0;
}

 

static void mXT224_work_func(struct work_struct *work)
{
    u8 type;
    //printk(KERN_INFO "%s\n", __func__);
   
    if(gpio_get_value(ts_data.int_gpio)){
        printk(KERN_INFO "%s:Error GPIO value is high\n", __func__);
        return;
    }
   
    mxt224_i2c_read(ts_data.client, ts_data.obj.msg_t5_addr,
                        (u8*)&msg_t5, sizeof(struct message_t5));
   
    //mxt224_mem_dbg((u8*)&msg_t5, sizeof(struct message_t5));
   
    type = mXT224_get_obj_type(msg_t5.report_id, id_table, ts_data.obj.table_size);
   
    if(type == 0){
        printk(KERN_INFO "%s: Get object type failed!, report id[0x%x]\n", __func__, msg_t5.report_id);
        return;
    }
   
    mXT224_process_msg(type, (u8*)&msg_t5.body);
}

 

static void mXT224_vreg_config(void)
{
    struct vreg *vreg_gp5;
    int rc;

    vreg_gp5 = vreg_get(NULL, "gp5");
    if (IS_ERR(vreg_gp5)) {
        printk(KERN_ERR "%s: vreg_get(%s) failed (%ld)\n", __func__, "gp5", PTR_ERR(vreg_gp5));
        return;
    }

    rc = vreg_set_level(vreg_gp5, 2700);
    if (rc) {
        printk(KERN_ERR "%s: vreg gp5 set level failed (%d)\n", __func__, rc);
    }

    rc = vreg_enable(vreg_gp5);
   
    if (rc) {
        printk(KERN_ERR "%s: vreg enable failed (%d)\n", __func__, rc);
    }
   
}


static int mXT224_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int     rc;
    int     index;
    int     info_size;
    u32     crc;


    //int     index;
    ///* store the value */
    i2c_set_clientdata(client, &ts_data);
    ts_data.client = client;
    client->driver = &mXT224_driver;  

    /* Init timer */
    hrtimer_init(&ts_data.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    ts_data.timer.function = mXT224_timer;


   
    /* Try get GPIO */
    rc = gpio_request(ts_data.int_gpio, "Touch_int");
   
    if(rc)
    {
        printk(KERN_INFO "%s: Request GPIO failed!\n", __func__);
        goto failed;
    }
   
    gpio_tlmm_config(GPIO_CFG(ts_data.int_gpio,0,GPIO_INPUT,GPIO_NO_PULL,GPIO_2MA), GPIO_ENABLE);
   
    rc = gpio_request(ts_data.reset_gpio, "Touch_reset");
   
    if(rc)
    {
        printk(KERN_INFO "%s: Request mXT224 reset GPIO failed!\n", __func__);
        goto failed;
    }
   
    gpio_tlmm_config(GPIO_CFG(ts_data.reset_gpio,0,GPIO_OUTPUT,GPIO_NO_PULL,GPIO_2MA),GPIO_ENABLE);


    /* Config vreg */
    mXT224_vreg_config();


   
    /* Reset mXT224 */
    gpio_set_value(ts_data.reset_gpio, 0);
    msleep(1);
    gpio_set_value(ts_data.reset_gpio, 1);
    msleep(50);

 

    /* Try get mXT224 table size */
    rc = mxt224_i2c_read(client, TABLE_SIZE_ADDR, &ts_data.obj.table_size, 1);
   
    if(rc)
    {
        printk(KERN_INFO "%s: Get table size failed!\n", __func__);
        goto failed;
    }


   
    /* Try get mXT224 device info */
    info_size = CRC_SIZE+ID_INFORMATION_SIZE+ts_data.obj.table_size*OBJECT_TABLE_ELEMENT_SIZE;
   
    ts_data.obj.table_info_byte = (u8*)kzalloc(info_size, GFP_KERNEL);
   
    if(!ts_data.obj.table_info_byte)
    {
        printk(KERN_INFO "%s: Can't get memory!\n", __func__);
        rc = -1;
        goto failed;
    }
   
    rc = mxt224_i2c_read(client, 0, ts_data.obj.table_info_byte, info_size);
   
    if(rc)
    {
        printk(KERN_INFO "%s: Get mXT224 info failed!\n", __func__);
        goto get_info_failed;
    }
   
    ts_data.obj.table_info = (struct mxt224_table_info*)(ts_data.obj.table_info_byte+ID_INFORMATION_SIZE);
    //mxt224_mem_dbg(ts_data.obj.table_info_byte, info_size);

 


    /* Try get and check CRC */
    ts_data.obj.info_crc = (ts_data.obj.table_info_byte[info_size-3])|
                           (ts_data.obj.table_info_byte[info_size-2]<<8)|
                           (ts_data.obj.table_info_byte[info_size-1]<<16);
    crc = get_crc24(ts_data.obj.table_info_byte, info_size-CRC_SIZE);
   
    if(ts_data.obj.info_crc != crc)
    {
        //1 TODO: Need set config table
       
        printk(KERN_INFO "%s:CRC failed, read CRC:[0x%x], get CRC:[0x%x]\n", __func__, ts_data.obj.info_crc, crc);
       
        mXT224_load_cfg();
    }

 

    /* Build cfg CRC */
    cfg_crc = mXT224_cfg_crc();

 

    /* Build report id table */
    mXT224_build_report_id_table(ts_data.obj.table_info, ts_data.obj.table_size);

 

    /* Dump mXT224 config setting */
    #ifdef FEATURE_CFG_DUMP
   
    printk(KERN_INFO "%s: Config size: %d\n", __func__, total_size);
   
    cfg_dmup = (u8*)kzalloc(info_size+total_size, GFP_KERNEL);
   
    if(!cfg_dmup)
    {
        printk(KERN_INFO "%s: Cannot get memory!\n", __func__);
        goto failed;
    }
   
    mxt224_i2c_read(client, 0, cfg_dmup, info_size+total_size);
    mxt224_mem_dbg(cfg_dmup, info_size+total_size);
    #endif

 

    /* Try get message T5 info */
    if(gpio_get_value(ts_data.int_gpio))
    {
        //1 TODO: Need check touch interrput pin
       
        printk(KERN_INFO "%s: GPIO status error!\n", __func__);
       
        rc = -1;
        goto failed;
    }

    ts_data.obj.msg_t5_addr = mXT224_get_obj_addr(0x5, ts_data.obj.table_info, ts_data.obj.table_size);
   
    rc = mxt224_i2c_read(client, ts_data.obj.msg_t5_addr, (u8*)&msg_t5, sizeof(struct message_t5));
   
    if(rc)
    {
        printk(KERN_INFO "%s:Can't get message T5!\n", __func__);
        goto failed;
    }
   
    mxt224_mem_dbg((u8*)&msg_t5, sizeof(struct message_t5));
    mXT224_process_msg(mXT224_get_obj_type(msg_t5.report_id, id_table, ts_data.obj.table_size), (u8*)&msg_t5.body);
   
    //printk(KERN_INFO "%s:Find obj report: 0x%x\n", __func__,
    //            mXT224_get_obj_type(msg_t5.report_id, id_table, obj_table_size));
    msleep(15);
   
    if(gpio_get_value(ts_data.int_gpio))
    {
        printk(KERN_INFO "%s: GPIO value is high\n", __func__);
    }
   

    ts_data.input_dev = input_allocate_device();
    if (!ts_data.input_dev)
    {
        rc = -ENOMEM;
        goto failed;
    }
   
    input_set_drvdata(ts_data.input_dev, &ts_data);

    ts_data.input_dev->name = "mXT224_touch";
    ts_data.input_dev->id.bustype = BUS_I2C;

    
    set_bit(EV_SYN, ts_data.input_dev->evbit);
    set_bit(EV_KEY, ts_data.input_dev->evbit);
    set_bit(BTN_TOUCH, ts_data.input_dev->keybit);
    set_bit(BTN_2, ts_data.input_dev->keybit);
    set_bit(EV_ABS, ts_data.input_dev->evbit);
   
    input_set_abs_params(ts_data.input_dev, ABS_X, 0, 240, 0, 0);
    input_set_abs_params(ts_data.input_dev, ABS_Y, 0, 320, 0, 0);
   
    for(index=0; index<(sizeof(key_info)/sizeof(key_info[0])); index++)
     {
        input_set_capability(ts_data.input_dev, EV_KEY, key_info[index].code);
    }
    
    rc = input_register_device(ts_data.input_dev);
   
    if (rc)
    {
        dev_err(&client->dev, "mXT224: input_register_device rc=%d\n", rc);
        goto failed;
    }
   
    #ifndef FEATURE_CFG_DUMP
    rc = request_irq(MSM_GPIO_TO_INT(ts_data.int_gpio), mXT224_ts_interrupt,
                     IRQF_TRIGGER_FALLING, "mXT224_touch", &ts_data);
    #endif
   
    if(rc)
    {
        printk(KERN_INFO "mXT224 request interrput failed!\n");
    }

    return 0;

get_info_failed:
    /* Free mXT224 info */
failed:
    return rc;
}



static int __init mXT_init(void)
{
 return i2c_add_driver(&mXT224_driver);
}

static void __exit mXT_exit(void)
{
 i2c_del_driver(&mXT224_driver);
}


module_init(mXT_init);
module_exit(mXT_exit);

举报
parry
发帖于7年前 5回/5K+阅
顶部