#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USING_IRQ 1 #ifdef CONFIG_NS2009_DEBUG #define dbg(msg...) printk(KERN_INFO msg) #else #define dbg(msg...) do{}while(0) #endif struct gpio gsc3280_gpio[1] = { {GSC3280_GPA(5), GPIOF_IN, "TP_IRQ"}, }; #define gsc3280_set_gpio_reg_bit(reg) do{\ unsigned int reg_val = 0; \ reg_val = __raw_readl((volatile unsigned int *)(reg));\ reg_val |= (0x1<input_dev,ABS_X,y); input_report_abs(dev->input_dev,ABS_Y,x); input_report_abs(dev->input_dev,ABS_PRESSURE,z); dbg("x = %d , y = %d , z = %d\n",x,y,z); if(z > 0) input_report_key(dev->input_dev,BTN_TOUCH,1); else input_report_key(dev->input_dev,BTN_TOUCH,0); input_sync(dev->input_dev); } static void gpio_int_enable(void) { gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_INTEN); gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_INTTYPE_LEVEL); gsc3280_clr_gpio_reg_bit(GSC3280_REGADDR_GPIO_INT_POLARITY); gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_DEBOUNCE); gsc3280_clr_gpio_reg_bit(GSC3280_REGADDR_GPIO_INTMASK); gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_PORTA_EOI); } static void gpio_int_disable(void) { gsc3280_clr_gpio_reg_bit(GSC3280_REGADDR_GPIO_INTEN); gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_INTMASK); } static irqreturn_t ns2009_interrupt_handle(int irq, void *dev_id) { dbg("ns2009 irq happen\n"); gpio_int_disable(); gsc3280_set_gpio_reg_bit(GSC3280_REGADDR_GPIO_PORTA_EOI); flush_workqueue(ns2009_dev->queue); schedule_work(&ns2009_dev->work); //清中断 return IRQ_HANDLED; } static int report_func(struct ns2009_data *work) { int i = 0; struct ns2009_event *event = ns2009_dev->event; //int buf0[2] = {0}; u16 buf1[2] = {0xC0}; //X 12ADC u16 buf2[2] = {0xD0}; //Y 12ADC u16 buf3[2] = {0xE0}; //Z1 u16 buf_z1[2] = {0}; u16 buf_x[2] = {0}; u16 buf_y[2] = {0}; u16 x = 0; u16 y = 0; u16 z = 0; u16 x_old = 0; u16 y_old = 0; u16 x_avrg = 0; u16 y_avrg = 0; unsigned int value; down: ns2009_i2c_write_bytes(i2cdev,buf3,1); ns2009_i2c_read_bytes(i2cdev,buf_z1,2); z =(buf_z1[0]<<4) | (buf_z1[1]>>4); for(i=0;i<10;i++) { ns2009_i2c_write_bytes(i2cdev,buf1,1); ns2009_i2c_read_bytes(i2cdev,buf_x,2); x =(buf_x[0]<<4) | (buf_x[1]>>4); ns2009_i2c_write_bytes(i2cdev,buf2,1); ns2009_i2c_read_bytes(i2cdev,buf_y,2); y = (buf_y[0]<<4) | (buf_y[1]>>4); if(x < 144) x=144; if(x > 3956) x=3956; if(y < 32) y=32; if(y > 4080) y=4080; x = ((3956-x)*480)/(3956-144); //这个计算出的是y值 //y = ((4080-y)*800)/(4080-32); y = ((y-32)*800)/(4080-32); //这个计算出的是x值 x_avrg += x; y_avrg += y; } x = x_avrg/10; y = y_avrg/10; x_avrg = 0; y_avrg = 0; value = *(volatile unsigned int *)0xbc110050; if(value&(1<<5)) { goto up; } else { gsc3280_report_event(ns2009_dev,x,y,z); x_old = x; y_old = y; goto down; } up: gsc3280_report_event(ns2009_dev,x_old,y_old,0); //dbg("-----------GPIO_EXT_PORTA = 0x%x-----------\n",*(volatile unsigned int *)0xbc110050); /* if(buf_z1[0]<1) { input_report_abs(ns2009_dev->input_dev,ABS_X,x_old); input_report_abs(ns2009_dev->input_dev,ABS_Y,y_old); input_report_key(ns2009_dev->input_dev,BTN_TOUCH,0); input_sync(ns2009_dev->input_dev); gpio_int_enable(); return 0; } else { ns2009_i2c_write_bytes(i2cdev,buf1,1); ns2009_i2c_read_bytes(i2cdev,buf_x,2); // dbg("buf_x[0] = 0x%x,buf_x[1] = 0x%x\n",buf_x[0],buf_x[1]); buf_x[0] =(buf_x[0]<<4) | (buf_x[1]>>4); if(buf_x[0] == 0) { gpio_int_enable(); return 0; } ns2009_i2c_write_bytes(i2cdev,buf2,1); ns2009_i2c_read_bytes(i2cdev,buf_y,2); //dbg("buf_y[0] = 0x%x,buf_y[1] = 0x%x\n",buf_y[0],buf_y[1]); buf_y[0] = (buf_y[0]<<4) | (buf_y[1]>>4); dbg("buf_x = %d, buf_y= %d\n",buf_x[0],buf_y[0]); } */ gpio_int_enable(); } static int ns2009_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; dbg("ns2009 probe .........\n"); /*检查当前总线支持的传输方式*/ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { err = -ENODEV; return -1; } i2cdev = client; i2cdev->addr = client->addr; ns2009_dev = kzalloc(sizeof(*ns2009_dev),GFP_KERNEL); dbg(".......GPIO_EXT_PORTA = 0x%x\n",*(volatile unsigned int *)0xbc110050); if(!ns2009_dev) { err = -ENOMEM; return -1; } i2c_set_clientdata(i2cdev,ns2009_dev); ns2009_dev->queue = create_singlethread_workqueue("TS"); if(!ns2009_dev->queue) { printk(KERN_INFO"creat_single_thread failed\n"); err = -ESRCH; goto exit_create_singlethread; } INIT_WORK(&ns2009_dev->work,(void *)report_func); ns2009_dev->input_dev = input_allocate_device(); if(!ns2009_dev->input_dev) { err = -ENOMEM; printk(KERN_INFO"ns2009 alloc input dev fail\n"); goto alloc_input_dev; } ns2009_dev->input_dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS)| BIT(ABS_PRESSURE); set_bit(BTN_TOUCH, ns2009_dev->input_dev->keybit); input_set_abs_params(ns2009_dev->input_dev, ABS_X, 0, 800, 0, 0); input_set_abs_params(ns2009_dev->input_dev, ABS_Y, 0, 480, 0, 0); input_set_abs_params(ns2009_dev->input_dev, ABS_PRESSURE, 0, 255, 0, 0); input_set_abs_params(ns2009_dev->input_dev, ABS_MT_TOUCH_MAJOR, 0, 50, 0, 0); ns2009_dev->input_dev->name = "ns2009"; ns2009_dev->input_dev->phys = "input/ns2009"; ns2009_dev->input_dev->id.bustype = BUS_HOST ; ns2009_dev->input_dev->id.vendor = 0x0001; ns2009_dev->input_dev->id.product = 0x0001; ns2009_dev->input_dev->id.version = 0x0100; err = input_register_device(ns2009_dev->input_dev); if(err){ printk(KERN_INFO"......failed to register input device ns2009\n"); goto input_register_device_failed; } dbg("-------register input_device ok!----------\n"); #ifdef USING_IRQ /*get gpio irq number */ dbg("-------ns2009 use irq--------------\n"); gpio_int_enable(); i2cdev->irq = gpio_to_irq(5); dbg("-------TP_IRQ = %d\n",i2cdev->irq); /*request virq,set virq type to high level trigger*/ int_handle = request_irq(i2cdev->irq, ns2009_interrupt_handle,IRQF_SHARED,"gsc3280-ns2009",ns2009_dev); if(IS_ERR_VALUE(int_handle)){ printk(KERN_INFO"request irq faild int ns2009\n"); return -EINVAL; } pr_info("int_handle=%d, apply for irq succeed!\n" ,int_handle); #else /*定时器 */ //setup_timer(&mytimer, timer_work, (unsigned long)"Timer_Out!"); //mytimer.expires = jiffies + HZ/10; //add_timer(&mytimer); #endif return 0; input_register_device_failed: input_free_device(ns2009_dev->input_dev); alloc_input_dev: exit_create_singlethread: // i2c_set_clientdata(ns2009_dev, NULL); kfree(ns2009_dev); return err; } static const struct i2c_device_id ns2009_id[] = { { "ns2009", 0 }, {} }; static int __devexit ns2009_ts_remove(struct i2c_client *client){ /* pr_info("====ns2009_ts_remove====\n"); //rtp_disable_irq(this_client->irq); //free_irq(this_client->irq, &RTP_NAME); del_timer(&mytimer); cancel_work_sync(&ts_work->work); destroy_workqueue(ts_work->queue); i2c_set_clientdata(this_client, NULL); input_unregister_device(ts_work->input_dev); kfree(ts_work->input_dev); */ return 0; } static struct i2c_driver ns2009_driver = { .probe = ns2009_probe, .remove = __devexit_p(ns2009_ts_remove), .id_table = ns2009_id, .driver = { .name = "ns2009", .owner = THIS_MODULE, }, .address_list = NULL, .detect = NULL, .suspend = NULL, .resume = NULL, }; static int __init ns2009_init(void) { int ret = -1; ret =i2c_add_driver(&ns2009_driver); if(ret < 0) printk(KERN_INFO"add ns2009 driver fail......\n"); return ret; } static int __exit ns2009_exit(void) { printk(KERN_INFO"ns2009 driver exit...\n"); i2c_del_driver(&ns2009_driver); return 0; } module_init(ns2009_init); module_init(ns2009_exit); MODULE_AUTHOR("linshangsheng@163.com"); MODULE_DESCRIPTION("TOUCH SCREEN DRIVER"); MODULE_LICENSE("GPL");