|
@@ -0,0 +1,578 @@
|
|
|
+// ===========================================================================
|
|
|
+// orizon_ts.c
|
|
|
+// Copyright (C) 2003-2010 Bookeen - All rights reserved
|
|
|
+// ===========================================================================
|
|
|
+
|
|
|
+/* TODO: Verify if all this includes are necessary */
|
|
|
+#include <linux/kernel.h>
|
|
|
+#include <linux/module.h>
|
|
|
+#include <asm/atomic.h>
|
|
|
+#include <asm/io.h>
|
|
|
+#include <asm/arch/irqs.h>
|
|
|
+#include <asm/arch/gpio.h>
|
|
|
+#include <linux/delay.h>
|
|
|
+#include <linux/interrupt.h>
|
|
|
+#include <linux/irq.h>
|
|
|
+#include <linux/jiffies.h>
|
|
|
+#include <linux/i2c.h>
|
|
|
+#include <linux/proc_fs.h>
|
|
|
+#include <linux/kthread.h>
|
|
|
+#include <linux/mutex.h>
|
|
|
+#include <linux/spinlock.h>
|
|
|
+#include <linux/ctype.h>
|
|
|
+
|
|
|
+#include <cybook.h>
|
|
|
+#include <linux/cyio.h>
|
|
|
+
|
|
|
+#define DEBUG_MESSAGES
|
|
|
+//#define DEBUG_TRACEFUNC
|
|
|
+
|
|
|
+#define MODULE_NAME "ORIZON-TS"
|
|
|
+
|
|
|
+#define FINGER_NUM 0x00
|
|
|
+#define INT_DELAY 0x64 /* Default 0x64 */
|
|
|
+#define INT_MODE 0x01
|
|
|
+#define X_SENS 0x22 /* Default 0x14 */
|
|
|
+#define Y_SENS 0x22 /* Default 0x14 */
|
|
|
+
|
|
|
+#ifdef DEBUG_MESSAGES
|
|
|
+
|
|
|
+enum InfoLevel
|
|
|
+{
|
|
|
+ INFO_ERROR = 0,
|
|
|
+ INFO_WARNING,
|
|
|
+ INFO_NORMAL,
|
|
|
+ INFO_DEBUG,
|
|
|
+ INFO_VERBOSE,
|
|
|
+};
|
|
|
+
|
|
|
+# ifndef VERBOSE_LEVEL
|
|
|
+# define VERBOSE_LEVEL INFO_VERBOSE
|
|
|
+# endif
|
|
|
+
|
|
|
+# ifdef DEBUG_TRACEFUNC
|
|
|
+
|
|
|
+static int _dbg_FunctionLevel = 0;
|
|
|
+
|
|
|
+# define MSG(str) {\
|
|
|
+ int __i;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk("||" str "\n");\
|
|
|
+}
|
|
|
+
|
|
|
+# define DBG(str, ...) {\
|
|
|
+ int __i;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk("||" str "\n", __VA_ARGS__);\
|
|
|
+}
|
|
|
+
|
|
|
+# define INFOL(level, s) do {\
|
|
|
+ if (level <= VERBOSE_LEVEL) {\
|
|
|
+ int __i;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
|
|
|
+ }\
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+# define FUNC_IN() {\
|
|
|
+ int __i;\
|
|
|
+ _dbg_FunctionLevel++;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk(">> %s() >>\n", __func__);\
|
|
|
+}
|
|
|
+
|
|
|
+# define FUNC_OUT() {\
|
|
|
+ int __i;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk("<< %s() <<\n", __func__);\
|
|
|
+ _dbg_FunctionLevel--;\
|
|
|
+}
|
|
|
+
|
|
|
+# define FUNC_OUTR(val) {\
|
|
|
+ int __i;\
|
|
|
+ printk(KERN_ALERT "+");\
|
|
|
+ for (__i = 0; __i < _dbg_FunctionLevel; __i++)\
|
|
|
+ printk("-");\
|
|
|
+ printk("<< %s() = %d <<\n", __func__, val);\
|
|
|
+ _dbg_FunctionLevel--;\
|
|
|
+}
|
|
|
+# else /* DEBUG_TRACEFUNC */
|
|
|
+
|
|
|
+# define MSG(str) do {\
|
|
|
+ printk(KERN_ALERT MODULE_NAME ": " str "\n");\
|
|
|
+} while(0)
|
|
|
+
|
|
|
+# define DBG(str, ...) do {\
|
|
|
+ printk(KERN_ALERT MODULE_NAME ": " str "\n", __VA_ARGS__);\
|
|
|
+} while(0)
|
|
|
+# define FUNC_IN() do {\
|
|
|
+} while(0)
|
|
|
+
|
|
|
+# define FUNC_OUT() do {\
|
|
|
+} while(0)
|
|
|
+
|
|
|
+# define FUNC_OUTR(val) do {\
|
|
|
+ printk(KERN_ALERT MODULE_NAME ": %s() return %d\n", __func__, val);\
|
|
|
+} while(0)
|
|
|
+
|
|
|
+# define INFOL(level, s) do {\
|
|
|
+ if (level <= VERBOSE_LEVEL) {\
|
|
|
+ printk("<%d>%s:%s(): ", level, __FILE__, __func__); printk s; printk("\n");\
|
|
|
+ }\
|
|
|
+ } while(0)
|
|
|
+
|
|
|
+# endif /* DEBUG_TRACEFUNC */
|
|
|
+#else /* DEBUG_MESSAGES */
|
|
|
+# define MSG(str)
|
|
|
+# define DBG(str, ...)
|
|
|
+# define FUNC_IN()
|
|
|
+# define FUNC_OUT()
|
|
|
+# define FUNC_OUTR(val)
|
|
|
+# define INFOL(level, s)
|
|
|
+# define INFO(s)
|
|
|
+#endif /* DEBUG_MESSAGES */
|
|
|
+
|
|
|
+typedef enum
|
|
|
+{
|
|
|
+ POWER_UNDEFINED = -1,
|
|
|
+ POWER_OFF = 0,
|
|
|
+ POWER_ON,
|
|
|
+ POWER_ONAUTOSTANDBY,
|
|
|
+ POWER_DEEPSLEEP,
|
|
|
+} Ots_PowerModes;
|
|
|
+
|
|
|
+/*============================================================================*/
|
|
|
+/*============================= Prototypes ===================================*/
|
|
|
+/*============================================================================*/
|
|
|
+
|
|
|
+/**************************** i2c functions ***********************************/
|
|
|
+static int ots_attachAdapter (struct i2c_adapter *adapter);
|
|
|
+static int ots_detect (struct i2c_adapter *adapter, int address, int kind);
|
|
|
+static int ots_detachClient (struct i2c_client *client);
|
|
|
+
|
|
|
+static int ots_suspend (struct device *dev, pm_message_t state);
|
|
|
+static int ots_resume (struct device *dev);
|
|
|
+
|
|
|
+//static void ots_dumpI2C(void);
|
|
|
+/**************************** irq functions ***********************************/
|
|
|
+static void ots_checkWorkFunction (struct work_struct *work);
|
|
|
+static irqreturn_t ots_interrupt (int irq, void *dev_id);
|
|
|
+/******************************* Chip functions *******************************/
|
|
|
+static void ots_setPowerMode (Ots_PowerModes power);
|
|
|
+static void ots_setDeviceParameters (unsigned char int_mode,
|
|
|
+ unsigned char x_sensitivity,
|
|
|
+ unsigned char y_sensitivity);
|
|
|
+static void ots_ackInterrupt (void);
|
|
|
+/****************************** Module functions ******************************/
|
|
|
+static int __init ots_init (void);
|
|
|
+static void __exit ots_exit (void);
|
|
|
+/*============================= End of prototypes ============================*/
|
|
|
+
|
|
|
+/*============================================================================*/
|
|
|
+/*============================= Variables ====================================*/
|
|
|
+/*============================================================================*/
|
|
|
+struct workqueue_struct *ots_check_workqueue;
|
|
|
+struct work_struct ots_check_work;
|
|
|
+
|
|
|
+static Ots_PowerModes ots_currentPowerMode = POWER_UNDEFINED;
|
|
|
+
|
|
|
+/****************************** i2c configuration *****************************/
|
|
|
+#define OTS_ADDR_I2C 0x5C
|
|
|
+
|
|
|
+static unsigned short normal_i2c[] = { OTS_ADDR_I2C,
|
|
|
+ I2C_CLIENT_END };
|
|
|
+
|
|
|
+/* Insmod parameters */
|
|
|
+I2C_CLIENT_INSMOD_1 (ots);
|
|
|
+struct i2c_client *ots_client;
|
|
|
+
|
|
|
+/* Each client has this additional data */
|
|
|
+struct ots_data
|
|
|
+{
|
|
|
+ struct i2c_client client;
|
|
|
+};
|
|
|
+
|
|
|
+/* This is the I2C driver that will be inserted */
|
|
|
+static struct i2c_driver ots_driver ={
|
|
|
+ .driver =
|
|
|
+ {
|
|
|
+ .name = "orizon_ts",
|
|
|
+ .suspend = ots_suspend,
|
|
|
+ .resume = ots_resume,
|
|
|
+ },
|
|
|
+ .id = I2C_DRIVERID_EEPROM,
|
|
|
+ .attach_adapter = ots_attachAdapter,
|
|
|
+ .detach_client = ots_detachClient,
|
|
|
+};
|
|
|
+
|
|
|
+/******************************************************************************/
|
|
|
+/**************************** i2c functions ***********************************/
|
|
|
+/******************************************************************************/
|
|
|
+#if 0
|
|
|
+static void ots_dumpI2C(void)
|
|
|
+{
|
|
|
+ int Addr = 0;
|
|
|
+ unsigned char value;
|
|
|
+ int I,J;
|
|
|
+ printk("-------------------------------------------------------------------------------\n");
|
|
|
+ printk("-------------------------------------I²C TS------------------------------------\n");
|
|
|
+ for ( J = 0; J < 16; J++ )
|
|
|
+ {
|
|
|
+ printk("%04X: ", Addr);
|
|
|
+ for ( I = 0; I < 16; I++, Addr++ )
|
|
|
+ {
|
|
|
+ value = i2c_smbus_read_byte_data(ots_client, Addr);
|
|
|
+ mdelay(4);
|
|
|
+ printk("%02X ", value);
|
|
|
+ }
|
|
|
+
|
|
|
+ printk(" | ");
|
|
|
+ Addr -= 16;
|
|
|
+
|
|
|
+ for ( I = 0; I < 16; I++, Addr++ )
|
|
|
+ {
|
|
|
+ value = i2c_smbus_read_byte_data(ots_client, Addr);
|
|
|
+ mdelay(4);
|
|
|
+ printk("%c", isprint(value) ? value : '.');
|
|
|
+ }
|
|
|
+ printk("\n");
|
|
|
+
|
|
|
+ }
|
|
|
+ printk("-------------------------------------------------------------------------------\n");
|
|
|
+ printk("-------------------------------------------------------------------------------\n");
|
|
|
+}
|
|
|
+#endif
|
|
|
+static int ots_attachAdapter (struct i2c_adapter *adapter)
|
|
|
+{
|
|
|
+ return i2c_probe(adapter, &addr_data, ots_detect);
|
|
|
+}
|
|
|
+
|
|
|
+/* This function is called by i2c_probe */
|
|
|
+static int ots_detect (struct i2c_adapter *adapter, int address, int kind)
|
|
|
+{
|
|
|
+ struct ots_data *data = NULL;
|
|
|
+
|
|
|
+ int err = 0;
|
|
|
+ FUNC_IN();
|
|
|
+ //DBG(">>%s(%p, 0x%X, 0x%X)", __func__, adapter, address, kind);
|
|
|
+
|
|
|
+
|
|
|
+ if ( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
|
|
+ | I2C_FUNC_SMBUS_BYTE) )
|
|
|
+ goto exit;
|
|
|
+
|
|
|
+ if ( address == OTS_ADDR_I2C )
|
|
|
+ {
|
|
|
+ if ( !(data = kzalloc(sizeof (struct ots_data), GFP_KERNEL)) )
|
|
|
+ {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ ots_client = &data->client;
|
|
|
+ i2c_set_clientdata(ots_client, data);
|
|
|
+ ots_client->addr = address;
|
|
|
+ ots_client->adapter = adapter;
|
|
|
+ ots_client->driver = &ots_driver;
|
|
|
+ ots_client->flags = 0;
|
|
|
+
|
|
|
+ /* Fill in the remaining client fields */
|
|
|
+ strlcpy(ots_client->name, "orizon_ts", I2C_NAME_SIZE);
|
|
|
+
|
|
|
+ /* Tell the I2C layer a new client has arrived */
|
|
|
+ if ( (err = i2c_attach_client(ots_client)) )
|
|
|
+ {
|
|
|
+ goto exit_kfree;
|
|
|
+ }
|
|
|
+
|
|
|
+ ots_setPowerMode(POWER_ONAUTOSTANDBY);
|
|
|
+ ots_setDeviceParameters(INT_MODE, X_SENS, Y_SENS);
|
|
|
+ /* Now we are sure that the driver init successfully, then aquire the IRQ */
|
|
|
+ set_irq_type(IRQ_EINT2, IRQT_FALLING);
|
|
|
+
|
|
|
+ if ( request_irq(IRQ_EINT2, ots_interrupt, SA_SHIRQ, "orizon_ts", &ots_client) )
|
|
|
+ {
|
|
|
+ printk(KERN_ERR "failed to get interrupt resouce at IRQ_EINT2.\n");
|
|
|
+ goto exit_kfree;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ goto exit;
|
|
|
+
|
|
|
+exit_kfree:
|
|
|
+ kfree(data);
|
|
|
+exit:
|
|
|
+ FUNC_OUTR(err);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int ots_detachClient (struct i2c_client *client)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ err = i2c_detach_client(client);
|
|
|
+ if ( err )
|
|
|
+ goto exit;
|
|
|
+
|
|
|
+ kfree(i2c_get_clientdata(client));
|
|
|
+
|
|
|
+exit:
|
|
|
+ FUNC_OUTR(err);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int ots_suspend (struct device *dev, pm_message_t state)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ FUNC_OUTR(ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int ots_resume (struct device *dev)
|
|
|
+{
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ FUNC_OUT();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/******************************************************************************/
|
|
|
+/********************** Interrupt Related functions ***************************/
|
|
|
+/******************************************************************************/
|
|
|
+static void ots_checkWorkFunction (struct work_struct *work)
|
|
|
+{
|
|
|
+ unsigned long x1, y1, x2, y2;
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ /* Here do what the interrupt should... (ie read touch values) */
|
|
|
+ x1 = i2c_smbus_read_byte_data(ots_client, 0);
|
|
|
+ x1 |= i2c_smbus_read_byte_data(ots_client, 1) << 8;
|
|
|
+
|
|
|
+ y1 = i2c_smbus_read_byte_data(ots_client, 2);
|
|
|
+ y1 |= i2c_smbus_read_byte_data(ots_client, 3) << 8;
|
|
|
+
|
|
|
+ x2 = i2c_smbus_read_byte_data(ots_client, 4);
|
|
|
+ x2 |= i2c_smbus_read_byte_data(ots_client, 5) << 8;
|
|
|
+
|
|
|
+ y2 = i2c_smbus_read_byte_data(ots_client, 6);
|
|
|
+ y2 |= i2c_smbus_read_byte_data(ots_client, 7) << 8;
|
|
|
+
|
|
|
+ DBG("x1: %lu\ty1: %lu\ty1: %lu\ty2: %lu", x1, y1, x2, y2);
|
|
|
+
|
|
|
+ /* Say I get the data */
|
|
|
+ ots_ackInterrupt();
|
|
|
+
|
|
|
+ FUNC_OUT();
|
|
|
+}
|
|
|
+
|
|
|
+static irqreturn_t ots_interrupt (int irq, void *dev_id)
|
|
|
+{
|
|
|
+ irqreturn_t ret = IRQ_HANDLED;
|
|
|
+ static int initialised = 0;
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ if (initialised == 0)
|
|
|
+ {
|
|
|
+ INIT_WORK(&ots_check_work, ots_checkWorkFunction);
|
|
|
+ initialised = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ PREPARE_WORK(&ots_check_work, ots_checkWorkFunction);
|
|
|
+ }
|
|
|
+ schedule_work(&ots_check_work);
|
|
|
+
|
|
|
+ //FUNC_OUTR((int)ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+/******************************************************************************/
|
|
|
+/******************************* Chip functions *******************************/
|
|
|
+/******************************************************************************/
|
|
|
+static void ots_setPowerMode (Ots_PowerModes power)
|
|
|
+{
|
|
|
+ unsigned char tmpReg;
|
|
|
+
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ if (power == ots_currentPowerMode)
|
|
|
+ return; /* No need to do anything, we are in the same power mode... */
|
|
|
+
|
|
|
+ switch(power)
|
|
|
+ {
|
|
|
+ default:
|
|
|
+ case POWER_UNDEFINED:
|
|
|
+ /* Error */
|
|
|
+ DBG("Error: invalid power mode #%d", power);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case POWER_ON:
|
|
|
+ /* Set the power to on */
|
|
|
+ s3c2410_gpio_setpin(S3C2410_GPD10, 1);
|
|
|
+ msleep(100);
|
|
|
+ /* TODO: Does we need to set chip settings? */
|
|
|
+ tmpReg = 0x0; /* Set in "Active Mode" */
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x73, tmpReg);
|
|
|
+ msleep(400);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case POWER_OFF:
|
|
|
+ /* Set the power to off */
|
|
|
+ s3c2410_gpio_setpin(S3C2410_GPD10, 0);
|
|
|
+ msleep(10);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case POWER_ONAUTOSTANDBY:
|
|
|
+ if ( (ots_currentPowerMode != POWER_ON) &&
|
|
|
+ (ots_currentPowerMode != POWER_DEEPSLEEP) )
|
|
|
+ ots_setPowerMode(POWER_ON); /* Set myself as Power ON before anything */
|
|
|
+
|
|
|
+ //tmpReg = i2c_smbus_read_byte_data(ots_client, 0x24);
|
|
|
+ tmpReg = (((50) /* timeout in ms for auto sleep */ ) & 0x0F) << 4;
|
|
|
+ tmpReg |= (1<< 2); /* Activate auto sleep mode */
|
|
|
+ tmpReg |= 0x1; /* Set in "Sleep Mode" */
|
|
|
+
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x73, tmpReg);
|
|
|
+ msleep(4);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case POWER_DEEPSLEEP:
|
|
|
+ if ( (ots_currentPowerMode != POWER_ON) &&
|
|
|
+ (ots_currentPowerMode != POWER_ONAUTOSTANDBY) )
|
|
|
+ ots_setPowerMode(POWER_ON); /* Set myself as Power ON before anything */
|
|
|
+
|
|
|
+ tmpReg = 0x02;
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x73, tmpReg);
|
|
|
+ msleep(4);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ ots_currentPowerMode = power;
|
|
|
+ FUNC_OUT();
|
|
|
+}
|
|
|
+
|
|
|
+static void ots_setDeviceParameters (unsigned char int_mode,
|
|
|
+ unsigned char x_sensitivity,
|
|
|
+ unsigned char y_sensitivity)
|
|
|
+{
|
|
|
+ unsigned char tmpReg;
|
|
|
+
|
|
|
+ FUNC_IN();
|
|
|
+ /* Then set INT_WIDTH */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Interrupt width register @114 [0x72]
|
|
|
+ * b7-b0: int width
|
|
|
+ * Default: 0x64
|
|
|
+ */
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x72, INT_DELAY);
|
|
|
+ mdelay(4);
|
|
|
+ /* Now set sensitivity */
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x6F, x_sensitivity);
|
|
|
+ mdelay(4);
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x70, y_sensitivity);
|
|
|
+ mdelay(4);
|
|
|
+
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0xBE, 0x01); // TEST
|
|
|
+ tmpReg = i2c_smbus_read_byte_data(ots_client, 0xBE); // TEST
|
|
|
+ DBG("0xBE = %02X", tmpReg);
|
|
|
+
|
|
|
+ DBG("Firmware Version =0x%x\n", i2c_smbus_read_byte_data(ots_client, 0x77));
|
|
|
+
|
|
|
+ /* Activate the device ! */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Interrupt mode Setting register @113 [0x71]
|
|
|
+ * b7-b6-b5: TP_NUM : How many finger, 000: none, 001: One, 010: Two
|
|
|
+ * b4: INT_RELEASE: used to ack (1) IRQ in periodical mode
|
|
|
+ * b3: EN_INT: Enable int (1: enabled, 0: disable)
|
|
|
+ * b2: INT_POL: 0: active low, 1: active high
|
|
|
+ * b1-b0: INT_MODE: 00: INT periodicaly, 01: INT assert when coord changes
|
|
|
+ * 10: TOuch indicate, 11: INT assert when INT_RELEASE modified
|
|
|
+ *
|
|
|
+ * Default 0x0C [000 0 1 1 00]
|
|
|
+ * Qisda: 0x0A [000 0 1 0 10]
|
|
|
+ * Int periodicaly, Active High, and INT enabled
|
|
|
+ */
|
|
|
+ /* 2 Finger Active High Mode */
|
|
|
+ tmpReg = (FINGER_NUM << 5) | (1 << 3) | (0 << 2) | ((int_mode & 0x03) << 0);
|
|
|
+ DBG("Settings: 0x%02X", tmpReg);
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x71, tmpReg);
|
|
|
+ mdelay(4);
|
|
|
+ tmpReg = i2c_smbus_read_byte_data(ots_client, 0x71); // TEST
|
|
|
+ DBG("[0x71] Settings = %02X", tmpReg);
|
|
|
+ FUNC_OUT();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void ots_ackInterrupt (void)
|
|
|
+{
|
|
|
+ unsigned char tmpReg;
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ tmpReg = i2c_smbus_read_byte_data(ots_client, 0x71);
|
|
|
+ tmpReg |= (1<<4);
|
|
|
+ i2c_smbus_write_byte_data(ots_client, 0x71, tmpReg);
|
|
|
+
|
|
|
+ FUNC_OUT();
|
|
|
+}
|
|
|
+/******************************************************************************/
|
|
|
+/****************************** Module functions ******************************/
|
|
|
+/******************************************************************************/
|
|
|
+static int __init ots_init (void)
|
|
|
+{
|
|
|
+ FUNC_IN();
|
|
|
+
|
|
|
+ /* if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GMMA7660)
|
|
|
+ {
|
|
|
+
|
|
|
+ }*/
|
|
|
+
|
|
|
+ /* Init GPIOs */
|
|
|
+ s3c2410_gpio_cfgpin(S3C2410_GPD10, S3C2410_GPD10_OUTP);
|
|
|
+ s3c2410_gpio_pullup(S3C2410_GPD10, 2);
|
|
|
+
|
|
|
+ i2c_add_driver(&ots_driver);
|
|
|
+
|
|
|
+ FUNC_OUT();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+
|
|
|
+static void __exit ots_exit (void)
|
|
|
+{
|
|
|
+ FUNC_IN();
|
|
|
+ /*if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GMMA7660)
|
|
|
+ {
|
|
|
+
|
|
|
+ }*/
|
|
|
+
|
|
|
+ /* Deinit GPIOs */
|
|
|
+ /* Nothing to do, leave it as output is good enought, just set the
|
|
|
+ * device as power off */
|
|
|
+ ots_setPowerMode(POWER_OFF);
|
|
|
+
|
|
|
+ i2c_del_driver(&ots_driver);
|
|
|
+ FUNC_OUT();
|
|
|
+}
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+module_init (ots_init);
|
|
|
+module_exit (ots_exit);
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+MODULE_LICENSE ("GPL");
|
|
|
+MODULE_AUTHOR ("Bookeen <developers@bookeen.com>");
|
|
|
+MODULE_VERSION ("1.0");
|
|
|
+MODULE_DESCRIPTION ("Cybook Orizon Touchpanel driver");
|
|
|
+// ===========================================================================
|