aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch')
-rw-r--r--recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch465
1 files changed, 465 insertions, 0 deletions
diff --git a/recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch b/recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch
new file mode 100644
index 0000000000..cd56e5837f
--- /dev/null
+++ b/recipes/linux/linux-mtx-2-2.4.27/36-sb2-lcd.patch
@@ -0,0 +1,465 @@
+--- linux-old/arch/mips/au1000/mtx-2/lcd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/arch/mips/au1000/mtx-2/lcd.c 2006-04-30 19:43:48.070431000 +0200
+@@ -0,0 +1,423 @@
++/*
++ * Driver for the KS0713 LCD controller
++ *
++ * Loading the module will cause DEVFS to create the device file /dev/misc/lcd,
++ * which can be written to to control the display.
++ */
++
++#include <linux/lcd-driver.h>
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <asm/uaccess.h>
++#include <asm/au1000.h>
++
++#include <asm/au1xxx_psc.h>
++
++/*---------[ declarations ]-----------------*/
++
++#if !defined(LCD_PLATFORM)
++# define LCD_PLATFORM SURFBOX2
++#endif
++
++#define BLA(X) #X
++#define BLA2(X) BLA(X)
++
++static enum lcd_platform lcd_platform = LCD_PLATFORM;
++MODULE_PARM(lcd_platform, "i");
++MODULE_PARM_DESC(lcd_platform, "The platform we are on (default " BLA2(LCD_PLATFORM) ")");
++
++static enum lcd_mode lcd_mode = COMMAND;
++MODULE_PARM(lcd_mode, "i");
++MODULE_PARM_DESC(lcd_mode, "The intial mode (default COMMAND)");
++
++static char lcd_use_dle = 0;
++MODULE_PARM(lcd_use_dle, "b");
++MODULE_PARM_DESC(lcd_use_dle, "Use DLE escapes (default no)");
++
++#define DLE 0x10
++
++static int lcd_minor = -1;
++static char is_inuse = 0;
++
++#define SBOX1_LCD_BACKLIGHT (1<<27) // GPIO27
++#define SBOX2_LCD_BACKLIGHT (1<<14) // GPIO14
++
++#define KS0713_BITMASK (0x1F << 10) /* GPIOs start at GPIO_10 */
++#define SBOX1_BITMASK ((0x1F << 10) | (3 << 25)) /* two GPIO blocks */
++#define SBOX2_BITMASK1 (1) /* GPIO 1 */
++#define SBOX2_BITMASK2 ((1 << 3) | (0x1F << 6)) /* GPIO 2 */
++
++/*---------[ Internal Functions ]-------------*/
++
++/* Layer 0 */
++
++static void set_backlight(const char on)
++{
++ if (lcd_platform == SURFBOX1)
++ au_writel(SBOX1_LCD_BACKLIGHT, on ? SYS_OUTPUTSET : SYS_OUTPUTCLR);
++ else if (lcd_platform == SURFBOX2)
++ au_writel(SBOX2_LCD_BACKLIGHT, on ? SYS_OUTPUTSET : SYS_OUTPUTCLR);
++}
++
++static inline void write_gpio1(const unsigned int line,
++ const unsigned int mask)
++{
++ const u32 reg = line & mask;
++ const u32 neg = (~reg) & mask;
++ au_writel(neg, SYS_OUTPUTCLR);
++ au_writel(reg, SYS_OUTPUTSET);
++}
++
++static inline void write_gpio2(const unsigned int line,
++ const unsigned int mask)
++{
++ au_writel((mask&0xffff) << 16 | (line&0xffff), GPIO2_OUTPUT);
++}
++
++static inline void write_flags(const int reset, const int cs, const int rs,
++ const int clock, const int data)
++{
++ switch (lcd_platform) {
++ case KS0713:
++ write_gpio1((!reset) << 14 | cs << 13 | rs << 12 |
++ clock << 11 | data << 10, KS0713_BITMASK);
++ break;
++ case SURFBOX1:
++ write_gpio1(rs << 25 | cs << 14 | !cs << 13 | 1 << 12 |
++ data << 11 | clock << 10, SBOX1_BITMASK);
++ break;
++ case SURFBOX2:
++ write_gpio1(0, SBOX2_BITMASK1);
++ write_gpio2(rs << 3 | cs << 7 | !cs << 6 | 0 << 8 |
++ data << 9 | clock << 10, SBOX2_BITMASK2);
++ break;
++ }
++}
++
++/* Layer 1 */
++
++static inline void write_line(unsigned int line)
++{
++ if (lcd_platform == KS0713) {
++ write_gpio1(line << 10, KS0713_BITMASK);
++ } else if (lcd_platform == SURFBOX1) {
++ const int hi = line >> 5;
++ line &= 0x1f;
++ write_gpio1(line << 10 | hi << 25, SBOX1_BITMASK | SBOX1_LCD_BACKLIGHT);
++ } else if (lcd_platform == SURFBOX2) {
++ int bm0 = line&1;
++ int bl = (line>>1)&1;
++ int cd = (line>>2)&1;
++ int rest = (line>>3)&0x1f;
++ write_gpio1(bm0 | bl<<14, SBOX2_BITMASK1 | SBOX2_LCD_BACKLIGHT);
++ write_gpio2(rest<<6 | cd<<3, SBOX2_BITMASK2);
++ }
++}
++
++static inline void release(void)
++{
++ return write_flags(0, 0, 0, 0, 0);
++}
++
++static inline void reset(void)
++{
++ return write_flags(1, 0, 0, 0, 0);
++}
++
++static void init_gpios(void)
++{
++ switch (lcd_platform) {
++ case KS0713:
++ // TODO: init lines?
++ release();
++ break;
++ case SURFBOX1:
++ if (lcd_mode == I2C)
++ write_gpio1(1 << 26 | 1 << 12 | 1 << 11 | 1 << 10, SBOX1_BITMASK);
++ else
++ release();
++ break;
++ case SURFBOX2:
++ au_writel(au_readl(GPIO2_DIR) | SBOX2_BITMASK2, GPIO2_DIR);
++ // au_writel(PSC_SEL_PS_DISABLED, PSC2_BASE_ADDR + PSC_CTRL_OFFSET);
++ au_writel(au_readl(SYS_PINFUNC) | SYS_PF_PSC2_GPIO, SYS_PINFUNC);
++ release();
++ break;
++ }
++}
++
++static inline void write_bit(const int rs, const int bit)
++{
++ /* Data is read on the rising edge */
++ write_flags(0, 1, rs, 0, bit);
++ write_flags(0, 1, rs, 1, bit);
++ if (lcd_platform != KS0713 && rs == LCD_RS_DATA) {
++ write_flags(0, 1, rs, 0, bit);
++ write_flags(0, 1, rs, 1, bit);
++ }
++}
++
++/* Layer 2 */
++
++static inline void write_byte(const int rs, const int byte)
++{
++ int i;
++ for (i = 7; i >= 0; i--)
++ write_bit(rs, (byte >> i) & 1);
++}
++
++DECLARE_WAIT_QUEUE_HEAD(lcd_sleep_q);
++
++static inline void sleep (long jiff)
++{
++ const long j = jiffies + jiff;
++ while (jiffies < j)
++ interruptible_sleep_on_timeout(&lcd_sleep_q, j - jiffies);
++}
++
++static inline void ctrl_init(void)
++{
++ switch (lcd_platform) {
++ case KS0713:
++ reset();
++ sleep(1L);
++ release();
++ sleep(1L);
++ // TODO: write_byte (LCD_RS_COMMAND, cmd|arg)
++/* do_command(fd, LCD_CMD_DISPSTART, 0, 0); */
++/* do_command(fd, LCD_CMD_DISPONOFF, 1, 0); */
++/* do_command(fd, LCD_CMD_ENTIREDISP, 0, 0); */
++/* do_command(fd, LCD_CMD_SHLSELECT, 0, 0); */
++/* do_command(fd, LCD_CMD_ADCSELECT, 1, 0); */
++/* do_command(fd, LCD_CMD_REFVOLTMODE, 0, 0); */
++/* do_command(fd, 0, 40, 0); */
++/* do_command(fd, LCD_CMD_LCDBIAS, 1, 0); */
++/* do_command(fd, LCD_CMD_POWERCTRL, 7, 0); */
++/* do_command(fd, LCD_CMD_REGRESISTOR, 6, 1); */
++ release();
++ sleep(1L);
++ break;
++ case SURFBOX1:
++ case SURFBOX2:
++ write_byte (LCD_RS_COMMAND, 0xe2); // RESET
++ release();
++ sleep(1L);
++ write_byte (LCD_RS_COMMAND, 0x81); // Vbias potentiometer
++ write_byte (LCD_RS_COMMAND, 0x1c); // set to 28 (conf?)
++ write_byte (LCD_RS_COMMAND, 0xad); // ON, b/w
++ release();
++ set_backlight(1);
++ break;
++ }
++}
++
++/* Layer i */
++
++static int dle = 0;
++
++static inline void handle_input (const unsigned char byte)
++{
++ if (dle) {
++ switch (byte) {
++ case DLE:
++ write_line (DLE);
++ break;
++ case 'B': /* backlight on */
++ set_backlight(1);
++ break;
++ case 'b': /* backlight off */
++ set_backlight(0);
++ break;
++ case 'r': /* reset */
++ reset();
++ break;
++ case 'l': /* release */
++ release();
++ break;
++ case 'i': /* init */
++ ctrl_init();
++ break;
++ case 's': /* serial mode */
++ lcd_mode = SERIAL;
++ break;
++ case 'c': /* command mode */
++ lcd_mode = COMMAND;
++ break;
++ case 'd': /* data mode */
++ lcd_mode = DATA;
++ break;
++ case '3': /* select mode by number */
++ case '2':
++ case '1':
++ case '0':
++ lcd_mode = (enum lcd_mode) (byte - '0');
++ break;
++ case 'e': /* stop dle mode, reversable by ioctl only */
++ lcd_use_dle = 0;
++ break;
++ }
++ dle = 0;
++ } else if (lcd_use_dle && byte == DLE) {
++ dle = 1;
++ } else switch (lcd_mode) {
++ case COMMAND:
++ write_byte (LCD_RS_COMMAND, byte);
++ break;
++ case DATA:
++ write_byte (LCD_RS_DATA, byte);
++ break;
++ case SERIAL:
++ case I2C:
++ write_line (byte);
++ break;
++ }
++}
++
++/*---------[ File Functions ]-----------------*/
++
++static int lcd_open (struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev) != lcd_minor)
++ return -ENODEV;
++ if (is_inuse)
++ return -EBUSY;
++ is_inuse = 1;
++ MOD_INC_USE_COUNT;
++ return 0;
++}
++
++static int lcd_release (struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev) == lcd_minor) {
++ is_inuse = 0;
++ }
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++static ssize_t lcd_write (struct file *file, const char *buf,
++ size_t count, loff_t *ppos)
++{
++ unsigned char localbuf;
++ ssize_t bytes_read = 0;
++ while (bytes_read < count) {
++ if (copy_from_user(&localbuf, buf + bytes_read, 1))
++ return -EFAULT;
++ ++bytes_read;
++ handle_input(localbuf);
++ }
++ return bytes_read; /* Everything read */
++}
++
++static int lcd_ioctl (struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ switch (cmd) {
++ case LCD_IOCRESET:
++ reset();
++ break;
++ case LCD_IOCRELEASE:
++ release ();
++ break;
++ case LCD_IOCSMODE:
++ lcd_mode = (enum lcd_mode) arg;
++ break;
++ case LCD_IOCGMODE:
++ return __put_user(lcd_mode, (enum lcd_mode *) arg);
++ case LCD_IOCSUSEDLE:
++ lcd_use_dle = (char) arg;
++ break;
++ case LCD_IOCGUSEDLE:
++ return __put_user(lcd_use_dle, (char *) arg);
++ case LCD_IOCCOMMAND:
++ write_byte (LCD_RS_COMMAND, arg);
++ break;
++ case LCD_IOCINIT:
++ ctrl_init();
++ break;
++ case LCD_IOCSBACKLIGHT:
++ set_backlight((char) arg);
++ break;
++ case LCD_IOCGPLATFORM:
++ return __put_user(lcd_platform, (enum lcd_platform *) arg);
++ break;
++
++ default:
++ return -ENOTTY; /* sic! "inappropiate ioctl for device" */
++ }
++ return 0;
++}
++
++/*---------[ Module stuff ]-----------------*/
++
++static struct file_operations lcd_fops = {
++ .owner = THIS_MODULE,
++ .llseek = NULL,
++ .read = NULL,
++ .write = lcd_write,
++ .readdir = NULL,
++ .poll = NULL,
++ .ioctl = lcd_ioctl,
++ .mmap = NULL,
++ .open = lcd_open,
++ .flush = NULL,
++ .release = lcd_release
++};
++
++static struct miscdevice lcd_miscdev = {
++ MISC_DYNAMIC_MINOR,
++ "lcd",
++ &lcd_fops
++};
++
++int __init lcd_init (void)
++{
++ is_inuse = 1;
++ printk(KERN_INFO "Surfbox2 LCD driver ...");
++
++ init_gpios();
++ //au_writel( 0x12000000 & LCD_BITMASK, SYS_OUTPUTCLR );
++ //au_writel( 0x0c000000, SYS_OUTPUTSET ); /* Magic GPIO to activate LED-driver */
++
++ /* Register device */
++ if (misc_register(&lcd_miscdev) >= 0) {
++ lcd_minor = lcd_miscdev.minor;
++ printk(" successfully loaded (platform=%d,mode=%d,dle=%d).\n",
++ lcd_platform, lcd_mode, lcd_use_dle);
++ is_inuse = 0;
++ return 0;
++ } else {
++ printk("failed.\n");
++ is_inuse = 0;
++ return 1;
++ }
++}
++
++void __exit lcd_cleanup (void)
++{
++ is_inuse = 1;
++ misc_deregister(&lcd_miscdev);
++ printk(KERN_INFO "Surfbox (%d) LCD driver unloaded (mode=%d,dle=%d).\n",
++ lcd_platform, lcd_mode, lcd_use_dle);
++ is_inuse = 0;
++}
++
++module_init(lcd_init);
++module_exit(lcd_cleanup);
++
++MODULE_AUTHOR("Simon Krahnke");
++MODULE_DESCRIPTION("Driver for MTX LCD");
++MODULE_LICENSE("GPL");
++EXPORT_NO_SYMBOLS;
+--- linux-old/include/linux/lcd-driver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/include/linux/lcd-driver.h 2006-04-30 19:44:02.035303750 +0200
+@@ -0,0 +1,26 @@
++#if !defined(LCD_DRIVER_H)
++#define LCD_DRIVER_H
++
++enum lcd_platform { KS0713 = 0, SURFBOX1, SURFBOX2 };
++
++enum lcd_mode { SERIAL = 0, COMMAND, DATA, I2C };
++
++#define LCD_RS_COMMAND 0
++#define LCD_RS_DATA 1
++
++/* We use the available magic L with number 0x40-0x4f */
++
++#define LCD_IOC_MAGIC 'L'
++
++#define LCD_IOCRESET _IO(LCD_IOC_MAGIC, 0x40)
++#define LCD_IOCRELEASE _IO(LCD_IOC_MAGIC, 0x41)
++#define LCD_IOCSMODE _IOW(LCD_IOC_MAGIC, 0x42, enum lcd_mode)
++#define LCD_IOCGMODE _IOR(LCD_IOC_MAGIC, 0x43, enum lcd_mode*)
++#define LCD_IOCSUSEDLE _IOW(LCD_IOC_MAGIC, 0x44, char)
++#define LCD_IOCGUSEDLE _IOR(LCD_IOC_MAGIC, 0x45, char*)
++#define LCD_IOCCOMMAND _IOW(LCD_IOC_MAGIC, 0x46, unsigned char)
++#define LCD_IOCINIT _IO(LCD_IOC_MAGIC, 0x47)
++#define LCD_IOCSBACKLIGHT _IOW(LCD_IOC_MAGIC, 0x48, char)
++#define LCD_IOCGPLATFORM _IOR(LCD_IOC_MAGIC, 0x49, enum lcd_platform*)
++
++#endif /* LCD_DRIVER_H */
+--- linux/arch/mips/au1000/mtx-2/Makefile.org 2006-05-01 13:36:01.675030000 +0200
++++ linux/arch/mips/au1000/mtx-2/Makefile 2006-05-01 13:36:11.175623750 +0200
+@@ -15,6 +15,6 @@
+
+ O_TARGET := mtx-2.o
+
+-obj-y := init.o board_setup.o irqmap.o slic.o
++obj-y := init.o board_setup.o irqmap.o slic.o lcd.o
+
+ include $(TOPDIR)/Rules.make