Commit for backup purpose

This commit is contained in:
mlt
2010-06-28 17:51:53 +00:00
committed by Godzil
parent 71062896b6
commit e3c7c1b8b5
17 changed files with 1809 additions and 261 deletions

View File

@@ -75,7 +75,7 @@
#define BATTERY_FULL 4005 /*100%*/ /*4.1V*/ /*4005*/
#define ADC_sample_count 100 //25 /*joey modify ADC read method to catch top 5 low value 2009/12/21*/
#define ADC_sample_count 10 //100 //25 /*joey modify ADC read method to catch top 5 low value 2009/12/21*/
#define ADC_jig_voltage 3700 /*joey for ENV ADC to voltage 2010/01/15*/
#define ADC_READ_LEVEL_VAULE _IOR('S', 0x01, unsigned long)
@@ -436,6 +436,9 @@ static int s3c_adc_ioctl(struct inode *inode, struct file *file,
ret = 0;
break;
/* case ((( 2U ) << ( ( ( 0 + 8 ) + 8 ) + 14 ) ) |
* (( ( 'S' ) ) << ( 0 + 8 ) ) | (( ( 0x04 ) ) << 0 ) |
* (( ( ((sizeof( unsigned long ) == sizeof( unsigned long [1]) && sizeof( unsigned long ) < (1 << 14 )) ? sizeof( unsigned long ) : __invalid_size_argument_for_IOC) ) ) << ( ( 0 + 8 ) + 8 ) )): */
case ADC_READ_RAW_VAULE:
for(i=0; i<ADC_sample_count ;i++)
{

477
drivers/input/cyevent.c Normal file
View File

@@ -0,0 +1,477 @@
h
// ===========================================================================
// cyio.c
// Copyright (C) 2008-2010 Bookeen - All rights reserved
// ===========================================================================
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/proc_fs.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-gpioj.h>
#include <cybook.h>
#include <linux/cyevent.h>
#define CYEV_MAX_EVENT 20
#define CYEV_REPEAT_DELAY (HZ/2); /* ~500ms */
#define CYEV_CURRENT_VERSION 0x10 /* 1.0 */
enum { INVALID = 0, VALID };
struct
{
char valid;
char wantRepeat;
char seen;
char unique;
int repeatDelay;
CyEvent_t payload;
} CyEv_PayList;
CyEv_PayList *cyev_eventList[CYEV_MAX_EVENT];
struct task_struct *openingTask = 0;
/* TODO: Add a locking method for accessing the eventList */
// ===========================================================================
// List management
void CyEv_ClearEventList(void)
{
int i;
for (i = 0; i < CYEV_MAX_EVENT; i++)
{
cyev_eventList[i].wantRepeat = false;
cyev_eventList[i].seen = false;
cyev_eventList[i].unique = false;
cyev_eventList[i].repeatDelay = 0;
cyev_eventList[i].valid = INVALID;
}
}
/* 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 */
/* We first start by the first event of the list then search for the first valid and return it */
CyEvent_t *CyEv_GetNextEvent(void)
{
static int listPos = 0;
int i;
CyEvent_t ret = NULL;
/* Scan the list starting from the last position stored */
for(i = listPos; i < (CYEV_MAX_EVENT + listPos); i++)
{
/* Stop on the first "VALID" event */
if (cyev_eventList[i % CYEV_MAX_EVENT].valid == VALID)
{
/* We already send this repeatable event. Did the delay occur ?
if not, ignore it and go to the next one */
if ( (cyev_eventList[i % CYEV_MAX_EVENT].seen == true) &&
(cyev_eventList[i % CYEV_MAX_EVENT].wantRepeat == true) )
{
if (cyev_eventList[i % CYEV_MAX_EVENT].repeatDelay < jiffies) )
{
continue;
}
else /* if (cyev_eventList[i % CYEV_MAX_EVENT].repeatDelay >= jiffies) ) */
{
/* Set the Repeat flag to true */
cyev_eventList[i % CYEV_MAX_EVENT].payload.flags |= CYEVENT_FLAG_REPEATEVENT;
}
}
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;
}
/* Update the index for the next element to scan */
listPos = (listPos + i + 1) % CYEV_MAX_EVENT;
break;
}
}
return ret; /* We will return NULL if no valid payload */
}
int isEventNotDuplicate(CyEvent_t *CyEvent)
{
int i;
CyEvent_t *cur:
for(i = 0; i < CYEV_MAX_EVENT; i++)
{
cur = &(cyev_eventList[i].payload);
if (cyev_eventList[i].unique == true)
{
if (cur->type == CyEvent->type) /* To be verified */
return false;
}
}
return true;
}
int CyEv_AddNewEvent(CyEvent_t *CyEvent, char wantRepeat, char wantUnique)
{
/* Search for the first "invalid" event, then put the given CyEvent in it. */
/* If no slot is valid, return an error */
int i;
int ret = -EIO; /* TODO: find a better error code.*/
/* If wantUnique, first check that there is not another unique event */
if ((wantUnique) && !isEventNotDuplicate(CyEvent))
goto exit;
/* Scan the list starting from the last position stored */
for(i = 0; i < CYEV_MAX_EVENT; i++)
{
/* Stop on the first "VALID" event */
if (cyev_eventList[i].valid == INVALID)
{
/* Store the event */
memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
/* Force version in the structure */
cyev_eventList[i].payload.version = CYEV_CURRENT_VERSION;
cyev_eventList[i].valid = VALID;
if (wantUnique)
cyev_eventList[i].unique = true;
else
cyev_eventList[i].unique = false;
if (wantRepeat)
{
cyev_eventList[i].wantRepeat = true;
cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
}
else
cyev_eventList[i].wantRepeat = false;
if (openingTask)
wake_up_process(openingTask);
ret = 0;
break;
}
}
exit:
return ret;
}
/* Return 0 if event found and updated, or anything else */
/* We could ONLY update event that are declared as unique */
int CyEv_UpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
{
int i;
int ret = -1;
/* Search for the event */
for(i = 0; i < CYEV_MAX_EVENT; i++)
{
if ( (cyev_eventList[i].unique == true) &&
(cyev_eventList[i].payload.type == CyEvent.type) )
{ /* Found it ! Now update the fields */
memcpy(&(cyev_eventList[i].payload), CyEvent, sizeof(CyEvent_t));
if (wantRepeat)
{
cyev_eventList[i].wantRepeat = true;
cyev_eventList[i].repeatDelay = jiffies + CYEV_REPEAT_DELAY;
}
else
cyev_eventList[i].wantRepeat = false;
if (openingTask)
wake_up_process(openingTask);
ret = 0;
}
}
return ret;
}
int CyEv_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
{
int i;
int ret = -1;
/* Search for the event */
for(i = 0; i < CYEV_MAX_EVENT; i++)
{
if ( (cyev_eventList[i].wantRepeat == true) &&
(cyev_eventList[i].payload.type == CyEvent.type) )
{ /* Found it ! Now update the fields */
/* In case the event has not been eaten, just remove the "repeat want"
ie: do not invalidate it */
cyev_eventList[i].wantRepeat = false;
if (cyev_eventList[i].seen == true)
{
/* set the event "end of repeat" flag */
cyev_eventList[i].payload.flags |= CYEVENT_FLAG_ENDOFREPEAT;
}
if (openingTask)
wake_up_process(openingTask);
ret = 0;
break;
}
}
return ret;
}
// ===========================================================================
// ===========================================================================
// External event managment
int CyEvent_PushNewEvent(CyEvent_t *CyEvent, char wantRepeat)
{
if (wantRepeat)
return CyEv_AddNewEvent(CyEvent, wantRepeat, true);
else
return CyEv_AddNewEvent(CyEvent, wantRepeat, false);
}
EXPORT_SYMBOL(CyEvent_PushNewEvent);
int CyEvent_PushOrUpdateUniqueEvent(CyEvent_t *CyEvent, char wantRepeat)
{
int ret;
/* For now a simple call to AddNewEvent */
ret = CyEv_UpdateUniqueEvent(CyEvent, wantRepeat);
if (ret != 0) /* The event is not present */
ret = CyEv_AddNewEvent(CyEvent, wantRepeat, true);
return ret;
}
EXPORT_SYMBOL(CyEvent_PushOrUpdateUniqueEvent);
int CyEvent_InvalidateRepeatableEvent(CyEvent_t *CyEvent)
{
ret = CyEv_InvalidateRepeatableEvent(CyEvent);
}
EXPORT_SYMBOL(CyEvent_InvalidateRepeatableEvent);
// ===========================================================================
static int ev_open(struct inode *inode, struct file *file)
{
/* Clear pending event list... */
CyEv_ClearEventList();
return 0;
}
// ---------------------------------------------------------------------------
static int ev_release(struct inode *inode, struct file *file)
{
/* Clear pending event list... */
CyEv_ClearEventList();
return 0;
}
// ---------------------------------------------------------------------------
ssize_t ev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
int nBytes = sizeof(CyEvent_t);
int ret = -EIO;
CyEvent_t *CyEvent = NULL;
if (count < nBytes)
{
ret = -EINVAL;
goto exit;
}
while (1)
{
if ((CyEvent = CyEv_GetNextEvent()) != NULL)
{
break;
}
openingTask = current;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
set_current_state(TASK_RUNNING);
openingTask = 0;
if (signal_pending(current))
{
ret = -ERESTARTSYS;
break;
}
}
if (CyEvent != NULL)
{
nRes = copy_to_user(buf, &CyEvent, nBytes);
if (!nRes)
nRes = nBytes;
}
return ret;
}
// ---------------------------------------------------------------------------
static int ev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret = -EINVAL;
unsigned long value;
switch(cmd)
{
default:
printk(KERN_ERR "Bad IOCTL\n");
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 */
{
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;
}
// ===========================================================================
static struct file_operations s_io_fops =
{
owner: THIS_MODULE,
read: ev_read,
ioctl: ev_ioctl,
open: ev_open,
release: ev_release,
};
gstatic struct miscdevice s_ev_dev =
{
.minor = 250,
.name = "cyio",
.fops = &s_ev_fops,
};
// ===========================================================================
// ---------------------------------------------------------------------------
static int io_probe(struct platform_device *dev)
{
return 0;
}
// ---------------------------------------------------------------------------
static int io_remove(struct platform_device *dev)
{
misc_deregister(&s_ev_dev);
return 0;
}
// --------------------------------------------------------------------------
static int io_resume(struct platform_device *dev)
{
return 0;
}
// ---------------------------------------------------------------------------
static struct platform_driver cyev_driver =
{
.driver =
{
.name = "cyevent",
.owner = THIS_MODULE,
},
.probe = ev_probe,
.remove = ev_remove,
.suspend = NULL,
.resume = ev_resume,
};
// ---------------------------------------------------------------------------
// ===========================================================================
static int __init cyEv_init(void)
{
if (misc_register(&s_ev_dev))
return -EBUSY;
platform_driver_register(&cyev_driver);
return 0;
}
// ---------------------------------------------------------------------------
static void __exit cyEv_exit(void)
{
platform_driver_unregister(&cyev_driver);
misc_deregister(&s_ev_dev);
}
// ---------------------------------------------------------------------------
module_init(cyEv_init);
module_exit(cyEv_exit);
// ---------------------------------------------------------------------------
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
MODULE_DESCRIPTION("Cybook Event Manager");
MODULE_VERSION("3.0");
// ===========================================================================

View File

@@ -24,8 +24,8 @@
#include <linux/cyio.h>
//#define DEBUG_MESSAGES
//#define DEBUG_TRACEFUNC
#define DEBUG_MESSAGES
#define DEBUG_TRACEFUNC
//#define DBG_IRQ
#define MODULE_NAME "CYB_TILT"
@@ -225,20 +225,20 @@ static irqreturn_t orizontilt_interrupt(int irq, void *dev_id)
switch(tmpReg)
{
case 0x00: /* 90 */
calcTilt = 90;
break;
calcTilt = 90;
break;
case 0x02: /* 0 */
calcTilt = 0;
break;
case 0x02: /* 0 */
calcTilt = 0;
break;
case 0x01: /* 180 */
calcTilt = 180;
break;
case 0x01: /* 180 */
calcTilt = 180;
break;
case 0x03: /* 270 */
calcTilt = 270;
break;
case 0x03: /* 270 */
calcTilt = 270;
break;
}
DBG("New Orientation is: %lu", calcTilt);
if (calcTilt != OrizonTilt_CurrentDirection)

View File

@@ -24,7 +24,7 @@
#include <cybook.h>
#include <linux/cyio.h>
#define DEBUG_MESSAGES
//#define DEBUG_MESSAGES
//#define DEBUG_TRACEFUNC
#define MODULE_NAME "ORIZON-TS"
@@ -299,12 +299,13 @@ static int ots_detect (struct i2c_adapter *adapter, int address, int kind)
ots_setDeviceParameters(INT_MODE, X_SENS, Y_SENS);
/* Now we are sure that the driver init successfully, then aquire the IRQ */
set_irq_type(IRQ_EINT2, IRQT_FALLING);
if ( request_irq(IRQ_EINT2, ots_interrupt, SA_SHIRQ, "orizon_ts", &ots_client) )
{
printk(KERN_ERR "failed to get interrupt resouce at IRQ_EINT2.\n");
goto exit_kfree;
}
enable_irq_wake(IRQ_EINT2);
}
goto exit;
@@ -352,25 +353,45 @@ static int ots_resume (struct device *dev)
/******************************************************************************/
/********************** Interrupt Related functions ***************************/
/******************************************************************************/
static int oldX = 0, oldY = 0;
static void ots_checkWorkFunction (struct work_struct *work)
{
unsigned long x1, y1, x2, y2;
FUNC_IN();
/* Here do what the interrupt should... (ie read touch values) */
x1 = i2c_smbus_read_byte_data(ots_client, 0);
x1 |= i2c_smbus_read_byte_data(ots_client, 1) << 8;
y1 = i2c_smbus_read_byte_data(ots_client, 2);
y1 |= i2c_smbus_read_byte_data(ots_client, 3) << 8;
/* TODO: I reversed the X / Y axis to match old driver and revese the X value */
y1 = i2c_smbus_read_byte_data(ots_client, 0);
y1 |= i2c_smbus_read_byte_data(ots_client, 1) << 8;
x2 = i2c_smbus_read_byte_data(ots_client, 4);
x2 |= i2c_smbus_read_byte_data(ots_client, 5) << 8;
x1 = i2c_smbus_read_byte_data(ots_client, 2);
x1 |= i2c_smbus_read_byte_data(ots_client, 3) << 8;
y2 = i2c_smbus_read_byte_data(ots_client, 6);
y2 |= i2c_smbus_read_byte_data(ots_client, 7) << 8;
y2 = i2c_smbus_read_byte_data(ots_client, 4);
y2 |= i2c_smbus_read_byte_data(ots_client, 5) << 8;
DBG("x1: %lu\ty1: %lu\ty1: %lu\ty2: %lu", x1, y1, x2, y2);
x2 = i2c_smbus_read_byte_data(ots_client, 6);
x2 |= i2c_smbus_read_byte_data(ots_client, 7) << 8;
DBG("x1: %lu\ty1: %lu\tx2: %lu\ty2: %lu", x1, y1, x2, y2);
if ((x1 == 0) && (y1 == 0))
{ /* We assume that this is a finger up event */
if ( Cyio_PushEvent('R', 1) >= 0 )
{
Cyio_PushEvent((oldX >> 8) & 0xFF, 0);
Cyio_PushEvent((oldX >> 0) & 0xFF, 0);
Cyio_PushEvent((oldY >> 8) & 0xFF, 0);
Cyio_PushEvent((oldY >> 0) & 0xFF, 0);
}
}
else
{
oldX = 600 - x1;
oldY = y1;
}
/* Say I get the data */
ots_ackInterrupt();

View File

@@ -40,6 +40,8 @@
#include "queue.h"
#include <cybook.h>
/*
* max 8 partitions per card
*/
@@ -48,6 +50,27 @@
static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
/* [MTR] Hackish, but needed:
* We need a way to not expose the last X MB of the MoviNand to protect the
* bootloader from unexpected erase. So we pass a parameter from the BL
* that will say that we allow us to access the BL partition
*
* TODO: This should be put somewhere else...
*/
static int __init get_movirestrict_mode(char *str)
{
int ints[2];
str = get_options(str, 2, ints);
if (ints[1] == 0xd34db33f)
{
platform_capability |= PLAT_CAP_UNRESTRICT;
}
printk(KERN_ERR "movirest = 0x%08X", ints[1]);
return 1;
}
__setup("movirest=", get_movirestrict_mode);
/*
* There is one mmc_blk_data per slot.
*/
@@ -425,6 +448,9 @@ static inline int mmc_blk_readonly(struct mmc_card *card)
!(card->csd.cmdclass & CCC_BLOCK_WRITE);
}
/* We will remove 10 MB of block, and block are 512 byte long */
#define BLK_COUNT_REMOVE ((10 * 1024 * 1024) / 512)
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
{
struct mmc_blk_data *md;
@@ -502,14 +528,31 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
* The EXT_CSD sector count is in number or 512 byte
* sectors.
*/
set_capacity(md->disk, card->ext_csd.sectors);
if ((devidx == 0) && (GET_CAPABILITY(PLAT_CAP_UNRESTRICT) != 0))
/* We are on the Movi Device and not booting in "full mode" */
{
set_capacity(md->disk, card->ext_csd.sectors);
}
else /* remove 10MB to the sector counts */
{
set_capacity(md->disk, card->ext_csd.sectors - BLK_COUNT_REMOVE);
}
} else {
/*
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
*/
set_capacity(md->disk,
if ((devidx == 0) && (GET_CAPABILITY(PLAT_CAP_UNRESTRICT) != 0))
/* We are on the Movi Device and not booting in "full mode" */
{
set_capacity(md->disk,
card->csd.capacity << (card->csd.read_blkbits - 9));
}
else /* remove 10MB to the sector counts */
{
set_capacity(md->disk,
(card->csd.capacity << (card->csd.read_blkbits - 9)) - BLK_COUNT_REMOVE);
}
}
return md;
@@ -566,7 +609,7 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
printk(KERN_INFO "%s: %s %s %lluKB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
(unsigned long long)(get_capacity(md->disk) >> 1),
md->read_only ? "(ro)" : "");

View File

@@ -2328,6 +2328,7 @@ static int s3c_hsmmc_probe (struct platform_device *pdev)
ret = request_irq(host->irq_cd, s3c_hsmmc_irq_cd, 0, DRIVER_NAME, host);
if (ret)
goto untasklet;
enable_irq_wake(host->irq_cd);
}
#endif

View File

@@ -350,8 +350,10 @@ MODULE_LICENSE("Dual BSD/GPL");
static struct {
char *file[MAX_LUNS];
int ro[MAX_LUNS];
int status[MAX_LUNS];
int num_filenames;
int num_ros;
int num_status;
unsigned int nluns;
int removable;
@@ -362,7 +364,8 @@ static struct {
unsigned short vendor;
unsigned short product;
unsigned short release;
unsigned int buflen;
char serial[12];
unsigned int buflen;
int transport_type;
char *transport_name;
@@ -378,6 +381,7 @@ static struct {
.product = DRIVER_PRODUCT_ID,
.release = 0xffff, // Use controller chip type
.buflen = 16384,
.serial = "CYBOR10",
};
@@ -388,6 +392,9 @@ MODULE_PARM_DESC(file, "names of backing files or devices");
module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
MODULE_PARM_DESC(ro, "true to force read-only");
module_param_array_named(status, mod_data.status, int, &mod_data.num_status, S_IRUGO);
MODULE_PARM_DESC(status, "get lun(s) status");
module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
MODULE_PARM_DESC(luns, "number of LUNs");
@@ -421,6 +428,9 @@ MODULE_PARM_DESC(release, "USB release number");
module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
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 */
@@ -560,6 +570,8 @@ struct interrupt_data {
struct lun {
u8 id;
struct file *filp;
loff_t file_length;
loff_t num_sectors;
@@ -569,6 +581,8 @@ struct lun {
unsigned int registered : 1;
unsigned int info_valid : 1;
unsigned int status : 1;
u32 sense_data;
u32 sense_data_info;
u32 unit_attention_data;
@@ -2061,8 +2075,8 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
/* 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[] = "e-Book ";
static char product_id[] = "Reader";
static char vendor_id[] = "Bookeen ";
static char product_id[] = "Cybook Orizon";
/* } Qisda, howard.hsu, 2010/01/26, change usb device name */
if (!fsg->curlun) { // Unsupported LUNs are okay
fsg->bad_lun_okay = 1;
@@ -2078,7 +2092,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
buf[3] = 2; // SCSI-2 INQUIRY data format
buf[4] = 31; // Additional length
// No special options
sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id,
sprintf(buf + 8, "%-8s%-13s-%-2s%04x", vendor_id, product_id, (fsg->curlun->id==1)?"FD":"SD",
mod_data.release);
return 36;
}
@@ -3625,6 +3639,12 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
return rc;
}
static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lun *curlun = dev_to_lun(dev);
return sprintf(buf, "%d\n", curlun->status);
}
static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
@@ -3650,6 +3670,12 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const
return rc;
}
static ssize_t store_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
return 0;
}
static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct lun *curlun = dev_to_lun(dev);
@@ -3687,6 +3713,7 @@ static ssize_t store_file(struct device *dev, struct device_attribute *attr, con
/* The write permissions and store_xxx pointers are set in fsg_bind() */
static DEVICE_ATTR(ro, 0444, show_ro, NULL);
static DEVICE_ATTR(file, 0444, show_file, NULL);
static DEVICE_ATTR(status, 0444, show_status, NULL);
/*-------------------------------------------------------------------------*/
@@ -3722,6 +3749,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file);
device_remove_file(&curlun->dev, &dev_attr_status);
device_unregister(&curlun->dev);
curlun->registered = 0;
}
@@ -3862,8 +3890,10 @@ static int __init fsg_bind(struct usb_gadget *gadget)
if (mod_data.removable) { // Enable the store_xxx attributes
dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644;
dev_attr_status.attr.mode = 0444;
dev_attr_ro.store = store_ro;
dev_attr_file.store = store_file;
dev_attr_status.store = store_status;
}
/* Find out how many LUNs there should be */
@@ -3902,10 +3932,13 @@ static int __init fsg_bind(struct usb_gadget *gadget)
if ((rc = device_create_file(&curlun->dev,
&dev_attr_ro)) != 0 ||
(rc = device_create_file(&curlun->dev,
&dev_attr_file)) != 0) {
&dev_attr_file)) != 0 ||
(rc = device_create_file(&curlun->dev,
&dev_attr_status)) != 0) {
device_unregister(&curlun->dev);
goto out;
}
curlun->id = i;
curlun->registered = 1;
kref_get(&fsg->ref);
@@ -4001,15 +4034,21 @@ static int __init fsg_bind(struct usb_gadget *gadget)
/* This should reflect the actual gadget power source */
usb_gadget_set_selfpowered(gadget);
#if 0
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
#else
snprintf(manufacturer, sizeof manufacturer, "Bookeen");
#endif
/* On a real device, serial[] would be loaded from permanent
* storage. We just encode it from the driver version string. */
for (i = 0; i < sizeof(serial) - 2; i += 2) {
#if 0
unsigned char c = DRIVER_VERSION[i / 2];
#else
unsigned char c = mod_data.serial[i / 2];
#endif
if (!c)
break;
sprintf(&serial[i], "%02X", c);

View File

@@ -3642,7 +3642,7 @@ static struct sleep_save lcd_save[] = {
static int auofb_suspend(struct platform_device *dev, pm_message_t state)
{
#if 0
#if 1
if(is_Epaper_Write_Ready())
{
//Suspend LCD controller

View File

@@ -155,6 +155,11 @@
#define PROGRESS_BAR_90_H (60)
#define PROGRESS_BAR_FRAME_LINE_W 8
/* Compat tools */
#define tcon_ndelay nDelay
static int tcon_inPortraitMode = 0;
#define tcon_set_write_to_data _SetWriteToData
/*******/
typedef enum {
EN_I80_NONE = -1,
@@ -218,6 +223,7 @@ static void __uDelay(unsigned long uTime)
nDelay(75);
}
void Epaper_Set_I80_Default_Speed(I80_HWE_SPEED_MODE i80_speed, unsigned short w, unsigned short h);
void Epaper_Change_I80_Speed(I80_HWE_SPEED_MODE i80_speed, unsigned short w, unsigned short h)
{
@@ -894,7 +900,10 @@ static inline void s3c2416_i80_write(int data)
tmp = __raw_readl(rSIFCCON0); // nWE enable
tmp |= SYS_WR_CON;
__raw_writel(tmp, rSIFCCON0);
if ( !tcon_inPortraitMode )
tcon_ndelay(25);
__raw_writel(data, rSIFCCON1); //rSIFCCON1 = CMD;
tmp = __raw_readl(rSIFCCON0); // nWE disables
@@ -2263,9 +2272,8 @@ enum InfoLevel
INFO_VERBOSE,
};
//#define EPAPER_DEBUG
//#define VERBOSE_LEVEL INFO_VERBOSE
#define EPAPER_DEBUG
#define VERBOSE_LEVEL INFO_VERBOSE
#ifndef VERBOSE_LEVEL
@@ -2290,5 +2298,227 @@ static int _dbgFL = 0;
#endif
/* [/MTR] */
//#define GET_COMMAND_PARAM_NUM(command) ((command >> 20) & 0x0F)
//#define GET_COMMAND_HAVE_DATA(command) ((command >> 28) & 0x01)
//#define GET_COMMAND_NEED_WAIT(command) ((command >> 29) & 0x01)
/* On the i80 port,
* i80 TCON
* -----------
* RS -> D/C
* CS0 -> CSEL
* nWE -> HWE
* OE -> HRD
*/
static inline void _InitI80Interface(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSYSIFCON0); //polarity of RS, set 1 for normal access
tmp |= (1<<2);
__raw_writel(tmp, rSYSIFCON0);
tmp = __raw_readl(rSIFCCON0); // command mode enable
tmp |= (1<<0);
__raw_writel(tmp, rSIFCCON0);
FUNC_OUT();
}
static inline void _DeinitI80Interface(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0); // command mode disable
tmp &= ~(1<<0);
__raw_writel(tmp, rSIFCCON0);
FUNC_OUT();
}
static inline void _SetWriteToData(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0);
// RS high -> D/nC set Data mode
tmp |= (1<<1);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _SetWriteToCommand(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0);
// RS low -> D/nC set Command mode
tmp &= ~(1<<1);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _EnableWrite(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0);
// nWE -> HWE enable
tmp |= (1<<6);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _DisableWrite(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0);
// nWE -> HWE disable
tmp &= ~(1<<6);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _EnableRead(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0); // nRD enable
tmp |= SYS_OE_CON;
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _DisableRead(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0); // nRD disable
tmp &= ~SYS_OE_CON;
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _SelectChip(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0); // Chip Select
tmp |= (1<<8);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
static inline void _UnselectChip(void)
{
unsigned long tmp;
FUNC_IN();
tmp = __raw_readl(rSIFCCON0); // nCS0(Main) enable
tmp &= ~(1<<8);
__raw_writel(tmp, rSIFCCON0);
__uDelay(1);
FUNC_OUT();
}
#define tcon_i80bus_write s3c2416_i80_write
int Epaper_sendCommandStart(sAUOCommand *cmd)
{
FUNC_IN();
INFOL(INFO_VERBOSE,("cmd #%08lX", cmd->cmd));
/* First: verify that the K1900 is ready */
INFOL(INFO_VERBOSE, ("/* First: verify that the K1900 is ready */"));
if (GET_COMMAND_NEED_WAIT(cmd->cmd) != 0x00)
{
INFOL(INFO_VERBOSE, ("Wait for non BUSY..."));
is_Epaper_Write_Ready();
}
if (cmd->cmd == AUOCMD_INIT_SET)
{
tcon_inPortraitMode = ~(cmd->params[0]) & (0x1 << 10);
if (tcon_inPortraitMode)
Epaper_Change_I80_Speed(EN_I80_PORTRAIT, 800, 600);
else
Epaper_Change_I80_Speed(EN_I80_LANDSCAPE, 600, 800);
INFOL(INFO_VERBOSE, ("Rotation set to 0x%08X...", tcon_inPortraitMode));
}
/* Second: init the i80 interface */
INFOL(INFO_VERBOSE, ("/* Second: init the i80 interface */"));
//tcon_i80bus_init_interface();
/* Third: Select the chip and set to Command mode */
INFOL(INFO_VERBOSE, ("/* Third: Select the chip and set to Command mode */"));
_SelectChip();
_SetWriteToCommand();
/* Fourth: Send command */
INFOL(INFO_VERBOSE, ("/* Fourth: Send command */"));
tcon_i80bus_write(cmd->cmd & 0xFFFF); /* This function already manage
* no need to do it here. */
/* Sixth: If parameters is needed, send them */
INFOL(INFO_VERBOSE, ("/* Sixth: If parameters is needed, send them */"));
if (GET_COMMAND_PARAM_NUM(cmd->cmd) > 0)
{
int i, paramNumbers = GET_COMMAND_PARAM_NUM(cmd->cmd);
INFOL(INFO_VERBOSE, ("YES! We have %d parameters", paramNumbers));
tcon_set_write_to_data();
for (i = 0; i < paramNumbers; i++)
{
INFOL(INFO_VERBOSE, (" parameter [%02d] = 0x%04X", i, cmd->params[i]));
tcon_i80bus_write(cmd->params[i]);
}
}
FUNC_OUT();
return 0;
}
int Epaper_sendData(unsigned short *buffer, unsigned long bufferLen)
{
/* Seventh: Send data if needed */
unsigned long i;
//FUNC_IN();
//INFOL(INFO_VERBOSE, ("Bufferlen: %ld", bufferLen));
tcon_set_write_to_data();
for (i = 0; i < bufferLen; i++)
{
tcon_i80bus_write(buffer[i]);
}
//FUNC_OUT();
return 0;
}
int Epaper_sendCommandEnd(sAUOCommand *cmd)
{
FUNC_IN();
INFOL(INFO_VERBOSE,("cmd #%08lX START:[#%08X]", cmd->cmd, AUOCMD_DISPLAY_START));
if (cmd->cmd == AUOCMD_DISPLAY_START)
{
_SetWriteToCommand();
INFOL(INFO_VERBOSE, ("/* Eight: Send STOP command */"));
tcon_i80bus_write(AUOCMD_DISPLAY_STOP & 0xFFFF);
_SetWriteToData();
}
INFOL(INFO_VERBOSE, ("/* Nineth: Close all */"));
_UnselectChip();
_DeinitI80Interface();
//tcon_i80bus_deinit_interface();
FUNC_OUT();
return 0;
}
/* [/MTR] */

View File

@@ -37,12 +37,14 @@
#include <cybook.h>
#define DEBUG_MESSAGES
#define DEBUG_TRACEFUNC
//#define DEBUG_MESSAGES
//#define DEBUG_TRACEFUNC
//#define VERBOSE_LEVEL INFO_WARNING
//#define DEBUG_SPI
#define MODULE_NAME "AUO-TCON"
#define BUSY_WAIT_TIMEOUT (40*5*2) //panel time out = 1s
#define BUSY_WAIT_TIMEOUT (40*5*2) //panel time out = 1s
#define SYS_WR_CON (1<<6)
#define SYS_OE_CON (1<<7)
@@ -57,12 +59,12 @@ enum InfoLevel
INFO_ERROR = 0,
INFO_WARNING,
INFO_NORMAL,
INFO_DEBUG,
INFO_VERBOSE,
INFO_DEBUG,
};
# ifndef VERBOSE_LEVEL
# define VERBOSE_LEVEL INFO_VERBOSE
# define VERBOSE_LEVEL INFO_WARNING
# endif
# ifdef DEBUG_TRACEFUNC
@@ -168,7 +170,7 @@ static int _dbg_FunctionLevel = 0;
#define VIDTCON2_LINEVAL_S (11)
static int tcon_inPortraitMode = 0;
static int tcon_lastModeWas = 0;
typedef enum Tcon_Speedclasses
{
EN_I80_NONE = -1,
@@ -186,6 +188,14 @@ typedef struct Tcon_SpeedclasseValue
u8 wr_hold;
} Tcon_SpeedclasseValue;
typedef enum Tcon_PowerMode
{
TCON_POWER_NORMALMODE,
TCON_POWER_STANDBYMODE,
TCON_POWER_SLEEPMODE,
TCON_POWER_OFF,
} Tcon_PowerMode;
static Tcon_SpeedclasseValue tcon_speedtable[] =
{
[EN_I80_LANDSCAPE] =
@@ -202,6 +212,7 @@ static Tcon_SpeedclasseValue tcon_speedtable[] =
.wr_act = 8,
.wr_hold = 3,
},
#if 1
[EN_I80_LANDSCAPE_HANDWRITING] =
{
.cs_setup = 0,
@@ -216,10 +227,26 @@ static Tcon_SpeedclasseValue tcon_speedtable[] =
.wr_act = 6,
.wr_hold = 2,
},
#else
[EN_I80_PORTRAIT_HANDWRITING] =
{
.cs_setup = 0,
.wr_setup = 1,
.wr_act = 1,
.wr_hold = 0,
},
[EN_I80_LANDSCAPE_HANDWRITING] =
{
.cs_setup = 0,
.wr_setup = 2,
.wr_act = 6,
.wr_hold = 2,
},
#endif
};
static Tcon_Speedclasses tcon_currentSpeedClass = EN_I80_NONE;
static Tcon_PowerMode tcon_currentPowerMode = TCON_POWER_NORMALMODE;
// ===========================================================================
// TCON Related functions
// ===========================================================================
@@ -311,6 +338,8 @@ void tcon_i80bus_set_speed(Tcon_Speedclasses i80_speed,
FUNC_IN();
INFOL(INFO_WARNING, ("speedclass: %d\n", i80_speed));
if ( tcon_currentSpeedClass == EN_I80_NONE)
set_clock = true;
@@ -318,7 +347,7 @@ void tcon_i80bus_set_speed(Tcon_Speedclasses i80_speed,
if (set_clock == true)
{
INFOL(INFO_VERBOSE, ("Will set clocks..."));
INFOL(INFO_DEBUG, ("Will set clocks..."));
tmp = __raw_readl(S3C_VIDCON0);
tmp = VIDCON0_S_CPU_IF_MAIN | VIDCON0_S_RGB_PAR | \
@@ -371,8 +400,12 @@ static inline void tcon_i80bus_write (int data)
tmp |= SYS_WR_CON;
__raw_writel(tmp, S3C_SIFCCON0);
if ( !tcon_inPortraitMode )
if (( !tcon_inPortraitMode ) && (tcon_lastModeWas != 4))
tcon_ndelay(25);
else if (( tcon_inPortraitMode ) && (tcon_lastModeWas == 4))
tcon_ndelay(15);
__raw_writel(data, S3C_SIFCCON1); //rSIFCCON1 = CMD;
@@ -381,6 +414,49 @@ static inline void tcon_i80bus_write (int data)
__raw_writel(tmp, S3C_SIFCCON0);
}
static inline void tcon_i80bus_write_LUT(int data)
{
int tmp;
tcon_delay(1);
tmp = __raw_readl(S3C_SIFCCON0); // nWE enable
tmp |= SYS_WR_CON;
__raw_writel(tmp, S3C_SIFCCON0);
tcon_delay(1);
__raw_writel(data, S3C_SIFCCON1); //rSIFCCON1 = CMD;
tcon_delay(1);
tmp = __raw_readl(S3C_SIFCCON0); // nWE disable
tmp &= ~SYS_WR_CON;
__raw_writel(tmp, S3C_SIFCCON0);
}
static inline void tcon_i80bus_read (unsigned short *data)
{
int tmp;
tcon_delay(1);
tmp = __raw_readl(S3C_SIFCCON0); // nRD enable
tmp |= SYS_OE_CON;
__raw_writel(tmp, S3C_SIFCCON0);
tcon_delay(1);
*data = __raw_readl(S3C_SIFCCON2); //CMD = rSIFCCON2;
tcon_delay(1);
tmp = __raw_readl(S3C_SIFCCON0); // nRD disable
tmp &= ~SYS_OE_CON;
__raw_writel(tmp, S3C_SIFCCON0);
}
static inline void tcon_set_write_to_data(void)
{
unsigned long tmp;
@@ -469,55 +545,108 @@ static inline void tcon_unselect_chip(void)
FUNC_OUT();
}
static inline void tcon_set_power_on(void)
{
unsigned long tmp = __raw_readl(S3C2410_GPBDAT);
tmp |= (1 << 3);
__raw_writel(tmp, S3C2410_GPBDAT);
tcon_currentPowerMode = TCON_POWER_NORMALMODE;
}
static inline void tcon_set_power_off(void)
{
unsigned long tmp = __raw_readl(S3C2410_GPBDAT);
tmp &= ~(1 << 3);
__raw_writel(tmp, S3C2410_GPBDAT);
tcon_currentPowerMode = TCON_POWER_OFF;
}
int tcon_send_command_start(sAUOCommand *cmd)
{
FUNC_IN();
INFOL(INFO_VERBOSE,("cmd #%08lX", cmd->cmd));
INFOL(INFO_DEBUG,("cmd #%08lX", cmd->cmd));
/* First: verify that the K1900 is ready */
INFOL(INFO_VERBOSE, ("/* First: verify that the K1900 is ready */"));
INFOL(INFO_DEBUG, ("/* First: verify that the K1900 is ready */"));
if (GET_COMMAND_NEED_WAIT(cmd->cmd) != 0x00)
{
INFOL(INFO_VERBOSE, ("Wait for non BUSY..."));
INFOL(INFO_DEBUG, ("Wait for non BUSY..."));
tcon_wait_ready();
}
if (cmd->cmd == AUOCMD_INIT_SET)
if (cmd->cmd == AUOCMD_STANDBY)
tcon_currentPowerMode = TCON_POWER_STANDBYMODE;
else if (cmd->cmd == AUOCMD_WAKEUP)
tcon_currentPowerMode = TCON_POWER_NORMALMODE;
else if (cmd->cmd == AUOCMD_INIT_SET)
{
tcon_inPortraitMode = ~(cmd->params[0]) & (0x1 << 10);
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 600, 800, false);
INFOL(INFO_VERBOSE, ("Rotation set to 0x%08X...", tcon_inPortraitMode));
if (tcon_lastModeWas != 4)
{
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 600, 800, false);
}
else
{
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT_HANDWRITING, 800, 600, false);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE_HANDWRITING, 600, 800, false);
}
INFOL(INFO_DEBUG, ("Rotation set to 0x%08X...", tcon_inPortraitMode));
}
else if (cmd->cmd == AUOCMD_DISPLAY_START)
{
INFOL(INFO_VERBOSE, ("Display Start (lastMode: %d)...", tcon_lastModeWas));
if (((cmd->params[0] >> 12) & 0x07) == 4) /* Handwriting mode... */
{
INFOL(INFO_VERBOSE, ("Mode 4"));
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT_HANDWRITING, 800, 600, false);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE_HANDWRITING, 600, 800, false);
}
else if (tcon_lastModeWas == 4)
{
INFOL(INFO_VERBOSE, ("--- NOT --- mode 4 (%d)", ((cmd->params[0] >> 12) & 0x07)));
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, false);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 600, 800, false);
}
tcon_lastModeWas = ((cmd->params[0] >> 12) & 0x07);
}
/* Second: init the i80 interface */
INFOL(INFO_VERBOSE, ("/* Second: init the i80 interface */"));
INFOL(INFO_DEBUG, ("/* Second: init the i80 interface */"));
tcon_i80bus_init_interface();
/* Third: Select the chip and set to Command mode */
INFOL(INFO_VERBOSE, ("/* Third: Select the chip and set to Command mode */"));
INFOL(INFO_DEBUG, ("/* Third: Select the chip and set to Command mode */"));
tcon_select_chip();
tcon_set_write_to_command();
/* Fourth: Send command */
INFOL(INFO_VERBOSE, ("/* Fourth: Send command */"));
INFOL(INFO_DEBUG, ("/* Fourth: Send command */"));
tcon_i80bus_write(cmd->cmd & 0xFFFF); /* This function already manage
* no need to do it here. */
/* Sixth: If parameters is needed, send them */
INFOL(INFO_VERBOSE, ("/* Sixth: If parameters is needed, send them */"));
INFOL(INFO_DEBUG, ("/* Sixth: If parameters is needed, send them */"));
if (GET_COMMAND_PARAM_NUM(cmd->cmd) > 0)
{
int i, paramNumbers = GET_COMMAND_PARAM_NUM(cmd->cmd);
INFOL(INFO_VERBOSE, ("YES! We have %d parameters", paramNumbers));
INFOL(INFO_DEBUG, ("YES! We have %d parameters", paramNumbers));
tcon_set_write_to_data();
for (i = 0; i < paramNumbers; i++)
{
INFOL(INFO_VERBOSE, (" parameter [%02d] = 0x%04X", i, cmd->params[i]));
INFOL(INFO_DEBUG, (" parameter [%02d] = 0x%04X", i, cmd->params[i]));
tcon_i80bus_write(cmd->params[i]);
}
@@ -544,20 +673,60 @@ int tcon_send_data(unsigned short *buffer, unsigned long bufferLen)
return 0;
}
int tcon_send_lut_data(unsigned short *buffer, unsigned long bufferLen)
{
/* Seventh: Send data if needed */
unsigned long i;
FUNC_IN();
INFOL(INFO_DEBUG, ("Bufferlen: %ld", bufferLen));
tcon_set_write_to_data();
for (i = 0; i < bufferLen; i++)
{
tcon_delay(1);
tcon_wait_ready();
tcon_delay(1);
tcon_i80bus_write_LUT(buffer[i]);
}
INFOL(INFO_DEBUG, ("Done."));
FUNC_OUT();
return 0;
}
int tcon_read_data(unsigned short *buffer, unsigned long bufferLen)
{
unsigned long i;
//FUNC_IN();
//INFOL(INFO_VERBOSE, ("Bufferlen: %ld", bufferLen));
tcon_set_write_to_data();
for (i = 0; i < bufferLen; i++)
{
tcon_i80bus_read(&(buffer[i]));
}
//FUNC_OUT();
return 0;
}
int tcon_send_command_end(sAUOCommand *cmd)
{
FUNC_IN();
INFOL(INFO_VERBOSE,("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)
{
tcon_set_write_to_command();
INFOL(INFO_VERBOSE, ("/* Eight: Send STOP command */"));
INFOL(INFO_DEBUG, ("/* Eight: Send STOP command */"));
tcon_i80bus_write(AUOCMD_DISPLAY_STOP & 0xFFFF);
tcon_set_write_to_data();
}
INFOL(INFO_VERBOSE, ("/* Nineth: Close all */"));
INFOL(INFO_DEBUG, ("/* Nineth: Close all */"));
tcon_unselect_chip();
tcon_i80bus_deinit_interface();
@@ -565,6 +734,234 @@ int tcon_send_command_end(sAUOCommand *cmd)
return 0;
}
// ===========================================================================
// Bit Bang SPI Interface
// ===========================================================================
#define TCON_SPI_CLK S3C2410_GPE13
#define TCON_SPI_DI S3C2410_GPE11
#define TCON_SPI_DO S3C2410_GPE12
#define TCON_SPI_CS S3C2410_GPL13
static void tcon_spi_init(void)
{
FUNC_IN();
/* First be sure that the Wifi is off */
/* GPK5 = PA 3.3V */
writel((readl(S3C2416_GPKDAT) & ~(1<<5)), S3C2416_GPKDAT);
/* GPK6 = PA 1.8V */
writel((readl(S3C2416_GPKDAT) & ~(1<<6)), S3C2416_GPKDAT);
/* Next, shutdown the TCON */
tcon_set_power_off();
mdelay(2000);
//GPD8, RESET
s3c2410_gpio_cfgpin(S3C2410_GPD8, S3C2410_GPD8_OUTP);
s3c2410_gpio_setpin(S3C2410_GPD8, 0);
/* Next, Switch the SPI */
s3c2410_gpio_cfgpin(S3C2410_GPH6, S3C2410_GPH6_OUTP);
s3c2410_gpio_setpin(S3C2410_GPH6, 1);
mdelay(200);
/* Next, init GPIOs */
/* GPL13 = SPI Chip Select */
s3c2410_gpio_cfgpin(S3C2410_GPL13, S3C2410_GPL13_OUTP);
s3c2410_gpio_setpin(S3C2410_GPL13, 1);
/* GPE11 = SPI DI */
s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_INP);
s3c2410_gpio_pullup(S3C2410_GPE11, 0);
/* GPE12 = SPI DO */
s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_OUTP);
s3c2410_gpio_setpin(S3C2410_GPE12, 1);
/* GPE13 = SPI CLK */
s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_OUTP);
s3c2410_gpio_setpin(S3C2410_GPE13, 0);
mdelay(50);
/* We are ready ! */
FUNC_OUT();
}
static void tcon_spi_deinit(void)
{
FUNC_IN();
/* First, switch the SPI */
s3c2410_gpio_setpin(S3C2410_GPH6, 1);
/* Then, restore GPIOs */
s3c2410_gpio_cfgpin(S3C2410_GPL13, S3C2410_GPL13_SS0);
/* GPE11 = SPI DI */
s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_SPIMISO0);
/* GPE12 = SPI DO */
s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_SPIMOSI0);
/* GPE13 = SPI CLK */
s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_SPICLK0);
/* Next, switch back on the TCON */
tcon_set_power_on();
s3c2410_gpio_setpin(S3C2410_GPD8, 1);
mdelay(100);
/* The calling must restore the TCON status, we only set it back on */
FUNC_OUT();
}
static inline unsigned char tcon_spi_read (void)
{
unsigned char k,
tmp_data = 0,
i = 0;
u32 read_pin;
#ifdef DEBUG_SPI
char strobe_str[9];
strobe_str[8] = 0;
#endif
/* sure that the clock is low */
for ( k = 0; k < 8; k++ )
{
/* Strobe clock */
s3c2410_gpio_setpin(TCON_SPI_CLK, 1);
udelay(2);
/* Sample */
read_pin = s3c2410_gpio_getpin(TCON_SPI_DI);//(readl(S3C2410_GPEDAT) & (1 << 11));
if ( read_pin )
{
i = (0x80 >> k);
tmp_data = (tmp_data | i);
}
#ifdef DEBUG_SPI
strobe_str[k] = (read_pin?'-':'_');
#endif
/* ACK bit read */
s3c2410_gpio_setpin(TCON_SPI_CLK, 0);
udelay(2);
}
#ifdef DEBUG_SPI
INFOL(INFO_VERBOSE, ("WFM:[%s] return %d", strobe_str, tmp_data));
#endif
return (tmp_data);
}
static inline void tcon_spi_write(unsigned char value)
{
unsigned char k;
#ifdef DEBUG_SPI
char strobe_str[9];
strobe_str[8] = 0;
#endif
for ( k = 0; k < 8; k++ )
{
if ( (value & 0x80) )
s3c2410_gpio_setpin(TCON_SPI_DO, 1);
else
s3c2410_gpio_setpin(TCON_SPI_DO, 0);
#ifdef DEBUG_SPI
strobe_str[k] = ((value&0x80)?'-':'_');
#endif
/* Strobe clock */
s3c2410_gpio_setpin(TCON_SPI_CLK, 1);
udelay(2);
s3c2410_gpio_setpin(TCON_SPI_CLK, 0);
udelay(2);
value = (value << 1);
}
#ifdef DEBUG_SPI
INFOL(INFO_VERBOSE, ("WFM:[%s]", strobe_str));
#endif
}
static unsigned char tcon_spi_flash_read(unsigned char value)
{
unsigned char ret;
s3c2410_gpio_setpin(TCON_SPI_CS, 0);
udelay(50);
tcon_spi_write(value);
udelay(2);
ret = tcon_spi_read();
s3c2410_gpio_setpin(TCON_SPI_CS, 1);
udelay(50);
return ret;
}
static void tcon_spi_flash_write(unsigned char value)
{
s3c2410_gpio_setpin(TCON_SPI_CS, 0);
udelay(50);
tcon_spi_write(value);
s3c2410_gpio_setpin(TCON_SPI_CS, 1);
udelay(50);
}
static void tcon_spi_flash_waitready(void)
{
unsigned char r_data;
FUNC_IN();
do
{
s3c2410_gpio_setpin(TCON_SPI_CS, 0);
udelay(50);
tcon_spi_write(0x05); //Write Read Status command
udelay(2);
r_data = tcon_spi_read();
udelay(50);
s3c2410_gpio_setpin(TCON_SPI_CS, 1);
INFOL(INFO_DEBUG, ("r_data: 0x%02x [SRWD:%c BP2:%d BP1:%d BP0:%d, WEL:%c, WIP:%c]\n", r_data,
(r_data & 0x80)?'E':'D',
(r_data & 0x10)?1:0,
(r_data & 0x08)?1:0,
(r_data & 0x04)?1:0,
(r_data & 0x02)?'E':'D',
(r_data & 0x01)?'W':'r'));
msleep(20);
} while ( r_data & 0x01 );
FUNC_OUT();
}
static void tcon_spi_flash_writepage(unsigned long addr, unsigned char *buffer, unsigned short buffer_len)
{
int i;
FUNC_IN();
s3c2410_gpio_setpin(TCON_SPI_CS, 0);
udelay(50);
tcon_spi_write(0x02); //Write Page Program command
tcon_spi_write( (addr & 0xFF0000) >> 16 );
tcon_spi_write( (addr & 0xFF00) >> 8 );
tcon_spi_write( (addr & 0xFF) );
for(i=0; i<buffer_len; i++)
{
tcon_spi_write(buffer[i]);
}
s3c2410_gpio_setpin(TCON_SPI_CS, 1);
mdelay(10);
tcon_spi_flash_waitready();
FUNC_OUT();
}
// ===========================================================================
// Device related functions
@@ -604,17 +1001,28 @@ int tcon_ioctl (struct inode *inode, struct file *file,
unsigned char *user_buffer;
unsigned long user_buflen, copysize, copysize16;
unsigned short *ptr16;
unsigned long tmp;
void __user *argp = (void __user *)arg;
int block_id = 0;
int flash_addr;
int ret = -EINVAL;
FUNC_IN();
INFOL(INFO_VERBOSE, ("Receive IOTCL #08%X", ioctl_cmd));
switch ( ioctl_cmd )
{
/* [MTR] */
case IOCTL_AUO_SENDCOMMAND:
if ( copy_from_user(&cmd, argp, sizeof (cmd)) )
return -EFAULT;
/* Prevent to send command if the user don't provide a buffer */
if ((GET_COMMAND_READ_WRITE(cmd.cmd) != 0) && (cmd.datalen == 0))
return -EFAULT;
/* Prevent if we set data and data prt is NULL */
if (( GET_COMMAND_HAVE_DATA(cmd.cmd) != 0 ) && (cmd.datalen > 0) && (cmd.data == NULL))
return -EFAULT;
/* Now execute the command */
tcon_send_command_start(&cmd);
@@ -631,16 +1039,30 @@ int tcon_ioctl (struct inode *inode, struct file *file,
if ( user_buflen > sizeof (buffer) )
copysize = sizeof (buffer);
if ( copy_from_user(buffer, user_buffer, copysize) )
return -EFAULT;
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;
tcon_send_data((unsigned short *)buffer, copysize16);
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;
@@ -649,12 +1071,134 @@ int tcon_ioctl (struct inode *inode, struct file *file,
tcon_send_command_end(&cmd);
ret = 0;
break;
case IOCTL_AUO_RESET:
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);
ret = 0;
break;
case IOCTL_AUO_SLEEP:
/* Only accept go to sleep if we are in standby, or else it will fail */
if (tcon_currentPowerMode == TCON_POWER_STANDBYMODE)
{
tcon_currentPowerMode = TCON_POWER_SLEEPMODE;
/* Set GPIO accordingly */
tmp = __raw_readl(S3C2410_GPBDAT);
tmp &= ~(1 << 1); //Set SLP_N to low
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
ret = 0;
}
else
ret = -ENAVAIL;
break;
case IOCTL_AUO_WAKEUP:
/* Only accept go to sleep if we are in standby, or else it will fail */
if (tcon_currentPowerMode == TCON_POWER_SLEEPMODE)
{
tcon_currentPowerMode = TCON_POWER_STANDBYMODE;
/* Set GPIO accordingly */
tmp = __raw_readl(S3C2410_GPBDAT);
tmp |= (1 << 1); //Set SLP_N to high
__raw_writel(tmp, S3C2410_GPBDAT);
msleep(10);
ret = 0;
}
else
ret = -ENAVAIL;
break;
case IOCTL_AUO_UPDATEFW:
INFOL(INFO_VERBOSE, ("Starting update of TCON firmware..."));
if ( copy_from_user(&cmd, argp, sizeof (cmd)) )
{
INFOL(INFO_ERROR, ("Copy from User error..."));
return -EFAULT;
}
INFOL(INFO_VERBOSE, ("Starting update of TCON firmware..."));
if ((cmd.data == NULL) || (cmd.datalen == 0))
{
INFOL(INFO_ERROR, ("Parameters error..."));
return -EFAULT;
}
/* First init SPI */
INFOL(INFO_VERBOSE, ("Will init BitBang SPI..."));
tcon_spi_init();
mdelay(3000);
flash_addr = 0;
INFOL(INFO_VERBOSE, ("Erasing SPI flash..."));
/* Erase Flash */
tcon_spi_flash_write(0x06); //Setting Write Enable Latch bit
tcon_spi_flash_write(0x60); //Write Chip Erase command
msleep(100);
tcon_spi_flash_waitready();
user_buflen = cmd.datalen;
user_buffer = (unsigned char *)cmd.data;
INFOL(INFO_VERBOSE, ("Will start write of TCON firmware..."));
/* Now, Write new Flash content */
while ( user_buflen != 0 )
{
copysize = user_buflen;
INFOL(INFO_DEBUG, ("Flash page @ addr 0x%08X", flash_addr));
if ( user_buflen > 256 )
copysize = 256;
if ( copy_from_user(buffer, user_buffer, copysize) )
return -EFAULT;
/* Send Buffer data */
tcon_spi_flash_write(0x06); /* Enable write... */
tcon_spi_flash_writepage(flash_addr, buffer, copysize);
flash_addr += copysize;
user_buflen -= copysize;
user_buffer += copysize;
}
/* Restore SPI */
tcon_spi_deinit();
break;
default:
printk(KERN_WARNING "Invalid ioctl");
ret = -EINVAL;
break;
}
FUNC_OUT();
return -EINVAL;
return ret;
}
// ===========================================================================
static struct file_operations s_tcon_fops =
@@ -733,13 +1277,13 @@ static int tcon_probe (struct platform_device *dev)
tmp |= (1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
tmp = __raw_readl(S3C2410_GPDDAT); // goes to LOW
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); // goes to HIGH
tmp = __raw_readl(S3C2410_GPDDAT); // RST_N goes to HIGH
tmp |= (1 << 9);
__raw_writel(tmp, S3C2410_GPDDAT);
@@ -769,6 +1313,11 @@ static int tcon_resume (struct platform_device *dev)
{
FUNC_IN();
if (tcon_inPortraitMode)
tcon_i80bus_set_speed(EN_I80_PORTRAIT, 800, 600, true);
else
tcon_i80bus_set_speed(EN_I80_LANDSCAPE, 600, 800, true);
FUNC_OUT();
return 0;
}