ckfwq/linux-3.0.4/drivers/input/touchscreen/gsc3280_ns2009.c

420 lines
10 KiB
C
Raw Normal View History

2024-12-30 10:53:50 +08:00
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/pm_runtime.h>
#include <linux/input/mt.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/async.h>
#include <linux/hrtimer.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/ioport.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <gsc3280/gpio.h>
#include <gsc3280/sysctl.h>
#include <asm/io.h>
#include <linux/i2c.h>
#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<<gsc3280_gpio[0].gpio);\
__raw_writel(reg_val, (volatile unsigned int *)(reg));\
}while(0)
#define gsc3280_clr_gpio_reg_bit(reg) do{\
unsigned int reg_val = 0; \
reg_val = __raw_readl((volatile unsigned int *)(reg));\
reg_val &= ~(0x1<<gsc3280_gpio[0].gpio);\
__raw_writel(reg_val, (volatile unsigned int *)(reg));\
}while(0)
enum finger_state {
FLAG_UP = 0,
FLAG_DOWN = 1,
FLAG_INVALID = 2,
};
struct ns2009_event {
int touch_point;
u16 x1[5];
u16 y1[5];
u16 id;
enum finger_state state;
unsigned int x;
unsigned int y;
unsigned int pressure;
};
struct ns2009_data{
struct input_dev *input_dev;
struct ns2009_event *event;
struct work_struct work;
struct workqueue_struct *queue;
struct timer_list touch_timer;
struct timer_list charge_detect;
int irq;
int (*power)(struct ns2009_data * ts, int on);
};
u32 x_old;
u32 y_old;
u32 flag;
struct ns2009_data *ns2009_dev;
struct i2c_client *i2cdev;
static unsigned int int_handle = 0;
int ns2009_i2c_write_bytes(struct i2c_client *client, uint8_t *reg, uint16_t len)
{
return i2c_master_send(client, reg, len);
}
int ns2009_i2c_read_bytes(struct i2c_client *client, uint8_t *data, uint16_t len)
{
return i2c_master_recv(client, data, len);
}
static void gsc3280_report_event(struct ns2009_data *dev, u16 x, u16 y , u16 z)
{
input_report_abs(dev->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);
//<2F><><EFBFBD>ж<EFBFBD>
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); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//y = ((4080-y)*800)/(4080-32);
y = ((y-32)*800)/(4080-32); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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");
/*<2A><><EFBFBD>鵱ǰ<E9B5B1><C7B0><EFBFBD><EFBFBD>֧<EFBFBD>ֵĴ<D6B5><C4B4>ʽ*/
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
/*<2A><>ʱ<EFBFBD><CAB1> */
//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");