From 5e8c7c54a9b297dae0081dd19a7bb94e23040a3d Mon Sep 17 00:00:00 2001 From: Joshua Lock Date: Tue, 18 May 2010 14:51:13 +0100 Subject: linux-moblin: add 2.6.33.2 kernel from MeeGo 1.0 Signed-off-by: Joshua Lock --- .../linux-2.6.34-cypress-touch-driver.patch | 870 +++++++++++++++++++++ 1 file changed, 870 insertions(+) create mode 100644 meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch') diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch new file mode 100644 index 000000000..2dae9ed82 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch @@ -0,0 +1,870 @@ +From 03e11a278286392dc20de57a24cadbc16d9aac3a Mon Sep 17 00:00:00 2001 +From: Priya Vijayan +Date: Tue, 27 Apr 2010 11:23:00 -0700 +Subject: [PATCH] Touchscreen driver for Cypress panels + +This driver is from aava + +Signed-off-by: Priya Vijayan +--- + drivers/input/touchscreen/Kconfig | 8 + + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/cy8ctmg110_ts.c | 815 +++++++++++++++++++++++++++++ + 3 files changed, 824 insertions(+), 0 deletions(-) + create mode 100644 drivers/input/touchscreen/cy8ctmg110_ts.c + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 6dd2674..5ecf00d 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -103,6 +103,14 @@ config TOUCHSCREEN_CORGI + NOTE: this driver is deprecated, try enable SPI and generic + ADS7846-based touchscreen driver. + ++config TOUCHSCREEN_CY8CTMG110 ++ tristate "cy8ctmg110 touchscreen" ++ depends on I2C ++ default y ++ help ++ Say Y here if you have a cy8ctmg110 touchscreen capasitive touchscreen ++ If unsure, say N. ++ + config TOUCHSCREEN_DA9034 + tristate "Touchscreen support for Dialog Semiconductor DA9034" + depends on PMIC_DA903X +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 15ad257..e5b5fae 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o + obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o + obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o + obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o ++obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o + obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o + obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o + obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o +diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c +new file mode 100644 +index 0000000..5587385 +--- /dev/null ++++ b/drivers/input/touchscreen/cy8ctmg110_ts.c +@@ -0,0 +1,815 @@ ++/* ++ * cy8ctmg110_ts.c Driver for cypress touch screen controller ++ * Copyright (c) 2009 Aava Mobile ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#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 CY8CTMG110_DRIVER_NAME "cy8ctmg110" ++#define CY8CTMG110_DRIVER_NAME_EXT "cy8ctmg110 ext" ++/*#define MOORESTOWN_CDK*/ ++/*#define CY8CTMG110_DEBUG_INFO*/ ++/*#define POLL_TOUCH_EVENTS*/ ++ ++ ++ ++/*HW definations*/ ++ ++/*Main touch specific*/ ++#define CY8CTMG110_I2C_ADDR 0x38 ++#define CY8CTMG110_RESET_PIN_GPIO 43 ++#define CY8CTMG110_IRQ_PIN_GPIO 59 ++ ++/*Extended specific*/ ++#define CY8CTMG110_I2C_ADDR_EXT 0x39 ++#define CY8CTMG110_RESET_PIN_GPIO_EXT 39 ++#define CY8CTMG110_IRQ_PIN_GPIO_EXT 31 ++ ++ ++#define CY8CTMG110_TOUCH_LENGHT 9787 ++#define CY8CTMG110_SCREEN_LENGHT 8424 ++ ++ ++/*Main Touch coordinates*/ ++#define CY8CTMG110_X_MIN 0 ++#define CY8CTMG110_Y_MIN 0 ++#define CY8CTMG110_X_MAX 864 ++#define CY8CTMG110_Y_MAX 480 ++ ++ ++/*cy8ctmg110 registers defination*/ ++#define CY8CTMG110_TOUCH_WAKEUP_TIME 0 ++#define CY8CTMG110_TOUCH_SLEEP_TIME 2 ++#define CY8CTMG110_TOUCH_X1 3 ++#define CY8CTMG110_TOUCH_Y1 5 ++#define CY8CTMG110_TOUCH_X2 7 ++#define CY8CTMG110_TOUCH_Y2 9 ++#define CY8CTMG110_FINGERS 11 ++#define CY8CTMG110_GESTURE 12 ++#define CY8CTMG110_VERSIONID 13 //not supported in touchpanel FW ++#define CY8CTMG110_REG_MAX 13 ++ ++#ifdef POLL_TOUCH_EVENTS ++ #define CY8CTMG110_POLL_TIMER_DELAY 1000*1000*100 ++ #define TOUCH_MAX_I2C_FAILS 50 ++#endif ++ ++#define CY8CTMG110_POLL_TIMER_DELAY 1000*1000*100 ++ ++/* Scale factors for coordinates */ ++#define X_SCALE_FACTOR 9387/8424 ++#define Y_SCALE_FACTOR 97/100 ++ ++/* For tracing */ ++static u16 g_y_trace_coord = 0; ++ ++/*if soutcanyon*/ ++static bool isSc = false; ++ ++ ++/* ++ * Touchtype ++ */ ++enum touch_type { ++ TOUCH_KOSKI=1, ++ TOUCH_SC, ++ TOUCH_EXT, ++}; ++ ++/* ++ * The touch position structure. ++ */ ++struct ts_event { ++ int x1; ++ int y1; ++ int x2; ++ int y2; ++ bool event_sended; ++}; ++ ++/* ++ * The touch driver structure. ++ */ ++struct cy8ctmg110 { ++ struct input_dev *input; ++ char phys[32]; ++ struct ts_event tc; ++ struct i2c_client *client; ++ bool pending; ++ spinlock_t lock; ++ bool initController; ++ bool sleepmode; ++ int irq_gpio; ++ int reset_gpio; ++ char driver_name[20]; ++ struct delayed_work work; ++ enum touch_type version_id; ++#ifdef POLL_TOUCH_EVENTS ++ struct hrtimer timer; ++ int i2c_fail_count; ++#endif ++}; ++ ++/* ++ * cy8ctmg110_poweroff is the routine that is called when touch hardware ++ * will powered off ++ */ ++static void cy8ctmg110_power(struct cy8ctmg110 *ts,bool poweron) ++{ ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("%s power:%d\n",ts->driver_name,poweron); ++#endif ++ if (poweron) ++ gpio_direction_output(ts->reset_gpio, 0); ++ else ++ gpio_direction_output(ts->reset_gpio, 1); ++} ++/* ++ * cy8ctmg110_write_req write regs to the i2c devices ++ * ++ */ ++static int cy8ctmg110_write_req(struct cy8ctmg110 *tsc,unsigned char reg,unsigned char len,unsigned char *value) ++{ ++ struct i2c_client *client = tsc->client; ++ unsigned int ret; ++ unsigned char i2c_data[]={0,0,0,0,0,0}; ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_init_req:\n"); ++#endif ++ ++ i2c_data[0]=reg; ++ memcpy(i2c_data+1,value,len); ++ ++ { ++ struct i2c_msg msg[] = { ++ { client->addr, 0, len+1, i2c_data }, ++ }; ++ ++ ret = i2c_transfer(client->adapter, msg, 1); ++ ++ if (ret != 1) { ++ printk("cy8ctmg110 touch : i2c write data cmd failed \n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++/* ++ * get_time ++ * ++ */ ++#ifdef CY8CTMG110_DEBUG_INFO ++static inline long cy8ctmg110_get_time(void) ++{ ++ struct timeval t; ++ do_gettimeofday(&t); ++ return t.tv_usec; ++} ++#endif ++/* ++ * cy8ctmg110_read_req read regs from i2c devise ++ * ++ */ ++static int cy8ctmg110_read_req(struct cy8ctmg110 *tsc,unsigned char *i2c_data,unsigned char len ,unsigned char cmd) ++{ ++ struct i2c_client *client = tsc->client; ++ unsigned int ret; ++ unsigned char regs_cmd[2]={0,0}; ++#ifdef CY8CTMG110_DEBUG_INFO ++ long starttime = cy8ctmg110_get_time(); ++#endif ++ regs_cmd[0]=cmd; ++ ++ ++ /* first write slave position to i2c devices*/ ++ { ++ struct i2c_msg msg1[] = { ++ { client->addr, 0, 1, regs_cmd }, ++ }; ++ ++ ret = i2c_transfer(client->adapter, msg1, 1); ++ ++ if (ret != 1) { ++#ifdef POLL_TOUCH_EVENTS ++ tsc->i2c_fail_count++; ++#endif ++ return ret; ++ } ++ } ++ ++ ++ /* Second read data from position*/ ++ { ++ struct i2c_msg msg2[] = { ++ { client->addr, I2C_M_RD, len, i2c_data }, ++ }; ++ ++ ret = i2c_transfer(client->adapter, msg2, 1); ++ ++ ++ if (ret != 1) { ++#ifdef POLL_TOUCH_EVENTS ++ tsc->i2c_fail_count++; ++#endif ++ return ret; ++ } ++ } ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("%s time to get data bytes read:%d time:%d\n",tsc->driver_name,len,(cy8ctmg110_get_time()-starttime)); ++#endif ++ return 0; ++} ++/* ++ * cy8ctmg110_send_event delevery touch event to the userpace ++ * function use normal input interface ++ */ ++static void cy8ctmg110_send_event(void *tsc,int x,int y) ++{ ++ struct cy8ctmg110 *ts = tsc; ++ struct input_dev *input = ts->input; ++ u16 x2, y2; ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_send_event\n"); ++#endif ++ ++ if(ts->tc.event_sended == false){ ++ ++ if (ts->client->addr==CY8CTMG110_I2C_ADDR_EXT){ ++ /*Extended touchpanel*/ ++ input_report_key(input, BTN_TOUCH, 1); ++ ++ ++ if ( ts->pending == true){ ++ input_report_rel(input, REL_Y, (ts->tc.x1-x)*2); ++ input_report_rel(input, REL_X, (y - ts->tc.y1)*3); ++ ts->tc.y1 = y; ++ ts->tc.x1 = x; ++ } ++ else{ ++ ts->pending = true; ++ ts->tc.y1 = y; ++ ts->tc.x1 = x; ++ } ++ ++ ++ } ++ else{ ++ /*Main touchpanel*/ ++ ts->tc.y1 = y; ++ ts->tc.x1 = x; ++ ts->pending = true; ++ input_report_key(input, BTN_TOUCH, 1); ++ ++ x2 = y; ++ y2 = x; ++ ++ if (isSc == false){ ++ /*Main touchpanel in koski*/ ++ x2 = (u16)(y*X_SCALE_FACTOR); ++ y2 = (u16)(x*Y_SCALE_FACTOR); ++ } ++ ++ input_report_abs(input, ABS_X, x2); ++ input_report_abs(input, ABS_Y, y2); ++ } ++ ++ input_sync(input); ++ if(g_y_trace_coord) ++ printk("%s touch position X:%d (was = %d) Y:%d (was = %d)\n",ts->driver_name, x2, y, y2, x); ++ } ++ ++} ++ ++/* ++ * cy8ctmg110_touch_pos check touch position from i2c devices ++ * ++ */ ++static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) ++{ ++ unsigned char reg_p[CY8CTMG110_REG_MAX]; ++ ++ memset(reg_p,0,CY8CTMG110_REG_MAX); ++ ++ /*Reading coordinates*/ ++ if (cy8ctmg110_read_req(tsc,reg_p,1,CY8CTMG110_FINGERS)==0){ ++ ++ /*number of touch*/ ++ if (reg_p[0]==0){ ++ if (tsc->pending == true){ ++ struct input_dev *input = tsc->input; ++ ++ input_report_key(input, BTN_TOUCH, 0); ++ ++ input_sync(input); ++ tsc->tc.event_sended = true; ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_send_event ts->pending = true;\n"); ++#endif ++ tsc->pending = false; ++ } ++ } ++ else { ++ ++ if (cy8ctmg110_read_req(tsc,reg_p,4,CY8CTMG110_TOUCH_X1)==0){ ++ int x = 0,y = 0; ++ y = reg_p[2]<<8 | reg_p[3]; ++ x = reg_p[0]<<8 | reg_p[1]; ++ ++ if (tsc->tc.x1 != x || tsc->tc.y1 != y){ ++ tsc->tc.event_sended = false; ++ cy8ctmg110_send_event(tsc,x,y); ++ } ++ } ++ } ++ } ++ else{ ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110 i2c reading error\n"); ++#endif ++ } ++ ++ return 0; ++} ++/* ++ * cy8ctmg110_read_versionid delevery touch event to the userpace ++ * function use normal input interface ++ */ ++static void cy8ctmg110_read_versionid(void *tsc) ++{ ++ struct cy8ctmg110 *ts = tsc; ++ unsigned char reg_p[2]; ++ ++ ++ if (cy8ctmg110_read_req(ts,reg_p,1,CY8CTMG110_VERSIONID)==0){ ++ printk("%s id 0x%x\n",ts->driver_name,reg_p[0]); ++ ++ /*Ugly hack solution if SC ++ */ ++ ++ if(ts->client->addr==CY8CTMG110_I2C_ADDR_EXT) ++ isSc = true; ++ ++ switch (reg_p[0]){ ++ case 0x01: ++ ts->version_id = TOUCH_EXT; ++ break; ++ case 0x02: ++ ts->version_id = TOUCH_SC; ++ break; ++ case 0x03: ++ ts->version_id = TOUCH_KOSKI; ++ break; ++ default: ++ ts->version_id = TOUCH_KOSKI; ++ break; ++ } ++ } ++} ++ ++ ++#ifdef POLL_TOUCH_EVENTS ++/* ++ * if interup is'n in use the touch positions can reads by polling ++ * ++ */ ++static enum hrtimer_restart cy8ctmg110_timer(struct hrtimer *handle) ++{ ++ struct cy8ctmg110 *ts = container_of(handle, struct cy8ctmg110, timer); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ts->lock, flags); ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_timer\n"); ++#endif ++ ++ cy8ctmg110_touch_pos(ts); ++ ++ if (ts->i2c_fail_counttimer, ktime_set(0, CY8CTMG110_POLL_TIMER_DELAY), ++ HRTIMER_MODE_REL); ++ ++ spin_unlock_irqrestore(&ts->lock, flags); ++ ++ return HRTIMER_NORESTART; ++} ++#endif ++/* ++ * cy8ctmg110_init_controller set init value to touchcontroller ++ * ++ */ ++static bool cy8ctmg110_set_sleepmode(struct cy8ctmg110 *ts) ++{ ++ unsigned char reg_p[3]; ++ ++ if(ts->sleepmode==true){ ++ reg_p[0] = 0x00; reg_p[1] =0xff; reg_p[2] =5; ++ }else{ ++ reg_p[0] = 0x10;reg_p[1] =0xff;reg_p[2] =0; ++ } ++ ++ if (cy8ctmg110_write_req(ts,CY8CTMG110_TOUCH_WAKEUP_TIME,3,reg_p)){ ++ return false; ++ } ++ ts->initController = true; ++ ++ return true; ++} ++ ++ ++ ++static void cy8ctmg110_work(struct work_struct *work) ++{ ++ struct cy8ctmg110 *ts = ++ container_of(to_delayed_work(work), struct cy8ctmg110, work); ++ ++ cy8ctmg110_touch_pos(ts); ++} ++ ++ ++/* ++ * cy8ctmg110_irq_handler irq handling function ++ * ++ */ ++static irqreturn_t cy8ctmg110_irq_handler(int irq, void *handle) ++{ ++ struct cy8ctmg110 * tsc = (struct cy8ctmg110 *)handle; ++ ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("%s cy8ctmg110_irq_handler\n",tsc->driver_name); ++#endif ++ if (tsc->initController == false){ ++ if (cy8ctmg110_set_sleepmode(tsc) == true) ++ tsc->initController = true; ++ } ++ else ++ { ++ schedule_delayed_work(&tsc->work, ++ msecs_to_jiffies(1)); ++ } ++ ++#ifdef POLL_TOUCH_EVENTS ++ /*if interrupt supported in the touch controller ++ timer polling need to stop*/ ++ tsc->i2c_fail_count = TOUCH_MAX_I2C_FAILS; ++#endif ++ return IRQ_HANDLED; ++} ++ ++ ++static int cy8ctmg110_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct cy8ctmg110 *ts; ++ struct input_dev *input_dev; ++ int err; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) ++ return -EIO; ++ ++ ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL); ++ input_dev = input_allocate_device(); ++ ++ if (!ts || !input_dev) { ++ err = -ENOMEM; ++ goto err_free_mem; ++ } ++ ++ ts->client = client; ++ i2c_set_clientdata(client, ts); ++ ++ ts->input = input_dev; ++ ts->pending = false; ++ ts->sleepmode = false; ++ ++ ++ if(client->addr==CY8CTMG110_I2C_ADDR){ ++ ts->reset_gpio = CY8CTMG110_RESET_PIN_GPIO; ++ input_dev->name = CY8CTMG110_DRIVER_NAME" Touchscreen"; ++ snprintf(ts->driver_name, sizeof(ts->driver_name),"%s", CY8CTMG110_DRIVER_NAME); ++ } ++ else if (client->addr==CY8CTMG110_I2C_ADDR_EXT){ ++ ts->reset_gpio = CY8CTMG110_RESET_PIN_GPIO_EXT; ++ input_dev->name = CY8CTMG110_DRIVER_NAME_EXT" Touchscreen"; ++ snprintf(ts->driver_name, sizeof(ts->driver_name),"%s", CY8CTMG110_DRIVER_NAME_EXT); ++ } ++ ++ snprintf(ts->phys, sizeof(ts->phys), ++ "%s/input0", dev_name(&client->dev)); ++ ++ INIT_DELAYED_WORK(&ts->work, cy8ctmg110_work); ++ ++ input_dev->phys = ts->phys; ++ input_dev->id.bustype = BUS_I2C; ++ ++ spin_lock_init(&ts->lock); ++ ++ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | ++ BIT_MASK(EV_REL) | BIT_MASK(EV_ABS); ++ ++ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); ++ ++ input_set_capability(input_dev, EV_KEY, KEY_F); ++ ++ ++ input_set_abs_params(input_dev, ABS_X, CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 0, 0); ++ input_set_abs_params(input_dev, ABS_Y, CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0); ++ input_dev->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X)| BIT_MASK(REL_Y); ++ ++ err = gpio_request(ts->reset_gpio, NULL); ++ ++ if (err) { ++ printk("GPIO pin %d failed to request.\n", ts->reset_gpio); ++ goto err_free_thread; ++ } ++ ++ cy8ctmg110_power(ts,true); ++ ++ ts->initController = false; ++#ifdef POLL_TOUCH_EVENTS ++ ts->i2c_fail_count = 0; ++ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ ts->timer.function = cy8ctmg110_timer; ++ ++ hrtimer_start(&ts->timer, ktime_set(10, 0), ++ HRTIMER_MODE_REL); ++#endif ++ err = gpio_request(client->irq, "touch_irq_key"); ++ ++ if (err < 0) { ++ printk("%s gpio-keys: failed to request GPIO %d," ++ " error %d\n",ts->driver_name,client->irq, err); ++ goto err_free_thread; ++ } ++ ++ err= gpio_direction_input(client->irq); ++ ++ if (err < 0) { ++ pr_err("%s gpio-keys: failed to configure input" ++ " direction for GPIO %d, error %d\n",ts->driver_name,client->irq, err); ++ gpio_free(client->irq); ++ goto err_free_thread; ++ } ++ ++ ts->irq_gpio = gpio_to_irq(client->irq); ++ ++ if (ts->irq_gpio < 0) { ++ err = ts->irq_gpio; ++ pr_err("cy8ctmg110 gpio-keys: Unable to get irq number" ++ " for GPIO %d, error %d\n", ++ ts->irq_gpio, err); ++ gpio_free(ts->irq_gpio); ++ goto err_free_thread; ++ } ++ ++ if (client->addr!=CY8CTMG110_I2C_ADDR_EXT){ ++ err = request_irq(ts->irq_gpio, cy8ctmg110_irq_handler, ++ IRQF_TRIGGER_RISING | IRQF_SHARED, ++ "touch_reset_key", ++ ts); ++ } ++ ++ if (err < 0) { ++ dev_err(&client->dev, "cy8ctmg110 irq %d busy? error %d\n", ts->irq_gpio ,err); ++ goto err_free_thread; ++ } ++ ++ err = input_register_device(input_dev); ++ cy8ctmg110_read_versionid(ts); ++ ++ if (err) ++ goto err_free_irq; ++ ++ return 0; ++ ++ err_free_irq: ++ printk("%s err_free_irq\n",ts->driver_name); ++ free_irq(client->irq, ts); ++ err_free_thread: ++ printk("%s err_free_thread\n",ts->driver_name); ++ err_free_mem: ++ printk("%s err_free_mem\n",ts->driver_name); ++ input_free_device(input_dev); ++ kfree(ts); ++ ++ return err; ++} ++/* ++ * cy8ctmg110_suspend ++ * ++ */ ++static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg) ++{ ++ if (device_may_wakeup(&client->dev)) ++ enable_irq_wake(client->irq); ++ ++ return 0; ++} ++/* ++ * cy8ctmg110_resume ++ * ++ */ ++static int cy8ctmg110_resume(struct i2c_client *client) ++{ ++ if (device_may_wakeup(&client->dev)) ++ disable_irq_wake(client->irq); ++ ++ return 0; ++} ++/* ++ * cy8ctmg110_remove ++ * ++ */ ++static int cy8ctmg110_remove(struct i2c_client *client) ++{ ++ struct cy8ctmg110 *ts = i2c_get_clientdata(client); ++ ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_remove\n"); ++#endif ++ ++ cy8ctmg110_power(ts,false); ++#ifdef POLL_TOUCH_EVENTS ++ hrtimer_cancel(&ts->timer); ++#endif ++ ++ free_irq(client->irq, ts); ++ input_unregister_device(ts->input); ++ kfree(ts); ++ ++ return 0; ++} ++ ++static struct i2c_device_id cy8ctmg110_idtable[] = { ++ { CY8CTMG110_DRIVER_NAME, 1 }, ++ { CY8CTMG110_DRIVER_NAME_EXT, 1 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable); ++ ++static struct i2c_driver cy8ctmg110_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = CY8CTMG110_DRIVER_NAME, ++ .bus = &i2c_bus_type, ++ }, ++ .id_table = cy8ctmg110_idtable, ++ .probe = cy8ctmg110_probe, ++ .remove = cy8ctmg110_remove, ++ .suspend = cy8ctmg110_suspend, ++ .resume = cy8ctmg110_resume, ++}; ++ ++ ++static int __init cy8ctmg110_init(void) ++{ ++ printk("cy8ctmg110_init\n"); ++ ++ return i2c_add_driver(&cy8ctmg110_driver); ++} ++ ++static void __exit cy8ctmg110_exit(void) ++{ ++#ifdef CY8CTMG110_DEBUG_INFO ++ printk("cy8ctmg110_exit\n"); ++#endif ++ i2c_del_driver(&cy8ctmg110_driver); ++} ++ ++module_init(cy8ctmg110_init); ++module_exit(cy8ctmg110_exit); ++ ++ ++struct i2c_board_info __initdata koski_i2c_board_info2[] = { ++ { ++ I2C_BOARD_INFO(CY8CTMG110_DRIVER_NAME, CY8CTMG110_I2C_ADDR), ++ .irq = CY8CTMG110_IRQ_PIN_GPIO ++ }, ++ { ++ I2C_BOARD_INFO(CY8CTMG110_DRIVER_NAME_EXT, CY8CTMG110_I2C_ADDR_EXT), ++ .irq = CY8CTMG110_IRQ_PIN_GPIO_EXT ++ }, ++}; ++ ++ ++static int __init koski_i2c_init(void) ++{ ++ printk("init koski board\n"); ++ ++#ifdef MOORESTOWN_CDK ++ /*init koski i2c*/ ++ i2c_register_board_info(1, koski_i2c_board_info2, ++ ARRAY_SIZE(koski_i2c_board_info2)); ++#else ++ /*init koski i2c*/ ++ i2c_register_board_info(0, koski_i2c_board_info2, ++ ARRAY_SIZE(koski_i2c_board_info2)); ++#endif ++ return 0; ++} ++ ++module_init(koski_i2c_init); ++ ++MODULE_AUTHOR("Samuli Konttila "); ++MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); ++MODULE_LICENSE("GPL v2"); ++ ++ ++// Aava access from sysfs begin ++static ssize_t aava_query_fw_info_func(struct class *class, char *buf) ++{ ++ ssize_t status; ++ int i = 0; ++ unsigned char mrst_fw_ver_info[16]; ++ ++ printk("!!! aava_query_fw_info_func() ENTER\n"); ++ ++ status = mrst_get_firmware_version(mrst_fw_ver_info); ++ for (i = 0; i < 16; i++){ ++ printk("%x\n", mrst_fw_ver_info[i]); ++ buf[i] = mrst_fw_ver_info[i]; ++ } ++ ++ return 16; ++} ++ ++static ssize_t aava_enable_touch_traces_func(struct class *class, \ ++ const char *buf, size_t len) ++{ ++ ssize_t status; ++ unsigned long value; ++ ++ status = strict_strtoul(buf, 0, &value); ++ printk("!!! aava_enable_touch_traces_func() = %d\n", (int)value); ++ ++ g_y_trace_coord = value; ++ ++ return len; ++} ++ ++static struct class_attribute aava_class_attrs[] = { ++ __ATTR(aava_query_fw_info, 0444, aava_query_fw_info_func, NULL), ++ __ATTR(aava_enable_touch_traces, 0200, NULL, aava_enable_touch_traces_func), ++ __ATTR_NULL, ++}; ++ ++static struct class aava_class = { ++ .name = "aava", ++ .owner = THIS_MODULE, ++ ++ .class_attrs = aava_class_attrs, ++}; ++ ++static int __init aava_sysfs_init(void) ++{ ++ int status; ++ ++ status = class_register(&aava_class); ++ if (status < 0) ++ return status; ++ ++ return status; ++} ++postcore_initcall(aava_sysfs_init); ++// Aava access from sysfs end +-- +1.6.2.2 + -- cgit v1.2.3