linux/cybook.config:
* Use new epaper driver instead of qisda fb driver linux/arch/arm/mach-s3c2416/orizon-devs.c: * Rename old cyio-dev.c linux/arch/arm/mach-s3c2416/mach-cybook_orizon.c, linux/arch/arm/mach-s3c2416/orizon-devs.c: + Add support for new drivers in platform device list linux/drivers/video/Makefile, linux/drivers/video/Kconfig, linux/drivers/video/epaper/*: + Add new epaper driver for tcon (resolve #9) linux/drivers/input/misc/orizon_tilt.c: + Add new driver for the tilt sensor linux/drivers/char/s3c-adc.c: - Remove bloated code (this code must be audited, see ticket #8) linux/include/cybook.h: * Extend the CAPABILITY Field
This commit is contained in:
400
drivers/input/misc/orizon_tilt.c
Normal file
400
drivers/input/misc/orizon_tilt.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/* ===========================================================================
|
||||
* orizon_tilt.c
|
||||
* Copyright (C) 2009-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/proc_fs.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <cybook.h>
|
||||
|
||||
#include <linux/cyio.h>
|
||||
|
||||
//#define DEBUG_MESSAGES
|
||||
//#define DEBUG_TRACEFUNC
|
||||
//#define DBG_IRQ
|
||||
|
||||
#define MODULE_NAME "CYB_TILT"
|
||||
|
||||
#undef MSG
|
||||
#undef DBG
|
||||
#ifdef DEBUG_MESSAGES
|
||||
|
||||
#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 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)
|
||||
|
||||
#endif /* DEBUG_TRACEFUNC */
|
||||
|
||||
#else /* DEBUG_MESSAGES */
|
||||
#define MSG(str)
|
||||
#define DBG(str, ...)
|
||||
#define FUNC_IN()
|
||||
#define FUNC_OUT()
|
||||
#define FUNC_OUTR(val)
|
||||
#endif /* DEBUG_MESSAGES */
|
||||
|
||||
#define GPROCFS_ROOTFOLDER "cybook"
|
||||
#define GPROCFS_MODULEFOLDER "gsensor"
|
||||
#define GPROCFS_IOFILE "io"
|
||||
|
||||
#define TRUE (1==1)
|
||||
#define FALSE (1==0)
|
||||
|
||||
static struct proc_dir_entry *rootDir,
|
||||
*ioProcEntry;
|
||||
|
||||
atomic_t OrizonTilt_Status;
|
||||
atomic_t OrizonTilt_IrqSet;
|
||||
|
||||
static volatile short OrizonTilt_CurrentDirection = 270;
|
||||
static int SensorsInt[2];
|
||||
static DEFINE_SPINLOCK(suspendLock);
|
||||
|
||||
static unsigned char OrizonTilt_finishedWork = 0;
|
||||
|
||||
/*============================================================================*/
|
||||
/*============================= Prototypes ===================================*/
|
||||
/*============================================================================*/
|
||||
|
||||
/********************************* PM *****************************************/
|
||||
static int orizontilt_suspend(struct device *dev, pm_message_t state);
|
||||
static int orizontilt_resume (struct device *dev);
|
||||
/************************* Data collection Functions **************************/
|
||||
|
||||
/********************** Interrupt Related functions ***************************/
|
||||
static void orizontilt_setMode(int mode);
|
||||
static int orizontilt_initIrq(void);
|
||||
static void orizontilt_deinitIrq(void);
|
||||
static irqreturn_t orizontilt_interrupt(int irq, void *dev_id);
|
||||
|
||||
/****************************** ProcFs functions ******************************/
|
||||
static int orizontilt_procReadIo (char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static int orizontilt_procWriteIo (struct file *file, const char *buffer,
|
||||
unsigned long count, void *data);
|
||||
/****************************** Module functions ******************************/
|
||||
static int __init orizontilt_init(void);
|
||||
static void __exit orizontilt_exit(void);
|
||||
/*============================= End of prototypes ============================*/
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Interrupt Related functions ***************************/
|
||||
/******************************************************************************/
|
||||
static int orizontilt_initIrq(void)
|
||||
{
|
||||
int ret = 0;
|
||||
FUNC_IN();
|
||||
|
||||
if ( atomic_read(&OrizonTilt_IrqSet) != TRUE )
|
||||
{
|
||||
MSG("I will enable IRQ\n");
|
||||
|
||||
set_irq_type(IRQ_EINT11, IRQT_BOTHEDGE);
|
||||
set_irq_type(IRQ_EINT12, IRQT_BOTHEDGE);
|
||||
s3c2410_gpio_pullup(S3C2410_GPG3, 0);
|
||||
s3c2410_gpio_pullup(S3C2410_GPG4, 0);
|
||||
if(request_irq(IRQ_EINT11, orizontilt_interrupt, SA_INTERRUPT, "TILT-SENSOR[1]", &SensorsInt[0]))
|
||||
{
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
if(request_irq(IRQ_EINT12, orizontilt_interrupt, SA_INTERRUPT, "TILT-SENSOR[2]", &SensorsInt[1]))
|
||||
{
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
atomic_set(&OrizonTilt_IrqSet, TRUE);
|
||||
}
|
||||
|
||||
exit:
|
||||
FUNC_OUTR(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void orizontilt_deinitIrq(void)
|
||||
{
|
||||
FUNC_IN();
|
||||
|
||||
/* Set the orizontilt to standby mode */
|
||||
if ( atomic_read(&OrizonTilt_IrqSet) == TRUE )
|
||||
{
|
||||
disable_irq_wake(IRQ_EINT11);
|
||||
disable_irq_wake(IRQ_EINT12);
|
||||
free_irq(IRQ_EINT11, NULL);
|
||||
free_irq(IRQ_EINT12, NULL);
|
||||
atomic_set(&OrizonTilt_IrqSet, FALSE);
|
||||
}
|
||||
|
||||
FUNC_OUT();
|
||||
}
|
||||
|
||||
static irqreturn_t orizontilt_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
irqreturn_t ret = IRQ_HANDLED;
|
||||
unsigned long tmpReg;
|
||||
unsigned long calcTilt;
|
||||
|
||||
FUNC_IN();
|
||||
|
||||
spin_lock(&suspendLock);
|
||||
OrizonTilt_finishedWork = 1;
|
||||
spin_unlock(&suspendLock);
|
||||
|
||||
|
||||
/* Do it here */
|
||||
MSG("Will read gpios...");
|
||||
tmpReg = (__raw_readl(S3C2410_GPGDAT) >> 3) & 0x3;
|
||||
DBG("Got reg: %lu", tmpReg);
|
||||
calcTilt = 0;
|
||||
switch(tmpReg)
|
||||
{
|
||||
case 0x00: /* 90 */
|
||||
calcTilt = 90;
|
||||
break;
|
||||
|
||||
case 0x02: /* 0 */
|
||||
calcTilt = 0;
|
||||
break;
|
||||
|
||||
case 0x01: /* 180 */
|
||||
calcTilt = 180;
|
||||
break;
|
||||
|
||||
case 0x03: /* 270 */
|
||||
calcTilt = 270;
|
||||
break;
|
||||
}
|
||||
DBG("New Orientation is: %lu", calcTilt);
|
||||
if (calcTilt != OrizonTilt_CurrentDirection)
|
||||
{
|
||||
MSG("Different from old one, push new event!");
|
||||
OrizonTilt_CurrentDirection = calcTilt;
|
||||
Cyio_PushEvent(CYEVENT_ORIENTATIONCHANGED, true);
|
||||
}
|
||||
|
||||
spin_lock(&suspendLock);
|
||||
OrizonTilt_finishedWork = 0;
|
||||
spin_unlock(&suspendLock);
|
||||
|
||||
FUNC_OUT();
|
||||
|
||||
exit:
|
||||
FUNC_OUTR((int)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void orizontilt_setMode(int mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case G_SENSOR_ON:
|
||||
orizontilt_initIrq();
|
||||
enable_irq_wake(IRQ_EINT11);
|
||||
enable_irq_wake(IRQ_EINT12);
|
||||
/* Switch TILT on */
|
||||
gpio_direction_output(S3C2410_GPC3, 1);
|
||||
atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_ENABLED);
|
||||
break;
|
||||
case G_SENSOR_OFF:
|
||||
atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_DISABLED);
|
||||
/* Switch TILT off */
|
||||
gpio_direction_output(S3C2410_GPC3, 0);
|
||||
orizontilt_deinitIrq();
|
||||
disable_irq_wake(IRQ_EINT11);
|
||||
disable_irq_wake(IRQ_EINT12);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/****************************** ProcFs functions ******************************/
|
||||
/******************************************************************************/
|
||||
static int orizontilt_procReadIo (char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
{
|
||||
int len;
|
||||
char tmp = 0;
|
||||
|
||||
|
||||
/* We are a tilt and need no calibration */
|
||||
tmp |= (1 << 6);
|
||||
|
||||
if ( atomic_read(&OrizonTilt_Status) != CYGSENSOR_STATUS_ENABLED )
|
||||
tmp |= (1 << 4);
|
||||
|
||||
switch (OrizonTilt_CurrentDirection)
|
||||
{
|
||||
case 270:
|
||||
tmp++;
|
||||
case 180:
|
||||
tmp++;
|
||||
case 90:
|
||||
tmp++;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len = sprintf (page, "%02X", tmp);
|
||||
DBG("io readed value: %02X", tmp);
|
||||
|
||||
FUNC_OUTR(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int orizontilt_procWriteIo (struct file *file, const char *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
char cmd;
|
||||
FUNC_IN();
|
||||
|
||||
/* in case of... */
|
||||
if ( count < 1 )
|
||||
return 0;
|
||||
|
||||
cmd = buffer[0];
|
||||
switch(cmd)
|
||||
{
|
||||
case G_SENSOR_ON:
|
||||
case G_SENSOR_OFF:
|
||||
orizontilt_setMode(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "ProcIO: Unknown command '%c'\n",cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
FUNC_OUTR((int)count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/****************************** Module functions ******************************/
|
||||
/******************************************************************************/
|
||||
static int __init orizontilt_init(void)
|
||||
{
|
||||
|
||||
FUNC_IN();
|
||||
//printk(KERN_ERR "Platform is Cybook %d\n", platform_type);
|
||||
|
||||
SensorsInt[0] = 1;
|
||||
SensorsInt[1] = 2;
|
||||
|
||||
if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GTILT)
|
||||
{
|
||||
atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_UNKNOWN);
|
||||
atomic_set(&OrizonTilt_IrqSet, FALSE);
|
||||
|
||||
rootDir = proc_mkdir(GPROCFS_ROOTFOLDER, NULL);
|
||||
|
||||
rootDir = proc_mkdir(GPROCFS_MODULEFOLDER, proc_root_driver);
|
||||
ioProcEntry = create_proc_entry(GPROCFS_IOFILE, 0644, rootDir);
|
||||
|
||||
ioProcEntry->read_proc = orizontilt_procReadIo;
|
||||
ioProcEntry->write_proc = orizontilt_procWriteIo;
|
||||
ioProcEntry->owner = THIS_MODULE;
|
||||
}
|
||||
|
||||
FUNC_OUT();
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static void __exit orizontilt_exit(void)
|
||||
{
|
||||
FUNC_IN();
|
||||
|
||||
if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GTILT)
|
||||
{
|
||||
orizontilt_setMode(G_SENSOR_OFF);
|
||||
|
||||
remove_proc_entry(GPROCFS_IOFILE, rootDir);
|
||||
remove_proc_entry(GPROCFS_MODULEFOLDER, proc_root_driver);
|
||||
}
|
||||
|
||||
FUNC_OUT();
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
module_init(orizontilt_init);
|
||||
module_exit(orizontilt_exit);
|
||||
// ---------------------------------------------------------------------------
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
|
||||
MODULE_VERSION("1.1");
|
||||
MODULE_DESCRIPTION("Orizon Tilt Sensor driver");
|
||||
// ===========================================================================
|
||||
Reference in New Issue
Block a user