Latest changes

This commit is contained in:
mlt 2010-07-26 13:16:12 +00:00 committed by Godzil
parent e3c7c1b8b5
commit db805e563c
15 changed files with 1561 additions and 1648 deletions

View File

@ -1,7 +1,7 @@
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.21.5-cfs-v19 # Linux kernel version: 2.6.21.5-cfs-v19
# Mon May 24 20:53:14 2010 # Mon Jun 28 18:41:53 2010
# #
CONFIG_ARM=y CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@ -602,6 +602,7 @@ CONFIG_SLHC=m
# Input device support # Input device support
# #
CONFIG_INPUT=y CONFIG_INPUT=y
CONFIG_CYBOOK_EVENT_MANAGER=y
# CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_FF_MEMLESS is not set
# #

View File

@ -24,6 +24,12 @@ config INPUT
if INPUT if INPUT
config CYBOOK_EVENT_MANAGER
bool "Cybook Event Manager"
default y
---help---
Say Y if you use a Cybook 2416.
config INPUT_FF_MEMLESS config INPUT_FF_MEMLESS
tristate "Support for memoryless force-feedback devices" tristate "Support for memoryless force-feedback devices"
default n default n

View File

@ -22,3 +22,4 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/ obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_CYBOOK_EVENT_MANAGER) += cyevent.o

View File

@ -1,6 +1,5 @@
h
// =========================================================================== // ===========================================================================
// cyio.c // Cybook Event Manager - cyevent.c
// Copyright (C) 2008-2010 Bookeen - All rights reserved // Copyright (C) 2008-2010 Bookeen - All rights reserved
// =========================================================================== // ===========================================================================
#include <linux/init.h> #include <linux/init.h>
@ -14,132 +13,328 @@ h
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/arch/gpio.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-irq.h>
#include <asm-arm/arch-s3c2410/irqs.h>
#include <asm-arm/arch-s3c2410/gpio.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <asm/arch/regs-gpio.h> #include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-gpioj.h> #include <asm/arch/regs-gpioj.h>
#include <asm/io.h>
#include <cybook.h> #include <cybook.h>
#include <linux/cyevent.h> #include <linux/cyevent.h>
#define CYEV_MAX_EVENT 20 // =============================================================================
#define CYEV_REPEAT_DELAY (HZ/2); /* ~500ms */ //#define DEBUG_MESSAGES
#define CYEV_CURRENT_VERSION 0x10 /* 1.0 */ //#define DEBUG_TRACEFUNC
enum { INVALID = 0, VALID }; //#define VERBOSE_LEVEL INFO_DEBUG
struct #define MODULE_NAME "CyEvent"
// =============================================================================
#define CYEV_MAX_EVENT 20
#define CYEV_MAX_DEV 5
#define CYEV_REPEAT_DELAY (HZ/2) /* ~500ms */
// =============================================================================
enum { INVALID = 0, VALID };
// =============================================================================
typedef struct sCyEv_PayList
{ {
char valid; char valid;
char wantRepeat; char wantRepeat;
char seen; char seen;
char repeat;
char unique; char unique;
int repeatDelay; unsigned long repeatDelay;
CyEvent_t payload; CyEvent_t payload;
} CyEv_PayList; } CyEv_PayList;
CyEv_PayList *cyev_eventList[CYEV_MAX_EVENT]; CyEv_PayList cyev_eventList[CYEV_MAX_EVENT];
// =============================================================================
/* We should change this to a linked list... */
struct cyevent_device *DevList[CYEV_MAX_DEV];
// =============================================================================
struct task_struct *openingTask = 0; struct task_struct *openingTask = 0;
static atomic_t waitingRepeat;
// =============================================================================
#ifdef DEBUG_MESSAGES
/* TODO: Add a locking method for accessing the eventList */ enum InfoLevel
{
INFO_ERROR = 0,
INFO_WARNING,
INFO_NORMAL,
INFO_DEBUG,
INFO_VERBOSE,
};
// =========================================================================== # ifndef VERBOSE_LEVEL
# define VERBOSE_LEVEL INFO_WARNING
# 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 */
#define DUMP_CYEVENT(lvl, ev) INFOL(lvl, ("Event: .type=%c, .flags=%02X, .version=%02X\n" \
".data = { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X }",\
ev.type, ev.flags, ev.version, ev.data.raw[0], ev.data.raw[1], ev.data.raw[2], ev.data.raw[3], ev.data.raw[4], ev.data.raw[5],\
ev.data.raw[6], ev.data.raw[7], ev.data.raw[8], ev.data.raw[9], ev.data.raw[10], ev.data.raw[11], ev.data.raw[12]))
#define DUMP_EVITEM(lvl, evi) INFOL(lvl, ("EvItem: .valid = %d, .wantRepeat = %d, .seen = %d, .repeat = %d, .unique = %d, .repeatDelay = %lu .payload:",\
evi.valid, evi.wantRepeat, evi.seen, evi.repeat, evi.unique, evi.repeatDelay)); DUMP_CYEVENT(lvl, evi.payload);
// =============================================================================
rwlock_t cyev_list_rwlock = RW_LOCK_UNLOCKED;
// =============================================================================
static void publish_read_event(unsigned char type);
static void publish_empty_event(void);
// =============================================================================
// List management // List management
void CyEv_ClearEventList(void) void CyEv_ClearEventList(void)
{ {
int i; int i;
FUNC_IN();
atomic_set(&waitingRepeat, 0);
write_lock(&cyev_list_rwlock);
for (i = 0; i < CYEV_MAX_EVENT; i++) for (i = 0; i < CYEV_MAX_EVENT; i++)
{ {
cyev_eventList[i].wantRepeat = false; cyev_eventList[i].wantRepeat = false;
cyev_eventList[i].repeat = false;
cyev_eventList[i].seen = false; cyev_eventList[i].seen = false;
cyev_eventList[i].unique = false; cyev_eventList[i].unique = false;
cyev_eventList[i].repeatDelay = 0; cyev_eventList[i].repeatDelay = 0;
cyev_eventList[i].valid = INVALID; cyev_eventList[i].valid = INVALID;
} }
write_unlock(&cyev_list_rwlock);
FUNC_OUT();
} }
int listPos = 0;
/* Get Next Event will invalidate the event if it is not marked as repeat */ /* Get Next Event will invalidate the event if it is not marked as repeat */
/* After the event is selected, it will point to the next one */ /* After the event is selected, it will point to the next one */
/* We first start by the first event of the list then search for the first valid and return it */ /* We first start by the first event of the list then search for the first valid and return it */
CyEvent_t *CyEv_GetNextEvent(void) CyEvent_t *CyEv_GetNextEvent(CyEvent_t *ret)
{ {
static int listPos = 0;
int i; int i;
CyEvent_t ret = NULL; char foundPayload = 0;
CyEv_PayList *cur;
FUNC_IN();
write_lock(&cyev_list_rwlock);
/* Scan the list starting from the last position stored */ /* Scan the list starting from the last position stored */
for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++) for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
{ {
/* Stop on the first "VALID" event */ /* Stop on the first "VALID" event */
if (cyev_eventList[i % CYEV_MAX_EVENT].valid == VALID) cur = &(cyev_eventList[i % CYEV_MAX_EVENT]);
//INFOL(INFO_VERBOSE, ("Position %d / %d", i % CYEV_MAX_EVENT, CYEV_MAX_EVENT));
if (cur->valid == VALID)
{ {
DUMP_EVITEM(INFO_DEBUG, (*cur));
/* We already send this repeatable event. Did the delay occur ? /* We already send this repeatable event. Did the delay occur ?
if not, ignore it and go to the next one */ if not, ignore it and go to the next one */
if ( (cyev_eventList[i % CYEV_MAX_EVENT].seen == true) && if ( (cur->seen == true) &&
(cyev_eventList[i % CYEV_MAX_EVENT].wantRepeat == true) ) (cur->wantRepeat == true) )
{ {
if (cyev_eventList[i % CYEV_MAX_EVENT].repeatDelay < jiffies) ) if (cur->repeatDelay > jiffies)
{ {
INFOL(INFO_DEBUG, ("Event delay not occured [%lu vs %lu (%lu)]...",
cur->repeatDelay, jiffies, cur->repeatDelay - jiffies));
continue; continue;
} }
else /* if (cyev_eventList[i % CYEV_MAX_EVENT].repeatDelay >= jiffies) ) */ else /* if (cur->repeatDelay >= jiffies) */
{ {
/* Set the Repeat flag to true */ /* Set the Repeat flag to true */
cyev_eventList[i % CYEV_MAX_EVENT].payload.flags |= CYEVENT_FLAG_REPEATEVENT; INFOL(INFO_DEBUG, ("Event repeating... (%d)", atomic_read(&waitingRepeat)));
} if (cur->repeat == false)
}
cyev_eventList[i % CYEV_MAX_EVENT].seen = true;
/* Return the event */
ret = &(cyev_eventList[i % CYEV_MAX_EVENT].payload);
/* If the event is not a repeatable event, invalidate it! */
if (cyev_eventList[i % CYEV_MAX_EVENT].wantRepeat == false)
{ {
cyev_eventList[i % CYEV_MAX_EVENT].valid = INVALID; atomic_dec(&waitingRepeat); /* Ack the repeat event */
}
INFOL(INFO_DEBUG, ("waiting (%d) (repeat:%d)", atomic_read(&waitingRepeat), cur->repeat));
cur->payload.flags |= CYEVENT_FLAG_REPEATEVENT;
cur->repeat = true;
}
}
cur->seen = true;
/* Return the event and do not give real access to the list */
memcpy(ret, &(cur->payload), sizeof(CyEvent_t));
foundPayload = 1;
/* If the event is not a repeatable event, invalidate it! */
if (cur->wantRepeat == false)
{
INFOL(INFO_VERBOSE, ("Non-repeat event, will invalidate it"));
cur->valid = INVALID;
} }
/* Update the index for the next element to scan */ /* Update the index for the next element to scan */
listPos = (listPos + i + 1) % CYEV_MAX_EVENT; listPos = (i + 1) % CYEV_MAX_EVENT;
INFOL(INFO_DEBUG, ("Next event slot: %d", listPos));
break; break;
} }
} }
write_unlock(&cyev_list_rwlock);
FUNC_OUT();
if (foundPayload == 1)
return ret; /* We will return NULL if no valid payload */ return ret; /* We will return NULL if no valid payload */
return NULL;
} }
int isEventNotDuplicate(CyEvent_t *CyEvent) int isEventNotDuplicate(CyEvent_t *CyEvent, unsigned char flagMask)
{ {
int i; int i;
CyEvent_t *cur: int ret = true;
CyEvent_t *cur;
FUNC_IN();
read_lock(&cyev_list_rwlock);
for(i = 0; i < CYEV_MAX_EVENT; i++) for(i = 0; i < CYEV_MAX_EVENT; i++)
{ {
cur = &(cyev_eventList[i].payload); cur = &(cyev_eventList[i].payload);
if (cyev_eventList[i].unique == true) /* The event must be valid to be treated as unique, else invalid event are ignored */
if ( (cyev_eventList[i].valid == VALID) &&
(cyev_eventList[i].unique == true) )
{ {
if (cur->type == CyEvent->type) /* To be verified */ if ( (cur->type == CyEvent->type) &&
return false; ((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) )
{
ret = false;
goto exit;
} }
} }
return true;
} }
int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique) exit:
read_unlock(&cyev_list_rwlock);
FUNC_OUTR(ret);
return ret;
}
int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique, unsigned char flagMask)
{ {
/* Search for the first "invalid" event, then put the given CyEvent in it. */ /* Search for the first "invalid" event, then put the given CyEvent in it. */
/* If no slot is valid, return an error */ /* If no slot is valid, return an error */
int i; int i;
int ret = -EIO; /* TODO: find a better error code.*/ int ret = -EIO; /* TODO: find a better error code.*/
FUNC_IN();
/* If wantUnique, first check that there is not another unique event */ /* If wantUnique, first check that there is not another unique event */
if ((wantUnique) && !isEventNotDuplicate(CyEvent)) if ((wantUnique) && !isEventNotDuplicate(CyEvent, flagMask))
goto exit; goto exit;
write_lock(&cyev_list_rwlock);
/* Scan the list starting from the last position stored */ /* Scan the list starting from the last position stored */
for(i = 0; i < CYEV_MAX_EVENT; i++) for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
{ {
/* Stop on the first "VALID" event */ /* Stop on the first "INVALID" event */
if (cyev_eventList[i].valid == INVALID) if (cyev_eventList[i].valid == INVALID)
{ {
/* Store the event */ /* Store the event */
@ -148,12 +343,16 @@ int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique)
/* Force version in the structure */ /* Force version in the structure */
cyev_eventList[i].payload.version = CYEV_CURRENT_VERSION; cyev_eventList[i].payload.version = CYEV_CURRENT_VERSION;
cyev_eventList[i].valid = VALID; cyev_eventList[i].valid = VALID;
cyev_eventList[i].seen = false;
cyev_eventList[i].repeat = false;
if (wantUnique) if (wantUnique)
cyev_eventList[i].unique = true; cyev_eventList[i].unique = true;
else else
cyev_eventList[i].unique = false; cyev_eventList[i].unique = false;
if (wantRepeat) if (wantRepeat)
{ {
atomic_inc(&waitingRepeat);
cyev_eventList[i].wantRepeat = true; cyev_eventList[i].wantRepeat = true;
cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY; cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
} }
@ -168,30 +367,42 @@ int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique)
break; break;
} }
} }
write_unlock(&cyev_list_rwlock);
exit: exit:
FUNC_OUTR(ret);
return ret; return ret;
} }
/* Return 0 if event found and updated, or anything else */ /* Return 0 if event found and updated, or anything else */
/* We could ONLY update event that are declared as unique */ /* We could ONLY update event that are declared as unique */
int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat) int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
{ {
int i; int i;
int ret = -1; int ret = -1;
FUNC_IN();
/* Search for the event */ /* Search for the event */
write_lock(&cyev_list_rwlock);
for(i = 0; i < CYEV_MAX_EVENT; i++) for(i = 0; i < CYEV_MAX_EVENT; i++)
{ {
if ( (cyev_eventList[i].unique == true) && if ( (cyev_eventList[i].valid == VALID) &&
(cyev_eventList[i].payload.type == CyEvent.type) ) (cyev_eventList[i].unique == true) &&
((cyev_eventList[i].payload.flags & flagMask) == (CyEvent->flags & flagMask)) &&
(cyev_eventList[i].payload.type == CyEvent->type) )
{ /* Found it ! Now update the fields */ { /* Found it ! Now update the fields */
memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t)); memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
cyev_eventList[i].seen = false;
if (wantRepeat) if (wantRepeat)
{ {
cyev_eventList[i].wantRepeat = true; cyev_eventList[i].wantRepeat = true;
cyev_eventList[i].repeat = false;
cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY; cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
if (cyev_eventList[i].repeat == true)
atomic_inc(&waitingRepeat);
} }
else else
cyev_eventList[i].wantRepeat = false; cyev_eventList[i].wantRepeat = false;
@ -202,6 +413,35 @@ int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
ret = 0; ret = 0;
} }
} }
write_unlock(&cyev_list_rwlock);
FUNC_OUTR(ret);
return ret;
}
int CyEv_InvalidateUniqueEvent (CyEvent_t *CyEvent)
{
int i;
int ret = -1;
FUNC_IN();
/* Search for the event */
write_lock(&cyev_list_rwlock);
for ( i = 0; i < CYEV_MAX_EVENT; i++ )
{
if ( (cyev_eventList[i].valid == VALID) &&
(cyev_eventList[i].unique == true) &&
(cyev_eventList[i].payload.type == CyEvent->type) )
{ /* Found it ! Now update the fields */
INFOL(INFO_DEBUG, ("Found event..."));
cyev_eventList[i].valid = INVALID;
ret = 0;
break;
}
}
write_unlock(&cyev_list_rwlock);
FUNC_OUTR(ret);
return ret; return ret;
} }
@ -210,22 +450,39 @@ int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
int i; int i;
int ret = -1; int ret = -1;
FUNC_IN();
/* Search for the event */ /* Search for the event */
write_lock(&cyev_list_rwlock);
for(i = 0; i < CYEV_MAX_EVENT; i++) for(i = 0; i < CYEV_MAX_EVENT; i++)
{ {
if ( (cyev_eventList[i].wantRepeat == true) && if ( (cyev_eventList[i].valid == VALID) &&
(cyev_eventList[i].payload.type == CyEvent.type) ) (cyev_eventList[i].wantRepeat == true) &&
(cyev_eventList[i].payload.type == CyEvent->type) )
{ /* Found it ! Now update the fields */ { /* Found it ! Now update the fields */
INFOL(INFO_DEBUG, ("Found event..."));
/* In case the event has not been eaten, just remove the "repeat want" /* In case the event has not been eaten, just remove the "repeat want"
ie: do not invalidate it */ ie: do not invalidate it */
cyev_eventList[i].wantRepeat = false; cyev_eventList[i].wantRepeat = false;
if (cyev_eventList[i].seen == true) if (cyev_eventList[i].repeat == true)
{ {
INFOL(INFO_DEBUG, ("Was repeating..."));
/* set the event "end of repeat" flag */ /* set the event "end of repeat" flag */
cyev_eventList[i].payload.flags |= CYEVENT_FLAG_ENDOFREPEAT; cyev_eventList[i].payload.flags |= CYEVENT_FLAG_ENDOFREPEAT;
cyev_eventList[i].payload.flags &= ~(CYEVENT_FLAG_REPEATEVENT);
} }
else
{
INFOL(INFO_DEBUG, ("Repeat not done... (%d)", atomic_read(&waitingRepeat)));
atomic_dec(&waitingRepeat); /* One less waiting event... */
INFOL(INFO_DEBUG, ("waiting (%d)", atomic_read(&waitingRepeat)));
if (cyev_eventList[i].seen == true)
cyev_eventList[i].valid = INVALID;
}
cyev_eventList[i].seen = false;
cyev_eventList[i].repeat = false;
if (openingTask) if (openingTask)
wake_up_process(openingTask); wake_up_process(openingTask);
@ -234,10 +491,11 @@ int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
break; break;
} }
} }
write_unlock(&cyev_list_rwlock);
FUNC_OUTR(ret);
return ret; return ret;
} }
// =========================================================================== // ===========================================================================
@ -245,55 +503,115 @@ int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
// External event managment // External event managment
int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat) int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat)
{ {
int ret = -1;
FUNC_IN();
if (wantRepeat) if (wantRepeat)
return CyEv_AddNewEvent(CyEvent, wantRepeat, true); ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
else else
return CyEv_AddNewEvent(CyEvent, wantRepeat, false); ret = CyEv_AddNewEvent(CyEvent, wantRepeat, false, 0);
FUNC_OUTR(ret);
return ret;
} }
EXPORT_SYMBOL(CyEvent_PushNewEvent); EXPORT_SYMBOL(CyEvent_PushNewEvent);
int CyEvent_PushNewUniqueEvent(CyEvent_t *CyEvent)
{
return CyEv_AddNewEvent(CyEvent, false, true, 0);
}
EXPORT_SYMBOL(CyEvent_PushNewUniqueEvent);
int CyEvent_PushOrUpdateUniqueEventFlaged(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask)
{
int ret;
FUNC_IN();
/* For now a simple call to AddNewEvent */
ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, flagMask);
if (ret != 0) /* The event is not present */
ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, flagMask);
FUNC_OUTR(ret);
return ret;
}
EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEventFlaged);
int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat) int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
{ {
int ret; int ret;
FUNC_IN();
/* For now a simple call to AddNewEvent */ /* For now a simple call to AddNewEvent */
ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat); ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat, 0);
if (ret != 0) /* The event is not present */ if (ret != 0) /* The event is not present */
ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true); ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true, 0);
FUNC_OUTR(ret);
return ret; return ret;
} }
EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEvent); EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEvent);
int CyEvent_InvalidateUniqueEvent(CyEvent_t *CyEvent)
{
int ret;
FUNC_IN();
ret = CyEv_InvalidateUniqueEvent(CyEvent);
FUNC_OUTR(ret);
return ret;
}
EXPORT_SYMBOL(CyEvent_InvalidateUniqueEvent);
int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent) int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
{ {
int ret;
FUNC_IN();
ret = CyEv_InvalidateRepeatableEvent(CyEvent); ret = CyEv_InvalidateRepeatableEvent(CyEvent);
FUNC_OUTR(ret);
return ret;
} }
EXPORT_SYMBOL(CyEvent_InvalidateRepeatableEvent); EXPORT_SYMBOL(CyEvent_InvalidateRepeatableEvent);
// =========================================================================== // ===========================================================================
static int ev_open(struct inode *inode, struct file *file) static int ev_open(struct inode *inode, struct file *file)
{ {
FUNC_IN();
/* Clear pending event list... */ /* Clear pending event list... */
CyEv_ClearEventList(); CyEv_ClearEventList();
FUNC_OUT();
return 0; return 0;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static int ev_release(struct inode *inode, struct file *file) static int ev_release(struct inode *inode, struct file *file)
{ {
FUNC_IN();
/* Clear pending event list... */ /* Clear pending event list... */
CyEv_ClearEventList(); CyEv_ClearEventList();
FUNC_OUT();
return 0; return 0;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
ssize_t ev_read (struct file *file, char *buf, size_t count, loff_t *ppos) ssize_t ev_read (struct file *file, char *buf, size_t count, loff_t *ppos)
{ {
int nBytes = sizeof (CyEvent_t); int nBytes = sizeof (CyEvent_t);
int ret = -EIO; int ret = -EIO;
CyEvent_t *CyEvent = NULL; int waitCount;
CyEvent_t CyEvent;
//FUNC_IN();
if ( count < nBytes ) if ( count < nBytes )
{ {
@ -303,14 +621,29 @@ ssize_t ev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
while ( 1 ) while ( 1 )
{ {
if ((CyEvent = CyEv_GetNextEvent()) != NULL) //printk(KERN_ERR "CyEvent: Check new event...\n");
if ( CyEv_GetNextEvent(&CyEvent) != NULL )
{ {
break; break;
} }
waitCount = atomic_read(&waitingRepeat);
if (waitCount == 0) /* If there are some waiting event, the list is not empty */
publish_empty_event();
openingTask = current; openingTask = current;
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
/* If there are some waiting repeat, schedule with a timeout, or else,
just go out of the schedule queue */
INFOL(INFO_DEBUG, ("Waiting repeat: %d", waitCount));
if ( waitCount > 0 )
schedule_timeout(CYEV_REPEAT_DELAY / 10);
else
schedule(); schedule();
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
openingTask = 0; openingTask = 0;
@ -321,13 +654,16 @@ ssize_t ev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
} }
} }
if (CyEvent != NULL) if ( ret != -ERESTARTSYS )
{ {
nRes = copy_to_user(buf, &CyEvent, nBytes); ret = copy_to_user(buf, &CyEvent, nBytes);
if (!nRes) if ( !ret )
nRes = nBytes; ret = nBytes;
publish_read_event(CyEvent.type);
} }
exit:
//FUNC_OUTR(ret);
return ret; return ret;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -336,72 +672,90 @@ static int ev_ioctl(struct inode *inode, struct file *file,
{ {
int ret = -EINVAL; int ret = -EINVAL;
unsigned long value; unsigned long value;
int i;
FUNC_IN();
switch(cmd) switch(cmd)
{ {
default: default:
for (i = 0; i < CYEV_MAX_DEV; i++ )
{
if ((DevList[i] != NULL) && (DevList[i]->ioctl != NULL))
{
if (GET_IOCTL_PREFIX(cmd) == DevList[i]->ioctl_prefix)
{
ret = DevList[i]->ioctl(cmd, arg);
/* if the ioctl called didn't return 0, try to see if there is
someone else for this one */
if (ret == 0)
break;
}
}
}
printk(KERN_ERR "Bad IOCTL\n"); printk(KERN_ERR "Bad IOCTL\n");
break; break;
case CYIO_CTL_LED_CMD:
DBG("CYIO_CTL_LED_CMD arg[0x%03X]", arg);
if ((arg & 0x2) && (arg & 0x1)) /* Power LED */
{
MSG("\n----------------> POWER LED ON\n");
//GPH12
__raw_writel(__raw_readl(S3C2410_GPHDAT) | (1 << 12), S3C2410_GPHDAT);
}
else if (arg & 0x2)
{
MSG("\n----------------> POWER LED OFF\n");
__raw_writel(__raw_readl(S3C2410_GPHDAT) & ~(1 << 12), S3C2410_GPHDAT);
} }
if ((arg & 0x20) && (arg & 0x10)) /* Wifi LED */ FUNC_OUT();
{
MSG("\n----------------> POWER WFI ON\n");
//GPK8
__raw_writel(__raw_readl(S3C2416_GPKDAT) | (1 << 8), S3C2416_GPKDAT);
}
else if (arg & 0x20)
{
MSG("\n----------------> POWER WFI OFF\n");
__raw_writel(__raw_readl(S3C2416_GPKDAT) & ~(1 << 8), S3C2416_GPKDAT);
}
if ((arg & 0x200) && (arg & 0x100)) /* Bluetooth LED */
{
MSG("\n----------------> POWER BTH ON\n");
//GPK9
__raw_writel(__raw_readl(S3C2416_GPKDAT) | (1 << 9), S3C2416_GPKDAT);
}
else if (arg & 0x200)
{
MSG("\n----------------> POWER BTH OFF\n");
__raw_writel(__raw_readl(S3C2416_GPKDAT) & ~(1 << 9), S3C2416_GPKDAT);
}
ret = 0;
break;
case CYIO_CTL_USB_STATUS:
value = gpio_get_value(S3C2410_GPG1);
put_user(value, (unsigned long __user *)arg);
ret = 0;
break;
case CYIO_CTL_SD_STATUS:
value = gpio_get_value(S3C2410_GPF1);
put_user(value, (unsigned long __user *)arg);
ret = 0;
break;
}
return ret; return ret;
} }
// =========================================================================== // =============================================================================
static struct file_operations s_io_fops = int CyEvent_RegisterDevice(cyevent_device *dev)
{
int i;
for (i = 0; i < CYEV_MAX_DEV; i++ )
{
if (DevList[i] == NULL)
{
DevList[i] = dev;
return 0;
}
}
return -1; /* Too many devices... */
}
// -----------------------------------------------------------------------------
int CyEvent_DeregisterDevice(cyevent_device *dev)
{
int i;
for (i = 0; i < CYEV_MAX_DEV; i++ )
{
if (DevList[i] == dev)
{
DevList[i] = NULL;
return 0;
}
}
return -1; /* Not found...*/
}
// -----------------------------------------------------------------------------
static void publish_read_event(unsigned char type)
{
int i;
for (i = 0; i < CYEV_MAX_DEV; i++ )
{
if ((DevList[i] != NULL) && (DevList[i]->event_read != NULL))
{
if ((DevList[i]->event_read_listen == 0) || (type == DevList[i]->event_read_listen))
DevList[i]->event_read(type);
}
}
}
// -----------------------------------------------------------------------------
static void publish_empty_event(void)
{
int i;
for (i = 0; i < CYEV_MAX_DEV; i++ )
{
if ((DevList[i] != NULL) && (DevList[i]->event_listempty != NULL))
{
DevList[i]->event_listempty();
}
}
}
// =============================================================================
static struct file_operations s_ev_fops =
{ {
owner: THIS_MODULE, owner: THIS_MODULE,
read: ev_read, read: ev_read,
@ -410,7 +764,7 @@ static struct file_operations s_io_fops =
release: ev_release, release: ev_release,
}; };
gstatic struct miscdevice s_ev_dev = static struct miscdevice s_ev_dev =
{ {
.minor = 250, .minor = 250,
.name = "cyio", .name = "cyio",
@ -418,22 +772,38 @@ gstatic struct miscdevice s_ev_dev =
}; };
// =========================================================================== // ===========================================================================
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static int io_probe(struct platform_device *dev) static int ev_probe(struct platform_device *dev)
{ {
FUNC_IN();
FUNC_OUT();
return 0; return 0;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static int io_remove(struct platform_device *dev) static int ev_remove(struct platform_device *dev)
{ {
FUNC_IN();
misc_deregister(&s_ev_dev); misc_deregister(&s_ev_dev);
FUNC_OUT();
return 0; return 0;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static int io_resume(struct platform_device *dev) static int ev_suspend(struct platform_device *dev)
{ {
FUNC_IN();
FUNC_OUT();
return 0; return 0;
} }
// --------------------------------------------------------------------------
static int ev_resume(struct platform_device *dev)
{
FUNC_IN();
FUNC_OUT();
return 0;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static struct platform_driver cyev_driver = static struct platform_driver cyev_driver =
{ {
@ -444,28 +814,34 @@ static struct platform_driver cyev_driver =
}, },
.probe = ev_probe, .probe = ev_probe,
.remove = ev_remove, .remove = ev_remove,
.suspend = NULL, .suspend = NULL, //ev_suspend,
.resume = ev_resume, .resume = ev_resume,
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// =========================================================================== // ===========================================================================
static int __init cyEv_init(void) static int __init cyEv_init(void)
{ {
FUNC_IN();
if (misc_register(&s_ev_dev)) if (misc_register(&s_ev_dev))
return -EBUSY; return -EBUSY;
platform_driver_register(&cyev_driver); platform_driver_register(&cyev_driver);
FUNC_OUT();
return 0; return 0;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static void __exit cyEv_exit(void) static void __exit cyEv_exit(void)
{ {
FUNC_IN();
platform_driver_unregister(&cyev_driver); platform_driver_unregister(&cyev_driver);
misc_deregister(&s_ev_dev); misc_deregister(&s_ev_dev);
}
FUNC_OUT();
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
module_init(cyEv_init); module_init(cyEv_init);
module_exit(cyEv_exit); module_exit(cyEv_exit);

View File

@ -231,6 +231,7 @@ config KEYBOARD_GPIO
config CYBOOK_CYIO config CYBOOK_CYIO
tristate "Cybook CyIO" tristate "Cybook CyIO"
depends on CYBOOK_EVENT_MANAGER
# depends on MACH_CYBOOK_ORIZON # depends on MACH_CYBOOK_ORIZON
default y default y
help help

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,10 @@
#include <cybook.h> #include <cybook.h>
#include <linux/cyio.h> #include <linux/cyevent.h>
#define DEBUG_MESSAGES //#define DEBUG_MESSAGES
#define DEBUG_TRACEFUNC //#define DEBUG_TRACEFUNC
//#define DBG_IRQ //#define DBG_IRQ
#define MODULE_NAME "CYB_TILT" #define MODULE_NAME "CYB_TILT"
@ -209,7 +209,7 @@ static irqreturn_t orizontilt_interrupt(int irq, void *dev_id)
irqreturn_t ret = IRQ_HANDLED; irqreturn_t ret = IRQ_HANDLED;
unsigned long tmpReg; unsigned long tmpReg;
unsigned long calcTilt; unsigned long calcTilt;
CyEvent_t event = NEW_CYEVENT(CYEVENT_TYPE_ORIENTATION);
FUNC_IN(); FUNC_IN();
spin_lock(&suspendLock); spin_lock(&suspendLock);
@ -245,7 +245,8 @@ static irqreturn_t orizontilt_interrupt(int irq, void *dev_id)
{ {
MSG("Different from old one, push new event!"); MSG("Different from old one, push new event!");
OrizonTilt_CurrentDirection = calcTilt; OrizonTilt_CurrentDirection = calcTilt;
Cyio_PushEvent(CYEVENT_ORIENTATIONCHANGED, true); event.data.orientation = calcTilt / 90;
CyEvent_PushOrUpdateUniqueEvent(&event, false);
} }
spin_lock(&suspendLock); spin_lock(&suspendLock);

View File

@ -22,7 +22,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <cybook.h> #include <cybook.h>
#include <linux/cyio.h> #include <linux/cyevent.h>
//#define DEBUG_MESSAGES //#define DEBUG_MESSAGES
//#define DEBUG_TRACEFUNC //#define DEBUG_TRACEFUNC
@ -189,8 +189,7 @@ static Ots_PowerModes ots_currentPowerMode = POWER_UNDEFINED;
/****************************** i2c configuration *****************************/ /****************************** i2c configuration *****************************/
#define OTS_ADDR_I2C 0x5C #define OTS_ADDR_I2C 0x5C
static unsigned short normal_i2c[] = { OTS_ADDR_I2C, static unsigned short normal_i2c[] = { OTS_ADDR_I2C, I2C_CLIENT_END };
I2C_CLIENT_END };
/* Insmod parameters */ /* Insmod parameters */
I2C_CLIENT_INSMOD_1 (ots); I2C_CLIENT_INSMOD_1 (ots);
@ -295,7 +294,7 @@ static int ots_detect (struct i2c_adapter *adapter, int address, int kind)
goto exit_kfree; goto exit_kfree;
} }
ots_setPowerMode(POWER_ONAUTOSTANDBY); ots_setPowerMode(POWER_ON/*AUTOSTANDBY*/);
ots_setDeviceParameters(INT_MODE, X_SENS, Y_SENS); ots_setDeviceParameters(INT_MODE, X_SENS, Y_SENS);
/* Now we are sure that the driver init successfully, then aquire the IRQ */ /* Now we are sure that the driver init successfully, then aquire the IRQ */
set_irq_type(IRQ_EINT2, IRQT_FALLING); set_irq_type(IRQ_EINT2, IRQT_FALLING);
@ -353,11 +352,17 @@ static int ots_resume (struct device *dev)
/******************************************************************************/ /******************************************************************************/
/********************** Interrupt Related functions ***************************/ /********************** Interrupt Related functions ***************************/
/******************************************************************************/ /******************************************************************************/
static int oldX = 0, oldY = 0; static int oldX1 = 0, oldY1 = 0;
static int oldX2 = 0, oldY2 = 0;
enum { FINGER_UP = 0, FINGER_MOVE, FINGER_DOWN };
static void ots_checkWorkFunction (struct work_struct *work) static void ots_checkWorkFunction (struct work_struct *work)
{ {
unsigned long x1, y1, x2, y2; unsigned long x1, y1, x2, y2;
static int status = FINGER_UP;
CyEvent_t event = NEW_CYEVENT(CYEVENT_TYPE_TOUCH);
FUNC_IN(); FUNC_IN();
/* Here do what the interrupt should... (ie read touch values) */ /* Here do what the interrupt should... (ie read touch values) */
@ -377,22 +382,57 @@ static void ots_checkWorkFunction (struct work_struct *work)
DBG("x1: %lu\ty1: %lu\tx2: %lu\ty2: %lu", x1, y1, x2, y2); DBG("x1: %lu\ty1: %lu\tx2: %lu\ty2: %lu", x1, y1, x2, y2);
if ((x1 == 0) && (y1 == 0)) if ((x1 == 0) && (y1 == 0) && (x2 == 0) && (y2 == 0))
{ /* We assume that this is a finger up event */ { /* We assume that this is a finger up event */
if ( Cyio_PushEvent('R', 1) >= 0 ) if (status != FINGER_UP)
{ {
Cyio_PushEvent((oldX >> 8) & 0xFF, 0); event.flags |= CYEVENT_FLAG_TOUCH_UP;
Cyio_PushEvent((oldX >> 0) & 0xFF, 0); status = FINGER_UP;
Cyio_PushEvent((oldY >> 8) & 0xFF, 0);
Cyio_PushEvent((oldY >> 0) & 0xFF, 0);
} }
else
goto exit; /* ignore the event */
} }
else else
{ {
oldX = 600 - x1; oldX1 = 600 - x1;
oldY = y1; oldY1 = y1;
if ((x2 != 0) || (y2 != 0))
{
oldX2 = 600 - x2;
oldY2 = y2;
event.data.touch.fingers = 2;
}
else
{
oldX2 = oldY2 = 0;
event.data.touch.fingers = 1;
} }
if (status == FINGER_UP)
{
event.flags |= CYEVENT_FLAG_TOUCH_DOWN;
status = FINGER_DOWN;
}
else
{
event.flags |= CYEVENT_FLAG_TOUCH_MOVE;
status = FINGER_MOVE;
}
}
event.data.touch.x1 = oldX1;
event.data.touch.y1 = oldY1;
event.data.touch.x2 = oldX2;
event.data.touch.y2 = oldY2;
if (status == FINGER_UP)
oldX1 = oldY1 = oldX2 = oldY2 = 0;
CyEvent_PushOrUpdateUniqueEventFlaged(&event, false, CYEVENT_FLASH_TOUCH_MASK);
exit:
/* Say I get the data */ /* Say I get the data */
ots_ackInterrupt(); ots_ackInterrupt();
@ -461,7 +501,7 @@ static void ots_setPowerMode (Ots_PowerModes power)
ots_setPowerMode(POWER_ON); /* Set myself as Power ON before anything */ ots_setPowerMode(POWER_ON); /* Set myself as Power ON before anything */
//tmpReg = i2c_smbus_read_byte_data(ots_client, 0x24); //tmpReg = i2c_smbus_read_byte_data(ots_client, 0x24);
tmpReg = (((50) /* timeout in ms for auto sleep */ ) & 0x0F) << 4; tmpReg = (((16) /* timeout in ms for auto sleep */ ) & 0x0F) << 4;
tmpReg |= (1<< 2); /* Activate auto sleep mode */ tmpReg |= (1<< 2); /* Activate auto sleep mode */
tmpReg |= 0x1; /* Set in "Sleep Mode" */ tmpReg |= 0x1; /* Set in "Sleep Mode" */
@ -510,7 +550,7 @@ static void ots_setDeviceParameters (unsigned char int_mode,
tmpReg = i2c_smbus_read_byte_data(ots_client, 0xBE); // TEST tmpReg = i2c_smbus_read_byte_data(ots_client, 0xBE); // TEST
DBG("0xBE = %02X", tmpReg); DBG("0xBE = %02X", tmpReg);
DBG("Firmware Version =0x%x\n", i2c_smbus_read_byte_data(ots_client, 0x77)); printk("TS Firmware Version = 0x%x\n", i2c_smbus_read_byte_data(ots_client, 0x77));
/* Activate the device ! */ /* Activate the device ! */

View File

@ -55,6 +55,8 @@
#include <asm/arch/hsmmc.h> #include <asm/arch/hsmmc.h>
#include <linux/cyevent.h>
/*Qisda , wenny cheng , 20091224 , board id info {*/ /*Qisda , wenny cheng , 20091224 , board id info {*/
#include <../include/asm-arm/plat-s3c24xx/common-smdk.h> #include <../include/asm-arm/plat-s3c24xx/common-smdk.h>
/*Qisda , wenny cheng , 20091224 , board id info }*/ /*Qisda , wenny cheng , 20091224 , board id info }*/
@ -1103,15 +1105,12 @@ out:
return result; return result;
} }
#include <linux/cyio.h>
int Cyio_PushEvent(char eventId, char unique);
static irqreturn_t s3c_hsmmc_irq_cd (int irq, void *dev_id) static irqreturn_t s3c_hsmmc_irq_cd (int irq, void *dev_id)
{ {
struct s3c_hsmmc_host *host = dev_id; struct s3c_hsmmc_host *host = dev_id;
int ext_CD_int = 0; int ext_CD_int = 0;
CyEvent_t CyEvent = NEW_CYEVENT(CYEVENT_TYPE_SYSTEM);
CyEvent.flags |= CYEVENT_FLAG_SD_MESSAGE;
#if defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416) #if defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
ext_CD_int = readl(S3C2410_GPFDAT); ext_CD_int = readl(S3C2410_GPFDAT);
ext_CD_int &= 0x2; /* GPF1 */ ext_CD_int &= 0x2; /* GPF1 */
@ -1120,7 +1119,8 @@ static irqreturn_t s3c_hsmmc_irq_cd (int irq, void *dev_id)
ext_CD_int &= 0x2000; /* GPN13 */ ext_CD_int &= 0x2000; /* GPN13 */
#endif #endif
//printk("\ns3c_hsmmc_irq_cd, ext_CD_int: %d, card_detect: %d, card_detect2: %d\n", ext_CD_int, card_detect, card_detect2); //printk("\ns3c_hsmmc_irq_cd, ext_CD_int: %d, card_detect: %d, card_detect2: %d\n", ext_CD_int, card_detect, card_detect2);
if(ext_CD_int && card_detect) { if(ext_CD_int && card_detect)
{
printk("s3c-hsmmc channel-0(EXT): card removed.\n"); printk("s3c-hsmmc channel-0(EXT): card removed.\n");
/*Qisda Qube for sd card detect20091124*/ /*Qisda Qube for sd card detect20091124*/
//set_irq_type(host->irq_cd, IRQT_FALLING); //set_irq_type(host->irq_cd, IRQT_FALLING);
@ -1133,10 +1133,12 @@ static irqreturn_t s3c_hsmmc_irq_cd (int irq, void *dev_id)
card_detect2 = 2; card_detect2 = 2;
/* Send CyIO event */ /* Send CyIO event */
Cyio_PushEvent(CYEVENT_SD_OUT, 1); /* SD OUT */
CyEvent_PushNewUniqueEvent(&CyEvent);
} }
else if(!ext_CD_int && !card_detect) { else if(!ext_CD_int && !card_detect)
{
printk("s3c-hsmmc channel-0(EXT): card inserted.\n"); printk("s3c-hsmmc channel-0(EXT): card inserted.\n");
/*Qisda Qube for sd card detect20091124*/ /*Qisda Qube for sd card detect20091124*/
//set_irq_type(host->irq_cd, IRQT_RISING); //set_irq_type(host->irq_cd, IRQT_RISING);
@ -1156,7 +1158,9 @@ static irqreturn_t s3c_hsmmc_irq_cd (int irq, void *dev_id)
} }
/* Send CyIO event */ /* Send CyIO event */
Cyio_PushEvent(CYEVENT_SD_IN, 1); /* SD IN */
CyEvent.flags |= CYEVENT_FLAG_SYS_STATUS;
CyEvent_PushNewUniqueEvent(&CyEvent);
} }
//Qisda, Asaku Chen, 2009/11/03 { //Qisda, Asaku Chen, 2009/11/03 {

View File

@ -286,9 +286,17 @@ MODULE_LICENSE("Dual BSD/GPL");
* and endpoint addresses. * and endpoint addresses.
*/ */
//#define DEBUG
//#define VERBOSE
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#if 0
#undef dev_printk
#define dev_printk(level, l, fmt, args...) \
printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args)
#endif
#define xprintk(f,level,fmt,args...) \ #define xprintk(f,level,fmt,args...) \
dev_printk(level , &(f)->gadget->dev , fmt , ## args) dev_printk(level , &(f)->gadget->dev , fmt , ## args)
#define yprintk(l,level,fmt,args...) \ #define yprintk(l,level,fmt,args...) \
@ -358,6 +366,7 @@ static struct {
int removable; int removable;
int can_stall; int can_stall;
int hw_disk_status;
char *transport_parm; char *transport_parm;
char *protocol_parm; char *protocol_parm;
@ -384,7 +393,8 @@ static struct {
.serial = "CYBOR10", .serial = "CYBOR10",
}; };
#undef S_IRUGO
#define S_IRUGO (0644)
module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
S_IRUGO); S_IRUGO);
MODULE_PARM_DESC(file, "names of backing files or devices"); MODULE_PARM_DESC(file, "names of backing files or devices");
@ -404,6 +414,14 @@ MODULE_PARM_DESC(removable, "true to simulate removable media");
module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
MODULE_PARM_DESC(vendor, "USB Vendor ID");
module_param_named(product, mod_data.product, ushort, S_IRUGO);
MODULE_PARM_DESC(product, "USB Product ID");
module_param_named(serial, mod_data.serial, charp, S_IRUGO);
MODULE_PARM_DESC(serial, "Device serial number");
/* In the non-TEST version, only the module parameters listed above /* In the non-TEST version, only the module parameters listed above
* are available. */ * are available. */
@ -416,21 +434,12 @@ module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
"8070, or SCSI)"); "8070, or SCSI)");
module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
MODULE_PARM_DESC(vendor, "USB Vendor ID");
module_param_named(product, mod_data.product, ushort, S_IRUGO);
MODULE_PARM_DESC(product, "USB Product ID");
module_param_named(release, mod_data.release, ushort, S_IRUGO); module_param_named(release, mod_data.release, ushort, S_IRUGO);
MODULE_PARM_DESC(release, "USB release number"); MODULE_PARM_DESC(release, "USB release number");
module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
MODULE_PARM_DESC(buflen, "I/O buffer size"); MODULE_PARM_DESC(buflen, "I/O buffer size");
module_param_named(serial, mod_data.serial, charp, S_IRUGO);
MODULE_PARM_DESC(serial, "Device serial number");
#endif /* CONFIG_USB_FILE_STORAGE_TEST */ #endif /* CONFIG_USB_FILE_STORAGE_TEST */
@ -2072,12 +2081,9 @@ static int do_verify(struct fsg_dev *fsg)
static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
/* Qisda, howard.hsu, 2010/01/26, change usb device name { */
//static char vendor_id[] = "Linux ";
//static char product_id[] = "File-Stor Gadget";
static char vendor_id[] = "Bookeen "; static char vendor_id[] = "Bookeen ";
static char product_id[] = "Cybook Orizon"; static char product_id[] = "Cybook Orizon";
/* } Qisda, howard.hsu, 2010/01/26, change usb device name */
if (!fsg->curlun) { // Unsupported LUNs are okay if (!fsg->curlun) { // Unsupported LUNs are okay
fsg->bad_lun_okay = 1; fsg->bad_lun_okay = 1;
memset(buf, 0, 36); memset(buf, 0, 36);
@ -2263,7 +2269,6 @@ static int do_start_stop(struct fsg_dev *fsg)
loej = fsg->cmnd[4] & 0x02; loej = fsg->cmnd[4] & 0x02;
start = fsg->cmnd[4] & 0x01; start = fsg->cmnd[4] & 0x01;
#ifdef CONFIG_USB_FILE_STORAGE_TEST
if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed
(fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
@ -2273,11 +2278,13 @@ static int do_start_stop(struct fsg_dev *fsg)
if (!start) { if (!start) {
/* Are we allowed to unload the media? */ /* Are we allowed to unload the media? */
#if 0 /* We can't prevent hardware removal */
if (curlun->prevent_medium_removal) { if (curlun->prevent_medium_removal) {
LDBG(curlun, "unload attempt prevented\n"); LDBG(curlun, "unload attempt prevented\n");
curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return -EINVAL; return -EINVAL;
} }
#endif
if (loej) { // Simulate an unload/eject if (loej) { // Simulate an unload/eject
up_read(&fsg->filesem); up_read(&fsg->filesem);
down_write(&fsg->filesem); down_write(&fsg->filesem);
@ -2294,11 +2301,10 @@ static int do_start_stop(struct fsg_dev *fsg)
return -EINVAL; return -EINVAL;
} }
} }
#endif
return 0; return 0;
} }
static int do_prevent_allow(struct fsg_dev *fsg) static int do_prevent_allow(struct fsg_dev *fsg)
{ {
struct lun *curlun = fsg->curlun; struct lun *curlun = fsg->curlun;
@ -3682,11 +3688,13 @@ static ssize_t store_file(struct device *dev, struct device_attribute *attr, con
struct fsg_dev *fsg = dev_get_drvdata(dev); struct fsg_dev *fsg = dev_get_drvdata(dev);
int rc = 0; int rc = 0;
#if 0 /* Current hardware can't prevent remove */
if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) { if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) {
LDBG(curlun, "eject attempt prevented\n"); LDBG(curlun, "eject attempt prevented\n");
return -EBUSY; // "Door is locked" return -EBUSY; // "Door is locked"
} } /* If file[] is NULL, then the media has been physically removed, we can't allow access to it */
#endif
LDBG(curlun, "Will try to mount floppy [%p] '%s'\n", buf, buf);
/* Remove a trailing newline */ /* Remove a trailing newline */
if (count > 0 && buf[count-1] == '\n') if (count > 0 && buf[count-1] == '\n')
((char *) buf)[count-1] = 0; // Ugh! ((char *) buf)[count-1] = 0; // Ugh!
@ -3694,12 +3702,14 @@ static ssize_t store_file(struct device *dev, struct device_attribute *attr, con
/* Eject current medium */ /* Eject current medium */
down_write(&fsg->filesem); down_write(&fsg->filesem);
if (backing_file_is_open(curlun)) { if (backing_file_is_open(curlun)) {
LDBG(curlun, "There is currently a floppy.. Eject it before...\n");
close_backing_file(curlun); close_backing_file(curlun);
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
} }
/* Load new medium */ /* Load new medium */
if (count > 0 && buf[0]) { if (count > 0 && buf[0]) {
LDBG(curlun, "File name is valide, now insert floppy...\n");
rc = open_backing_file(curlun, buf); rc = open_backing_file(curlun, buf);
if (rc == 0) if (rc == 0)
curlun->unit_attention_data = curlun->unit_attention_data =
@ -3889,7 +3899,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
goto out; goto out;
if (mod_data.removable) { // Enable the store_xxx attributes if (mod_data.removable) { // Enable the store_xxx attributes
dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644; dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0664;
dev_attr_status.attr.mode = 0444; dev_attr_status.attr.mode = 0444;
dev_attr_ro.store = store_ro; dev_attr_ro.store = store_ro;
dev_attr_file.store = store_file; dev_attr_file.store = store_file;

View File

@ -901,8 +901,6 @@ static inline void s3c2416_i80_write(int data)
tmp |= SYS_WR_CON; tmp |= SYS_WR_CON;
__raw_writel(tmp, rSIFCCON0); __raw_writel(tmp, rSIFCCON0);
if ( !tcon_inPortraitMode )
tcon_ndelay(25);
__raw_writel(data, rSIFCCON1); //rSIFCCON1 = CMD; __raw_writel(data, rSIFCCON1); //rSIFCCON1 = CMD;

View File

@ -37,14 +37,14 @@
#include <cybook.h> #include <cybook.h>
//#define DEBUG_MESSAGES #define DEBUG_MESSAGES
//#define DEBUG_TRACEFUNC //#define DEBUG_TRACEFUNC
//#define VERBOSE_LEVEL INFO_WARNING #define VERBOSE_LEVEL INFO_VERBOSE
//#define DEBUG_SPI //#define DEBUG_SPI
#define MODULE_NAME "AUO-TCON" #define MODULE_NAME "AUO-TCON"
#define BUSY_WAIT_TIMEOUT (40*5*2) //panel time out = 1s #define BUSY_WAIT_TIMEOUT (40*5*2*2) //panel time out = 1s
#define SYS_WR_CON (1<<6) #define SYS_WR_CON (1<<6)
#define SYS_OE_CON (1<<7) #define SYS_OE_CON (1<<7)
@ -171,6 +171,7 @@ static int _dbg_FunctionLevel = 0;
static int tcon_inPortraitMode = 0; static int tcon_inPortraitMode = 0;
static int tcon_lastModeWas = 0; static int tcon_lastModeWas = 0;
typedef enum Tcon_Speedclasses typedef enum Tcon_Speedclasses
{ {
EN_I80_NONE = -1, EN_I80_NONE = -1,
@ -196,8 +197,7 @@ typedef enum Tcon_PowerMode
TCON_POWER_OFF, TCON_POWER_OFF,
} Tcon_PowerMode; } Tcon_PowerMode;
static Tcon_SpeedclasseValue tcon_speedtable[] = static Tcon_SpeedclasseValue tcon_speedtable[] ={
{
[EN_I80_LANDSCAPE] = [EN_I80_LANDSCAPE] =
{ {
.cs_setup = 0, .cs_setup = 0,
@ -245,11 +245,25 @@ static Tcon_SpeedclasseValue tcon_speedtable[] =
#endif #endif
}; };
static struct proc_dir_entry *epaperProcEntry;
static Tcon_Speedclasses tcon_currentSpeedClass = EN_I80_NONE; static Tcon_Speedclasses tcon_currentSpeedClass = EN_I80_NONE;
static Tcon_PowerMode tcon_currentPowerMode = TCON_POWER_NORMALMODE; static Tcon_PowerMode tcon_currentPowerMode = TCON_POWER_NORMALMODE;
static unsigned short tcon_currentVersion = 0;
void tcon_i80bus_set_speed (Tcon_Speedclasses i80_speed,
unsigned short display_w,
unsigned short display_h,
unsigned char set_clock);
static int tcon_command (sAUOCommand *cmd, char userland);
static int tcon_send_command_start (sAUOCommand *cmd);
static int tcon_send_command_end (sAUOCommand *cmd);
// =========================================================================== // ===========================================================================
// TCON Related functions // TCON Related functions
// =========================================================================== // ===========================================================================
/* /*
1. loops = 1 --> 25ns 1. loops = 1 --> 25ns
2. loops = 75 --> 1 us 2. loops = 75 --> 1 us
@ -284,12 +298,12 @@ static int tcon_wait_ready (void)
iBusyCnt++; iBusyCnt++;
if ( iBusyCnt >= BUSY_WAIT_TIMEOUT ) if ( iBusyCnt >= BUSY_WAIT_TIMEOUT )
{ {
return 0; INFOL(INFO_WARNING, ("TCON Wait timedout!!!"));
return -EIO;
} }
tmp = __raw_readl(S3C2410_GPBDAT); tmp = __raw_readl(S3C2410_GPBDAT);
} }
return 0;
return 1;
} }
/* On the i80 port, /* On the i80 port,
@ -338,8 +352,6 @@ void tcon_i80bus_set_speed(Tcon_Speedclasses i80_speed,
FUNC_IN(); FUNC_IN();
INFOL(INFO_WARNING, ("speedclass: %d\n", i80_speed));
if ( tcon_currentSpeedClass == EN_I80_NONE ) if ( tcon_currentSpeedClass == EN_I80_NONE )
set_clock = true; set_clock = true;
@ -360,6 +372,7 @@ void tcon_i80bus_set_speed(Tcon_Speedclasses i80_speed,
lcd_clock = clk_get(NULL, "hclk"); lcd_clock = clk_get(NULL, "hclk");
HCLK = clk_get_rate(lcd_clock); HCLK = clk_get_rate(lcd_clock);
//printk(KERN_ERR "-------- HCLK: %d --------", HCLK);
clkval = (unsigned int)(HCLK / (display_w * display_h * 50 /* FPS ???? */)); clkval = (unsigned int)(HCLK / (display_w * display_h * 50 /* FPS ???? */));
vclk = (HCLK / (clkval + 1)) / 1000; vclk = (HCLK / (clkval + 1)) / 1000;
@ -396,16 +409,24 @@ static inline void tcon_i80bus_write (int data)
{ {
int tmp; int tmp;
if ( (tcon_lastModeWas == 4) && (!tcon_inPortraitMode) )
tcon_delay(1);
tmp = __raw_readl(S3C_SIFCCON0); // nWE enable tmp = __raw_readl(S3C_SIFCCON0); // nWE enable
tmp |= SYS_WR_CON; tmp |= SYS_WR_CON;
__raw_writel(tmp, S3C_SIFCCON0); __raw_writel(tmp, S3C_SIFCCON0);
if ( (!tcon_inPortraitMode) && (tcon_lastModeWas != 4) ) if ( (!tcon_inPortraitMode) && (tcon_lastModeWas != 4) )
{
tcon_ndelay(25); tcon_ndelay(25);
else if (( tcon_inPortraitMode ) && (tcon_lastModeWas == 4)) }
else if ( tcon_lastModeWas == 4 )
{
if ( tcon_inPortraitMode )
tcon_ndelay(15); tcon_ndelay(15);
else
tcon_delay(1);
}
__raw_writel(data, S3C_SIFCCON1); //rSIFCCON1 = CMD; __raw_writel(data, S3C_SIFCCON1); //rSIFCCON1 = CMD;
@ -469,6 +490,7 @@ static inline void tcon_set_write_to_data(void)
tcon_delay(1); tcon_delay(1);
//FUNC_OUT(); //FUNC_OUT();
} }
static inline void tcon_set_write_to_command (void) static inline void tcon_set_write_to_command (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -481,6 +503,7 @@ static inline void tcon_set_write_to_command(void)
tcon_delay(1); tcon_delay(1);
//FUNC_OUT(); //FUNC_OUT();
} }
static inline void tcon_enable_write (void) static inline void tcon_enable_write (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -493,6 +516,7 @@ static inline void tcon_enable_write(void)
tcon_delay(1); tcon_delay(1);
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_disable_write (void) static inline void tcon_disable_write (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -504,6 +528,7 @@ static inline void tcon_disable_write(void)
tcon_delay(1); tcon_delay(1);
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_enable_read (void) static inline void tcon_enable_read (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -514,6 +539,7 @@ static inline void tcon_enable_read(void)
tcon_delay(1); tcon_delay(1);
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_disable_read (void) static inline void tcon_disable_read (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -524,6 +550,7 @@ static inline void tcon_disable_read(void)
tcon_delay(1); tcon_delay(1);
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_select_chip (void) static inline void tcon_select_chip (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -534,6 +561,7 @@ static inline void tcon_select_chip(void)
tcon_delay(1); tcon_delay(1);
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_unselect_chip (void) static inline void tcon_unselect_chip (void)
{ {
unsigned long tmp; unsigned long tmp;
@ -545,26 +573,165 @@ static inline void tcon_unselect_chip(void)
FUNC_OUT(); FUNC_OUT();
} }
static inline void tcon_set_power_on(void) static inline void tcon_goto_sleep (void)
{
/* Set GPIO accordingly */
unsigned long tmp = __raw_readl(S3C2410_GPBDAT);
tmp &= ~(1 << 1); //Set SLP_N to low
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
}
static inline void tcon_wakeup_sleep (void)
{ {
unsigned long tmp = __raw_readl(S3C2410_GPBDAT); unsigned long tmp = __raw_readl(S3C2410_GPBDAT);
tmp |= (1 << 3); tmp |= (1 << 1); //Set SLP_N to high
__raw_writel(tmp, S3C2410_GPBDAT); __raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
}
static inline void tcon_reset (void)
{
// LCD module reset
unsigned long tmp = __raw_readl(S3C2410_GPDDAT);
tmp |= (1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
tmp = __raw_readl(S3C2410_GPDDAT); // RST_N goes to LOW
tmp &= ~(1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
tcon_delay(5);
tmp = __raw_readl(S3C2410_GPDDAT); // RST_N goes to HIGH
tmp |= (1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
// delay about 10ms
msleep(10);
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
/* Reseting the TCON will set the tcon in Level0 power mode */
tcon_currentPowerMode = TCON_POWER_NORMALMODE;
}
static inline void tcon_set_power_on (void)
{
unsigned long tmp;
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 800, 600, true);
// POWER pin config
tmp = __raw_readl(S3C2410_GPBCON);
tmp = (tmp & ~(3 << 6)) | (1 << 6);
__raw_writel(tmp, S3C2410_GPBCON);
// BUSY pin config
tmp = __raw_readl(S3C2410_GPBCON);
tmp = (tmp & ~(3 << 4));
__raw_writel(tmp, S3C2410_GPBCON);
// SLEEP pin config
tmp = __raw_readl(S3C2410_GPBCON);
tmp = (tmp & ~(3 << 2)) | (1 << 2);
__raw_writel(tmp, S3C2410_GPBCON);
msleep(1);
// Panel power on
tmp = __raw_readl(S3C2410_GPBDAT);
tmp |= (1 << 3);
//SLP_N high
tmp |= (1 << 1);
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(100);
tcon_reset();
tcon_currentPowerMode = TCON_POWER_NORMALMODE; tcon_currentPowerMode = TCON_POWER_NORMALMODE;
} }
static inline void tcon_set_power_off(void) static inline int tcon_set_power_off (void)
{ {
unsigned long tmp = __raw_readl(S3C2410_GPBDAT); unsigned long tmp;
sAUOCommand cmd;
switch ( tcon_currentPowerMode )
{
default:
return -EBADF; /* Invalide power mode, can't shutdown... */
break;
case TCON_POWER_NORMALMODE:
cmd.cmd = AUOCMD_STANDBY;
tcon_command(&cmd, false);
case TCON_POWER_STANDBYMODE:
tcon_goto_sleep();
case TCON_POWER_SLEEPMODE:
/*Standby -> Off = shutdown the power pin */
tmp = __raw_readl(S3C2410_GPBDAT);
tmp &= ~(1 << 3); tmp &= ~(1 << 3);
__raw_writel(tmp, S3C2410_GPBDAT); __raw_writel(tmp, S3C2410_GPBDAT);
tcon_currentPowerMode = TCON_POWER_OFF; case TCON_POWER_OFF:
break;
} }
tcon_currentPowerMode = TCON_POWER_OFF;
return 0;
}
int tcon_send_command_start(sAUOCommand *cmd) struct tcon_info
{
unsigned short temperature,
epd_type,
panel_size_int,
panel_size_float,
model,
lut_version,
tcon_version;
};
static void tcon_get_info (struct tcon_info *info)
{
sAUOCommand cmd;
unsigned short buf[4] = { 0, 0, 0, 0 };
if ( info == NULL )
return;
cmd.cmd = AUOCMD_READ_FUNC;
cmd.data = buf;
cmd.datalen = 8;
tcon_command(&cmd, false);
info->temperature = buf[0] & 0x01FF;
info->epd_type = buf[1] & 0x00FF;
info->panel_size_int = (buf[2] & 0xFC00) >> 10;
info->panel_size_float = (buf[2] & 0x03C0) >> 6;
info->model = buf[2] & 0x003F;
info->lut_version = buf[3] & 0x00FF;
info->tcon_version = (buf[3] & 0xFF00) >> 8;
tcon_currentVersion = info->tcon_version;
}
static void tcon_display_info (void)
{
struct tcon_info info;
tcon_get_info(&info);
printk("TCON FW v%d, LUT v%d, EPD {v[%d];Size[%d:%d];Model[%d]}\n",
info.tcon_version, info.lut_version,
info.epd_type, info.panel_size_int, info.panel_size_float, info.model);
if ( tcon_currentVersion != AUO_FIRMWARE_VERSION )
printk(KERN_WARNING "!!! Warning: TCON Firmware version and Driver version mismatch !!!\n");
}
static int tcon_send_command_start (sAUOCommand *cmd)
{ {
FUNC_IN(); FUNC_IN();
INFOL(INFO_DEBUG, ("cmd #%08lX", cmd->cmd)); INFOL(INFO_DEBUG, ("cmd #%08lX", cmd->cmd));
@ -574,14 +741,25 @@ int tcon_send_command_start(sAUOCommand *cmd)
if ( GET_COMMAND_NEED_WAIT(cmd->cmd) != 0x00 ) if ( GET_COMMAND_NEED_WAIT(cmd->cmd) != 0x00 )
{ {
INFOL(INFO_DEBUG, ("Wait for non BUSY...")); INFOL(INFO_DEBUG, ("Wait for non BUSY..."));
tcon_wait_ready(); // TODO: return error on timeout
if ( tcon_wait_ready() < 0 )
{
INFOL(INFO_ERROR, ("Waiting timed out"));
return -EIO;
}
} }
if (cmd->cmd == AUOCMD_STANDBY) if ( AUOCMD_EQUAL(cmd->cmd, AUOCMD_STANDBY) )
{
INFOL(INFO_VERBOSE, ("TCON Switching to Standby mode (Level1)"));
tcon_currentPowerMode = TCON_POWER_STANDBYMODE; tcon_currentPowerMode = TCON_POWER_STANDBYMODE;
else if (cmd->cmd == AUOCMD_WAKEUP) }
else if ( AUOCMD_EQUAL(cmd->cmd, AUOCMD_WAKEUP) )
{
INFOL(INFO_VERBOSE, ("TCON Switching to Normal mode (Level0)"));
tcon_currentPowerMode = TCON_POWER_NORMALMODE; tcon_currentPowerMode = TCON_POWER_NORMALMODE;
else if (cmd->cmd == AUOCMD_INIT_SET) }
else if ( AUOCMD_EQUAL(cmd->cmd, AUOCMD_INIT_SET) )
{ {
tcon_inPortraitMode = ~(cmd->params[0]) & (0x1 << 10); tcon_inPortraitMode = ~(cmd->params[0]) & (0x1 << 10);
if ( tcon_lastModeWas != 4 ) if ( tcon_lastModeWas != 4 )
@ -600,12 +778,11 @@ int tcon_send_command_start(sAUOCommand *cmd)
} }
INFOL(INFO_DEBUG, ("Rotation set to 0x%08X...", tcon_inPortraitMode)); INFOL(INFO_DEBUG, ("Rotation set to 0x%08X...", tcon_inPortraitMode));
} }
else if (cmd->cmd == AUOCMD_DISPLAY_START) else if ( AUOCMD_EQUAL(cmd->cmd, AUOCMD_DISPLAY_START) )
{ {
INFOL(INFO_VERBOSE, ("Display Start (lastMode: %d)...", tcon_lastModeWas)); INFOL(INFO_DEBUG, ("Display Start (lastMode: %d)...", tcon_lastModeWas));
if ( ((cmd->params[0] >> 12) & 0x07) == 4 ) /* Handwriting mode... */ if ( ((cmd->params[0] >> 12) & 0x07) == 4 ) /* Handwriting mode... */
{ {
INFOL(INFO_VERBOSE, ("Mode 4"));
if ( tcon_inPortraitMode ) if ( tcon_inPortraitMode )
tcon_i80bus_set_speed(EN_I80_PORTRAIT_HANDWRITING, 800, 600, false); tcon_i80bus_set_speed(EN_I80_PORTRAIT_HANDWRITING, 800, 600, false);
else else
@ -613,7 +790,6 @@ int tcon_send_command_start(sAUOCommand *cmd)
} }
else if ( tcon_lastModeWas == 4 ) else if ( tcon_lastModeWas == 4 )
{ {
INFOL(INFO_VERBOSE, ("--- NOT --- mode 4 (%d)", ((cmd->params[0] >> 12) & 0x07)));
if ( tcon_inPortraitMode ) if ( tcon_inPortraitMode )
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false); tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
else else
@ -655,7 +831,7 @@ int tcon_send_command_start(sAUOCommand *cmd)
return 0; return 0;
} }
int tcon_send_data(unsigned short *buffer, unsigned long bufferLen) static int tcon_send_data (unsigned short *buffer, unsigned long bufferLen)
{ {
/* Seventh: Send data if needed */ /* Seventh: Send data if needed */
unsigned long i; unsigned long i;
@ -673,7 +849,7 @@ int tcon_send_data(unsigned short *buffer, unsigned long bufferLen)
return 0; return 0;
} }
int tcon_send_lut_data(unsigned short *buffer, unsigned long bufferLen) static int tcon_send_lut_data (unsigned short *buffer, unsigned long bufferLen)
{ {
/* Seventh: Send data if needed */ /* Seventh: Send data if needed */
unsigned long i; unsigned long i;
@ -695,11 +871,10 @@ int tcon_send_lut_data(unsigned short *buffer, unsigned long bufferLen)
return 0; return 0;
} }
static int tcon_read_data (unsigned short *buffer, unsigned long bufferLen)
int tcon_read_data(unsigned short *buffer, unsigned long bufferLen)
{ {
unsigned long i; unsigned long i;
//FUNC_IN(); FUNC_IN();
//INFOL(INFO_VERBOSE, ("Bufferlen: %ld", bufferLen)); //INFOL(INFO_VERBOSE, ("Bufferlen: %ld", bufferLen));
@ -709,16 +884,16 @@ int tcon_read_data(unsigned short *buffer, unsigned long bufferLen)
{ {
tcon_i80bus_read(&(buffer[i])); tcon_i80bus_read(&(buffer[i]));
} }
//FUNC_OUT(); FUNC_OUT();
return 0; return 0;
} }
int tcon_send_command_end(sAUOCommand *cmd) static int tcon_send_command_end (sAUOCommand *cmd)
{ {
FUNC_IN(); FUNC_IN();
INFOL(INFO_DEBUG, ("cmd #%08lX START:[#%08X]", cmd->cmd, AUOCMD_DISPLAY_START)); INFOL(INFO_DEBUG, ("cmd #%08lX START:[#%08X]", cmd->cmd, AUOCMD_DISPLAY_START));
if (cmd->cmd == AUOCMD_DISPLAY_START) if ( AUOCMD_EQUAL(cmd->cmd, AUOCMD_DISPLAY_START) )
{ {
tcon_set_write_to_command(); tcon_set_write_to_command();
INFOL(INFO_DEBUG, ("/* Eight: Send STOP command */")); INFOL(INFO_DEBUG, ("/* Eight: Send STOP command */"));
@ -742,7 +917,7 @@ int tcon_send_command_end(sAUOCommand *cmd)
#define TCON_SPI_DO S3C2410_GPE12 #define TCON_SPI_DO S3C2410_GPE12
#define TCON_SPI_CS S3C2410_GPL13 #define TCON_SPI_CS S3C2410_GPL13
static void tcon_spi_init(void) static int tcon_spi_init (void)
{ {
FUNC_IN(); FUNC_IN();
/* First be sure that the Wifi is off */ /* First be sure that the Wifi is off */
@ -752,7 +927,8 @@ static void tcon_spi_init(void)
writel((readl(S3C2416_GPKDAT) & ~(1 << 6)), S3C2416_GPKDAT); writel((readl(S3C2416_GPKDAT) & ~(1 << 6)), S3C2416_GPKDAT);
/* Next, shutdown the TCON */ /* Next, shutdown the TCON */
tcon_set_power_off(); if ( tcon_set_power_off() != 0 )
return -1;
mdelay(2000); mdelay(2000);
//GPD8, RESET //GPD8, RESET
@ -785,6 +961,7 @@ static void tcon_spi_init(void)
/* We are ready ! */ /* We are ready ! */
FUNC_OUT(); FUNC_OUT();
return 0;
} }
static void tcon_spi_deinit (void) static void tcon_spi_deinit (void)
@ -966,6 +1143,7 @@ static void tcon_spi_flash_writepage(unsigned long addr, unsigned char *buffer,
// =========================================================================== // ===========================================================================
// Device related functions // Device related functions
// =========================================================================== // ===========================================================================
static int tcon_open (struct inode *inode, struct file *file) static int tcon_open (struct inode *inode, struct file *file)
{ {
FUNC_IN(); FUNC_IN();
@ -984,7 +1162,7 @@ static int tcon_release (struct inode *inode, struct file *file)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
ssize_t tcon_read (struct file *file, char *buf, size_t count, loff_t *ppos) static ssize_t tcon_read (struct file *file, char *buf, size_t count, loff_t *ppos)
{ {
FUNC_IN(); FUNC_IN();
@ -993,22 +1171,100 @@ ssize_t tcon_read (struct file *file, char *buf, size_t count, loff_t *ppos)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
int tcon_ioctl (struct inode *inode, struct file *file, static int tcon_command (sAUOCommand *cmd, char userland)
{
unsigned char buffer[2048];
unsigned char *user_buffer;
unsigned long user_buflen, copysize, copysize16;
unsigned short *ptr16;
//int block_id;
int ret = 0;
/* Now execute the command */
if ( tcon_send_command_start(cmd) != 0 )
{
ret = -EIO;
goto exit;
}
if ( GET_COMMAND_HAVE_DATA(cmd->cmd) != 0 )
{
user_buflen = cmd->datalen;
user_buffer = (unsigned char *)cmd->data;
while ( user_buflen != 0 )
{
copysize = user_buflen;
if ( user_buflen > sizeof (buffer) )
copysize = sizeof (buffer);
if ( GET_COMMAND_READ_WRITE(cmd->cmd) == 0 )
{ /* Write mode */
if (userland)
{
if ( copy_from_user(buffer, user_buffer, copysize) )
{
ret = -EFAULT;
goto exit;
}
}
else
{
memcpy(buffer, user_buffer, copysize);
}
}
copysize16 = (copysize + 1) / 2;
ptr16 = (unsigned short *)buffer;
if ( GET_COMMAND_READ_WRITE(cmd->cmd) == 0 )
{ /* Write mode */
if ( cmd->cmd == AUOCMD_LUT_START )
tcon_send_lut_data((unsigned short *)buffer, copysize16);
else
tcon_send_data((unsigned short *)buffer, copysize16);
}
else
{ /* Read mode */
tcon_read_data((unsigned short *)buffer, copysize16);
if (userland)
{
if ( copy_to_user(user_buffer, buffer, copysize) )
return -EFAULT;
}
else
{
memcpy(user_buffer, buffer, copysize);
}
}
user_buflen -= copysize;
user_buffer += copysize;
}
}
tcon_send_command_end(cmd);
exit:
return ret;
}
static int tcon_ioctl (struct inode *inode, struct file *file,
unsigned int ioctl_cmd, unsigned long arg) unsigned int ioctl_cmd, unsigned long arg)
{ {
sAUOCommand cmd; sAUOCommand cmd;
unsigned char buffer[2048]; unsigned char buffer[2048];
unsigned char *user_buffer; unsigned char *user_buffer;
unsigned long user_buflen, copysize, copysize16; unsigned long user_buflen, copysize;
unsigned short *ptr16;
unsigned long tmp;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int block_id = 0; int block_id;
int flash_addr; int flash_addr;
int ret = -EINVAL; int ret = -EINVAL;
FUNC_IN(); FUNC_IN();
INFOL(INFO_VERBOSE, ("Receive IOTCL #08%X", ioctl_cmd));
block_id = 0;
//INFOL(INFO_VERBOSE, ("Receive IOTCL #08%X", ioctl_cmd));
switch ( ioctl_cmd ) switch ( ioctl_cmd )
{ {
case IOCTL_AUO_SENDCOMMAND: case IOCTL_AUO_SENDCOMMAND:
@ -1023,92 +1279,49 @@ int tcon_ioctl (struct inode *inode, struct file *file,
if ( (GET_COMMAND_HAVE_DATA(cmd.cmd) != 0) && (cmd.datalen > 0) && (cmd.data == NULL) ) if ( (GET_COMMAND_HAVE_DATA(cmd.cmd) != 0) && (cmd.datalen > 0) && (cmd.data == NULL) )
return -EFAULT; return -EFAULT;
/* Now execute the command */ ret = tcon_command(&cmd, true);
tcon_send_command_start(&cmd);
///INFOL(INFO_VERBOSE, ("/* Seventh: Send data if needed */")); //INFOL(INFO_VERBOSE, ("tcon_command returned: %d", ret));
if ( GET_COMMAND_HAVE_DATA(cmd.cmd) != 0 )
{
//INFOL(INFO_VERBOSE, ("Yes, we have data to send!"));
user_buflen = cmd.datalen;
user_buffer = (unsigned char *)cmd.data;
while ( user_buflen != 0 )
{
copysize = user_buflen;
if ( user_buflen > sizeof (buffer) )
copysize = sizeof (buffer);
if (GET_COMMAND_READ_WRITE(cmd.cmd) == 0)
{ /* Write mode */
if ( copy_from_user(buffer, user_buffer, copysize) )
return -EFAULT;
}
copysize16 = (copysize + 1) / 2;
//printk(KERN_ERR "cp16=%ld cp=%ld\n", copysize16, copysize);
ptr16 = (unsigned short *)buffer;
if (GET_COMMAND_READ_WRITE(cmd.cmd) == 0)
{ /* Write mode */
INFOL(INFO_DEBUG, ("Will send block %d", block_id++));
if (cmd.cmd == AUOCMD_LUT_START)
tcon_send_lut_data((unsigned short *)buffer, copysize16);
else
tcon_send_data((unsigned short *)buffer, copysize16);
}
else
{
tcon_read_data((unsigned short *)buffer, copysize16);
if ( copy_to_user(user_buffer, buffer, copysize) )
return -EFAULT;
}
user_buflen -= copysize;
user_buffer += copysize;
}
}
tcon_send_command_end(&cmd);
ret = 0;
break; break;
case IOCTL_AUO_RESET: case IOCTL_AUO_RESET:
tmp = __raw_readl(S3C2410_GPDDAT); // RST_N goes to LOW tcon_reset();
tmp &= ~(1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
tcon_delay(5);
tmp = __raw_readl(S3C2410_GPDDAT); // RST_N goes to HIGH
tmp |= (1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
// delay about 10ms
msleep(10);
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
ret = 0; ret = 0;
break; break;
case IOCTL_AUO_POWEROFF:
//
INFOL(INFO_VERBOSE, ("Switching to power OFF (Level3)..."));
ret = tcon_set_power_off();
break;
case IOCTL_AUO_POWERON:
//
INFOL(INFO_VERBOSE, ("Switching to power Normal Mode (Level0)..."));
tcon_set_power_on();
ret = 0;
break;
case IOCTL_AUO_WAITBUSY:
ret = tcon_wait_ready();
break;
case IOCTL_AUO_SLEEP: case IOCTL_AUO_SLEEP:
/* Only accept go to sleep if we are in standby, or else it will fail */ /* Only accept go to sleep if we are in standby, or else it will fail */
if ( tcon_currentPowerMode == TCON_POWER_STANDBYMODE ) if ( tcon_currentPowerMode == TCON_POWER_STANDBYMODE )
{ {
INFOL(INFO_VERBOSE, ("Switching Standby to Sleep mode (Level2)..."));
tcon_currentPowerMode = TCON_POWER_SLEEPMODE; tcon_currentPowerMode = TCON_POWER_SLEEPMODE;
/* Set GPIO accordingly */ tcon_goto_sleep();
tmp = __raw_readl(S3C2410_GPBDAT);
tmp &= ~(1 << 1); //Set SLP_N to low
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
ret = 0; ret = 0;
} }
else else
{
ret = -ENAVAIL; ret = -ENAVAIL;
}
break; break;
@ -1116,12 +1329,12 @@ int tcon_ioctl (struct inode *inode, struct file *file,
/* Only accept go to sleep if we are in standby, or else it will fail */ /* Only accept go to sleep if we are in standby, or else it will fail */
if ( tcon_currentPowerMode == TCON_POWER_SLEEPMODE ) if ( tcon_currentPowerMode == TCON_POWER_SLEEPMODE )
{ {
INFOL(INFO_VERBOSE, ("Switching Sleep to Standby Mode (Level1)..."));
tcon_currentPowerMode = TCON_POWER_STANDBYMODE; tcon_currentPowerMode = TCON_POWER_STANDBYMODE;
/* Set GPIO accordingly */ /* Set GPIO accordingly */
tmp = __raw_readl(S3C2410_GPBDAT);
tmp |= (1 << 1); //Set SLP_N to high tcon_wakeup_sleep();
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
ret = 0; ret = 0;
} }
else else
@ -1137,8 +1350,6 @@ int tcon_ioctl (struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
} }
INFOL(INFO_VERBOSE, ("Starting update of TCON firmware..."));
if ( (cmd.data == NULL) || (cmd.datalen == 0) ) if ( (cmd.data == NULL) || (cmd.datalen == 0) )
{ {
INFOL(INFO_ERROR, ("Parameters error...")); INFOL(INFO_ERROR, ("Parameters error..."));
@ -1146,7 +1357,7 @@ int tcon_ioctl (struct inode *inode, struct file *file,
} }
/* First init SPI */ /* First init SPI */
INFOL(INFO_VERBOSE, ("Will init BitBang SPI...")); INFOL(INFO_DEBUG, ("Will init BitBang SPI..."));
tcon_spi_init(); tcon_spi_init();
mdelay(3000); mdelay(3000);
@ -1190,9 +1401,34 @@ int tcon_ioctl (struct inode *inode, struct file *file,
tcon_spi_deinit(); tcon_spi_deinit();
break; break;
case IOCTL_AUO_PROGRESSBAR:
{
unsigned short *buf;
copysize = (arg * 492) / 100;
copysize -= (copysize % 8);
buf = (unsigned short *)kmalloc(copysize * 24 * 4, GFP_KERNEL);
if ( buf )
{
memset(buf, 0x00, copysize * 24 * 4);
cmd.cmd = AUOCMD_DISPLAY_START;
cmd.params[0] = AUO_DSPPARAM_MODE_GRAYnFLASH | ((((600 - 500) / 2) + 4) & 0x0FFF);
cmd.params[1] = (((800 - (30 + 20)) + 4) & 0x0FFF);
cmd.params[2] = ((copysize) & 0x0FFF);
cmd.params[3] = (24 & 0x0FFF);
cmd.data = buf;
cmd.datalen = ((copysize>>1) * 24) >> 1;
tcon_command(&cmd, false);
kfree(buf);
}
ret = 0;
}
break;
default: default:
printk(KERN_WARNING "Invalid ioctl"); printk(KERN_WARNING "Invalid IOCTL");
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
@ -1201,8 +1437,7 @@ int tcon_ioctl (struct inode *inode, struct file *file,
return ret; return ret;
} }
// =========================================================================== // ===========================================================================
static struct file_operations s_tcon_fops = static struct file_operations s_tcon_fops ={
{
owner : THIS_MODULE, owner : THIS_MODULE,
read : tcon_read, read : tcon_read,
ioctl : tcon_ioctl, ioctl : tcon_ioctl,
@ -1210,8 +1445,7 @@ static struct file_operations s_tcon_fops =
release : tcon_release, release : tcon_release,
}; };
static struct miscdevice s_tcon_dev = static struct miscdevice s_tcon_dev ={
{
.minor = 242, .minor = 242,
.name = "epaper", .name = "epaper",
.fops = &s_tcon_fops, .fops = &s_tcon_fops,
@ -1230,13 +1464,14 @@ static int tcon_probe (struct platform_device *dev)
printk(" ok\n"); printk(" ok\n");
ret = 0; ret = 0;
printk("Cybook Orizon Layout\n");
// set gpio for lcd // set gpio for lcd
tmp = __raw_readl(S3C2410_GPCCON); tmp = __raw_readl(S3C2410_GPCCON);
//tmp = (tmp & ~(0xffff03ff))|(0xaaaa02aa); //tmp = (tmp & ~(0xffff03ff))|(0xaaaa02aa);
tmp = (tmp & ~(0xffff033f)) | (0xaaaa022a); //Do not config SYS_CS1(GPC3) tmp = (tmp & ~(0xffff033f)) | (0xaaaa022a); //Do not config SYS_CS1(GPC3)
__raw_writel(tmp, S3C2410_GPCCON); __raw_writel(tmp, S3C2410_GPCCON);
printk("Cybook Orizon Layout\n");
tmp = __raw_readl(S3C2410_GPDCON); //tmp=0x40000 tmp = __raw_readl(S3C2410_GPDCON); //tmp=0x40000
tmp = (tmp & ~(0x0CFFFF)) | (0x04AAAA); tmp = (tmp & ~(0x0CFFFF)) | (0x04AAAA);
__raw_writel(tmp, S3C2410_GPDCON); // GPD9 is RST_N __raw_writel(tmp, S3C2410_GPDCON); // GPD9 is RST_N
@ -1244,6 +1479,7 @@ static int tcon_probe (struct platform_device *dev)
__raw_writel(0, S3C2410_GPCUP); //S3C2410_GPCUP = 0; __raw_writel(0, S3C2410_GPCUP); //S3C2410_GPCUP = 0;
__raw_writel(0, S3C2410_GPDUP); //S3C2410_GPDUP = 0; __raw_writel(0, S3C2410_GPDUP); //S3C2410_GPDUP = 0;
#if 0
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 800, 600, true); tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 800, 600, true);
// POWER pin config // POWER pin config
@ -1272,6 +1508,7 @@ static int tcon_probe (struct platform_device *dev)
msleep(100); msleep(100);
// LCD module reset // LCD module reset
tmp = __raw_readl(S3C2410_GPDDAT); tmp = __raw_readl(S3C2410_GPDDAT);
tmp |= (1 << 9); tmp |= (1 << 9);
@ -1291,6 +1528,11 @@ static int tcon_probe (struct platform_device *dev)
msleep(10); msleep(10);
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false); tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
#else
tcon_set_power_on();
#endif
tcon_display_info();
} }
else else
printk(" not ok\n"); printk(" not ok\n");
@ -1313,6 +1555,8 @@ static int tcon_resume (struct platform_device *dev)
{ {
FUNC_IN(); FUNC_IN();
//tcon_set_power_on();
if ( tcon_inPortraitMode ) if ( tcon_inPortraitMode )
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, true); tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, true);
else else
@ -1329,6 +1573,8 @@ static int tcon_suspend (struct platform_device *dev, pm_message_t state)
DBG("state event: %X", state.event); DBG("state event: %X", state.event);
//tcon_set_power_off();
FUNC_OUT(); FUNC_OUT();
return 0; return 0;
} }
@ -1347,6 +1593,24 @@ static struct platform_driver tcon_driver ={
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// =========================================================================== // ===========================================================================
static int tcon_procReadEpaper (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int len;
struct tcon_info info;
tcon_get_info(&info);
len = sprintf(page, "tcon_k1900;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
tcon_currentPowerMode, tcon_currentSpeedClass,
info.tcon_version, info.lut_version,
info.temperature>>1, info.model,
info.epd_type, info.panel_size_int, info.panel_size_float);
return len;
}
// ===========================================================================
static int __init tcon_init (void) static int __init tcon_init (void)
{ {
int ret = 0; int ret = 0;
@ -1362,6 +1626,10 @@ static int __init tcon_init (void)
platform_driver_register(&tcon_driver); platform_driver_register(&tcon_driver);
epaperProcEntry = create_proc_entry("epaper", 0644, proc_root_driver);
epaperProcEntry->read_proc = tcon_procReadEpaper;
epaperProcEntry->owner = THIS_MODULE;
exit: exit:
FUNC_OUTR(ret); FUNC_OUTR(ret);
return ret; return ret;
@ -1375,6 +1643,7 @@ static void __exit tcon_exit (void)
platform_driver_unregister(&tcon_driver); platform_driver_unregister(&tcon_driver);
misc_deregister(&s_tcon_dev); misc_deregister(&s_tcon_dev);
remove_proc_entry("epaper", proc_root_driver);
FUNC_OUT(); FUNC_OUT();
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -21,7 +21,7 @@
#ifndef AUOFB_IOCTL_H #ifndef AUOFB_IOCTL_H
#define AUOFB_IOCTL_H #define AUOFB_IOCTL_H
#define AUO_FIRMWARE_VERSION 33 #define AUO_FIRMWARE_VERSION 39
#pragma pack(1) #pragma pack(1)
typedef struct sAUOCommand_t typedef struct sAUOCommand_t
@ -45,6 +45,8 @@ typedef struct sAUOCommand_t
#define IOCTL_AUO_POWERON (IOCTL_AUO_PREFIX | 0x05) #define IOCTL_AUO_POWERON (IOCTL_AUO_PREFIX | 0x05)
#define IOCTL_AUO_POWEROFF (IOCTL_AUO_PREFIX | 0x06) #define IOCTL_AUO_POWEROFF (IOCTL_AUO_PREFIX | 0x06)
#define IOCTL_AUO_UPDATEFW (IOCTL_AUO_PREFIX | 0x07) #define IOCTL_AUO_UPDATEFW (IOCTL_AUO_PREFIX | 0x07)
#define IOCTL_AUO_PROGRESSBAR (IOCTL_AUO_PREFIX | 0x08)
#define IOCTL_AUO_WAITBUSY (IOCTL_AUO_PREFIX | 0x09)
/* Command definition * /* Command definition *
* 3322 2222 2222 1111 1111 1100 0000 0000 * * 3322 2222 2222 1111 1111 1100 0000 0000 *
@ -68,7 +70,7 @@ typedef struct sAUOCommand_t
#define SET_AUO_COMMAND SET_AUO_WRITE_COMMAND #define SET_AUO_COMMAND SET_AUO_WRITE_COMMAND
#define SET_AUO_READ_COMMAND(command, nb_param, have_data, need_wait) SET_AUO_COMMAND_EXT(command, nb_param, have_data, need_wait, 1) #define SET_AUO_READ_COMMAND(command, nb_param, have_data, need_wait) SET_AUO_COMMAND_EXT(command, nb_param, have_data, need_wait, 1)
#if (AUO_FIRMWARE_VERSION == 33) /* Command set for TCON firmware v33 */ #if (AUO_FIRMWARE_VERSION >= 33) /* Command set for TCON firmware v33 and more */
/* Initialisation commands */ /* Initialisation commands */
#define AUOCMD_INIT_SET SET_AUO_COMMAND(0x0000, 1, 0, 1) #define AUOCMD_INIT_SET SET_AUO_COMMAND(0x0000, 1, 0, 1)
@ -76,7 +78,7 @@ typedef struct sAUOCommand_t
#define AUOCMD_VCOM_FRAMERATE SET_AUO_COMMAND(0x0004, 1, 0, 0) #define AUOCMD_VCOM_FRAMERATE SET_AUO_COMMAND(0x0004, 1, 0, 0)
/* Power management */ /* Power management */
#define AUOCMD_STANDBY SET_AUO_COMMAND(0x0001, 0, 0, 1) #define AUOCMD_STANDBY SET_AUO_COMMAND(0x0001, 1, 0, 1)
#define AUOCMD_WAKEUP SET_AUO_COMMAND(0x0002, 0, 0, 0) #define AUOCMD_WAKEUP SET_AUO_COMMAND(0x0002, 0, 0, 0)
/* Display commands */ /* Display commands */
@ -120,7 +122,6 @@ typedef struct sAUOCommand_t
#define AUO_DSPPARAM_MODE_TEXT (0x02 << 12) /* Mode 2: Text mode 2bit */ #define AUO_DSPPARAM_MODE_TEXT (0x02 << 12) /* Mode 2: Text mode 2bit */
#define AUO_DSPPARAM_MODE_HIGHSPEED (0x03 << 12) /* Mode 3: Highspeed mode 1bit */ #define AUO_DSPPARAM_MODE_HIGHSPEED (0x03 << 12) /* Mode 3: Highspeed mode 1bit */
#define AUO_DSPPARAM_MODE_HANDWRITE (0x04 << 12) /* Mode 4: Handwriting mode 1bit */ #define AUO_DSPPARAM_MODE_HANDWRITE (0x04 << 12) /* Mode 4: Handwriting mode 1bit */
#define AUO_DSPPARAM_MODE_AUTOSELECT (0x05 << 12) /* Mode 5: Autoselect mode */
/* INIT_SET command parameters */ /* INIT_SET command parameters */
#define AUO_INITPARAM_OUT_DATA_ARR (0x01 << 5) /* Set to 0 (default) for normal, 1 for inverse byte order */ #define AUO_INITPARAM_OUT_DATA_ARR (0x01 << 5) /* Set to 0 (default) for normal, 1 for inverse byte order */
@ -145,12 +146,12 @@ typedef struct sAUOCommand_t
#define AUO_INITPARAM_DATA_FILTER (0x01 << 12) /* Data filter (1: active, 0: inactive) */ #define AUO_INITPARAM_DATA_FILTER (0x01 << 12) /* Data filter (1: active, 0: inactive) */
#define AUO_INITPARAM_TEMP_AVERAGE (0x01 << 13) /* Temperature average (1: active, 0: inactive) */ #define AUO_INITPARAM_TEMP_AVERAGE (0x01 << 13) /* Temperature average (1: active, 0: inactive) */
int Epaper_sendCommand(sAUOCommand *cmd);
/* Please, do not use these #define s */ /* Please, do not use these #define s */
#define GET_COMMAND_PARAM_NUM(command) ((command >> 20) & 0x0F) #define GET_COMMAND_PARAM_NUM(command) ((command >> 20) & 0x0F)
#define GET_COMMAND_HAVE_DATA(command) ((command >> 28) & 0x01) #define GET_COMMAND_HAVE_DATA(command) ((command >> 28) & 0x01)
#define GET_COMMAND_NEED_WAIT(command) ((command >> 29) & 0x01) #define GET_COMMAND_NEED_WAIT(command) ((command >> 29) & 0x01)
#define GET_COMMAND_READ_WRITE(command) ((command >> 30) & 0x01) #define GET_COMMAND_READ_WRITE(command) ((command >> 30) & 0x01)
#define AUOCMD_EQUAL(c,v) (((c) & 0xFFFF) == ((v) & 0xFFFF))
#endif /* AUOFB_IOCTL_H */ #endif /* AUOFB_IOCTL_H */

View File

@ -1,10 +1,11 @@
// =========================================================================== // ===========================================================================
// cyio.h // Cybook Event Manager - cyevent.h
// Copyright (C) 2008-2010 Bookeen - All rights reserved // Copyright (C) 2008-2010 Bookeen - All rights reserved
// =========================================================================== // ===========================================================================
#define CYIO_EVENT_VERSION 1 #define CYEV_CURRENT_VERSION 0x10 /* 1.0 */
#pragma pack(1)
typedef struct sCyEvent_t typedef struct sCyEvent_t
{ {
unsigned char type; unsigned char type;
@ -19,19 +20,26 @@ typedef struct sCyEvent_t
unsigned short y1; unsigned short y1;
unsigned short x2; unsigned short x2;
unsigned short y2; unsigned short y2;
unsigned char fingers;
} touch; } touch;
struct unsigned char key;
{ unsigned char orientation;
unsigned char key_ascii; unsigned char timer_type;
} key;
} data; } data;
} CyEvent_t; } CyEvent_t;
#pragma pack()
#define NEW_CYEVENT(evType) { \
.type = evType, \
.flags = 0, \
.version = CYEV_CURRENT_VERSION, \
.data.raw = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }
enum enum
{ {
CYEVENT_TYPE_KEY = 'k', CYEVENT_TYPE_KEY = 'k',
CYEVENT_TYPE_TOUCH = 't', CYEVENT_TYPE_TOUCH = 't',
CYEVENT_TYPE_ACCEL = 'a', CYEVENT_TYPE_ORIENTATION = 'o',
CYEVENT_TYPE_TIMER = 'z', CYEVENT_TYPE_TIMER = 'z',
CYEVENT_TYPE_SYSTEM = 's', CYEVENT_TYPE_SYSTEM = 's',
//CYIO_EVENT_ = '', //CYIO_EVENT_ = '',
@ -53,42 +61,69 @@ enum
#define CYEVENT_KEY_VOLN '-' #define CYEVENT_KEY_VOLN '-'
#define CYEVENT_KEY_TOGGLE_ACCEL 'a' #define CYEVENT_KEY_TOGGLE_ACCEL 'a'
#define CYEVENT_KEY_FACTORY_RESET 'f' #define CYEVENT_KEY_FACTORY_RESET 'f'
#define CYEVENT_KEY_USB_IN 'p'
#define CYEVENT_KEY_USB_OUT 'P'
/* Timer event */
#define CYEVENT_TIMER_SCREEN 's'
#define CYEVENT_TIMER_DEVICE 'd'
/* Flags definitions */ /* Flags definitions */
/* Bit 7 to Bit 4 are event type dependent. If the event need more than 4 flags, /* Bit 7 to Bit 4 are event type dependent. If the event need more than 4 flags,
* it can use it's own "private" values * it can use it's own "private" values
*/ */
/* Key event flags */ /* Key event flags */
#define CYEVENT_FLAG_KEY_CONTROL_CHARS (1 << 7) /*** Signal that the current key is not a real key (ie not an ascii value) */ #define CYEVENT_FLAG_KEY_CONTROL_CHARS (1 << 7) /***< Signal that the current key is not a real key (ie not an ascii value) */
/* Touch event flags */ /* Touch event flags */
#define CYEVENT_FLAG_TOUCH_UP (0x1 << 6) #define CYEVENT_FLAG_TOUCH_UP (0x1 << 6)
#define CYEVENT_FLAG_TOUCH_MOVE (0x2 << 6) #define CYEVENT_FLAG_TOUCH_MOVE (0x2 << 6)
#define CYEVENT_FLAG_TOUCH_DOWN (0x3 << 6) #define CYEVENT_FLAG_TOUCH_DOWN (0x3 << 6)
#define CYEVENT_FLASH_TOUCH_MASK (0x3 << 6)
#define CYEVENT_FLAG_TWO_FINGER_DOWN (1 << 5)
/* System Event */ /* System Event */
#define CYEVENT_FLAG_USB_STATE (1 << 7) /*** If not set, the USB is unplugged */ #define CYEVENT_FLAG_USB_MESSAGE (0x0 << 6) /***< this is an USB event */
#define CYEVENT_FLAG_AC_STATE (1 << 6) /*** If not set, the AC is unplugged */ //#define CYEVENT_FLAG_AC_MESSAGE (0x1 << 6) /***< this is an AC event */
#define CYEVENT_FLAG_AC_STATE (1 << 5) /*** If not set, the SD is unplugged */ #define CYEVENT_FLAG_SD_MESSAGE (0x2 << 6) /***< this is a SD event */
#define CYEVENT_FLAG_SYS_STATUS (1 << 5) /***< this event is a plug (1) or unplug (0) event */
/* Timer event */
#define CYEVENT_FLAG_TIMER_SCREEN (1 << 7)
#define CYEVENT_FLAG_TIMER_DEVICE (1 << 6)
/* These bits are set by the implementation and should not be touched by the driver / receiver */
/* Bit 3 to Bit 2 are reserved (v1) */ /* Bit 3 to Bit 2 are reserved (v1) */
#define CYEVENT_FLAG_ENDOFREPEAT (1 << 1) #define CYEVENT_FLAG_ENDOFREPEAT (1 << 1)
#define CYEVENT_FLAG_REPEATEVENT (1 << 0) #define CYEVENT_FLAG_REPEATEVENT (1 << 0)
// ===========================================================================
#ifdef __KERNEL__
// =========================================================================== // ===========================================================================
/* Exported function of CyEvent */ /* Exported function of CyEvent */
int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat);
int CyEvent_PushNewUniqueEvent(CyEvent_t *CyEvent);
int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat);
int CyEvent_PushOrUpdateUniqueEventFlaged(CyEvent_t *CyEvent, char wantRepeat, unsigned char flagMask);
int CyEvent_InvalidateUniqueEvent(CyEvent_t *CyEvent);
int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent);
// ===========================================================================
typedef void (*callback_func)(void);
typedef void (*callback2_func)(unsigned char data);
typedef int (*ioctl_func)(unsigned int cmd, unsigned long arg);
typedef struct cyevent_device
{
callback_func resume, suspend, deepsleep;
callback2_func event_read;
callback_func event_listempty;
ioctl_func ioctl;
unsigned int ioctl_prefix;
unsigned char event_read_listen; /* 0 here mean all events */
} cyevent_device;
#define NEW_CYDEV() { .resume = NULL, .suspend = NULL, .deepsleep = NULL .ioctl = NULL,\
.event_listempty = NULL, .event_read = NULL, .event_read_listen = 0, }
#define IOCTL_PFX(c) ((c & 0xFF) << 8)
int CyEvent_RegisterDevice(cyevent_device *dev);
int CyEvent_DeregisterDevice(cyevent_device *dev);
// ===========================================================================
#endif
// =========================================================================== // ===========================================================================
/* TODO: This part should be moved elsewhere... */ /* TODO: This part should be moved elsewhere... */
// =========================================================================== // ===========================================================================
/* Non directly CyIO related values, but used for the Accelerometer */ /* Non directly CyIO related values, but used for the Accelerometer */
@ -106,3 +141,23 @@ enum
CYGSENSOR_STATUS_CRITICALERROR = 6, /** If we are in this status, the G-Sensor is non working: possible cause, defective chip */ CYGSENSOR_STATUS_CRITICALERROR = 6, /** If we are in this status, the G-Sensor is non working: possible cause, defective chip */
CYGSENSOR_STATUS_SUSPENDED = 7, /** The GSENSOR was on, the device go to deepsleep, so we go in this state. */ CYGSENSOR_STATUS_SUSPENDED = 7, /** The GSENSOR was on, the device go to deepsleep, so we go in this state. */
}; };
#define SET_IOCTL(c, v) (((c & 0xFF) << 8) | (v & 0xFF))
#define GET_IOCTL_PREFIX(c) (c & 0xFF00)
#define CYIO_CTL_LED_CMD SET_IOCTL('C', 'l')
#define CYIO_CTL_USB_STATUS SET_IOCTL('C', 'u')
#define CYIO_CTL_SD_STATUS SET_IOCTL('C', 's')
#define CYIO_CTL_PWRLED_CHANGE 0x002
#define CYIO_CTL_WFILED_CHANGE 0x020
#define CYIO_CTL_BTHLED_CHANGE 0x200
#define CYIO_CTL_PWRLED_SETON (CYIO_CTL_PWRLED_CHANGE | 0x001)
#define CYIO_CTL_WFILED_SETON (CYIO_CTL_WFILED_CHANGE | 0x010)
#define CYIO_CTL_BTHLED_SETON (CYIO_CTL_BTHLED_CHANGE | 0x100)
#define CYIO_CTL_PWRLED_SETOFF (CYIO_CTL_PWRLED_CHANGE | 0x000)
#define CYIO_CTL_WFILED_SETOFF (CYIO_CTL_WFILED_CHANGE | 0x000)
#define CYIO_CTL_BTHLED_SETOFF (CYIO_CTL_BTHLED_CHANGE | 0x000)