diff options
Diffstat (limited to 'packages')
19 files changed, 0 insertions, 7251 deletions
diff --git a/packages/linux/linux-rp-2.6.22/wm97xx-lcdnoise-r0.patch b/packages/linux/linux-rp-2.6.22/wm97xx-lcdnoise-r0.patch deleted file mode 100644 index 191de3af22..0000000000 --- a/packages/linux/linux-rp-2.6.22/wm97xx-lcdnoise-r0.patch +++ /dev/null @@ -1,208 +0,0 @@ -Index: linux-tosa/drivers/input/touchscreen/wm9712.c -=================================================================== ---- linux-tosa.orig/drivers/input/touchscreen/wm9712.c 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/drivers/input/touchscreen/wm9712.c 2006-08-29 16:52:50.923275896 +0100 -@@ -1,7 +1,7 @@ - /* - * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. - * -- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC. -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com - * Parts Copyright : Ian Molton <spyro@f2s.com> -@@ -13,6 +13,12 @@ - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * -+ * Revision history -+ * 4th Jul 2005 Initial version. -+ * 29th Aug 2006 Mike Arthur <mike@mikearthur.co.uk> -+ * Added fixes for Sharp SL-6000 (Tosa) LCD noise causing -+ * touchscreen interference. -+ * - */ - - #include <linux/module.h> -@@ -28,6 +34,10 @@ - #define WM9705_VERSION "0.60" - #define DEFAULT_PRESSURE 0xb0c0 - -+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -+#define CCNT_ON() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+#define CCNT_OFF() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+ - /* - * Debug - */ -@@ -243,6 +253,36 @@ - return wm->dig[2] & WM9712_PDEN; - } - -+ -+#ifdef CONFIG_MACH_TOSA -+/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait -+ * before sampling the Y axis of the touchscreen */ -+static inline void wm9712_lcd_sync_on(struct wm97xx* wm, int adcsel) { -+ unsigned long timer1 = 0, timer2 = 0, wait_time = 0; -+ if (adcsel == WM97XX_ADCSEL_Y) { -+ wait_time = wm97xx_calc_lcd_waittime(wm); -+ -+ CCNT_ON(); -+ -+ if (wait_time) { -+ /* wait for LCD rising edge */ -+ wm_machinfo->wait_hsync(); -+ /* get clock */ -+ CCNT(timer1); -+ CCNT(timer2); -+ -+ while ((timer2 - timer1) < wait_time) { -+ CCNT(timer2); -+ } -+ } -+ } -+} -+ -+static inline void wm9712_lcd_sync_off(void) { -+ CCNT_OFF(); -+} -+#endif -+ - /* - * Read a sample from the WM9712 adc in polling mode. - */ -@@ -260,6 +300,9 @@ - /* set up digitiser */ - if (adcsel & 0x8000) - adcsel = ((adcsel & 0x7fff) + 3) << 12; -+ #ifdef CONFIG_MACH_TOSA -+ wm9712_lcd_sync_on(wm, adcsel); -+ #endif - wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); - - /* wait 3 AC97 time slots + delay for conversion */ -@@ -282,6 +325,10 @@ - - *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); - -+ #ifdef CONFIG_MACH_TOSA -+ wm9712_lcd_sync_off(); -+ #endif -+ - /* check we have correct sample */ - if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { - dbg ("adc wrong sample, read %x got %x", adcsel, -@@ -303,11 +350,12 @@ - static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data) - { - int rc; -- - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID) - return rc; -+ - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID) - return rc; -+ - if (pil && !five_wire) { - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID) - return rc; -Index: linux-tosa/drivers/input/touchscreen/wm97xx-core.c -=================================================================== ---- linux-tosa.orig/drivers/input/touchscreen/wm97xx-core.c 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/drivers/input/touchscreen/wm97xx-core.c 2006-08-29 16:52:50.924275744 +0100 -@@ -2,7 +2,7 @@ - * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712 - * and WM9713 AC97 Codecs. - * -- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC. -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com - * Parts Copyright : Ian Molton <spyro@f2s.com> -@@ -67,6 +67,9 @@ - * GPIOs) and 2.6 power management. - * 29th Nov 2004 Added WM9713 support. - * 4th Jul 2005 Moved codec specific code out to seperate files. -+ * 29th Aug 2006 Mike Arthur <mike@mikearthur.co.uk> -+ * Added fixes for Sharp SL-6000 (Tosa) LCD noise causing -+ * touchscreen interference. - */ - - #include <linux/module.h> -@@ -94,6 +97,7 @@ - static DECLARE_MUTEX(gpio_sem); - static LIST_HEAD(wm97xx_misc_list); - static struct wm97xx* wm_codec = NULL; -+struct wm97xx_machinfo *wm_machinfo; - - /* - * WM97xx - enable/disable AUX ADC sysfs -@@ -832,6 +836,23 @@ - mdev->remove(wm_codec); - } - -+#ifdef CONFIG_MACH_TOSA -+/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait -+ * before sampling the Y axis of the touchscreen */ -+unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm) { -+ unsigned long hsync_time = wm_machinfo->get_hsync_time(); -+ return hsync_time; -+} -+ -+void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo) { -+ wm_machinfo = machinfo; -+} -+ -+void wm97xx_unset_machinfo() { -+ wm_machinfo = NULL; -+} -+#endif -+ - static struct device_driver wm97xx_driver = { - .name = "ac97", - .bus = &ac97_bus_type, -@@ -861,6 +882,9 @@ - EXPORT_SYMBOL_GPL(wm97xx_reg_write); - EXPORT_SYMBOL_GPL(wm97xx_register_misc_dev); - EXPORT_SYMBOL_GPL(wm97xx_unregister_misc_dev); -+EXPORT_SYMBOL_GPL(wm97xx_calc_lcd_waittime); -+EXPORT_SYMBOL_GPL(wm97xx_set_machinfo); -+EXPORT_SYMBOL_GPL(wm97xx_unset_machinfo); - - module_init(wm97xx_init); - module_exit(wm97xx_exit); -Index: linux-tosa/include/linux/wm97xx.h -=================================================================== ---- linux-tosa.orig/include/linux/wm97xx.h 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/include/linux/wm97xx.h 2006-08-29 16:52:50.924275744 +0100 -@@ -207,6 +207,7 @@ - - struct wm97xx; - extern struct wm97xx_codec_drv wm97xx_codec; -+extern struct wm97xx_machinfo *wm_machinfo; - - /* - * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs -@@ -253,6 +254,11 @@ - struct list_head list; - }; - -+struct wm97xx_machinfo { -+ unsigned long (*get_hsync_time)(void); -+ void (*wait_hsync)(void); -+}; -+ - int wm97xx_register_misc_dev(struct wm97xx_misc_dev* mdev); - void wm97xx_unregister_misc_dev(struct wm97xx_misc_dev* mdev); - -@@ -281,4 +287,9 @@ - int wm97xx_acc_startup(struct wm97xx* wm); - void wm97xx_acc_shutdown(struct wm97xx* wm); - -+ -+unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm); -+void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo); -+void wm97xx_unset_machinfo(void); -+ - #endif diff --git a/packages/linux/linux-rp-2.6.23/sharpsl-pm-postresume-r1.patch b/packages/linux/linux-rp-2.6.23/sharpsl-pm-postresume-r1.patch index e1491d6d49..409daf03e6 100644 --- a/packages/linux/linux-rp-2.6.23/sharpsl-pm-postresume-r1.patch +++ b/packages/linux/linux-rp-2.6.23/sharpsl-pm-postresume-r1.patch @@ -28,33 +28,3 @@ Index: git/arch/arm/common/sharpsl_pm.c dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); return 0; - arch/arm/common/sharpsl_pm.c | 3 +++ - include/asm-arm/hardware/sharpsl_pm.h | 1 + - 2 files changed, 4 insertions(+) - -Index: git/include/asm-arm/hardware/sharpsl_pm.h -=================================================================== ---- git.orig/include/asm-arm/hardware/sharpsl_pm.h 2006-10-31 16:09:33.000000000 +0000 -+++ git/include/asm-arm/hardware/sharpsl_pm.h 2006-11-07 22:08:41.000000000 +0000 -@@ -26,6 +26,7 @@ struct sharpsl_charger_machinfo { - void (*presuspend)(void); - void (*postsuspend)(void); - void (*earlyresume)(void); -+ void (*postresume)(void); - unsigned long (*read_devdata)(int); - #define SHARPSL_BATT_VOLT 1 - #define SHARPSL_BATT_TEMP 2 -Index: git/arch/arm/common/sharpsl_pm.c -=================================================================== ---- git.orig/arch/arm/common/sharpsl_pm.c 2006-11-07 22:03:48.000000000 +0000 -+++ git/arch/arm/common/sharpsl_pm.c 2006-11-07 22:04:20.000000000 +0000 -@@ -584,6 +584,9 @@ static int corgi_pxa_pm_enter(suspend_st - if (sharpsl_pm.machinfo->earlyresume) - sharpsl_pm.machinfo->earlyresume(); - -+ if (sharpsl_pm.machinfo->postresume) -+ sharpsl_pm.machinfo->postresume(); -+ - dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); - - return 0; diff --git a/packages/linux/linux-rp-2.6.23/tmio-fb-r6-fix-r0.patch b/packages/linux/linux-rp-2.6.23/tmio-fb-r6-fix-r0.patch index 523edec381..eab57c50e8 100644 --- a/packages/linux/linux-rp-2.6.23/tmio-fb-r6-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/tmio-fb-r6-fix-r0.patch @@ -43,48 +43,3 @@ index 10b0105..72eb76c 100644 -- 1.4.4.4 -From 302745ce6f3bab7b1a97de32339405ae3fd8eacb Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 00:05:54 +0400 -Subject: [PATCH] tmio-fb-r6.patch fixes - ---- - drivers/video/tmiofb.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c -index 10b0105..72eb76c 100644 ---- a/drivers/video/tmiofb.c -+++ b/drivers/video/tmiofb.c -@@ -463,8 +463,8 @@ static int tmiofb_vblank (struct fb_info *fbi, struct fb_vblank *vblank) - #define FBIO_TMIO_ACC_WRITE 0x7C639300 - #define FBIO_TMIO_ACC_SYNC 0x7C639301 - --static int tmiofb_ioctl (struct inode *inode, struct file *file, -- unsigned int cmd, unsigned long arg, struct fb_info *fbi) -+static int tmiofb_ioctl (struct fb_info *fbi, -+ unsigned int cmd, unsigned long arg) - { - switch (cmd) { - case FBIOGET_VBLANK: { -@@ -677,7 +677,7 @@ static struct fb_ops tmiofb_ops_acc = { - * 2000 0002 display start - * 2000 0004 line number match (0x1ff mask???) - */ --static irqreturn_t tmiofb_irq (int irq, void *__fbi, struct pt_regs *r) -+static irqreturn_t tmiofb_irq (int irq, void *__fbi) - { - struct fb_info* fbi = __fbi; - struct tmiofb_par* par = fbi->par; -@@ -762,7 +762,7 @@ static int __init tmiofb_probe (struct device *dev) - } - fbi->screen_base = par->sram; - -- retval = request_irq (irq->start, &tmiofb_irq, SA_INTERRUPT, -+ retval = request_irq (irq->start, &tmiofb_irq, IRQF_DISABLED, - TMIO_NAME_LCD, fbi); - if (retval) - goto err_request_irq; --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tmio-nand-r8.patch b/packages/linux/linux-rp-2.6.23/tmio-nand-r8.patch index 3a30c2f34c..a71fd114a8 100644 --- a/packages/linux/linux-rp-2.6.23/tmio-nand-r8.patch +++ b/packages/linux/linux-rp-2.6.23/tmio-nand-r8.patch @@ -592,597 +592,3 @@ index 0000000..d196553 +MODULE_LICENSE ("GPL"); +MODULE_AUTHOR ("Dirk Opfer, Chris Humbert"); +MODULE_DESCRIPTION ("NAND flash driver on Toshiba Mobile IO controller"); - drivers/mtd/nand/Kconfig | 7 + - drivers/mtd/nand/Makefile | 1 + - drivers/mtd/nand/tmio.c | 554 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 562 insertions(+), 0 deletions(-) - -diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index f1d60b6..b9c8796 100644 ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -69,6 +69,13 @@ config MTD_NAND_AMS_DELTA - help - Support for NAND flash on Amstrad E3 (Delta). - -+config MTD_NAND_TMIO -+ tristate "NAND Flash device on Toshiba Mobile IO Controller" -+ depends on MTD_NAND && TOSHIBA_TC6393XB -+ help -+ Support for NAND flash connected to a Toshiba Mobile IO -+ Controller in some PDAs, including the Sharp SL6000x. -+ - config MTD_NAND_TOTO - tristate "NAND Flash device on TOTO board" - depends on ARCH_OMAP && BROKEN -diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile -index edba1db..64f24e1 100644 ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -27,5 +27,6 @@ obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o - obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o - obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o - obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o -+obj-$(CONFIG_MTD_NAND_TMIO) += tmio.o - - nand-objs := nand_base.o nand_bbt.o -diff --git a/drivers/mtd/nand/tmio.c b/drivers/mtd/nand/tmio.c -new file mode 100644 -index 0000000..d196553 ---- /dev/null -+++ b/drivers/mtd/nand/tmio.c -@@ -0,0 +1,554 @@ -+/* -+ * A device driver for NAND flash connected to a Toshiba Mobile IO -+ * controller. This is known to work with the following variants: -+ * TC6393XB revision 3 -+ * -+ * Maintainer: Chris Humbert <mahadri+mtd@drigon.com> -+ * -+ * Copyright (C) 2005 Chris Humbert -+ * Copyright (C) 2005 Dirk Opfer -+ * Copyright (C) 2004 SHARP -+ * Copyright (C) 2002 Lineo Japan, Inc. -+ * Copyright (C) Ian Molton and Sebastian Carlier -+ * -+ * Based on Sharp's NAND driver, sharp_sl_tc6393.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/wait.h> -+#include <linux/ioport.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/nand.h> -+#include <linux/mtd/nand_ecc.h> -+#include <linux/mtd/partitions.h> -+#include <asm/io.h> -+#include <asm/hardware/tmio.h> -+ -+#include <linux/interrupt.h> -+ -+#define mtd_printk(level, mtd, format, arg...) \ -+ printk (level "%s: " format, mtd->name, ## arg) -+#define mtd_warn(mtd, format, arg...) \ -+ mtd_printk (KERN_WARNING, mtd, format, ## arg) -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* tmio_nfcr.mode Register Command List */ -+#define FCR_MODE_DATA 0x94 // Data Data_Mode -+#define FCR_MODE_COMMAND 0x95 // Data Command_Mode -+#define FCR_MODE_ADDRESS 0x96 // Data Address_Mode -+ -+#define FCR_MODE_HWECC_CALC 0xB4 // HW-ECC Data -+#define FCR_MODE_HWECC_RESULT 0xD4 // HW-ECC Calculation Result Read_Mode -+#define FCR_MODE_HWECC_RESET 0xF4 // HW-ECC Reset -+ -+#define FCR_MODE_POWER_ON 0x0C // Power Supply ON to SSFDC card -+#define FCR_MODE_POWER_OFF 0x08 // Power Supply OFF to SSFDC card -+ -+#define FCR_MODE_LED_OFF 0x00 // LED OFF -+#define FCR_MODE_LED_ON 0x04 // LED ON -+ -+#define FCR_MODE_EJECT_ON 0x68 // Ejection Demand from Penguin is Advanced -+#define FCR_MODE_EJECT_OFF 0x08 // Ejection Demand from Penguin is Not Advanced -+ -+#define FCR_MODE_LOCK 0x6C // Operates By Lock_Mode. Ejection Switch is Invalid -+#define FCR_MODE_UNLOCK 0x0C // Operates By UnLock_Mode.Ejection Switch is Effective -+ -+#define FCR_MODE_CONTROLLER_ID 0x40 // Controller ID Read -+#define FCR_MODE_STANDBY 0x00 // SSFDC card Changes Standby State -+ -+#define FCR_MODE_WE 0x80 -+#define FCR_MODE_ECC1 0x40 -+#define FCR_MODE_ECC0 0x20 -+#define FCR_MODE_CE 0x10 -+#define FCR_MODE_PCNT1 0x08 -+#define FCR_MODE_PCNT0 0x04 -+#define FCR_MODE_ALE 0x02 -+#define FCR_MODE_CLE 0x01 -+ -+#define FCR_STATUS_BUSY 0x80 -+ -+/* -+ * NAND Flash Host Controller Configuration Register -+ */ -+struct tmio_nfhccr { -+ u8 x00[4]; -+ u16 command; /* 0x04 Command */ -+ u8 x01[0x0a]; -+ u16 base[2]; /* 0x10 NAND Flash Control Reg Base Addr*/ -+ u8 x02[0x29]; -+ u8 intp; /* 0x3d Interrupt Pin */ -+ u8 x03[0x0a]; -+ u8 inte; /* 0x48 Interrupt Enable */ -+ u8 x04; -+ u8 ec; /* 0x4a Event Control */ -+ u8 x05; -+ u8 icc; /* 0x4c Internal Clock Control */ -+ u8 x06[0x0e]; -+ u8 eccc; /* 0x5b ECC Control */ -+ u8 x07[4]; -+ u8 nftc; /* 0x60 NAND Flash Transaction Control */ -+ u8 nfm; /* 0x61 NAND Flash Monitor */ -+ u8 nfpsc; /* 0x62 NAND Flash Power Supply Control */ -+ u8 nfdc; /* 0x63 NAND Flash Detect Control */ -+ u8 x08[0x9c]; -+} __attribute__ ((packed)); -+ -+/* -+ * NAND Flash Control Register -+ */ -+struct tmio_nfcr { -+union { -+ u8 u8; /* 0x00 Data Register */ -+ u16 u16; -+ u32 u32; -+} __attribute__ ((packed)); -+ u8 mode; /* 0x04 Mode Register */ -+ u8 status; /* 0x05 Status Register */ -+ u8 isr; /* 0x06 Interrupt Status Register */ -+ u8 imr; /* 0x07 Interrupt Mask Register */ -+} __attribute__ ((packed)); -+ -+struct tmio_nand { -+ struct mtd_info mtd; -+ struct nand_chip chip; -+ -+ struct tmio_nfhccr __iomem * ccr; -+ struct tmio_nfcr __iomem * fcr; -+ -+ unsigned int irq; -+ -+ /* for tmio_nand_read_byte */ -+ u8 read; -+ unsigned read_good:1; -+}; -+ -+#define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd) -+ -+/*--------------------------------------------------------------------------*/ -+ -+static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd, -+ unsigned int ctrl) -+{ -+ struct tmio_nand *tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem *fcr = tmio->fcr; -+ struct nand_chip *chip = mtd->priv; -+ -+ if (ctrl & NAND_CTRL_CHANGE) { -+ u8 mode; -+ -+ if (ctrl & NAND_NCE) { -+ mode = FCR_MODE_DATA; -+ -+ if (ctrl & NAND_CLE) -+ mode |= FCR_MODE_CLE; -+ else -+ mode &= ~FCR_MODE_CLE; -+ -+ if (ctrl & NAND_ALE) -+ mode |= FCR_MODE_ALE; -+ else -+ mode &= ~FCR_MODE_ALE; -+ } else { -+ mode = FCR_MODE_STANDBY; -+ } -+ -+ iowrite8 (mode, &fcr->mode); -+ tmio->read_good = 0; -+ } -+ -+ if (cmd != NAND_CMD_NONE) -+ writeb(cmd, chip->IO_ADDR_W); -+} -+ -+static int tmio_nand_dev_ready (struct mtd_info* mtd) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ return !(ioread8 (&fcr->status) & FCR_STATUS_BUSY); -+} -+ -+static irqreturn_t tmio_irq (int irq, void *__tmio) -+{ -+ struct tmio_nand* tmio = __tmio; -+ struct nand_chip* this = &tmio->chip; -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ /* disable RDYREQ interrupt */ -+ iowrite8 (0x00, &fcr->imr); -+ -+ if (unlikely (!waitqueue_active (&this->controller->wq))) -+ printk (KERN_WARNING TMIO_NAME_NAND ": spurious interrupt\n"); -+ -+ wake_up (&this->controller->wq); -+ return IRQ_HANDLED; -+} -+ -+/* -+ * The TMIO core has a RDYREQ interrupt on the posedge of #SMRB. -+ * This interrupt is normally disabled, but for long operations like -+ * erase and write, we enable it to wake us up. The irq handler -+ * disables the interrupt. -+ */ -+static int -+tmio_nand_wait (struct mtd_info *mtd, struct nand_chip *this) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ long timeout; -+ -+ /* enable RDYREQ interrupt */ -+ iowrite8 (0x0f, &fcr->isr); -+ iowrite8 (0x81, &fcr->imr); -+ -+ timeout = wait_event_timeout (this->controller->wq, tmio_nand_dev_ready (mtd), -+ msecs_to_jiffies (this->state == FL_ERASING ? 400 : 20)); -+ -+ if (unlikely (!tmio_nand_dev_ready (mtd))) { -+ iowrite8 (0x00, &fcr->imr); -+ mtd_warn (mtd, "still busy with %s after %d ms\n", -+ this->state == FL_ERASING ? "erase" : "program", -+ this->state == FL_ERASING ? 400 : 20); -+ -+ } else if (unlikely (!timeout)) { -+ iowrite8 (0x00, &fcr->imr); -+ mtd_warn (mtd, "timeout waiting for interrupt\n"); -+ } -+ -+ this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -+ return this->read_byte (mtd); -+} -+ -+/* -+ * The TMIO controller combines two 8-bit data bytes into one 16-bit -+ * word. This function separates them so nand_base.c works as expected, -+ * especially its NAND_CMD_READID routines. -+ * -+ * To prevent stale data from being read, tmio_nand_hwcontrol() clears -+ * tmio->read_good. -+ */ -+static u_char tmio_nand_read_byte (struct mtd_info *mtd) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ unsigned int data; -+ -+ if (tmio->read_good--) -+ return tmio->read; -+ -+ data = ioread16 (&fcr->u16); -+ tmio->read = data >> 8; -+ return data; -+} -+ -+/* -+ * The TMIO controller converts an 8-bit NAND interface to a 16-bit -+ * bus interface, so all data reads and writes must be 16-bit wide. -+ * Thus, we implement 16-bit versions of the read, write, and verify -+ * buffer functions. -+ */ -+static void -+tmio_nand_write_buf (struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ iowrite16_rep (&fcr->u16, buf, len >> 1); -+} -+ -+static void tmio_nand_read_buf (struct mtd_info *mtd, u_char *buf, int len) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ ioread16_rep (&fcr->u16, buf, len >> 1); -+} -+ -+static int -+tmio_nand_verify_buf (struct mtd_info *mtd, const u_char *buf, int len) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ u16* p = (u16*) buf; -+ -+ for (len >>= 1; len; len--) -+ if (*(p++) != ioread16 (&fcr->u16)) -+ return -EFAULT; -+ return 0; -+} -+ -+static void tmio_nand_enable_hwecc (struct mtd_info* mtd, int mode) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ iowrite8 (FCR_MODE_HWECC_RESET, &fcr->mode); -+ ioread8 (&fcr->u8); /* dummy read */ -+ iowrite8 (FCR_MODE_HWECC_CALC, &fcr->mode); -+} -+ -+static int tmio_nand_calculate_ecc (struct mtd_info* mtd, const u_char* dat, -+ u_char* ecc_code) -+{ -+ struct tmio_nand* tmio = mtd_to_tmio (mtd); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ unsigned int ecc; -+ -+ iowrite8 (FCR_MODE_HWECC_RESULT, &fcr->mode); -+ -+ ecc = ioread16 (&fcr->u16); -+ ecc_code[1] = ecc; // 000-255 LP7-0 -+ ecc_code[0] = ecc >> 8; // 000-255 LP15-8 -+ ecc = ioread16 (&fcr->u16); -+ ecc_code[2] = ecc; // 000-255 CP5-0,11b -+ ecc_code[4] = ecc >> 8; // 256-511 LP7-0 -+ ecc = ioread16 (&fcr->u16); -+ ecc_code[3] = ecc; // 256-511 LP15-8 -+ ecc_code[5] = ecc >> 8; // 256-511 CP5-0,11b -+ -+ iowrite8 (FCR_MODE_DATA, &fcr->mode); -+ return 0; -+} -+ -+static void tmio_hw_init (struct device *dev, struct tmio_nand *tmio) -+{ -+ struct resource* nfcr = tmio_resource_control (dev); -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ struct tmio_nfhccr __iomem * ccr = tmio->ccr; -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ unsigned long base; -+ -+ /* (89h) SMD Buffer ON By TC6393XB SystemConfig gpibfc1 */ -+ tdev->ops->clock (dev, 1); -+ tdev->ops->function (dev, 1); -+ -+ /* (4Ch) CLKRUN Enable 1st spcrunc */ -+ iowrite8 (0x81, &ccr->icc); -+ -+ /* (10h)BaseAddress 0x1000 spba.spba2 */ -+ base = nfcr->start - tdev->iomem->start; -+ iowrite16 (base, ccr->base + 0); -+ iowrite16 (base >> 16, ccr->base + 1); -+ -+ /* (04h)Command Register I/O spcmd */ -+ iowrite8 (0x02, &ccr->command); -+ -+ /* (62h) Power Supply Control ssmpwc */ -+ /* HardPowerOFF - SuspendOFF - PowerSupplyWait_4MS */ -+ iowrite8 (0x02, &ccr->nfpsc); -+ -+ /* (63h) Detect Control ssmdtc */ -+ iowrite8 (0x02, &ccr->nfdc); -+ -+ /* Interrupt status register clear sintst */ -+ iowrite8 (0x0f, &fcr->isr); -+ -+ /* After power supply, Media are reset smode */ -+ iowrite8 (FCR_MODE_POWER_ON, &fcr->mode); -+ iowrite8 (FCR_MODE_COMMAND, &fcr->mode); -+ iowrite8 (NAND_CMD_RESET, &fcr->u8); -+ -+ /* Standby Mode smode */ -+ iowrite8 (FCR_MODE_STANDBY, &fcr->mode); -+ -+ mdelay (5); -+} -+ -+static void tmio_hw_stop (struct device *dev, struct tmio_nand *tmio) -+{ -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ struct tmio_nfcr __iomem * fcr = tmio->fcr; -+ -+ iowrite8 (FCR_MODE_POWER_OFF, &fcr->mode); -+ tdev->ops->function (dev, 0); -+ tdev->ops->clock (dev, 0); -+} -+ -+/*--------------------------------------------------------------------------*/ -+ -+#ifdef CONFIG_MTD_PARTITIONS -+static const char *part_probes[] = { "cmdlinepart", NULL }; -+#endif -+ -+static int tmio_probe (struct device *dev) -+{ -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ struct tmio_nand_platform_data* tnpd = dev->platform_data; -+ struct resource* ccr = tmio_resource_config (dev); -+ struct resource* fcr = tmio_resource_control (dev); -+ struct resource* irq = tmio_resource_irq (dev); -+ struct tmio_nand* tmio; -+ struct mtd_info* mtd; -+ struct nand_chip* this; -+ struct mtd_partition* parts; -+ int nbparts = 0; -+ int retval; -+ -+ if (!tnpd) -+ return -EINVAL; -+ -+ retval = request_resource (tdev->iomem, ccr); -+ if (retval) -+ goto err_request_ccr; -+ -+ retval = request_resource (tdev->iomem, fcr); -+ if (retval) -+ goto err_request_fcr; -+ -+ tmio = kzalloc (sizeof *tmio, GFP_KERNEL); -+ if (!tmio) { -+ retval = -ENOMEM; -+ goto err_kzalloc; -+ } -+ -+ dev_set_drvdata (dev, tmio); -+ mtd = &tmio->mtd; -+ this = &tmio->chip; -+ mtd->priv = this; -+ mtd->name = TMIO_NAME_NAND; -+ -+ tmio->ccr = ioremap (ccr->start, ccr->end - ccr->start + 1); -+ if (!tmio->ccr) { -+ retval = -EIO; -+ goto err_iomap_ccr; -+ } -+ -+ tmio->fcr = ioremap (fcr->start, fcr->end - fcr->start + 1); -+ if (!tmio->fcr) { -+ retval = -EIO; -+ goto err_iomap_fcr; -+ } -+ -+ tmio_hw_init (dev, tmio); -+ -+ /* Set address of NAND IO lines */ -+ this->IO_ADDR_R = tmio->fcr; -+ this->IO_ADDR_W = tmio->fcr; -+ -+ /* Set address of hardware control function */ -+ this->cmd_ctrl = tmio_nand_hwcontrol; -+ this->dev_ready = tmio_nand_dev_ready; -+ this->read_byte = tmio_nand_read_byte; -+ this->write_buf = tmio_nand_write_buf; -+ this->read_buf = tmio_nand_read_buf; -+ this->verify_buf = tmio_nand_verify_buf; -+ -+ /* set eccmode using hardware ECC */ -+ this->ecc.mode = NAND_ECC_HW; -+ this->ecc.size = 512; -+ this->ecc.bytes = 6; -+ this->ecc.hwctl = tmio_nand_enable_hwecc; -+ this->ecc.calculate = tmio_nand_calculate_ecc; -+ this->ecc.correct = nand_correct_data; -+ this->badblock_pattern = tnpd->badblock_pattern; -+ -+ /* 15 us command delay time */ -+ this->chip_delay = 15; -+ -+ if (irq->start) { -+ retval = request_irq (irq->start, &tmio_irq, -+ IRQF_DISABLED, irq->name, tmio); -+ if (!retval) { -+ tmio->irq = irq->start; -+ this->waitfunc = tmio_nand_wait; -+ } else -+ mtd_warn (mtd, "request_irq error %d\n", retval); -+ } -+ -+ /* Scan to find existence of the device */ -+ if (nand_scan (mtd, 1)) { -+ retval = -ENODEV; -+ goto err_scan; -+ } -+ -+ /* Register the partitions */ -+#ifdef CONFIG_MTD_PARTITIONS -+ nbparts = parse_mtd_partitions (mtd, part_probes, &parts, 0); -+#endif -+ if (nbparts <= 0) { -+ parts = tnpd->partition; -+ nbparts = tnpd->num_partitions; -+ } -+ -+ add_mtd_partitions (mtd, parts, nbparts); -+ return 0; -+ -+err_scan: -+ if (tmio->irq) -+ free_irq (tmio->irq, tmio); -+ tmio_hw_stop (dev, tmio); -+ iounmap (tmio->fcr); -+err_iomap_fcr: -+ iounmap (tmio->ccr); -+err_iomap_ccr: -+ kfree (tmio); -+err_kzalloc: -+ release_resource (fcr); -+err_request_fcr: -+ release_resource (ccr); -+err_request_ccr: -+ return retval; -+} -+ -+static int tmio_remove (struct device *dev) -+{ -+ struct tmio_nand* tmio = dev_get_drvdata (dev); -+ -+ nand_release (&tmio->mtd); -+ if (tmio->irq) -+ free_irq (tmio->irq, tmio); -+ tmio_hw_stop (dev, tmio); -+ iounmap (tmio->fcr); -+ iounmap (tmio->ccr); -+ kfree (tmio); -+ release_resource (tmio_resource_control (dev)); -+ release_resource (tmio_resource_config (dev)); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int tmio_suspend (struct device *dev, pm_message_t state) -+{ -+ tmio_hw_stop (dev, dev_get_drvdata (dev)); -+ return 0; -+} -+ -+static int tmio_resume (struct device *dev) -+{ -+ tmio_hw_init (dev, dev_get_drvdata (dev)); -+ return 0; -+} -+#endif -+ -+static struct device_driver tmio_driver = { -+ .name = TMIO_NAME_NAND, -+ .bus = &tmio_bus_type, -+ .probe = tmio_probe, -+ .remove = tmio_remove, -+#ifdef CONFIG_PM -+ .suspend = tmio_suspend, -+ .resume = tmio_resume, -+#endif -+}; -+ -+static int __init tmio_init (void) { -+ return driver_register (&tmio_driver); -+} -+ -+static void __exit tmio_exit (void) { -+ driver_unregister (&tmio_driver); -+} -+ -+module_init (tmio_init); -+module_exit (tmio_exit); -+ -+MODULE_LICENSE ("GPL"); -+MODULE_AUTHOR ("Dirk Opfer, Chris Humbert"); -+MODULE_DESCRIPTION ("NAND flash driver on Toshiba Mobile IO controller"); diff --git a/packages/linux/linux-rp-2.6.23/tmio-tc6393-r8.patch b/packages/linux/linux-rp-2.6.23/tmio-tc6393-r8.patch index 500fa837ec..1bfdc23630 100644 --- a/packages/linux/linux-rp-2.6.23/tmio-tc6393-r8.patch +++ b/packages/linux/linux-rp-2.6.23/tmio-tc6393-r8.patch @@ -798,803 +798,3 @@ Index: git/include/asm-arm/arch-pxa/irqs.h #elif defined(CONFIG_ARCH_LUBBOCK) || \ defined(CONFIG_MACH_LOGICPD_PXA270) || \ defined(CONFIG_MACH_MAINSTONE) - arch/arm/common/Kconfig | 3 - arch/arm/common/Makefile | 1 - arch/arm/common/tc6393xb.c | 668 ++++++++++++++++++++++++++++++++++++++++ - arch/arm/mach-pxa/Kconfig | 1 - include/asm-arm/arch-pxa/irqs.h | 10 - include/asm-arm/hardware/tmio.h | 44 ++ - 6 files changed, 727 insertions(+) - -Index: git/arch/arm/common/tc6393xb.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/arch/arm/common/tc6393xb.c 2006-11-07 22:14:49.000000000 +0000 -@@ -0,0 +1,668 @@ -+/* -+ * Toshiba TC6393XB SoC support -+ * -+ * Maintainer: Chris Humbert <mahadri-kernel@drigon.com> -+ * -+ * Copyright (c) 2005-2006 Chris Humbert -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * Based on code written by Sharp/Lineo for 2.4 kernels -+ * Based on locomo.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/delay.h> -+#include <linux/errno.h> -+#include <linux/ioport.h> -+#include <linux/device.h> -+#include <linux/platform_device.h> -+#include <linux/slab.h> -+#include <linux/spinlock.h> -+#include <linux/fb.h> -+ -+#include <asm/hardware.h> -+#include <asm/mach-types.h> -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <asm/mach/irq.h> -+#include <asm/arch/irqs.h> -+#include <asm/hardware/tmio.h> -+ -+#ifndef TMIO_SOC_TC6393XB -+#error "TC6393XB SoC not configured" -+#endif -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* cell ids must be 0-based because they are used as array indexes. */ -+#define TC6393_CELL_NAND 0 -+#define TC6393_CELL_SD 1 -+#define TC6393_CELL_OHCI 2 -+#define TC6393_CELL_SERIAL 3 -+#define TC6393_CELL_LCD 4 -+#define TC6393_NUM_CELLS 5 -+ -+#define TC6393_RESOURCE(_name, _start, _end, _flags) \ -+ { \ -+ .name = _name, \ -+ .start = _start, \ -+ .end = _end, \ -+ .flags = _flags, \ -+ } -+ -+#define TC6393_MEM(name, start, size) \ -+ TC6393_RESOURCE(name, start, (start) + (size) - 1, IORESOURCE_MEM) -+ -+#define TC6393_IRQ(name, irq) \ -+ TC6393_RESOURCE(name, irq, irq, IORESOURCE_IRQ) -+ -+const static struct resource tc6393_NAND_resource[] = { -+ TC6393_MEM (TMIO_NAME_NAND, 0x000100, 0x100), -+ TC6393_MEM (TMIO_NAME_NAND, 0x001000, 0x008), -+ TC6393_MEM (TMIO_NAME_NAND, 0, 0), -+ TC6393_IRQ (TMIO_NAME_NAND, IRQ_TC6393_NAND), -+}; -+ -+const static struct resource tc6393_SD_resource[] = { -+ TC6393_MEM (TMIO_NAME_SD, 0x000200, 0x100), -+ TC6393_MEM (TMIO_NAME_SD, 0x002000, 0x200), -+ TC6393_MEM (TMIO_NAME_SD, 0, 0), -+ TC6393_IRQ (TMIO_NAME_SD, IRQ_TC6393_SD), -+}; -+ -+const static struct resource tc6393_OHCI_resource[] = { -+ TC6393_MEM (TMIO_NAME_OHCI, 0x000300, 0x100), -+ TC6393_MEM (TMIO_NAME_OHCI, 0x003000, 0x100), -+ TC6393_MEM (TMIO_NAME_OHCI, 0x010000, 32 * 1024), -+ TC6393_IRQ (TMIO_NAME_OHCI, IRQ_TC6393_OHCI), -+}; -+ -+const static struct resource tc6393_SERIAL_resource[] = { -+ TC6393_MEM (TMIO_NAME_SERIAL, 0x000400, 0x100), -+ TC6393_MEM (TMIO_NAME_SERIAL, 0x004000, 0x100), -+ TC6393_MEM (TMIO_NAME_SERIAL, 0, 0), -+ TC6393_IRQ (TMIO_NAME_SERIAL, IRQ_TC6393_SERIAL), -+}; -+ -+const static struct resource tc6393_LCD_resource[] = { -+ TC6393_MEM (TMIO_NAME_LCD, 0x000500, 0x100), -+ TC6393_MEM (TMIO_NAME_LCD, 0x005000, 0x200), -+ TC6393_MEM (TMIO_NAME_LCD, 0x100000, 1024 * 1024), -+ TC6393_IRQ (TMIO_NAME_LCD, IRQ_TC6393_LCD), -+}; -+ -+#define TC6393_CELL(_NAME) \ -+ [TC6393_CELL_##_NAME] = { \ -+ .name = TMIO_NAME_##_NAME, \ -+ .id = TC6393_CELL_##_NAME, \ -+ .resource = tc6393_##_NAME##_resource, \ -+ .num_resources = ARRAY_SIZE (tc6393_##_NAME##_resource), \ -+ } -+ -+struct tc6393_cell { -+ const char* name; -+ unsigned int id; -+ const struct resource* resource; -+ unsigned int num_resources; -+}; -+ -+const static struct tc6393_cell tc6393_cell [TC6393_NUM_CELLS] = { -+ TC6393_CELL (NAND ), -+ TC6393_CELL (SD ), -+ TC6393_CELL (OHCI ), -+ TC6393_CELL (SERIAL ), -+ TC6393_CELL (LCD ), -+}; -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* -+ * TC6393 System Configuration Register -+ */ -+struct tc6393_scr { -+ u8 x00[8]; -+ u8 revid; /* 0x08 Revision ID */ -+ u8 x01[0x47]; -+ u8 isr; /* 0x50 Interrupt Status */ -+ u8 x02; -+ u8 imr; /* 0x52 Interrupt Mask */ -+ u8 x03; -+ u8 irr; /* 0x54 Interrupt Routing */ -+ u8 x04[0x0b]; -+ u16 gper; /* 0x60 GP Enable */ -+ u8 x05[2]; -+ u16 gpi_sr[2]; /* 0x64 GPI Status */ -+ u16 gpi_imr[2]; /* 0x68 GPI INT Mask */ -+ u16 gpi_eder[2]; /* 0x6c GPI Edge Detect Enable */ -+ u16 gpi_lir[4]; /* 0x70 GPI Level Invert */ -+ u16 gpo_dsr[2]; /* 0x78 GPO Data Set */ -+ u16 gpo_doecr[2]; /* 0x7c GPO Data OE Control */ -+ u16 gp_iarcr[2]; /* 0x80 GP Internal Active Reg Control */ -+ u16 gp_iarlcr[2]; /* 0x84 GP Internal Active Reg Level Con*/ -+ u8 gpi_bcr[4]; /* 0x88 GPI Buffer Control */ -+ u16 gpa_iarcr; /* 0x8c GPa Internal Active Reg Control */ -+ u8 x06[2]; -+ u16 gpa_iarlcr; /* 0x90 GPa Internal Active Reg Level Co*/ -+ u8 x07[2]; -+ u16 gpa_bcr; /* 0x94 GPa Buffer Control */ -+ u8 x08[2]; -+ u16 ccr; /* 0x98 Clock Control */ -+ u16 pll2cr; /* 0x9a PLL2 Control */ -+ u16 pll1cr[2]; /* 0x9c PLL1 Control */ -+ u8 diarcr; /* 0xa0 Device Internal Active Reg Contr*/ -+ u8 dbocr; /* 0xa1 Device Buffer Off Control */ -+ u8 x09[0x3e]; -+ u8 fer; /* 0xe0 Function Enable */ -+ u8 x10[3]; -+ u16 mcr; /* 0xe4 Mode Control */ -+ u8 x11[0x14]; -+ u8 config; /* 0xfc Configuration Control */ -+ u8 x12[2]; -+ u8 debug; /* 0xff Debug */ -+} __attribute__ ((packed)); -+ -+union tc6393_scr_fer { -+ u8 raw; -+struct { -+ unsigned usben:1; /* D0 USB enable */ -+ unsigned lcdcven:1; /* D1 polysylicon TFT enable */ -+ unsigned slcden:1; /* D2 SLCD enable */ -+} __attribute__ ((packed)); -+} __attribute__ ((packed)); -+ -+union tc6393_scr_ccr { -+ u16 raw; -+struct { -+ unsigned ck32ken:1; /* D0 SD host clock enable */ -+ unsigned usbcken:1; /* D1 USB host clock enable */ -+ unsigned x00:2; -+ unsigned sharp:1; /* D4 ??? set in Sharp's code */ -+ unsigned x01:3; -+ enum { disable = 0, -+ m12MHz = 1, -+ m24MHz = 2, -+ m48MHz = 3, -+ } mclksel:3; /* D10-D8 LCD controller clock */ -+ unsigned x02:1; -+ enum { h24MHz = 0, -+ h48MHz = 1, -+ } hclksel:2; /* D13-D12 host bus clock */ -+ unsigned x03:2; -+} __attribute__ ((packed)); -+} __attribute__ ((packed)); -+ -+/*--------------------------------------------------------------------------*/ -+ -+struct tc6393 { -+ spinlock_t lock; /* read-modify-write lock */ -+ struct device* dev; /* TC6393 device */ -+ struct tc6393_scr __iomem *scr; /* system configuration reg */ -+ -+ struct resource rscr; /* system config reg resource */ -+ struct resource* iomem; /* entire TC6393 iomem resource */ -+ unsigned int irq; /* hardware cascade irq */ -+ -+ struct tmio_device tdev [TC6393_NUM_CELLS]; -+}; -+ -+/*--------------------------------------------------------------------------*/ -+ -+static u32 tc6393_ioread32 (const void __iomem *addr) -+{ -+ return ((u32) ioread16 (addr)) | (((u32) ioread16 (addr + 2)) << 16); -+} -+ -+static u32 tc6393_iowrite32 (u32 val, const void __iomem *addr) -+{ -+ iowrite16 (val, addr); -+ iowrite16 (val >> 16, addr + 2); -+ return val; -+} -+ -+u32 get_tc6393_gpio (struct device *dev) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ -+ return tc6393_ioread32 (scr->gpo_dsr); -+} -+EXPORT_SYMBOL (get_tc6393_gpio); -+ -+u32 set_tc6393_gpio (struct device *dev, u32 bits) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ unsigned long flags; -+ u32 dsr; -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ dsr = tc6393_ioread32 (scr->gpo_dsr) | bits; -+ tc6393_iowrite32 (dsr, scr->gpo_dsr); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+ -+ return dsr; -+} -+EXPORT_SYMBOL (set_tc6393_gpio); -+ -+u32 reset_tc6393_gpio (struct device *dev, u32 bits) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ unsigned long flags; -+ u32 dsr; -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ dsr = tc6393_ioread32 (scr->gpo_dsr) & ~bits; -+ tc6393_iowrite32 (dsr, scr->gpo_dsr); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+ -+ return dsr; -+} -+EXPORT_SYMBOL (reset_tc6393_gpio); -+ -+/*--------------------------------------------------------------------------*/ -+ -+static void -+tc6393_irq (unsigned int irq, struct irq_desc *desc) -+{ -+ struct tc6393* tc6393 = get_irq_chip_data (irq); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ unsigned int isr; -+ unsigned int bit; -+ unsigned int i; -+ -+ desc->chip->ack (irq); -+ -+ while ((isr = ioread8(&scr->isr) & ~ioread8(&scr->imr))) -+ for (bit = 1, i = IRQ_TC6393_START; i <= IRQ_TC6393_LCD; -+ bit <<= 1, i++) -+ if (isr & bit) -+ desc_handle_irq (i, irq_desc + i); -+} -+ -+static void tc6393_irq_ack (unsigned int irq) -+{ -+} -+ -+static void tc6393_irq_mask (unsigned int irq) -+{ -+ struct tc6393* tc6393 = get_irq_chip_data (irq); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ iowrite8 (ioread8 (&scr->imr) | (1 << (irq - IRQ_TC6393_START)), -+ &scr->imr); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+} -+ -+static void tc6393_irq_unmask (unsigned int irq) -+{ -+ struct tc6393* tc6393 = get_irq_chip_data (irq); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ iowrite8 (ioread8 (&scr->imr) & ~(1 << (irq - IRQ_TC6393_START)), -+ &scr->imr); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+} -+ -+static struct irq_chip tc6393_chip = { -+ .ack = tc6393_irq_ack, -+ .mask = tc6393_irq_mask, -+ .unmask = tc6393_irq_unmask, -+}; -+ -+static void tc6393_attach_irq (struct tc6393 *tc6393) -+{ -+ unsigned int irq; -+ -+ for (irq = IRQ_TC6393_START; irq <= IRQ_TC6393_LCD; irq++) { -+ set_irq_chip (irq, &tc6393_chip); -+ set_irq_chip_data(irq, tc6393); -+ set_irq_handler (irq, handle_edge_irq); -+ set_irq_flags (irq, IRQF_VALID | IRQF_PROBE); -+ } -+ -+ set_irq_type (tc6393->irq, IRQT_FALLING); -+ set_irq_chip_data (tc6393->irq, tc6393); -+ set_irq_chained_handler (tc6393->irq, tc6393_irq); -+} -+ -+static void tc6393_detach_irq (struct tc6393 *tc6393) -+{ -+ unsigned int irq; -+ -+ set_irq_chained_handler (tc6393->irq, NULL); -+ set_irq_chip_data (tc6393->irq, NULL); -+ -+ for (irq = IRQ_TC6393_START; irq <= IRQ_TC6393_LCD; irq++) { -+ set_irq_flags (irq, 0); -+ set_irq_chip (irq, NULL); -+ set_irq_chip_data(irq, NULL); -+ } -+} -+ -+/*--------------------------------------------------------------------------*/ -+ -+static int tc6393_bus_match (struct device *dev, struct device_driver *drv) -+{ -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ const struct tc6393_cell* cell = tdev->soc_data; -+ -+ return !strcmp (cell->name, drv->name); -+} -+ -+static int tc6393_bus_suspend (struct device *dev, pm_message_t state) -+{ -+ struct device_driver* drv = dev->driver; -+ return drv && drv->suspend ? drv->suspend (dev, state) : 0; -+} -+ -+static int tc6393_bus_resume (struct device *dev) -+{ -+ struct device_driver* drv = dev->driver; -+ return drv && drv->resume ? drv->resume (dev) : 0; -+} -+ -+struct bus_type tc6393_bus_type = { -+ .name = TMIO_NAME_BUS, -+ .match = tc6393_bus_match, -+ .suspend = tc6393_bus_suspend, -+ .resume = tc6393_bus_resume, -+}; -+EXPORT_SYMBOL (tc6393_bus_type); -+ -+/*--------------------------------------------------------------------------*/ -+ -+static void tc6393_cell_clock (struct device *dev, int enable) -+{ -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ const struct tc6393_cell* cell = tdev->soc_data; -+ struct tc6393* tc6393 = dev_get_drvdata (dev->parent); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ union tc6393_scr_ccr ccr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ ccr.raw = ioread16 (&scr->ccr); -+ -+ switch (cell->id) { -+ case TC6393_CELL_SD: ccr.ck32ken = enable; break; -+ case TC6393_CELL_OHCI: ccr.usbcken = enable; break; -+ case TC6393_CELL_LCD: -+ ccr.mclksel = enable ? m48MHz : disable; -+ break; -+ } -+ -+ printk (KERN_DEBUG TMIO_NAME_CORE ": scr->ccr = %04x\n", ccr.raw); -+ -+ iowrite16(ccr.raw, &scr->ccr); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+} -+ -+static void tc6393_cell_function (struct device *dev, int enable) -+{ -+ struct tmio_device* tdev = dev_to_tdev (dev); -+ const struct tc6393_cell* cell = tdev->soc_data; -+ struct tc6393* tc6393 = dev_get_drvdata (dev->parent); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ union tc6393_scr_fer fer; -+ unsigned long flags; -+ -+ if (cell->id == TC6393_CELL_NAND) { -+ if (enable) { -+ /* SMD buffer on */ -+ printk (KERN_DEBUG TMIO_NAME_CORE ": SMD buffer on\n"); -+ iowrite8 (0xff, scr->gpi_bcr + 1); -+ } -+ return; -+ } -+ -+ spin_lock_irqsave (&tc6393->lock, flags); -+ fer.raw = ioread16 (&scr->fer); -+ -+ switch (cell->id) { -+ case TC6393_CELL_OHCI: fer.usben = enable; break; -+ case TC6393_CELL_LCD: fer.slcden = enable; break; -+ } -+ -+ printk (KERN_DEBUG TMIO_NAME_CORE ": scr->fer = %02x\n", fer.raw); -+ -+ iowrite8 (fer.raw, &scr->fer); -+ spin_unlock_irqrestore (&tc6393->lock, flags); -+} -+ -+static void -+tc6393_lcd_mode (struct device *dev, const struct fb_videomode *mode) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev->parent); -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ -+ iowrite16 (mode->pixclock, scr->pll1cr + 0); -+ iowrite16 (mode->pixclock >> 16, scr->pll1cr + 1); -+} -+ -+static struct tmio_cell_ops tc6393_cell_ops = { -+ .clock = tc6393_cell_clock, -+ .function = tc6393_cell_function, -+ .lcd_mode = tc6393_lcd_mode, -+}; -+ -+static void tc6393_device_release (struct device *dev) -+{ -+} -+ -+static int -+tc6393_device_register (struct tc6393 *tc6393, struct tmio_cell *tcell) -+{ -+ const struct tc6393_cell* cell; -+ struct tmio_device* tdev; -+ struct device* dev; -+ int i; -+ -+ for (i = 0; strcmp (tcell->name, tc6393_cell [i].name); ) -+ if (++i >= ARRAY_SIZE(tc6393_cell)) -+ return -EINVAL; -+ -+ cell = tc6393_cell + i; -+ tdev = tc6393->tdev + i; -+ dev = &tdev->dev; -+ -+ tdev->ops = &tc6393_cell_ops; -+ tdev->iomem = tc6393->iomem; -+ tdev->soc_data = (void*) cell; -+ -+ dev->parent = tc6393->dev; -+ strncpy (dev->bus_id, cell->name, sizeof dev->bus_id); -+ dev->bus = &tc6393_bus_type; -+ dev->dma_mask = tc6393->dev->dma_mask; -+ dev->coherent_dma_mask = tc6393->dev->coherent_dma_mask; -+ dev->release = tc6393_device_release; -+ dev->platform_data = tcell->platform_data; -+ -+ for (i=0; i < cell->num_resources; i++) { -+ const struct resource* cr = cell->resource + i; -+ struct resource* dr = tdev->resource + i; -+ -+ dr->name = cr->name; -+ dr->start = cr->start; -+ dr->end = cr->end; -+ dr->flags = cr->flags; -+ -+ /* convert memory offsets to absolutes */ -+ if (cr->flags & IORESOURCE_MEM) { -+ dr->start += tc6393->iomem->start; -+ dr->end += tc6393->iomem->start; -+ } -+ } -+ -+ return device_register (dev); -+} -+ -+/*--------------------------------------------------------------------------*/ -+ -+static void tc6393_hw_init (struct tc6393 *tc6393) -+{ -+ struct tc6393_scr __iomem * scr = tc6393->scr; -+ struct tc6393_platform_data* tcpd = tc6393->dev->platform_data; -+ -+ tcpd->enable (tc6393->dev); -+ -+ iowrite8 (0, &scr->fer); -+ iowrite16(tcpd->scr_pll2cr, &scr->pll2cr); -+ iowrite16(tcpd->scr_ccr, &scr->ccr); -+ iowrite16(tcpd->scr_mcr, &scr->mcr); -+ iowrite16(tcpd->scr_gper, &scr->gper); -+ iowrite8 (0, &scr->irr); -+ iowrite8 (0xbf, &scr->imr); -+ iowrite16(tcpd->scr_gpo_dsr, scr->gpo_dsr + 0); -+ iowrite16(tcpd->scr_gpo_dsr >> 16, scr->gpo_dsr + 1); -+ iowrite16(tcpd->scr_gpo_doecr, scr->gpo_doecr + 0); -+ iowrite16(tcpd->scr_gpo_doecr >> 16, scr->gpo_doecr + 1); -+} -+ -+static int tc6393_probe (struct device *dev) -+{ -+ struct platform_device* pdev = to_platform_device (dev); -+ struct tc6393_platform_data* tcpd = dev->platform_data; -+ struct tc6393* tc6393; -+ struct resource* iomem; -+ struct resource* rscr; -+ int retval; -+ int i; -+ -+ iomem = platform_get_resource (pdev, IORESOURCE_MEM, 0); -+ if (!iomem) -+ return -EINVAL; -+ -+ tc6393 = kzalloc (sizeof *tc6393, GFP_KERNEL); -+ if (!tc6393) { -+ retval = -ENOMEM; -+ goto err_kzalloc; -+ } -+ -+ dev_set_drvdata (dev, tc6393); -+ spin_lock_init (&tc6393->lock); -+ tc6393->dev = dev; -+ tc6393->iomem = iomem; -+ tc6393->irq = platform_get_irq (pdev, 0); -+ -+ rscr = &tc6393->rscr; -+ rscr->name = TMIO_NAME_CORE; -+ rscr->start = iomem->start; -+ rscr->end = iomem->start + 0xff; -+ rscr->flags = IORESOURCE_MEM; -+ -+ retval = request_resource (iomem, rscr); -+ if (retval) -+ goto err_request_scr; -+ -+ tc6393->scr = ioremap (rscr->start, rscr->end - rscr->start + 1); -+ if (!tc6393->scr) { -+ retval = -ENOMEM; -+ goto err_ioremap; -+ } -+ -+ tc6393_hw_init (tc6393); -+ -+ printk (KERN_INFO "Toshiba %s revision %d at 0x%08lx, irq %d\n", -+ TMIO_SOC_NAME, ioread8 (&tc6393->scr->revid), -+ iomem->start, tc6393->irq); -+ -+ if (tc6393->irq) -+ tc6393_attach_irq (tc6393); -+ -+ for (i = 0; i < tcpd->num_cells; i++) -+ tc6393_device_register (tc6393, tcpd->cell + i); -+ -+ return 0; -+ -+err_ioremap: -+ release_resource (rscr); -+err_request_scr: -+ kfree(tc6393); -+err_kzalloc: -+ release_resource (iomem); -+ return retval; -+} -+ -+static int tc6393_dev_remove (struct device *dev, void *data) -+{ -+ device_unregister (dev); -+ return 0; -+} -+ -+static int tc6393_remove (struct device *dev) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev); -+ -+ device_for_each_child (dev, tc6393, tc6393_dev_remove); -+ -+ if (tc6393->irq) -+ tc6393_detach_irq (tc6393); -+ -+ iounmap (tc6393->scr); -+ release_resource (&tc6393->rscr); -+ release_resource (tc6393->iomem); -+ kfree (tc6393); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int tc6393_suspend (struct device *dev, pm_message_t state) -+{ -+ struct tc6393_platform_data* tcpd = dev->platform_data; -+ tcpd->disable (dev); -+ return 0; -+} -+ -+static int tc6393_resume (struct device *dev) -+{ -+ struct tc6393* tc6393 = dev_get_drvdata (dev); -+ tc6393_hw_init (tc6393); -+ return 0; -+} -+#endif -+ -+static struct device_driver tc6393_device_driver = { -+ .name = TMIO_SOC_NAME, -+ .bus = &platform_bus_type, -+ .probe = tc6393_probe, -+ .remove = tc6393_remove, -+#ifdef CONFIG_PM -+ .suspend = tc6393_suspend, -+ .resume = tc6393_resume, -+#endif -+}; -+ -+/*--------------------------------------------------------------------------*/ -+ -+static int __init tc6393_init (void) -+{ -+ int retval = bus_register (&tc6393_bus_type); -+ if (retval) -+ return retval; -+ -+ return driver_register (&tc6393_device_driver); -+} -+ -+static void __exit tc6393_exit (void) -+{ -+ driver_unregister (&tc6393_device_driver); -+ bus_unregister (&tc6393_bus_type); -+} -+ -+module_init (tc6393_init); -+module_exit (tc6393_exit); -+ -+MODULE_DESCRIPTION ("TC6393 SoC bus driver"); -+MODULE_AUTHOR ("Chris Humbert, Dirk Opfer"); -+MODULE_LICENSE ("GPL"); -Index: git/arch/arm/common/Kconfig -=================================================================== ---- git.orig/arch/arm/common/Kconfig 2006-10-31 16:08:28.000000000 +0000 -+++ git/arch/arm/common/Kconfig 2006-11-07 22:13:09.000000000 +0000 -@@ -31,3 +31,6 @@ config SHARPSL_PM - - config SHARP_SCOOP - bool -+ -+config TOSHIBA_TC6393XB -+ bool -Index: git/arch/arm/mach-pxa/Kconfig -=================================================================== ---- git.orig/arch/arm/mach-pxa/Kconfig 2006-11-07 22:13:06.000000000 +0000 -+++ git/arch/arm/mach-pxa/ 2006-11-07 23:30:34.000000000 +0000 -@@ -128,6 +128,7 @@ config MACH_BORZOI - config MACH_TOSA - bool "Enable Sharp SL-6000x (Tosa) Support" - depends on PXA_SHARPSL_25x -+ select TOSHIBA_TC6393XB - - config PXA25x - bool -Index: git/arch/arm/common/Makefile -=================================================================== ---- git.orig/arch/arm/common/Makefile 2006-10-31 16:08:28.000000000 +0000 -+++ git/arch/arm/common/Makefile 2006-11-07 22:13:09.000000000 +0000 -@@ -17,3 +17,4 @@ obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o - obj-$(CONFIG_SHARP_SCOOP) += scoop.o - obj-$(CONFIG_ARCH_IXP2000) += uengine.o - obj-$(CONFIG_ARCH_IXP23XX) += uengine.o -+obj-$(CONFIG_TOSHIBA_TC6393XB) += tc6393xb.o -Index: git/include/asm-arm/hardware/tmio.h -=================================================================== ---- git.orig/include/asm-arm/hardware/tmio.h 2006-11-07 22:13:09.000000000 +0000 -+++ git/include/asm-arm/hardware/tmio.h 2006-11-07 22:13:09.000000000 +0000 -@@ -91,6 +91,50 @@ struct tmio_device { - - /*--------------------------------------------------------------------------*/ - -+/* -+ * TC6393XB SoC -+ */ -+#ifdef CONFIG_TOSHIBA_TC6393XB -+#define TMIO_SOC_TC6393XB -+#define TMIO_SOC_NAME "TC6393XB" -+#define TMIO_NAME_BUS "tc6393-bus" -+#define TMIO_NAME_CORE "tc6393-core" -+#define TMIO_NAME_NAND "tc6393-nand" -+#define TMIO_NAME_SD "tc6393-sd" -+#define TMIO_NAME_OHCI "tc6393-ohci" -+#define TMIO_NAME_SERIAL "tc6393-serial" -+#define TMIO_NAME_LCD "tc6393-lcd" -+#define tmio_bus_type tc6393_bus_type -+ -+#define TC6393_GPIO(x) (1 << (x)) -+ -+extern struct bus_type tc6393_bus_type; -+ -+struct tc6393_platform_data { -+ u16 scr_pll2cr; /* PLL2 Control */ -+ u16 scr_ccr; /* Clock Control */ -+ u16 scr_mcr; /* Mode Control */ -+ u16 scr_gper; /* GP Enable */ -+ u32 scr_gpo_doecr; /* GPO Data OE Control */ -+ u32 scr_gpo_dsr; /* GPO Data Set */ -+ -+ /* cells to register as devices */ -+ struct tmio_cell* cell; -+ unsigned int num_cells; -+ -+ /* callbacks to enable and disable the TC6393XB's power and clock */ -+ void (*enable) (struct device *dev); -+ void (*disable) (struct device *dev); -+}; -+ -+u32 get_tc6393_gpio (struct device *dev); -+u32 set_tc6393_gpio (struct device *dev, u32 bits); -+u32 reset_tc6393_gpio (struct device *dev, u32 bits); -+ -+/*--------------------------------------------------------------------------*/ -+ -+#else - #error "no TMIO SoC configured" -+#endif - - #endif -Index: git/include/asm-arm/arch-pxa/irqs.h -=================================================================== ---- git.orig/include/asm-arm/arch-pxa/irqs.h 2006-10-31 16:09:33.000000000 +0000 -+++ git/include/asm-arm/arch-pxa/irqs.h 2006-11-07 22:13:09.000000000 +0000 -@@ -163,17 +163,27 @@ - #define IRQ_LOCOMO_SPI_OVRN (IRQ_BOARD_END + 20) - #define IRQ_LOCOMO_SPI_TEND (IRQ_BOARD_END + 21) - -+#define IRQ_TC6393_START (IRQ_BOARD_END) -+#define IRQ_TC6393_NAND (IRQ_BOARD_END + 0) -+#define IRQ_TC6393_SD (IRQ_BOARD_END + 1) -+#define IRQ_TC6393_OHCI (IRQ_BOARD_END + 2) -+#define IRQ_TC6393_SERIAL (IRQ_BOARD_END + 3) -+#define IRQ_TC6393_LCD (IRQ_BOARD_END + 4) -+ - /* - * Figure out the MAX IRQ number. - * - * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1. - * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1 -+ * If we have an TC6393XB, the max IRQ is IRQ_TC6393_LCD+1 - * Otherwise, we have the standard IRQs only. - */ - #ifdef CONFIG_SA1111 - #define NR_IRQS (IRQ_S1_BVD1_STSCHG + 1) - #elif defined(CONFIG_SHARP_LOCOMO) - #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) -+#elif defined(CONFIG_TOSHIBA_TC6393XB) -+#define NR_IRQS (IRQ_TC6393_LCD + 1) - #elif defined(CONFIG_ARCH_LUBBOCK) || \ - defined(CONFIG_MACH_LOGICPD_PXA270) || \ - defined(CONFIG_MACH_MAINSTONE) diff --git a/packages/linux/linux-rp-2.6.23/tosa-bluetooth-r8.patch b/packages/linux/linux-rp-2.6.23/tosa-bluetooth-r8.patch index 9976549956..7873cffef5 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-bluetooth-r8.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-bluetooth-r8.patch @@ -192,197 +192,3 @@ Index: linux-2.6.17/arch/arm/mach-pxa/tosa.c }; static void tosa_poweroff(void) -Index: linux-2.6.17/arch/arm/mach-pxa/Makefile -=================================================================== ---- linux-2.6.17.orig/arch/arm/mach-pxa/Makefile 2006-06-20 11:45:51.252467944 +0200 -+++ linux-2.6.17/arch/arm/mach-pxa/Makefile 2006-06-20 11:46:33.619027248 +0200 -@@ -16,7 +16,7 @@ - obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o - obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o - obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o --obj-$(CONFIG_MACH_TOSA) += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o -+obj-$(CONFIG_MACH_TOSA) += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o tosa_bt.o - obj-$(CONFIG_MACH_EM_X270) += em-x270.o - obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o - -Index: linux-2.6.17/arch/arm/mach-pxa/tosa_bt.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/arch/arm/mach-pxa/tosa_bt.c 2006-06-20 11:46:08.107905528 +0200 -@@ -0,0 +1,128 @@ -+/* -+ * Bluetooth control code for Sharp SL-6000x (tosa) -+ * -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <asm/hardware.h> -+ -+#include <asm/hardware/scoop.h> -+#include <asm/arch/tosa.h> -+#include <asm/arch/pxa-regs.h> -+ -+ -+static int tosa_bluetooth_power(int on) -+{ -+ -+ if (!on) { //off -+ -+ set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET); -+ pxa_gpio_mode(GPIO42_BTRXD|GPIO_IN); -+ pxa_gpio_mode(GPIO43_BTTXD|GPIO_IN); -+ pxa_gpio_mode(GPIO44_BTCTS|GPIO_IN); -+ pxa_gpio_mode(GPIO45_BTRTS|GPIO_IN); -+ mdelay(10); // wait 10ms -+ reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET); -+ reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN); -+ reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_BT_LED); // turn off BT LED -+ -+ } else { // on -+ -+ reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET); -+ set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN); -+ pxa_gpio_mode(GPIO42_HWRXD_MD); -+ pxa_gpio_mode(GPIO43_HWTXD_MD); -+ pxa_gpio_mode(GPIO44_HWCTS_MD); -+ pxa_gpio_mode(GPIO45_HWRTS_MD); -+ -+ set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET); -+ mdelay(20); // wait 20ms -+ reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_RESET); -+ set_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_BT_LED); // turn BT LED on -+ } -+ return 0; -+} -+ -+/* -+ * Support Routines -+ */ -+int __init tosa_bluetooth_probe(struct platform_device *dev) -+{ -+ int ret = 0; -+ pxa_gpio_mode(GPIO42_BTRXD|GPIO_IN); -+ pxa_gpio_mode(GPIO43_BTTXD|GPIO_IN); -+ pxa_gpio_mode(GPIO44_BTCTS|GPIO_IN); -+ pxa_gpio_mode(GPIO45_BTRTS|GPIO_IN); -+ set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN); -+ mdelay(5); -+ -+ if ( (GPLR(GPIO42_BTRXD) & GPIO_bit(GPIO42_BTRXD))==0 && -+ (GPLR(GPIO44_BTCTS) & GPIO_bit(GPIO44_BTCTS))==0) { -+ printk(KERN_INFO "No Bluetooth Device found!\n"); -+ ret = ENODEV; // no bluetooth -+ } else { -+ printk(KERN_INFO "Tosa Bluetooth Device found on ttyS3!\n"); -+ } -+ reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_BT_PWR_EN); -+ -+ tosa_bluetooth_power(1); // Power on -+ return ret; -+} -+ -+static int tosa_bluetooth_remove(struct platform_device *dev) -+{ -+ tosa_bluetooth_power(0); // Power off -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int tosa_bluetooth_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ tosa_bluetooth_power(0); // Power off -+ return 0; -+} -+ -+static int tosa_bluetooth_resume(struct platform_device *dev) -+{ -+ tosa_bluetooth_power(1); // Power on -+ return 0; -+} -+#else -+#define tosa_bluetooth_suspend NULL -+#define tosa_bluetooth_resume NULL -+#endif -+ -+static struct platform_driver tosa_bluetooth_driver = { -+ .probe = tosa_bluetooth_probe, -+ .remove = tosa_bluetooth_remove, -+ .suspend = tosa_bluetooth_suspend, -+ .resume = tosa_bluetooth_resume, -+ .driver = { -+ .name = "tosa-bluetooth", -+ }, -+}; -+ -+int __init tosa_bluetooth_init(void) -+{ -+ return platform_driver_register(&tosa_bluetooth_driver); -+} -+ -+void __exit tosa_bluetooth_cleanup(void) -+{ -+ platform_driver_unregister(&tosa_bluetooth_driver); -+} -+ -+module_init(tosa_bluetooth_init); -+module_exit(tosa_bluetooth_cleanup); -Index: linux-2.6.17/arch/arm/mach-pxa/tosa.c -=================================================================== ---- linux-2.6.17.orig/arch/arm/mach-pxa/tosa.c 2006-06-20 11:45:51.254467640 +0200 -+++ linux-2.6.17/arch/arm/mach-pxa/tosa.c 2006-06-20 11:46:08.112904768 +0200 -@@ -288,7 +288,7 @@ - - static void tosa_tc6393_enable(struct device *dev) - { -- -+ printk("!!tosa_tc6393_enable!!\n"); - reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); - reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393_SUSPEND); - reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_TC6393_REST_IN); //#PCLR -@@ -303,7 +303,7 @@ - - static void tosa_tc6393_disable(struct device *dev) - { -- -+ printk("!!tosa_tc6393_disable!!\n"); - reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); - reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC6393_SUSPEND); - reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_TC6393_REST_IN); //#PCLR -@@ -428,6 +428,17 @@ - }, - }; - -+/* -+ * Tosa Blueooth -+ */ -+static struct platform_device tosa_bluetooth_device = { -+ .name = "tosa-bluetooth", -+ .id = -1, -+ .dev = { -+ .parent = &tosascoop_jc_device.dev, -+ }, -+}; -+ - static struct platform_device *devices[] __initdata = { - &tosascoop_device, - &tosascoop_jc_device, -@@ -435,6 +446,7 @@ - &tosaled_device, - &tc6393_device, - &tosalcd_device, -+ &tosa_bluetooth_device, - }; - - static void tosa_poweroff(void) diff --git a/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch b/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch index 5d94f25527..948c27fdce 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch @@ -512,517 +512,3 @@ Index: git/drivers/input/keyboard/tosakbd.c +MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); +MODULE_DESCRIPTION("Tosa Keyboard Driver"); +MODULE_LICENSE("GPLv2"); - drivers/input/keyboard/Kconfig | 12 - - drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/tosakbd.c | 467 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 479 insertions(+), 1 deletion(-) - -Index: git/drivers/input/keyboard/Kconfig -=================================================================== ---- git.orig/drivers/input/keyboard/Kconfig 2006-10-31 16:08:57.000000000 +0000 -+++ git/drivers/input/keyboard/Kconfig 2006-11-07 22:13:10.000000000 +0000 -@@ -148,12 +148,22 @@ config KEYBOARD_SPITZ - depends on PXA_SHARPSL - default y - help -- Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, -+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. - - To compile this driver as a module, choose M here: the - module will be called spitzkbd. - -+config KEYBOARD_TOSA -+ tristate "Tosa keyboard" -+ depends on PXA_SHARPSL -+ default y -+ help -+ Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) -+ -+ To compile this driver as a module, choose M here: the -+ module will be called tosakbd. -+ - config KEYBOARD_AMIGA - tristate "Amiga keyboard" - depends on AMIGA -Index: git/drivers/input/keyboard/Makefile -=================================================================== ---- git.orig/drivers/input/keyboard/Makefile 2006-10-31 16:08:57.000000000 +0000 -+++ git/drivers/input/keyboard/Makefile 2006-11-07 22:13:10.000000000 +0000 -@@ -17,3 +17,4 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkb - obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o - obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o - obj-$(CONFIG_KEYBOARD_ASIC3) += asic3_keys.o -+obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o -Index: git/drivers/input/keyboard/tosakbd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/drivers/input/keyboard/tosakbd.c 2006-11-07 23:27:19.000000000 +0000 -@@ -0,0 +1,467 @@ -+/* -+ * Keyboard driver for Sharp Tosa models (SL-6000x) -+ * -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * Based on xtkbd.c/locomkbd.c/corgikbd.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/init.h> -+#include <linux/input.h> -+#include <linux/interrupt.h> -+#include <linux/jiffies.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+ -+#include <asm/arch/tosa.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+ -+ -+#define TOSA_KEY_STROBE_NUM (11) -+#define TOSA_KEY_SENSE_NUM (7) -+ -+#define KEYMASK_ON (0x1<<0) -+#define KEYMASK_REC (0x1<<1) -+#define KEYMASK_SYNC (0x1<<2) -+ -+#define KB_ROWS 7 -+#define KB_COLS 11 -+#define KB_ROWMASK(r) (1 << (r)) -+#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -+#define NR_SCANCODES (SCANCODE(KB_ROWS-1,KB_COLS)+1+1) -+ -+#define SCAN_INTERVAL (HZ/10) -+#define HP_SCAN_INTERVAL (150) /* ms */ -+#define HP_STABLE_COUNT 2 -+ -+#define TOSA_KEY_CALENDER KEY_F1 -+#define TOSA_KEY_ADDRESS KEY_F2 -+#define TOSA_KEY_FN KEY_F3 -+#define TOSA_KEY_CANCEL KEY_F4 -+#define TOSA_KEY_OFF KEY_SUSPEND -+#define TOSA_KEY_CENTER KEY_F5 -+#define TOSA_KEY_REC KEY_F6 -+#define TOSA_KEY_LIGHT KEY_F7 -+#define TOSA_KEY_RECORD KEY_F8 -+#define TOSA_KEY_HOME KEY_F9 -+#define TOSA_KEY_MAIL KEY_F10 -+#define TOSA_KEY_OK KEY_F11 -+#define TOSA_KEY_MENU KEY_F12 -+#define TOSA_KEY_SYNC KEY_F13 -+ -+#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) -+#define KB_DISCHARGE_DELAY 10 -+#define KB_ACTIVATE_DELAY 10 -+ -+ -+static unsigned char tosakbd_keycode[NR_SCANCODES] = { -+ 0, /* 0 */ -+ 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, 0, 0, 0, TOSA_KEY_OFF, 0, 0, 0, 0, /*1 - 16*/ -+ KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, 0, 0, 0, TOSA_KEY_RECORD, 0, 0, 0, 0, /*17 - 32*/ -+ KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, 0, 0, 0, TOSA_KEY_SYNC, 0, 0, 0, 0, /*33 - 48*/ -+ KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESS, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, KEY_LEFTSHIFT, 0 , 0,0 , 0, 0, 0, 0, /*49 - 64*/ -+ KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDER, TOSA_KEY_HOME, TOSA_KEY_REC, TOSA_KEY_LIGHT, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /*65 - 80*/ -+ KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, /*81 - 96*/ -+ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, /*97 - 109*/ -+}; -+ -+struct tosakbd { -+ unsigned char keycode[ARRAY_SIZE(tosakbd_keycode)]; -+ struct input_dev *input; -+ -+ spinlock_t lock; -+ struct timer_list timer; -+ struct timer_list hptimer; -+ -+ int hp_state; -+ int hp_count; -+ -+ unsigned int suspended; -+ unsigned long suspend_jiffies; -+}; -+ -+/* Helper functions for reading the keyboard matrix -+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it -+ * requires a function call per GPIO bit which is excessive -+ * when we need to access 12 bits at once, multiple times. -+ * These functions must be called within local_irq_save()/local_irq_restore() -+ * or similar. -+ */ -+static inline void tosakbd_discharge_all(void) -+{ -+ /* STROBE All HiZ */ -+ GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; -+ GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; -+ GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; -+ GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; -+} -+ -+static inline void tosakbd_activate_all(void) -+{ -+ /* STROBE ALL -> High */ -+ GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; -+ GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; -+ GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; -+ GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; -+ -+ udelay(KB_DISCHARGE_DELAY); -+ -+ /* STATE CLEAR */ -+ GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; -+} -+ -+static inline void tosakbd_activate_col(int col) -+{ -+ if (col<=5) { -+ /* STROBE col -> High, not col -> HiZ */ -+ GPSR1 = TOSA_GPIO_STROBE_BIT(col); -+ GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } else { -+ /* STROBE col -> High, not col -> HiZ */ -+ GPSR2 = TOSA_GPIO_STROBE_BIT(col); -+ GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } -+} -+ -+static inline void tosakbd_reset_col(int col) -+{ -+ if (col<=5) { -+ /* STROBE col -> Low */ -+ GPCR1 = TOSA_GPIO_STROBE_BIT(col); -+ /* STROBE col -> out, not col -> HiZ */ -+ GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } else { -+ /* STROBE col -> Low */ -+ GPCR2 = TOSA_GPIO_STROBE_BIT(col); -+ /* STROBE col -> out, not col -> HiZ */ -+ GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } -+} -+ -+/* -+ * Read the GPIOs for POWER, RECORD and SYNC -+ */ -+static int read_port_key_status_raw(void) -+{ -+ int val=0; -+ -+ /* Power key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_ON_KEY))==0) -+ val |= KEYMASK_ON; -+ /* Record key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_RECORD_BTN))==0) -+ val |= KEYMASK_REC; -+ /* Sync key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_SYNC))==0) -+ val |= KEYMASK_SYNC; -+ return val; -+} -+ -+ -+/* -+ * The tosa keyboard only generates interrupts when a key is pressed. -+ * So when a key is pressed, we enable a timer. This timer scans the -+ * keyboard, and this is how we detect when the key is released. -+ */ -+ -+/* Scan the hardware keyboard and push any changes up through the input layer */ -+static void tosakbd_scankeyboard(struct tosakbd *tosakbd_data) -+{ -+ unsigned int row, col, rowd; -+ unsigned long flags; -+ unsigned int num_pressed = 0; -+ -+ if (tosakbd_data->suspended) -+ return; -+ -+ spin_lock_irqsave(&tosakbd_data->lock, flags); -+ -+ for (col = 0; col < KB_COLS; col++) { -+ /* -+ * Discharge the output driver capacitatance -+ * in the keyboard matrix. (Yes it is significant..) -+ */ -+ tosakbd_discharge_all(); -+ udelay(KB_DISCHARGE_DELAY); -+ -+ tosakbd_activate_col( col); -+ udelay(KB_ACTIVATE_DELAY); -+ -+ rowd = GET_ROWS_STATUS(col); -+ -+ for (row = 0; row < KB_ROWS; row++) { -+ unsigned int scancode, pressed; -+ scancode = SCANCODE(row, col); -+ pressed = rowd & KB_ROWMASK(row); -+ input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed); -+ if (pressed) -+ num_pressed++; -+ } -+ -+ tosakbd_reset_col(col); -+ } -+ -+ tosakbd_activate_all(); -+ -+ rowd = read_port_key_status_raw(); -+ -+ for (row = 0; row < 3; row++ ) { -+ unsigned int scancode, pressed; -+ scancode = SCANCODE(row, KB_COLS); -+ pressed = rowd & KB_ROWMASK(row); -+ input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed); -+ if (pressed) -+ num_pressed++; -+ -+ if (pressed && (tosakbd_data->keycode[scancode] == TOSA_KEY_OFF) -+ && time_after(jiffies, tosakbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { -+ input_event(tosakbd_data->input, EV_PWR, TOSA_KEY_OFF, 1); -+ tosakbd_data->suspend_jiffies = jiffies; -+ } -+ } -+ -+ input_sync(tosakbd_data->input); -+ -+ /* if any keys are pressed, enable the timer */ -+ if (num_pressed) -+ mod_timer(&tosakbd_data->timer, jiffies + SCAN_INTERVAL); -+ -+ spin_unlock_irqrestore(&tosakbd_data->lock, flags); -+} -+ -+/* -+ * tosa keyboard interrupt handler. -+ */ -+static irqreturn_t tosakbd_interrupt(int irq, void *dev_id) -+{ -+ struct tosakbd *tosakbd_data = dev_id; -+ -+ if (!timer_pending(&tosakbd_data->timer)) -+ { -+ /** wait chattering delay **/ -+ udelay(20); -+ tosakbd_scankeyboard(tosakbd_data); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * tosa timer checking for released keys -+ */ -+static void tosakbd_timer_callback(unsigned long data) -+{ -+ struct tosakbd *tosakbd_data = (struct tosakbd *) data; -+ tosakbd_scankeyboard(tosakbd_data); -+} -+ -+/* -+ * The headphone generates an interrupt. -+ * We debounce the switche and pass them to the input system. -+ */ -+ -+static irqreturn_t tosakbd_hp_isr(int irq, void *dev_id) -+{ -+ struct tosakbd *tosakbd_data = dev_id; -+ -+ if (!timer_pending(&tosakbd_data->hptimer)) -+ mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void tosakbd_hp_timer(unsigned long data) -+{ -+ struct tosakbd *tosakbd_data = (struct tosakbd *) data; -+ unsigned long state; -+ unsigned long flags; -+ -+ state = (GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)); -+ if (state != tosakbd_data->hp_state) { -+ tosakbd_data->hp_count = 0; -+ tosakbd_data->hp_state = state; -+ } else if (tosakbd_data->hp_count < HP_STABLE_COUNT) { -+ tosakbd_data->hp_count++; -+ } -+ -+ if (tosakbd_data->hp_count >= HP_STABLE_COUNT) { -+ spin_lock_irqsave(&tosakbd_data->lock, flags); -+ -+ input_report_switch(tosakbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)) == 0)); -+ input_sync(tosakbd_data->input); -+ -+ spin_unlock_irqrestore(&tosakbd_data->lock, flags); -+ } else { -+ mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL)); -+ } -+} -+ -+#ifdef CONFIG_PM -+static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ tosakbd->suspended = 1; -+ -+ return 0; -+} -+ -+static int tosakbd_resume(struct platform_device *dev) -+{ -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ /* Upon resume, ignore the suspend key for a short while */ -+ tosakbd->suspend_jiffies = jiffies; -+ tosakbd->suspended = 0; -+ -+ return 0; -+} -+#else -+#define tosakbd_suspend NULL -+#define tosakbd_resume NULL -+#endif -+ -+static int __init tosakbd_probe(struct platform_device *pdev) { -+ -+ int i; -+ struct tosakbd *tosakbd; -+ struct input_dev *input_dev; -+ -+ tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); -+ if (!tosakbd) -+ return -ENOMEM; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) { -+ kfree(tosakbd); -+ return -ENOMEM; -+ } -+ -+ platform_set_drvdata(pdev,tosakbd); -+ -+ spin_lock_init(&tosakbd->lock); -+ -+ /* Init Keyboard rescan timer */ -+ init_timer(&tosakbd->timer); -+ tosakbd->timer.function = tosakbd_timer_callback; -+ tosakbd->timer.data = (unsigned long) tosakbd; -+ -+ /* Init Headphone Timer */ -+ init_timer(&tosakbd->hptimer); -+ tosakbd->hptimer.function = tosakbd_hp_timer; -+ tosakbd->hptimer.data = (unsigned long) tosakbd; -+ -+ tosakbd->suspend_jiffies = jiffies; -+ -+ tosakbd->input = input_dev; -+ -+ input_dev->private = tosakbd; -+ input_dev->name = "Tosa Keyboard"; -+ input_dev->phys = "tosakbd/input0"; -+ input_dev->cdev.dev = &pdev->dev; -+ -+ input_dev->id.bustype = BUS_HOST; -+ input_dev->id.vendor = 0x0001; -+ input_dev->id.product = 0x0001; -+ input_dev->id.version = 0x0100; -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); -+ input_dev->keycode = tosakbd->keycode; -+ input_dev->keycodesize = sizeof(unsigned char); -+ input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); -+ -+ memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd->keycode)); -+ for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) -+ set_bit(tosakbd->keycode[i], input_dev->keybit); -+ clear_bit(0, input_dev->keybit); -+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); -+ -+ input_register_device(tosakbd->input); -+ -+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ -+ for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { -+ pxa_gpio_mode( TOSA_GPIO_KEY_SENSE(i) | GPIO_IN); -+ if (request_irq(TOSA_IRQ_GPIO_KEY_SENSE(i), tosakbd_interrupt, -+ IRQF_DISABLED | IRQF_TRIGGER_RISING, "tosakbd", tosakbd)) { -+ printk("tosakbd: Can't get IRQ: %d !\n", i); -+ } -+ } -+ -+ /* Set Strobe lines as outputs - set high */ -+ for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { -+ pxa_gpio_mode( TOSA_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); -+ } -+ -+ // Power&Rec Button -+ pxa_gpio_mode( TOSA_GPIO_ON_KEY | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_RECORD_BTN | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_SYNC | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_EAR_IN | GPIO_IN); -+ -+ if (request_irq(TOSA_IRQ_GPIO_ON_KEY, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "On key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_RECORD_BTN, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Record key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_SYNC, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Sync key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_EAR_IN, tosakbd_hp_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "HP in", tosakbd)) { -+ printk("Could not allocate KEYBD IRQ!\n"); -+ } -+ -+ printk(KERN_INFO "input: Tosa Keyboard Registered\n"); -+ -+ return 0; -+} -+ -+static int tosakbd_remove(struct platform_device *dev) { -+ -+ int i; -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) -+ free_irq(TOSA_IRQ_GPIO_KEY_SENSE(i),tosakbd); -+ -+ free_irq(TOSA_IRQ_GPIO_ON_KEY,tosakbd); -+ free_irq(TOSA_IRQ_GPIO_RECORD_BTN,tosakbd); -+ free_irq(TOSA_IRQ_GPIO_SYNC,tosakbd); -+ -+ del_timer_sync(&tosakbd->timer); -+ -+ input_unregister_device(tosakbd->input); -+ -+ kfree(tosakbd); -+ -+ return 0; -+} -+ -+static struct platform_driver tosakbd_driver = { -+ .probe = tosakbd_probe, -+ .remove = tosakbd_remove, -+ .suspend = tosakbd_suspend, -+ .resume = tosakbd_resume, -+ .driver = { -+ .name = "tosa-keyboard", -+ }, -+}; -+ -+static int __devinit tosakbd_init(void) -+{ -+ return platform_driver_register(&tosakbd_driver); -+} -+ -+static void __exit tosakbd_exit(void) -+{ -+ platform_driver_unregister(&tosakbd_driver); -+} -+ -+module_init(tosakbd_init); -+module_exit(tosakbd_exit); -+ -+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); -+MODULE_DESCRIPTION("Tosa Keyboard Driver"); -+MODULE_LICENSE("GPLv2"); diff --git a/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1-fix-r0.patch b/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1-fix-r0.patch index 02dd6a74eb..93a9c18720 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1-fix-r0.patch @@ -133,138 +133,3 @@ index ce7322d..7f446fd 100644 -- 1.4.4.4 -From eada869814636157956641ba1503f0d6cc04e2b7 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 17:43:51 +0400 -Subject: [PATCH] tosa-lcdnoise-r1.patch fixes - ---- - arch/arm/mach-pxa/tosa_lcd.c | 34 ++++++++++++++++++++++++++++++++++ - drivers/input/touchscreen/tosa_ts.c | 9 +-------- - include/asm-arm/arch-pxa/tosa.h | 5 +++++ - 3 files changed, 40 insertions(+), 8 deletions(-) - -diff --git a/arch/arm/mach-pxa/tosa_lcd.c b/arch/arm/mach-pxa/tosa_lcd.c -index d52f63f..447ca86 100644 ---- a/arch/arm/mach-pxa/tosa_lcd.c -+++ b/arch/arm/mach-pxa/tosa_lcd.c -@@ -59,6 +59,8 @@ static int bl_intensity; - static struct ssp_dev tosa_nssp_dev; - static struct ssp_state tosa_nssp_state; - static spinlock_t tosa_nssp_lock; -+static int blanked; -+static unsigned long hsync_time; - - static unsigned short normal_i2c[] = { - DAC_BASE, -@@ -130,6 +132,17 @@ static void tosa_lcd_tg_init(struct device *dev) - pxa_nssp_output(TG_GPOSR,0x02); /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */ - } - -+static unsigned long calc_hsync_time(const struct fb_videomode *mode) { -+ /* The 25 and 44 'magic numbers' are from Sharp's 2.4 patches */ -+ if (mode->yres == 640) { -+ return 25; -+ } -+ if (mode->yres == 320) { -+ return 44; -+ } -+ return 0; -+} -+ - static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode) - { - const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR; -@@ -154,6 +167,8 @@ static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode) - /* set common voltage */ - i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj); - -+ blanked = 0; -+ hsync_time = calc_hsync_time(mode); - } - - static void tosa_lcd_tg_off(struct device *dev) -@@ -172,6 +187,8 @@ static void tosa_lcd_tg_off(struct device *dev) - - /* L3V Off */ - reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); -+ -+ blanked = 1; - } - - static int tosa_detect_client(struct i2c_adapter* adapter, int address, int kind) { -@@ -238,6 +255,23 @@ static int tosa_detach_client(struct i2c_client* client) { - return 0; - } - -+unsigned long tosa_lcd_get_hsync_time(void) -+{ -+/* This method should eventually contain the correct algorithm for calculating -+ the hsync_time */ -+ if (blanked) -+ return 0; -+ else -+ return hsync_time; -+} -+ -+void tosa_lcd_wait_hsync(void) -+{ -+ /* Waits for a rising edge on the VGA line */ -+ while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0); -+ while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0); -+} -+ - static struct i2c_driver tosa_driver={ - .id = TOSA_LCD_I2C_DEVICEID, - .attach_adapter = tosa_attach_adapter, -diff --git a/drivers/input/touchscreen/tosa_ts.c b/drivers/input/touchscreen/tosa_ts.c -index bc733e9..134f8ce 100644 ---- a/drivers/input/touchscreen/tosa_ts.c -+++ b/drivers/input/touchscreen/tosa_ts.c -@@ -25,13 +25,6 @@ - #define CCNT_ON() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) - #define CCNT_OFF() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) - --static inline void tosa_lcd_wait_hsync(void) --{ -- /* Waits for a rising edge on the VGA line */ -- while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0); -- while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0); --} -- - /* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait - * before sampling the Y axis of the touchscreen */ - void tosa_lcd_sync_on(int adcsel) { -@@ -54,7 +47,7 @@ void tosa_lcd_sync_on(int adcsel) { - } - } - --void tosa_lcd_sync_off(void) { -+void tosa_lcd_sync_off(int adcsel) { - CCNT_OFF(); - } - -diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h -index ce7322d..7f446fd 100644 ---- a/include/asm-arm/arch-pxa/tosa.h -+++ b/include/asm-arm/arch-pxa/tosa.h -@@ -1,6 +1,7 @@ - /* - * Hardware specific definitions for Sharp SL-C6000x series of PDAs - * -+ * Copyright (c) 2006 Wolfson Microelectronics PLC. - * Copyright (c) 2005 Dirk Opfer - * - * Based on Sharp's 2.4 kernel patches -@@ -187,4 +188,8 @@ - extern struct platform_device tosascoop_jc_device; - extern struct platform_device tosascoop_device; - extern struct platform_device tc6393_device; -+ -+unsigned long tosa_lcd_get_hsync_time(void); -+void tosa_lcd_wait_hsync(void); -+ - #endif /* _ASM_ARCH_TOSA_H_ */ --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1.patch b/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1.patch index 910b727b82..21f3cf66b1 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-lcdnoise-r1.patch @@ -156,161 +156,3 @@ index 0000000..bc733e9 -- 1.4.4.4 -From 564b757ba44b517ac6d693b94a177708bb5d3887 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 17:30:30 +0400 -Subject: [PATCH] tosa-lcdnoise-r1.patch - ---- - drivers/input/touchscreen/Kconfig | 13 +++++ - drivers/input/touchscreen/Makefile | 1 + - drivers/input/touchscreen/tosa_ts.c | 102 +++++++++++++++++++++++++++++++++++ - 3 files changed, 116 insertions(+), 0 deletions(-) - -diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 3ac01b4..6862e8f 100644 ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -219,6 +219,19 @@ config TOUCHSCREEN_USB_DMC_TSC10 - bool "DMC TSC-10/25 device support" if EMBEDDED - depends on TOUCHSCREEN_USB_COMPOSITE - -+config TOUCHSCREEN_TOSA -+ tristate "Sharp Tosa touchscreen driver" -+ depends on TOUCHSCREEN_WM97XX && MACH_TOSA -+ default n -+ help -+ Say Y here to enable the driver for the touchscreen on the -+ Sharp Tosa PDA. -+ depends on TOUCHSCREEN_WM97XX && MACH_TOSA -+ If unsure, say N. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called tosa_ts. -+ - config TOUCHSCREEN_TSC2101 - tristate "TI TSC2101 touchscreen input driver" - depends on MACH_HX2750 && INPUT && INPUT_TOUCHSCREEN -diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index f64d1a5..4fc0e17 100644 ---- a/drivers/input/touchscreen/Makefile -+++ b/drivers/input/touchscreen/Makefile -@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o - obj-$(CONFIG_TOUCHSCREEN_TSC2101) += tsc2101_ts.o - obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o - obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA) += pxa-wm97xx.o -+obj-$(CONFIG_TOUCHSCREEN_TOSA) += tosa_ts.o - - ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y) - wm97xx-ts-objs += wm9713.o -diff --git a/drivers/input/touchscreen/tosa_ts.c b/drivers/input/touchscreen/tosa_ts.c -new file mode 100644 -index 0000000..bc733e9 ---- /dev/null -+++ b/drivers/input/touchscreen/tosa_ts.c -@@ -0,0 +1,102 @@ -+/* -+ * tosa_ts.c -- Touchscreen driver for Sharp SL-6000 (Tosa). -+ * -+ * Copyright 2006 Wolfson Microelectronics PLC. -+ * Author: Mike Arthur -+ * linux@wolfsonmicro.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Revision history -+ * 1st Sep 2006 Initial version. -+ * -+ */ -+ -+#include <linux/wm97xx.h> -+#include <asm/arch/tosa.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+ -+/* Taken from the Sharp 2.4 kernel code */ -+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -+#define CCNT_ON() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+#define CCNT_OFF() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+ -+static inline void tosa_lcd_wait_hsync(void) -+{ -+ /* Waits for a rising edge on the VGA line */ -+ while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) == 0); -+ while((GPLR(TOSA_GPIO_VGA_LINE) & GPIO_bit(TOSA_GPIO_VGA_LINE)) != 0); -+} -+ -+/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait -+ * before sampling the Y axis of the touchscreen */ -+void tosa_lcd_sync_on(int adcsel) { -+ unsigned long timer1 = 0, timer2 = 0, wait_time = 0; -+ if (adcsel == WM97XX_ADCSEL_Y) { -+ wait_time = tosa_lcd_get_hsync_time(); -+ CCNT_ON(); -+ -+ if (wait_time) { -+ /* wait for LCD rising edge */ -+ tosa_lcd_wait_hsync(); -+ /* get clock */ -+ CCNT(timer1); -+ CCNT(timer2); -+ -+ while ((timer2 - timer1) < wait_time) { -+ CCNT(timer2); -+ } -+ } -+ } -+} -+ -+void tosa_lcd_sync_off(void) { -+ CCNT_OFF(); -+} -+ -+static struct wm97xx_mach_ops tosa_mach_ops = { -+ .pre_sample = tosa_lcd_sync_on, -+ .post_sample = tosa_lcd_sync_off, -+}; -+ -+int tosa_ts_probe(struct device *dev) { -+ struct wm97xx *wm = dev->driver_data; -+ return wm97xx_register_mach_ops (wm, &tosa_mach_ops); -+} -+ -+ -+int tosa_ts_remove(struct device *dev) { -+ struct wm97xx *wm = dev->driver_data; -+ wm97xx_unregister_mach_ops (wm); -+ return 0; -+} -+ -+static struct device_driver tosa_ts_driver = { -+ .name = "wm97xx-touchscreen", -+ .bus = &wm97xx_bus_type, -+ .owner = THIS_MODULE, -+ .probe = tosa_ts_probe, -+ .remove = tosa_ts_remove, -+}; -+ -+static int __init tosa_ts_init(void) -+{ -+ return driver_register(&tosa_ts_driver); -+} -+ -+static void __exit tosa_ts_exit(void) -+{ -+ driver_unregister(&tosa_ts_driver); -+} -+ -+module_init(tosa_ts_init); -+module_exit(tosa_ts_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Mike Arthur, mike@mikearthur.co.uk, www.wolfsonmicro.com"); -+MODULE_DESCRIPTION("Sharp SL6000 Tosa Touch Screen Driver"); -+MODULE_LICENSE("GPL"); --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tosa-power-r18-fix-r0.patch b/packages/linux/linux-rp-2.6.23/tosa-power-r18-fix-r0.patch index fdfbea8ee0..8899ae270b 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-power-r18-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-power-r18-fix-r0.patch @@ -57,62 +57,3 @@ index 1eab1af..2df75f0 100644 -- 1.4.4.4 -From 24813da9b0aac0e92635d7307837d89a9f4a1ee7 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 16:47:15 +0400 -Subject: [PATCH] tosa-power-r18.patch fixes - ---- - arch/arm/mach-pxa/tosa_pm.c | 9 +++++---- - 1 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/mach-pxa/tosa_pm.c b/arch/arm/mach-pxa/tosa_pm.c -index 1eab1af..2df75f0 100644 ---- a/arch/arm/mach-pxa/tosa_pm.c -+++ b/arch/arm/mach-pxa/tosa_pm.c -@@ -17,9 +17,9 @@ - #include <linux/interrupt.h> - #include <linux/platform_device.h> - #include <linux/pm.h> -+#include <linux/apm-emulation.h> - #include <linux/wm97xx.h> - --#include <asm/apm.h> - #include <asm/irq.h> - #include <asm/mach-types.h> - #include <asm/hardware.h> -@@ -144,7 +144,7 @@ static int tosa_ac97_init(void) - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); - pxa_gpio_mode(GPIO20_DREQ0_MD); - -- pxa_set_cken(CKEN2_AC97, 1); -+ pxa_set_cken(CKEN_AC97, 1); - /* AC97 power on sequense */ - while ( 1 ) { - GCR = 0; -@@ -184,11 +184,12 @@ static int tosa_ac97_init(void) - pxa_gpio_mode(GPIO32_SDATA_IN1_AC97_MD); - ad_polling = 1; - printk("tosa_ac97_init\n"); -+ return 0; - } - - void tosa_ac97_exit(void) - { -- if (!(CKEN & CKEN2_AC97)) -+ if (!(CKEN & CKEN_AC97)) - return; - - // power down the whole chip -@@ -197,7 +198,7 @@ void tosa_ac97_exit(void) - // GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN); - // GSR = GSR; - // GCR = GCR_ACLINK_OFF; -- pxa_set_cken(CKEN2_AC97, 0); -+ pxa_set_cken(CKEN_AC97, 0); - /* switch back to irq driver */ - ad_polling = 0; - printk("tosa_ac97_exit\n"); --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tosa-power-r18.patch b/packages/linux/linux-rp-2.6.23/tosa-power-r18.patch index a099717749..ca703cb188 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-power-r18.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-power-r18.patch @@ -689,694 +689,3 @@ Index: linux-2.6.17/arch/arm/mach-pxa/Kconfig config PXA25x bool -Index: linux-2.6.17/arch/arm/mach-pxa/Makefile -=================================================================== ---- linux-2.6.17.orig/arch/arm/mach-pxa/Makefile 2006-09-19 20:51:33.984424500 +0200 -+++ linux-2.6.17/arch/arm/mach-pxa/Makefile 2006-09-19 21:08:04.922354250 +0200 -@@ -16,7 +16,7 @@ obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o - obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o - obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o - obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o --obj-$(CONFIG_MACH_TOSA) += tosa.o -+obj-$(CONFIG_MACH_TOSA) += tosa.o sharpsl_pm.o tosa_pm.o - obj-$(CONFIG_MACH_EM_X270) += em-x270.o - obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o - -Index: linux-2.6.17/arch/arm/mach-pxa/tosa_pm.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/arch/arm/mach-pxa/tosa_pm.c 2006-09-19 21:08:34.476201250 +0200 -@@ -0,0 +1,661 @@ -+/* -+ * Battery and Power Management code for the Sharp SL-6000x -+ * -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/stat.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+#include <linux/platform_device.h> -+#include <linux/pm.h> -+#include <linux/wm97xx.h> -+ -+#include <asm/apm.h> -+#include <asm/irq.h> -+#include <asm/mach-types.h> -+#include <asm/hardware.h> -+#include <asm/hardware/scoop.h> -+#include <asm/hardware/tmio.h> -+ -+#include <asm/arch/sharpsl.h> -+#include <asm/arch/tosa.h> -+#include <asm/arch/pxa-regs.h> -+#include <sound/soc.h> -+#include <sound/ac97_codec.h> -+#include "sharpsl.h" -+ -+extern int tosa_bl_intensity(void); -+volatile static int ad_polling; -+static int tosa_pm_driver_probe(struct device *dev); -+static int tosa_pm_driver_remove(struct device *dev); -+static struct wm97xx *wm9712; -+ -+/************************************************************ -+ * AC97 functions -+ ************************************************************/ -+#define AC97_TIMEOUT_VAL 0x1000000 -+ -+#define AC97_MISC_MODEM_STAT 0x0056 -+#define AC97_GPIO_CONFIG 0x004C -+ -+static u16 tosa_ac97_read(unsigned short reg) -+{ -+ volatile u32 *reg_addr; -+ volatile int timeout; -+ unsigned short data; -+ -+ if (CAR & CAR_CAIP) { -+ printk(KERN_CRIT ": CAR_CAIP already set\n"); -+ return 0; -+ } -+ -+ if (reg == AC97_GPIO_STATUS) -+ reg_addr = &PMC_REG_BASE; -+ else -+ reg_addr = &PAC_REG_BASE; -+ -+ reg_addr += (reg >> 1); -+ -+ data=0; -+ GSR = GSR_CDONE | GSR_SDONE; -+ -+ data = *reg_addr; -+ timeout = 0; -+ -+ while(((GSR & GSR_SDONE)) == 0 && (timeout++ < AC97_TIMEOUT_VAL)); -+ -+ if ((timeout >= AC97_TIMEOUT_VAL)) { -+ GSR = GSR; -+ printk(KERN_CRIT ": AC97 is busy1.\n"); -+ return data; -+ } -+ -+ // actual read -+ GSR = GSR_CDONE | GSR_SDONE; -+ data = *reg_addr; -+ -+ timeout = 0; -+ while(((GSR & GSR_SDONE) == 0) && (timeout++<AC97_TIMEOUT_VAL)); -+ if ((timeout >= AC97_TIMEOUT_VAL)) { -+ GSR = GSR; -+ printk(KERN_CRIT ": AC97 is busy2.\n"); -+ return data; -+ } -+ -+ return data; -+} -+ -+static void tosa_ac97_write(unsigned short reg, unsigned short val) -+{ -+ volatile u32 *reg_addr; -+ volatile int timeout=0; -+ -+ if (CAR & CAR_CAIP) { -+ printk(KERN_CRIT ": CAR_CAIP already set\n"); -+ return; -+ } -+ -+ GSR = GSR_CDONE | GSR_SDONE; -+ if (reg == AC97_GPIO_STATUS) -+ reg_addr = &PMC_REG_BASE; -+ else -+ reg_addr = &PAC_REG_BASE; -+ -+ reg_addr += (reg >> 1); -+ -+ *reg_addr = val; -+ while(((GSR & GSR_CDONE) == 0) && (timeout++ < AC97_TIMEOUT_VAL)); -+ if (timeout >= AC97_TIMEOUT_VAL) { -+ printk(KERN_CRIT ": AC97 is busy.\n"); -+ } -+} -+ -+static void tosa_ac97_bit_clear(u8 reg, u16 val) -+{ -+ unsigned short dat = tosa_ac97_read(reg); -+ dat &= ~val; -+ tosa_ac97_write(reg, dat); -+} -+ -+static void tosa_ac97_bit_set(u8 reg, u16 val) -+{ -+ unsigned short dat = tosa_ac97_read(reg); -+ dat |= val; -+ tosa_ac97_write(reg, dat); -+} -+ -+ -+static int tosa_ac97_init(void) -+{ -+ int timeo; -+ -+ pxa_gpio_mode(GPIO31_SYNC_AC97_MD); -+ pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); -+ pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); -+ pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); -+ pxa_gpio_mode(GPIO20_DREQ0_MD); -+ -+ pxa_set_cken(CKEN2_AC97, 1); -+ /* AC97 power on sequense */ -+ while ( 1 ) { -+ GCR = 0; -+ udelay(100); -+ GCR |= GCR_COLD_RST; -+ udelay(5); -+ GCR |= GCR_WARM_RST; -+ udelay(5); -+ for ( timeo = 0x10000; timeo > 0; timeo-- ) { -+ if ( GSR & GSR_PCR ) break; -+ mdelay(5); -+ } -+ if( timeo > 0 ) break; -+ printk(KERN_WARNING "AC97 power on retry!!\n"); -+ } -+ -+ tosa_ac97_write(AC97_EXTENDED_STATUS, 1); -+ /* -+ * Setting AC97 GPIO -+ * i/o function -+ * GPIO1: input EAR_IN signal -+ * GPIO2: output IRQ signal -+ * GPIO3: output PENDOWN signal -+ * GPIO4: input MASK signal -+ * GPIO5: input DETECT MIC signal -+ */ -+ // AC97_GPIO_FUNC AC97_MISC_MODEM_STAT -+ -+ tosa_ac97_bit_clear(AC97_MISC_MODEM_STAT, -+ ((1<<2)|(1<<3)|(1<<4)|(1<<5))); -+ tosa_ac97_bit_clear(AC97_GPIO_CONFIG,(1<<2)|(1<<3)); -+ tosa_ac97_bit_set(AC97_GPIO_CONFIG, (1<<1)|(1<<4)|(1<<5)); -+ -+ tosa_ac97_write(AC97_WM97XX_DIGITISER2, 0xc009); -+ tosa_ac97_write(AC97_WM97XX_DIGITISER1, 0x0030 | WM97XX_DELAY(4)); -+ -+ pxa_gpio_mode(GPIO32_SDATA_IN1_AC97_MD); -+ ad_polling = 1; -+ printk("tosa_ac97_init\n"); -+} -+ -+void tosa_ac97_exit(void) -+{ -+ if (!(CKEN & CKEN2_AC97)) -+ return; -+ -+ // power down the whole chip -+ tosa_ac97_write(AC97_POWERDOWN, 0x7fff); -+ -+// GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN); -+// GSR = GSR; -+// GCR = GCR_ACLINK_OFF; -+ pxa_set_cken(CKEN2_AC97, 0); -+ /* switch back to irq driver */ -+ ad_polling = 0; -+ printk("tosa_ac97_exit\n"); -+} -+ -+int ac97_ad_input(u16 adcsel) -+{ -+ unsigned short val = 0; -+ unsigned long timeout; -+ -+ // prepare -+ tosa_ac97_read(AC97_WM97XX_DIGITISER_RD); -+ -+ if (adcsel & 0x8000) -+ adcsel = ((adcsel & 0x7fff) + 3) << 12; -+ -+ /* Conversion start */ -+ tosa_ac97_write(AC97_WM97XX_DIGITISER1, (adcsel | WM97XX_POLL | WM97XX_DELAY(4))); -+ timeout = 0x1000; -+ /* wait for POLL to go low */ -+ while ((tosa_ac97_read(AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) { -+ udelay(100); -+ timeout--; -+ } -+ -+ val = tosa_ac97_read(AC97_WM97XX_DIGITISER_RD); -+ -+ val &= 0xFFF ; -+ -+ return val; -+} -+ -+ -+int tosa_read_aux_adc(u16 adcsel) -+{ -+ if (ad_polling) -+ return (ac97_ad_input(adcsel)); -+ else -+ return (wm97xx_read_aux_adc(wm9712, adcsel)); -+} -+ -+static struct device_driver tosa_pm_driver = { -+ .name = "wm97xx-battery", -+ .bus = &wm97xx_bus_type, -+ .owner = THIS_MODULE, -+ .probe = tosa_pm_driver_probe, -+ .remove = tosa_pm_driver_remove, -+}; -+ -+#if 0 -+#define TOSA_TEMP_READ_WAIT_TIME (5) // 5msec [Fix] -+int tosa_read_battery(struct wm97xx* wm, int channel) -+{ -+ //return sprintf(buf, "%d\n", wm97xx_read_aux_adc(wm, input)); -+ -+ int wm_aux,i; -+ int value = 0; -+ int clear_mux; -+ -+ switch(channel) { -+ -+ case 0: // Main -+ -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON); -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON); -+ wm_aux = WM97XX_AUX_ID3; -+ break; -+ -+ case 1: // Jacket -+ -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_V_ON); -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON | TOSA_TC6393_BAT_SW_ON); -+ wm_aux = WM97XX_AUX_ID3; -+ break; -+ -+ case 2: // BU -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BU_CHRG_ON); -+ wm_aux = WM97XX_AUX_ID4; -+ break; -+ -+ case 3: // Main Temp -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON); -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON); -+ wm_aux = WM97XX_AUX_ID2; -+ break; -+ -+ case 4: // Jacket Temp -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON); -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON); -+ wm_aux = WM97XX_AUX_ID2; -+ break; -+ -+ default: -+ return -1; -+ } -+ -+ mdelay(TOSA_TEMP_READ_WAIT_TIME); -+ for(i=0;i<4;i++) -+ { -+ if (wm9712) -+ value += wm97xx_read_aux_adc(wm, wm_aux); -+ else -+ value += ac97_ad_input(wm, wm_aux); -+ } -+ -+ value>>=2; -+ // reset the multiplexer -+ clear_mux = TOSA_TC6393_BAT0_V_ON | TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON | TOSA_TC6393_BAT0_TH_ON | TOSA_TC6393_BAT1_TH_ON | TOSA_TC6393_BU_CHRG_ON; -+ -+ return value; -+ -+} -+#endif -+ -+/* BL 5-3 */ -+struct battery_thresh tosa_battery_levels_bl[] = { -+ { 1663, 100 }, -+ { 1605, 75 }, -+ { 1564, 50 }, -+ { 1510, 25 }, -+ { 1435, 5 }, -+ { 0, 0 }, -+}; -+ -+/* BL 2-0 */ -+struct battery_thresh tosa_battery_levels[] = { -+ { 1679, 100 }, -+ { 1617, 75 }, -+ { 1576, 50 }, -+ { 1530, 25 }, -+ { 1448, 5 }, -+ { 0, 0 }, -+}; -+ -+struct pm_devices { -+ const char * name; -+ struct bus_type *bus; -+ struct device_driver *driver; -+ struct device * dev; -+ int (*resume)(struct device *dev, void * data); // int (*resume)(struct device *dev); -+ int (*suspend)(struct device *dev, void * data);// int (*suspend)(struct device *dev, pm_message_t state); -+}; -+ -+/* Ugly -+ We need the following devices to measure the battery and control the charger: -+ Also we need access to these before we sleep and immediatly after we resume so we can't -+ control their pm via the kernel device manager. To access their pm functions we will backup -+ the suspend and resume handler and clear these pointers. -+ After that we can suspend and resume these devices. -+ -+ Don't change the order of this table!!!!! -+*/ -+static struct pm_devices dev_table[] = { -+ [0] = { -+ .name = TMIO_SOC_NAME, -+ .bus = &platform_bus_type, -+ }, -+}; -+ -+static int tosa_pm_driver_probe(struct device *dev) -+{ -+ wm9712 = dev->driver_data; -+ ad_polling = 0; -+ return 0; -+} -+ -+static int tosa_pm_driver_remove(struct device *dev) -+{ -+ wm9712 = NULL; -+ return 0; -+} -+ -+ -+static void tosa_charger_init(void) -+{ -+ int i; -+ -+ /* If this driver doesn't register, bad things will happen, Tosa won't boot, -+ and the world will possibly explode */ -+ i = driver_register(&tosa_pm_driver); -+ if (i < 0) -+ panic("Cannot register the tosa_pm driver on the wm97xx bus. Halting."); -+ -+ for(i=0;i<ARRAY_SIZE(dev_table);i++) -+ { -+ dev_table[i].driver = driver_find(dev_table[i].name, dev_table[i].bus); -+ if (dev_table[i].driver) -+ { -+ dev_table[i].resume = dev_table[i].driver->resume; -+ dev_table[i].suspend = dev_table[i].driver->suspend; -+ dev_table[i].driver->resume = NULL; -+ dev_table[i].driver->suspend = NULL; -+ } -+ } -+ -+ pxa_gpio_mode(TOSA_GPIO_AC_IN | GPIO_IN); -+ pxa_gpio_mode(TOSA_GPIO_BAT0_CRG | GPIO_IN); -+ pxa_gpio_mode(TOSA_GPIO_BAT1_CRG | GPIO_IN); -+ pxa_gpio_mode(TOSA_GPIO_BAT0_LOW | GPIO_IN); -+ pxa_gpio_mode(TOSA_GPIO_BAT1_LOW | GPIO_IN); -+ -+ pxa_gpio_mode(TOSA_GPIO_JACKET_DETECT | GPIO_IN); -+ pxa_gpio_mode(TOSA_GPIO_POWERON | GPIO_IN); -+ sharpsl_pm_pxa_init(); -+} -+ -+ -+static void tosa_measure_temp(int on) -+{ -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_TH_ON | TOSA_TC6393_BAT1_TH_ON); -+ -+ if (on) -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT1_TH_ON); -+ -+} -+ -+static void tosa_charge(int on) -+{ -+ if(on) -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_CHARGE_OFF); -+ else -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_CHARGE_OFF); -+} -+ -+static void tosa_discharge1(int on) -+{ -+} -+ -+static void tosa_discharge(int on) -+{ -+} -+ -+ -+static void tosa_presuspend(void) -+{ -+ int i; -+ unsigned long wakeup_mask; -+ -+ // put remaining devices into sleep -+ for(i=0;i<ARRAY_SIZE(dev_table);i++) -+ { -+ if(dev_table[i].suspend) -+ driver_for_each_device(dev_table[i].driver, NULL, -+ (void*)&PMSG_SUSPEND, dev_table[i].suspend); -+ } -+ -+ tosa_ac97_exit(); -+ -+ wakeup_mask = GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) | GPIO_bit(TOSA_GPIO_AC_IN); -+ -+ wakeup_mask |= GPIO_bit(TOSA_GPIO_BAT0_LOW); -+ PWER = wakeup_mask | PWER_RTC; -+ -+ PRER = wakeup_mask; -+ PFER = wakeup_mask; -+ -+ for (i = 0; i <=15; i++) { -+ if (PRER & PFER & GPIO_bit(i)) { -+ if (GPLR0 & GPIO_bit(i) ) -+ PRER &= ~GPIO_bit(i); -+ else -+ PFER &= ~GPIO_bit(i); -+ } -+ } -+ -+ /* Clear reset status */ -+ RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; -+ -+ /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ -+ PCFR = PCFR_OPDE; -+ -+ /* Resume on keyboard power key */ -+ PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT); -+ PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT); -+ -+ GPDR0 = 0xC3810940; -+ GPDR1 = 0xFCFFAB82; -+ GPDR2 = 0x000F501f; -+// write_scoop_reg(&tosascoop_device.dev,SCOOP_GPWR,0); -+// only debug -+reset_scoop_gpio(&tosascoop_jc_device.dev, TOSA_SCOOP_JC_NOTE_LED); -+} -+ -+void tosa_postsuspend(void) -+{ -+ int i; -+// only debug -+set_scoop_gpio(&tosascoop_jc_device.dev, TOSA_SCOOP_JC_NOTE_LED); -+ -+ for(i=ARRAY_SIZE(dev_table);i;i--) -+ { -+ if(dev_table[i-1].resume) -+ driver_for_each_device(dev_table[i-1].driver, NULL, -+ NULL, dev_table[i-1].resume); -+ } -+ tosa_ac97_init(); -+ PMCR = 0x01; -+} -+ -+void tosa_postresume(void) -+{ -+ tosa_ac97_exit(); -+} -+ -+/* -+ * Check what brought us out of the suspend. -+ * Return: 0 to sleep, otherwise wake -+ */ -+static int tosa_should_wakeup(unsigned int resume_on_alarm) -+{ -+ int is_resume = 0; -+ -+ dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); -+ -+ if ((PEDR & GPIO_bit(TOSA_GPIO_AC_IN))) { -+ if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { -+ /* charge on */ -+ dev_dbg(sharpsl_pm.dev, "ac insert\n"); -+ sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; -+ } else { -+ /* charge off */ -+ dev_dbg(sharpsl_pm.dev, "ac remove\n"); -+ sharpsl_pm_led(SHARPSL_LED_OFF); -+ sharpsl_pm.machinfo->charge(0); -+ sharpsl_pm.charge_mode = CHRG_OFF; -+ } -+ } -+ -+ if ((PEDR & GPIO_bit(GPIO_bit(TOSA_GPIO_BAT0_CRG)))) -+ dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n"); -+ -+ if (PEDR & GPIO_bit(TOSA_GPIO_POWERON)) -+ is_resume |= GPIO_bit(TOSA_GPIO_POWERON); -+ -+ if (PEDR & GPIO_bit(TOSA_GPIO_ON_KEY)) -+ is_resume |= GPIO_bit(TOSA_GPIO_ON_KEY); -+ -+ if (resume_on_alarm && (PEDR & PWER_RTC)) -+ is_resume |= PWER_RTC; -+ -+ return is_resume; -+} -+ -+static unsigned long tosa_charger_wakeup(void) -+{ -+// return ~GPLR0 & ( GPIO_bit(TOSA_GPIO_AC_IN) | GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) ); -+ return (~GPLR0 & ( GPIO_bit(TOSA_GPIO_POWERON) | GPIO_bit(TOSA_GPIO_ON_KEY) )) | (GPLR0 & GPIO_bit(TOSA_GPIO_AC_IN)); -+} -+ -+unsigned long tosa_read_bat(void) -+{ -+ unsigned long value; -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON | TOSA_TC6393_BAT1_V_ON | TOSA_TC6393_BAT_SW_ON); -+ mdelay(5); -+ value = tosa_read_aux_adc(WM97XX_AUX_ID3); -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BAT0_V_ON); -+ return value; -+} -+ -+unsigned long tosapm_read_devdata(int type) -+{ -+ switch(type) { -+ case SHARPSL_STATUS_ACIN: -+ return ((GPLR(TOSA_GPIO_AC_IN) & GPIO_bit(TOSA_GPIO_AC_IN)) == 0); -+ case SHARPSL_STATUS_LOCK: -+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock); -+ case SHARPSL_STATUS_CHRGFULL: -+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull); -+ case SHARPSL_STATUS_FATAL: -+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal); -+ case SHARPSL_ACIN_VOLT: -+ return 1000; // not used on tosa -+ case SHARPSL_BATT_TEMP: -+ return tosa_read_aux_adc(WM97XX_AUX_ID2); -+ case SHARPSL_BATT_VOLT: -+ return tosa_read_bat(); -+ default: -+ return tosa_read_bat(); -+ } -+} -+ -+static struct sharpsl_charger_machinfo tosa_pm_machinfo = { -+ .init = tosa_charger_init, -+ .exit = sharpsl_pm_pxa_remove, -+ .gpio_batlock = TOSA_GPIO_BAT_LOCKED, -+ .gpio_acin = TOSA_GPIO_AC_IN, -+ .gpio_batfull = TOSA_GPIO_BAT0_CRG, -+ .batfull_irq = 0, -+ .discharge = tosa_discharge, -+ .discharge1 = tosa_discharge1, -+ .charge = tosa_charge, -+ .measure_temp = tosa_measure_temp, -+ .presuspend = tosa_presuspend, -+ .postsuspend = tosa_postsuspend, -+ .postresume = tosa_postresume, -+ .read_devdata = tosapm_read_devdata, -+ .charger_wakeup = tosa_charger_wakeup, -+ .should_wakeup = tosa_should_wakeup, -+ .backlight_limit = corgibl_limit_intensity, -+ .backlight_get_status= tosa_bl_intensity, -+ .bat_levels = 6, -+ .bat_levels_noac = tosa_battery_levels, -+ .bat_levels_acin = tosa_battery_levels, -+ .bat_levels_noac_bl = tosa_battery_levels_bl, -+ .bat_levels_acin_bl = tosa_battery_levels_bl, -+ .charge_on_volt = 1200, // 2.9V TOSA_MAIN_BATTERY_ERR_THRESH voltage < 1200 -> error -+ .charge_on_temp = 3600, // -- TOSA_MAIN_BATTERY_EXIST_THRESH temp > 3600 -> error, no battery -+ .charge_acin_high = 1500, // not used default value -+ .charge_acin_low = 500, // not used default value -+ .fatal_acin_volt = 1572, // 3.8V -+ .fatal_noacin_volt= 1551, // 3.75V -+ .status_high_acin = 1564, // 3.78V -+ .status_low_acin = 1510, // 3.65V -+ .status_high_noac = 1564, // 3.78V -+ .status_low_noac = 1510, // 3.65V -+}; -+ -+static struct platform_device *tosapm_device; -+ -+static int __devinit tosapm_init(void) -+{ -+ int ret; -+ -+ tosapm_device = platform_device_alloc("sharpsl-pm", -1); -+ if (!tosapm_device) -+ return -ENOMEM; -+ -+ tosapm_device->dev.platform_data = &tosa_pm_machinfo; -+ ret = platform_device_add(tosapm_device); -+ -+ if (ret) -+ platform_device_put(tosapm_device); -+ -+ return ret; -+} -+ -+static void tosapm_exit(void) -+{ -+ int i; -+ -+ // restore the resume / suspend handler -+ for(i=0;i<ARRAY_SIZE(dev_table);i++) -+ { -+ if (dev_table[i].driver) -+ { -+ dev_table[i].driver->resume = dev_table[i].resume; -+ dev_table[i].driver->suspend = dev_table[i].suspend; -+ dev_table[i].resume = NULL; -+ dev_table[i].suspend = NULL; -+ put_driver(dev_table[i].driver); -+ } -+ } -+ -+ if (wm9712) -+ driver_unregister(&tosa_pm_driver); -+ -+ platform_device_unregister(tosapm_device); -+} -+ -+module_init(tosapm_init); -+module_exit(tosapm_exit); -Index: linux-2.6.17/arch/arm/mach-pxa/Kconfig -=================================================================== ---- linux-2.6.17.orig/arch/arm/mach-pxa/Kconfig 2006-09-19 20:51:40.160810500 +0200 -+++ linux-2.6.17/arch/arm/mach-pxa/Kconfig 2006-09-19 21:08:04.926354500 +0200 -@@ -110,6 +110,7 @@ config MACH_TOSA - bool "Enable Sharp SL-6000x (Tosa) Support" - depends PXA_SHARPSL_25x - select TOSHIBA_TC6393XB -+ select SHARPSL_PM - - config PXA25x - bool diff --git a/packages/linux/linux-rp-2.6.23/tosa-pxaac97-r6-fix-r0.patch b/packages/linux/linux-rp-2.6.23/tosa-pxaac97-r6-fix-r0.patch index 6f6f540eff..9c18aae98d 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-pxaac97-r6-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-pxaac97-r6-fix-r0.patch @@ -27,32 +27,3 @@ index 059fa07..61536d4 100644 -- 1.4.4.4 -From 005693333f4b3e0495bb80cc3cfd812e3e6f0a30 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 00:48:42 +0400 -Subject: [PATCH] tosa-pxaac97-r6.patch fixes - ---- - arch/arm/mach-pxa/tosa.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c -index 059fa07..61536d4 100644 ---- a/arch/arm/mach-pxa/tosa.c -+++ b/arch/arm/mach-pxa/tosa.c -@@ -310,10 +310,10 @@ static void __init tosa_init(void) - PMCR = 0x01; - - // AC97 Disable all IRQ's -- pxa_set_cken(CKEN2_AC97, 1); -+ pxa_set_cken(CKEN_AC97, 1); - GCR &= ~(GCR_CDONE_IE | GCR_SDONE_IE | GCR_SECRDY_IEN | GCR_PRIRDY_IEN | GCR_SECRES_IEN | GCR_PRIRES_IEN); - GSR = GSR; -- pxa_set_cken(CKEN2_AC97, 0); -+ pxa_set_cken(CKEN_AC97, 0); - - pxa_set_mci_info(&tosa_mci_platform_data); - pxa_set_udc_info(&udc_info); --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch b/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch index 73913bccc8..a2e2bee151 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10-fix-r0.patch @@ -33,38 +33,3 @@ index eeeee3e..d52f63f 100644 -- 1.4.4.4 -From bb3ed6577c592d86f0976a92978c9454bbdfbe59 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Fri, 19 Oct 2007 02:01:23 +0400 -Subject: [PATCH] tosa-tmio-lcd-r10.patch fixes - ---- - arch/arm/mach-pxa/tosa_lcd.c | 5 +++-- - 1 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/mach-pxa/tosa_lcd.c b/arch/arm/mach-pxa/tosa_lcd.c -index eeeee3e..d52f63f 100644 ---- a/arch/arm/mach-pxa/tosa_lcd.c -+++ b/arch/arm/mach-pxa/tosa_lcd.c -@@ -66,7 +66,7 @@ static unsigned short normal_i2c[] = { - }; - I2C_CLIENT_INSMOD; - --static struct corgibl_machinfo tosa_bl_machinfo = { -+static struct generic_bl_info tosa_bl_machinfo = { - .max_intensity = 255, - .default_intensity = 68, - .limit_mask = 0x0b, -@@ -80,7 +80,8 @@ int tosa_bl_intensity(void) - - static void pxa_nssp_output(unsigned char reg, unsigned char data) - { -- unsigned long flag, dummy; -+ unsigned long flag; -+ u32 dummy; - u32 dat = ( ((reg << 5) & 0xe0) | (data & 0x1f) ); - spin_lock_irqsave(&tosa_nssp_lock, flag); - --- -1.4.4.4 - diff --git a/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10.patch b/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10.patch index cd24cc6cdc..fe5c45d249 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-tmio-lcd-r10.patch @@ -462,467 +462,3 @@ Index: git/arch/arm/mach-pxa/Kconfig config PXA25x bool - arch/arm/mach-pxa/Kconfig | 5 - arch/arm/mach-pxa/Makefile | 2 - arch/arm/mach-pxa/tosa.c | 49 +++++- - arch/arm/mach-pxa/tosa_lcd.c | 344 +++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 396 insertions(+), 4 deletions(-) - -Index: git/arch/arm/mach-pxa/Makefile -=================================================================== ---- git.orig/arch/arm/mach-pxa/Makefile 2006-11-07 22:13:10.000000000 +0000 -+++ git/arch/arm/mach-pxa/Makefile 2006-11-07 23:29:38.000000000 +0000 -@@ -17,7 +17,7 @@ obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o - obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o - obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o - obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o --obj-$(CONFIG_MACH_TOSA) += tosa.o sharpsl_pm.o tosa_pm.o -+obj-$(CONFIG_MACH_TOSA) += tosa.o sharpsl_pm.o tosa_pm.o tosa_lcd.o - obj-$(CONFIG_MACH_EM_X270) += em-x270.o - obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o - -Index: git/arch/arm/mach-pxa/tosa_lcd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/arch/arm/mach-pxa/tosa_lcd.c 2006-11-07 23:29:25.000000000 +0000 -@@ -0,0 +1,344 @@ -+/* -+ * LCD / Backlight control code for Sharp SL-6000x (tosa) -+ * -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/i2c.h> -+#include <linux/fb.h> -+ -+#include <asm/mach/sharpsl_param.h> -+#include <asm/hardware.h> -+#include <asm/hardware/scoop.h> -+#include <asm/hardware/tmio.h> -+#include <asm/arch/ssp.h> -+#include <asm/arch/sharpsl.h> -+#include <asm/arch/tosa.h> -+#include <asm/arch/pxa-regs.h> -+ -+#define DAC_BASE 0x4e -+#define DAC_CH1 0 -+#define DAC_CH2 1 -+ -+#define TG_REG0_VQV 0x0001 -+#define TG_REG0_COLOR 0x0002 -+#define TG_REG0_UD 0x0004 -+#define TG_REG0_LR 0x0008 -+#define COMADJ_DEFAULT 97 -+#define TOSA_LCD_I2C_DEVICEID 0x4711 // Fixme: new value -+ -+static void tosa_lcd_tg_init(struct device *dev); -+static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode); -+static void tosa_lcd_tg_off(struct device *dev); -+static void tosa_set_backlight(int intensity); -+ -+const static struct tmio_lcd_ops tosa_tc6393_lcd_ops = { -+ .init = tosa_lcd_tg_init, -+ .tg_on = tosa_lcd_tg_on, -+ .tg_off = tosa_lcd_tg_off, -+}; -+ -+static struct platform_device *tosabl_device; -+static struct i2c_driver tosa_driver; -+static struct i2c_client* tosa_i2c_dac; -+static int initialised; -+static int comadj; -+static int bl_intensity; -+static struct ssp_dev tosa_nssp_dev; -+static struct ssp_state tosa_nssp_state; -+static spinlock_t tosa_nssp_lock; -+ -+static unsigned short normal_i2c[] = { -+ DAC_BASE, -+ I2C_CLIENT_END -+}; -+I2C_CLIENT_INSMOD; -+ -+static struct corgibl_machinfo tosa_bl_machinfo = { -+ .max_intensity = 255, -+ .default_intensity = 68, -+ .limit_mask = 0x0b, -+ .set_bl_intensity = tosa_set_backlight, -+}; -+ -+int tosa_bl_intensity(void) -+{ -+ return bl_intensity; -+} -+ -+static void pxa_nssp_output(unsigned char reg, unsigned char data) -+{ -+ unsigned long flag, dummy; -+ u32 dat = ( ((reg << 5) & 0xe0) | (data & 0x1f) ); -+ spin_lock_irqsave(&tosa_nssp_lock, flag); -+ -+ ssp_config(&tosa_nssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(128)); -+ ssp_enable(&tosa_nssp_dev); -+ -+ ssp_write_word(&tosa_nssp_dev,dat); -+ -+ /* Read null data back from device to prevent SSP overflow */ -+ ssp_read_word(&tosa_nssp_dev, &dummy); -+ ssp_disable(&tosa_nssp_dev); -+ spin_unlock_irqrestore(&tosa_nssp_lock, flag); -+ -+} -+ -+static void tosa_set_backlight(int intensity) -+{ -+ if (!tosa_i2c_dac) -+ return; -+ -+ bl_intensity = intensity; -+ /* SetBacklightDuty */ -+ i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH2, (unsigned char)intensity); -+ -+ /* SetBacklightVR */ -+ if (intensity) -+ set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BL_C20MA); -+ else -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_BL_C20MA); -+ -+ /* bl_enable GP04=1 otherwise GP04=0*/ -+ pxa_nssp_output(TG_GPODR2, intensity ? 0x01 : 0x00); -+} -+ -+static void tosa_lcd_tg_init(struct device *dev) -+{ -+ /* L3V On */ -+ set_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); -+ mdelay(60); -+ -+ /* TG On */ -+ reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_TG_ON); -+ mdelay(60); -+ -+ pxa_nssp_output(TG_TPOSCTL,0x00); /* delayed 0clk TCTL signal for VGA */ -+ pxa_nssp_output(TG_GPOSR,0x02); /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */ -+} -+ -+static void tosa_lcd_tg_on(struct device *dev, const struct fb_videomode *mode) -+{ -+ const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR; -+ pxa_nssp_output(TG_PNLCTL, value | (mode->yres == 320 ? 0 : TG_REG0_VQV)); -+ -+ /* TG LCD pannel power up */ -+ pxa_nssp_output(TG_PINICTL,0x4); -+ mdelay(50); -+ -+ /* TG LCD GVSS */ -+ pxa_nssp_output(TG_PINICTL,0x0); -+ -+ if (!initialised) -+ { -+ /* after the pannel is powered up the first time, we can access the i2c bus */ -+ /* so probe for the DAC */ -+ i2c_add_driver(&tosa_driver); -+ initialised = 1; -+ mdelay(50); -+ } -+ if (tosa_i2c_dac) -+ /* set common voltage */ -+ i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj); -+ -+} -+ -+static void tosa_lcd_tg_off(struct device *dev) -+{ -+ /* TG LCD VHSA off */ -+ pxa_nssp_output(TG_PINICTL,0x4); -+ mdelay(50); -+ -+ /* TG LCD signal off */ -+ pxa_nssp_output(TG_PINICTL,0x6); -+ mdelay(50); -+ -+ /* TG Off */ -+ set_tc6393_gpio(&tc6393_device.dev, TOSA_TC6393_TG_ON); -+ mdelay(100); -+ -+ /* L3V Off */ -+ reset_scoop_gpio( &tosascoop_jc_device.dev,TOSA_SCOOP_JC_TC3693_L3V_ON); -+} -+ -+static int tosa_detect_client(struct i2c_adapter* adapter, int address, int kind) { -+ int err = 0; -+ -+ printk("Tosa-LCD: DAC detected address:0x%2.2x\n",address); -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA )) -+ goto ERROR0; -+ -+ if (!(tosa_i2c_dac = (struct i2c_client*)kzalloc(sizeof(*tosa_i2c_dac), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto ERROR0; -+ } -+ -+ //i2c_set_clientdata(tosa_i2c_dac, data); -+ tosa_i2c_dac->addr = address; -+ tosa_i2c_dac->adapter = adapter; -+ tosa_i2c_dac->driver = &tosa_driver; -+ tosa_i2c_dac->dev.parent = &tc6393_device.dev; -+ strcpy(tosa_i2c_dac->name, "tosa lcd"); -+ if ((err = i2c_attach_client(tosa_i2c_dac))) -+ goto ERROR3; -+ -+ /* Now i2c is ready, allocate the backlight device*/ -+ tosabl_device = platform_device_alloc("corgi-bl", -1); -+ if (!tosabl_device) { -+ err = -ENOMEM; -+ goto ERROR4; -+ } -+ -+ /* set parent device */ -+ tosabl_device->dev.parent = &tosa_i2c_dac->dev; -+ tosabl_device->dev.platform_data = &tosa_bl_machinfo; -+ -+ err = platform_device_add(tosabl_device); -+ -+ if (err) -+ platform_device_put(tosabl_device); -+ -+ /* set common voltage */ -+ i2c_smbus_write_byte_data(tosa_i2c_dac, DAC_CH1, comadj); -+ -+ return 0; -+ERROR4: -+ i2c_detach_client(tosa_i2c_dac); -+ERROR3: -+ kfree(tosa_i2c_dac); -+ERROR0: -+ return err; -+} -+ -+static int tosa_attach_adapter(struct i2c_adapter* adapter) { -+ return i2c_probe(adapter, &addr_data, &tosa_detect_client); -+} -+ -+static int tosa_detach_client(struct i2c_client* client) { -+ int err; -+ -+ if ((err = i2c_detach_client(client))) { -+ printk(KERN_ERR "tosa: Cannot deregister client\n"); -+ return err; -+ } -+ kfree(client); -+ return 0; -+} -+ -+static struct i2c_driver tosa_driver={ -+ .id = TOSA_LCD_I2C_DEVICEID, -+ .attach_adapter = tosa_attach_adapter, -+ .detach_client = tosa_detach_client, -+}; -+ -+static int __init tosa_lcd_probe(struct platform_device *pdev) -+{ -+ int ret; -+ spin_lock_init(&tosa_nssp_lock); -+ -+ if (!pdev->dev.platform_data) -+ return -EINVAL; -+ -+ /* Set Common Voltage */ -+ comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; -+ -+ ret=ssp_init(&tosa_nssp_dev,2,0); -+ -+ /* initialize SSP */ -+ pxa_gpio_mode(GPIO83_NSSP_TX); -+ pxa_gpio_mode(GPIO81_NSSP_CLK_OUT); -+ pxa_gpio_mode(GPIO82_NSSP_FRM_OUT); -+ -+ if (ret) -+ printk(KERN_ERR "Unable to register NSSP handler!\n"); -+ else { -+ struct tmio_lcd_ops* *tmio_ops = pdev->dev.platform_data; -+ ssp_disable(&tosa_nssp_dev); -+ initialised = 0; -+ -+ /* Set the lcd functions */ -+ *tmio_ops = (struct tmio_lcd_ops*) &tosa_tc6393_lcd_ops; -+ } -+ -+ return ret; -+} -+ -+static int tosa_lcd_remove(struct platform_device *pdev) -+{ -+ /* delete the lcd functions */ -+ struct tmio_lcd_ops* *tmio_ops = pdev->dev.platform_data; -+ *tmio_ops = NULL; -+ -+ ssp_exit(&tosa_nssp_dev); -+ -+ if (tosa_i2c_dac) { -+ i2c_detach_client(tosa_i2c_dac); -+ kfree(tosa_i2c_dac); -+ } -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+static int tosa_lcd_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ ssp_flush(&tosa_nssp_dev); -+ ssp_save_state(&tosa_nssp_dev,&tosa_nssp_state); -+ return 0; -+} -+ -+static int tosa_lcd_resume(struct platform_device *pdev) -+{ -+ printk("tosa_lcd_resume\n"); -+ ssp_restore_state(&tosa_nssp_dev,&tosa_nssp_state); -+ ssp_enable(&tosa_nssp_dev); -+ printk("tosa_lcd_resume ok\n"); -+ return 0; -+} -+#else -+ -+#define tosa_lcd_suspend NULL -+#define tosa_lcd_resume NULL -+ -+#endif -+ -+ -+static struct platform_driver tosalcd_driver = { -+ .probe = tosa_lcd_probe, -+ .remove = tosa_lcd_remove, -+ .suspend = tosa_lcd_suspend, -+ .resume = tosa_lcd_resume, -+ .driver = { -+ .name = "tosa-lcd", -+ }, -+}; -+ -+static int __init tosa_lcd_init(void) -+{ -+ return platform_driver_register(&tosalcd_driver); -+} -+ -+static void __exit tosa_lcd_cleanup (void) -+{ -+ platform_driver_unregister (&tosalcd_driver); -+} -+ -+device_initcall(tosa_lcd_init); -+module_exit (tosa_lcd_cleanup); -+ -+MODULE_DESCRIPTION ("Tosa LCD device"); -+MODULE_AUTHOR ("Dirk Opfer"); -+MODULE_LICENSE ("GPL v2"); -Index: git/arch/arm/mach-pxa/tosa.c -=================================================================== ---- git.orig/arch/arm/mach-pxa/tosa.c 2006-11-07 22:13:10.000000000 +0000 -+++ git/arch/arm/mach-pxa/tosa.c 2006-11-07 23:29:38.000000000 +0000 -@@ -24,6 +24,7 @@ - #include <linux/mtd/partitions.h> - #include <linux/pm.h> - #include <linux/delay.h> -+#include <linux/fb.h> - - #include <asm/setup.h> - #include <asm/memory.h> -@@ -345,7 +345,38 @@ static struct tmio_nand_platform_data to - .badblock_pattern = &tosa_tc6393_nand_bbt, - }; - --extern struct tmio_lcd_platform_data tosa_tc6393_lcd_platform_data; -+static struct fb_videomode tosa_tc6393_lcd_mode[] = { -+ { -+ .xres = 480, -+ .yres = 640, -+ .pixclock = 0x002cdf00,/* PLL divisor */ -+ .left_margin = 0x004c, -+ .right_margin = 0x005b, -+ .upper_margin = 0x0001, -+ .lower_margin = 0x000d, -+ .hsync_len = 0x0002, -+ .vsync_len = 0x0001, -+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, -+ .vmode = FB_VMODE_NONINTERLACED, -+ },{ -+ .xres = 240, -+ .yres = 320, -+ .pixclock = 0x00e7f203,/* PLL divisor */ -+ .left_margin = 0x0024, -+ .right_margin = 0x002f, -+ .upper_margin = 0x0001, -+ .lower_margin = 0x000d, -+ .hsync_len = 0x0002, -+ .vsync_len = 0x0001, -+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, -+ .vmode = FB_VMODE_NONINTERLACED, -+}}; -+ -+struct tmio_lcd_platform_data tosa_tc6393_lcd_platform_data = { -+ .ops = NULL, -+ .modelist = tosa_tc6393_lcd_mode, -+ .num_modes = ARRAY_SIZE(tosa_tc6393_lcd_mode), -+}; - - static struct tmio_cell tosa_tc6393_cells[] = { - { -@@ -384,6 +415,19 @@ struct platform_device tc6393_device = { - .num_resources = ARRAY_SIZE(tc6393_resources), - .resource = tc6393_resources, - }; -+EXPORT_SYMBOL (tc6393_device); -+ -+/* -+ * Tosa LCD / Backlight stuff -+ */ -+static struct platform_device tosalcd_device = { -+ .name = "tosa-lcd", -+ .id = -1, -+ .dev = { -+ .parent = &tc6393_device.dev, -+ .platform_data = &tosa_tc6393_lcd_platform_data.ops, -+ }, -+}; - - static struct platform_device *devices[] __initdata = { - &tosascoop_device, -@@ -391,6 +435,7 @@ static struct platform_device *devices[] - &tosakbd_device, - &tosaled_device, - &tc6393_device, -+ &tosalcd_device, - }; - - static void tosa_poweroff(void) -Index: git/arch/arm/mach-pxa/Kconfig -=================================================================== ---- git.orig/arch/arm/mach-pxa/Kconfig 2006-11-07 22:13:10.000000000 +0000 -+++ git/arch/arm/mach-pxa/Kconfig 2006-11-07 22:13:10.000000000 +0000 -@@ -129,7 +129,10 @@ config MACH_TOSA - bool "Enable Sharp SL-6000x (Tosa) Support" - depends PXA_SHARPSL_25x - select TOSHIBA_TC6393XB -- select SHARPSL_PM -+ select I2C -+ select I2C_PXA -+ select SHARPSL_PM -+ select PXA_SSP - - config PXA25x - bool diff --git a/packages/linux/linux-rp-2.6.23/wm9712-reset-loop-r2.patch b/packages/linux/linux-rp-2.6.23/wm9712-reset-loop-r2.patch index 0e32a62ea6..78e81ea83a 100644 --- a/packages/linux/linux-rp-2.6.23/wm9712-reset-loop-r2.patch +++ b/packages/linux/linux-rp-2.6.23/wm9712-reset-loop-r2.patch @@ -42,47 +42,3 @@ Index: git/sound/soc/codecs/wm9712.c printk(KERN_ERR "WM9712 AC97 reset failed\n"); return -EIO; } - sound/soc/codecs/wm9712.c | 28 ++++++++++++++++++---------- - 1 file changed, 18 insertions(+), 10 deletions(-) - -Index: git/sound/soc/codecs/wm9712.c -=================================================================== ---- git.orig/sound/soc/codecs/wm9712.c 2006-11-07 22:10:01.000000000 +0000 -+++ git/sound/soc/codecs/wm9712.c 2006-11-07 22:11:50.000000000 +0000 -@@ -618,18 +618,26 @@ static int wm9712_dapm_event(struct snd_ - - static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) - { -- if (try_warm && soc_ac97_ops.warm_reset) { -- soc_ac97_ops.warm_reset(codec->ac97); -- if (!(ac97_read(codec, 0) & 0x8000)) -- return 1; -- } -+ int retry = 3; - -- soc_ac97_ops.reset(codec->ac97); -- if (ac97_read(codec, 0) & 0x8000) -- goto err; -- return 0; -+ while (retry--) -+ { -+ if(try_warm && soc_ac97_ops.warm_reset) { -+ soc_ac97_ops.warm_reset(codec->ac97); -+ if(ac97_read(codec, 0) & 0x8000) -+ continue; -+ else -+ return 1; -+ } -+ -+ soc_ac97_ops.reset(codec->ac97); -+ if(ac97_read(codec, 0) & 0x8000) -+ continue; -+ else -+ return 0; -+ -+ } - --err: - printk(KERN_ERR "WM9712 AC97 reset failed\n"); - return -EIO; - } diff --git a/packages/linux/linux-rp-2.6.23/wm9712-suspend-cold-res-r2.patch b/packages/linux/linux-rp-2.6.23/wm9712-suspend-cold-res-r2.patch index cbf854d772..5179b47cc4 100644 --- a/packages/linux/linux-rp-2.6.23/wm9712-suspend-cold-res-r2.patch +++ b/packages/linux/linux-rp-2.6.23/wm9712-suspend-cold-res-r2.patch @@ -14,19 +14,3 @@ Index: git/sound/soc/codecs/wm9712.c if (ret < 0){ printk(KERN_ERR "could not reset AC97 codec\n"); return ret; - sound/soc/codecs/wm9712.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: git/sound/soc/codecs/wm9712.c -=================================================================== ---- git.orig/sound/soc/codecs/wm9712.c 2006-11-07 21:57:34.000000000 +0000 -+++ git/sound/soc/codecs/wm9712.c 2006-11-07 21:59:30.000000000 +0000 -@@ -651,7 +651,7 @@ static int wm9712_soc_resume(struct plat - int i, ret; - u16 *cache = codec->reg_cache; - -- ret = wm9712_reset(codec, 1); -+ ret = wm9712_reset(codec, 0); - if (ret < 0){ - printk(KERN_ERR "could not reset AC97 codec\n"); - return ret; diff --git a/packages/linux/linux-rp-2.6.23/wm97xx-lcdnoise-r0.patch b/packages/linux/linux-rp-2.6.23/wm97xx-lcdnoise-r0.patch deleted file mode 100644 index 191de3af22..0000000000 --- a/packages/linux/linux-rp-2.6.23/wm97xx-lcdnoise-r0.patch +++ /dev/null @@ -1,208 +0,0 @@ -Index: linux-tosa/drivers/input/touchscreen/wm9712.c -=================================================================== ---- linux-tosa.orig/drivers/input/touchscreen/wm9712.c 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/drivers/input/touchscreen/wm9712.c 2006-08-29 16:52:50.923275896 +0100 -@@ -1,7 +1,7 @@ - /* - * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. - * -- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC. -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com - * Parts Copyright : Ian Molton <spyro@f2s.com> -@@ -13,6 +13,12 @@ - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * -+ * Revision history -+ * 4th Jul 2005 Initial version. -+ * 29th Aug 2006 Mike Arthur <mike@mikearthur.co.uk> -+ * Added fixes for Sharp SL-6000 (Tosa) LCD noise causing -+ * touchscreen interference. -+ * - */ - - #include <linux/module.h> -@@ -28,6 +34,10 @@ - #define WM9705_VERSION "0.60" - #define DEFAULT_PRESSURE 0xb0c0 - -+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -+#define CCNT_ON() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+#define CCNT_OFF() asm("mcr p14, 0, %0, C0, C0, 0" : : "r"(1)) -+ - /* - * Debug - */ -@@ -243,6 +253,36 @@ - return wm->dig[2] & WM9712_PDEN; - } - -+ -+#ifdef CONFIG_MACH_TOSA -+/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait -+ * before sampling the Y axis of the touchscreen */ -+static inline void wm9712_lcd_sync_on(struct wm97xx* wm, int adcsel) { -+ unsigned long timer1 = 0, timer2 = 0, wait_time = 0; -+ if (adcsel == WM97XX_ADCSEL_Y) { -+ wait_time = wm97xx_calc_lcd_waittime(wm); -+ -+ CCNT_ON(); -+ -+ if (wait_time) { -+ /* wait for LCD rising edge */ -+ wm_machinfo->wait_hsync(); -+ /* get clock */ -+ CCNT(timer1); -+ CCNT(timer2); -+ -+ while ((timer2 - timer1) < wait_time) { -+ CCNT(timer2); -+ } -+ } -+ } -+} -+ -+static inline void wm9712_lcd_sync_off(void) { -+ CCNT_OFF(); -+} -+#endif -+ - /* - * Read a sample from the WM9712 adc in polling mode. - */ -@@ -260,6 +300,9 @@ - /* set up digitiser */ - if (adcsel & 0x8000) - adcsel = ((adcsel & 0x7fff) + 3) << 12; -+ #ifdef CONFIG_MACH_TOSA -+ wm9712_lcd_sync_on(wm, adcsel); -+ #endif - wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); - - /* wait 3 AC97 time slots + delay for conversion */ -@@ -282,6 +325,10 @@ - - *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); - -+ #ifdef CONFIG_MACH_TOSA -+ wm9712_lcd_sync_off(); -+ #endif -+ - /* check we have correct sample */ - if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { - dbg ("adc wrong sample, read %x got %x", adcsel, -@@ -303,11 +350,12 @@ - static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data) - { - int rc; -- - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID) - return rc; -+ - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID) - return rc; -+ - if (pil && !five_wire) { - if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID) - return rc; -Index: linux-tosa/drivers/input/touchscreen/wm97xx-core.c -=================================================================== ---- linux-tosa.orig/drivers/input/touchscreen/wm97xx-core.c 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/drivers/input/touchscreen/wm97xx-core.c 2006-08-29 16:52:50.924275744 +0100 -@@ -2,7 +2,7 @@ - * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712 - * and WM9713 AC97 Codecs. - * -- * Copyright 2003, 2004, 2005 Wolfson Microelectronics PLC. -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com - * Parts Copyright : Ian Molton <spyro@f2s.com> -@@ -67,6 +67,9 @@ - * GPIOs) and 2.6 power management. - * 29th Nov 2004 Added WM9713 support. - * 4th Jul 2005 Moved codec specific code out to seperate files. -+ * 29th Aug 2006 Mike Arthur <mike@mikearthur.co.uk> -+ * Added fixes for Sharp SL-6000 (Tosa) LCD noise causing -+ * touchscreen interference. - */ - - #include <linux/module.h> -@@ -94,6 +97,7 @@ - static DECLARE_MUTEX(gpio_sem); - static LIST_HEAD(wm97xx_misc_list); - static struct wm97xx* wm_codec = NULL; -+struct wm97xx_machinfo *wm_machinfo; - - /* - * WM97xx - enable/disable AUX ADC sysfs -@@ -832,6 +836,23 @@ - mdev->remove(wm_codec); - } - -+#ifdef CONFIG_MACH_TOSA -+/* On the Sharp SL-6000 (Tosa), due to a noisy LCD, we need to perform a wait -+ * before sampling the Y axis of the touchscreen */ -+unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm) { -+ unsigned long hsync_time = wm_machinfo->get_hsync_time(); -+ return hsync_time; -+} -+ -+void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo) { -+ wm_machinfo = machinfo; -+} -+ -+void wm97xx_unset_machinfo() { -+ wm_machinfo = NULL; -+} -+#endif -+ - static struct device_driver wm97xx_driver = { - .name = "ac97", - .bus = &ac97_bus_type, -@@ -861,6 +882,9 @@ - EXPORT_SYMBOL_GPL(wm97xx_reg_write); - EXPORT_SYMBOL_GPL(wm97xx_register_misc_dev); - EXPORT_SYMBOL_GPL(wm97xx_unregister_misc_dev); -+EXPORT_SYMBOL_GPL(wm97xx_calc_lcd_waittime); -+EXPORT_SYMBOL_GPL(wm97xx_set_machinfo); -+EXPORT_SYMBOL_GPL(wm97xx_unset_machinfo); - - module_init(wm97xx_init); - module_exit(wm97xx_exit); -Index: linux-tosa/include/linux/wm97xx.h -=================================================================== ---- linux-tosa.orig/include/linux/wm97xx.h 2006-08-29 16:52:36.008543280 +0100 -+++ linux-tosa/include/linux/wm97xx.h 2006-08-29 16:52:50.924275744 +0100 -@@ -207,6 +207,7 @@ - - struct wm97xx; - extern struct wm97xx_codec_drv wm97xx_codec; -+extern struct wm97xx_machinfo *wm_machinfo; - - /* - * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs -@@ -253,6 +254,11 @@ - struct list_head list; - }; - -+struct wm97xx_machinfo { -+ unsigned long (*get_hsync_time)(void); -+ void (*wait_hsync)(void); -+}; -+ - int wm97xx_register_misc_dev(struct wm97xx_misc_dev* mdev); - void wm97xx_unregister_misc_dev(struct wm97xx_misc_dev* mdev); - -@@ -281,4 +287,9 @@ - int wm97xx_acc_startup(struct wm97xx* wm); - void wm97xx_acc_shutdown(struct wm97xx* wm); - -+ -+unsigned long wm97xx_calc_lcd_waittime(struct wm97xx *wm); -+void wm97xx_set_machinfo(struct wm97xx_machinfo *machinfo); -+void wm97xx_unset_machinfo(void); -+ - #endif diff --git a/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0-fix-r0.patch b/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0-fix-r0.patch index f246fbfed5..5ad0d8703d 100644 --- a/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0-fix-r0.patch +++ b/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0-fix-r0.patch @@ -126,131 +126,3 @@ index b1c1740..a9bd57e 100644 struct device *dev; /* ALSA device */ struct device *battery_dev; struct device *touch_dev; - drivers/input/power.c | 2 +- - drivers/input/touchscreen/Kconfig | 2 +- - drivers/input/touchscreen/wm97xx-core.c | 35 ++++++++++++++++--------------- - include/linux/wm97xx.h | 2 +- - 4 files changed, 21 insertions(+), 20 deletions(-) - -diff --git a/drivers/input/power.c b/drivers/input/power.c -index 4443e34..7aac875 100644 ---- a/drivers/input/power.c -+++ b/drivers/input/power.c -@@ -156,7 +156,7 @@ static void power_event(struct input_handle *handle, unsigned int type, - } - } - --static struct input_handle *power_connect(struct input_handler *handler, -+static int power_connect(struct input_handler *handler, - struct input_dev *dev, - const struct input_device_id *id) - { -diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index 6862e8f..9b532e9 100644 ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -247,7 +247,7 @@ config TOUCHSCREEN_TSC2101 - - config TOUCHSCREEN_WM97XX - tristate "Support for WM97xx AC97 touchscreen controllers" -- depends SND_AC97_BUS -+ depends AC97_BUS - - choice - prompt "WM97xx codec type" -diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c -index 9b2710e..d3ce3f3 100644 ---- a/drivers/input/touchscreen/wm97xx-core.c -+++ b/drivers/input/touchscreen/wm97xx-core.c -@@ -84,6 +84,7 @@ - #include <linux/bitops.h> - #include <linux/workqueue.h> - #include <linux/device.h> -+#include <linux/freezer.h> - #include <linux/wm97xx.h> - #include <asm/uaccess.h> - #include <asm/io.h> -@@ -241,14 +242,15 @@ WM97XX_STATUS_ATTR(gpio); - - static int wm97xx_sys_add(struct device *dev) - { -+ int err; - if (aux_sys) { -- device_create_file(dev, &dev_attr_aux1); -- device_create_file(dev, &dev_attr_aux2); -- device_create_file(dev, &dev_attr_aux3); -- device_create_file(dev, &dev_attr_aux4); -+ err = device_create_file(dev, &dev_attr_aux1); -+ err = device_create_file(dev, &dev_attr_aux2); -+ err = device_create_file(dev, &dev_attr_aux3); -+ err = device_create_file(dev, &dev_attr_aux4); - } - if (status_sys) -- device_create_file(dev, &dev_attr_gpio); -+ err = device_create_file(dev, &dev_attr_gpio); - return 0; - } - -@@ -366,12 +368,12 @@ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir, - - /* - * Handle a pen down interrupt. -- */ --static void wm97xx_pen_irq_worker(void *ptr) --{ -- struct wm97xx *wm = (struct wm97xx *) ptr; -- -- /* do we need to enable the touch panel reader */ -+ */ -+static void wm97xx_pen_irq_worker(struct work_struct *work) -+{ -+ struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work); -+ -+ /* do we need to enable the touch panel reader */ - if (wm->id == WM9705_ID2) { - if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN) - wm->pen_is_down = 1; -@@ -411,9 +413,8 @@ static void wm97xx_pen_irq_worker(void *ptr) - * We have to disable the codec interrupt in the handler because it can - * take upto 1ms to clear the interrupt source. The interrupt is then enabled - * again in the slow handler when the source has been cleared. -- */ --static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id, -- struct pt_regs *regs) -+ */ -+static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id) - { - struct wm97xx *wm = (struct wm97xx *) dev_id; - disable_irq(wm->pen_irq); -@@ -428,15 +429,15 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm) - { - u16 reg; - -- INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker, wm); -- if ((wm->pen_irq_workq = -+ INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker); -+ if ((wm->pen_irq_workq = - create_singlethread_workqueue("kwm97pen")) == NULL) { - err("could not create pen irq work queue"); - wm->pen_irq = 0; - return -EINVAL; - } - -- if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) { -+ if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED, "wm97xx-pen", wm)) { - err("could not register codec pen down interrupt, will poll for pen down"); - destroy_workqueue(wm->pen_irq_workq); - wm->pen_irq = 0; -diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h -index b1c1740..a9bd57e 100644 ---- a/include/linux/wm97xx.h -+++ b/include/linux/wm97xx.h -@@ -243,7 +243,7 @@ struct wm97xx { - u16 dig_save[3]; /* saved during aux reading */ - struct wm97xx_codec_drv *codec; /* attached codec driver*/ - struct input_dev* input_dev; /* touchscreen input device */ -- ac97_t *ac97; /* ALSA codec access */ -+ struct snd_ac97 *ac97; /* ALSA codec access */ - struct device *dev; /* ALSA device */ - struct device *battery_dev; - struct device *touch_dev; diff --git a/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch b/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch index b029ccc066..c918c5daff 100644 --- a/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch +++ b/packages/linux/linux-rp-2.6.23/wm97xx-lg13-r0.patch @@ -2897,2902 +2897,3 @@ Index: linux-2.6.17/include/linux/wm97xx.h + +extern struct bus_type wm97xx_bus_type; +#endif -Index: linux-2.6.17/drivers/input/touchscreen/Kconfig -=================================================================== ---- linux-2.6.17.orig/drivers/input/touchscreen/Kconfig 2006-09-19 20:35:35.060495500 +0200 -+++ linux-2.6.17/drivers/input/touchscreen/Kconfig 2006-09-19 20:36:47.965051750 +0200 -@@ -121,4 +121,57 @@ config TOUCHSCREEN_TSC2101 - To compile this driver as a module, choose M here: the - module will be called ads7846_ts. - -+config TOUCHSCREEN_WM97XX -+ tristate "Support for WM97xx AC97 touchscreen controllers" -+ depends SND_AC97_BUS -+ -+choice -+ prompt "WM97xx codec type" -+ -+config TOUCHSCREEN_WM9705 -+ bool "WM9705 Touchscreen interface support" -+ depends on TOUCHSCREEN_WM97XX -+ help -+ Say Y here if you have the wm9705 touchscreen. -+ -+ If unsure, say N. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called wm9705. -+ -+config TOUCHSCREEN_WM9712 -+ bool "WM9712 Touchscreen interface support" -+ depends on TOUCHSCREEN_WM97XX -+ help -+ Say Y here if you have the wm9712 touchscreen. -+ -+ If unsure, say N. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called wm9712. -+ -+config TOUCHSCREEN_WM9713 -+ bool "WM9713 Touchscreen interface support" -+ depends on TOUCHSCREEN_WM97XX -+ help -+ Say Y here if you have the wm9713 touchscreen. -+ -+ If unsure, say N. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called wm9713. -+ -+endchoice -+ -+config TOUCHSCREEN_WM97XX_PXA -+ tristate "WM97xx PXA accelerated touch" -+ depends on TOUCHSCREEN_WM97XX && ARCH_PXA -+ help -+ Say Y here for continuous mode touch on the PXA -+ -+ If unsure, say N -+ -+ To compile this driver as a module, choose M here: the -+ module will be called pxa-wm97xx -+ - endif -Index: linux-2.6.17/drivers/input/touchscreen/Makefile -=================================================================== ---- linux-2.6.17.orig/drivers/input/touchscreen/Makefile 2006-09-19 20:35:35.072496250 +0200 -+++ linux-2.6.17/drivers/input/touchscreen/Makefile 2006-09-19 20:37:40.540337500 +0200 -@@ -4,6 +4,8 @@ - - # Each configuration option enables a list of files. - -+wm97xx-ts-objs := wm97xx-core.o -+ - obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o - obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o - obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o -@@ -13,3 +15,16 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtou - obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o - obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o - obj-$(CONFIG_TOUCHSCREEN_TSC2101) += tsc2101_ts.o -+obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o -+obj-$(CONFIG_TOUCHSCREEN_WM97XX_PXA) += pxa-wm97xx.o -+ -+ifeq ($(CONFIG_TOUCHSCREEN_WM9713),y) -+wm97xx-ts-objs += wm9713.o -+endif -+ -+ifeq ($(CONFIG_TOUCHSCREEN_WM9712),y) -+wm97xx-ts-objs += wm9712.o -+endif -+ifeq ($(CONFIG_TOUCHSCREEN_WM9705),y) -+wm97xx-ts-objs += wm9705.o -+endif -Index: linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/drivers/input/touchscreen/pxa-wm97xx.c 2006-09-19 20:36:47.965051750 +0200 -@@ -0,0 +1,289 @@ -+/* -+ * pxa-wm97xx.c -- pxa-wm97xx Continuous Touch screen driver for -+ * Wolfson WM97xx AC97 Codecs. -+ * -+ * Copyright 2004 Wolfson Microelectronics PLC. -+ * Author: Liam Girdwood -+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com -+ * Parts Copyright : Ian Molton <spyro@f2s.com> -+ * Andrew Zabolotny <zap@homelink.ru> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Notes: -+ * This is a wm97xx extended touch driver to capture touch -+ * data in a continuous manner on the Intel XScale archictecture -+ * -+ * Features: -+ * - codecs supported:- WM9705, WM9712, WM9713 -+ * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x -+ * -+ * Revision history -+ * 18th Aug 2004 Initial version. -+ * 26th Jul 2005 Improved continous read back and added FIFO flushing. -+ * 06th Sep 2005 Mike Arthur <linux@wolfsonmicro.com> -+ * Moved to using the wm97xx bus -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/version.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/irq.h> -+#include <linux/wm97xx.h> -+#include <asm/io.h> -+#include <asm/arch/pxa-regs.h> -+ -+#define VERSION "0.13" -+ -+struct continuous { -+ u16 id; /* codec id */ -+ u8 code; /* continuous code */ -+ u8 reads; /* number of coord reads per read cycle */ -+ u32 speed; /* number of coords per second */ -+}; -+ -+#define WM_READS(sp) ((sp / HZ) + 1) -+ -+static const struct continuous cinfo[] = { -+ {WM9705_ID2, 0, WM_READS(94), 94}, -+ {WM9705_ID2, 1, WM_READS(188), 188}, -+ {WM9705_ID2, 2, WM_READS(375), 375}, -+ {WM9705_ID2, 3, WM_READS(750), 750}, -+ {WM9712_ID2, 0, WM_READS(94), 94}, -+ {WM9712_ID2, 1, WM_READS(188), 188}, -+ {WM9712_ID2, 2, WM_READS(375), 375}, -+ {WM9712_ID2, 3, WM_READS(750), 750}, -+ {WM9713_ID2, 0, WM_READS(94), 94}, -+ {WM9713_ID2, 1, WM_READS(120), 120}, -+ {WM9713_ID2, 2, WM_READS(154), 154}, -+ {WM9713_ID2, 3, WM_READS(188), 188}, -+}; -+ -+/* continuous speed index */ -+static int sp_idx = 0; -+static u16 last = 0, tries = 0; -+ -+/* -+ * Pen sampling frequency (Hz) in continuous mode. -+ */ -+static int cont_rate = 200; -+module_param(cont_rate, int, 0); -+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); -+ -+/* -+ * Pen down detection. -+ * -+ * This driver can either poll or use an interrupt to indicate a pen down -+ * event. If the irq request fails then it will fall back to polling mode. -+ */ -+static int pen_int = 1; -+module_param(pen_int, int, 0); -+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)"); -+ -+/* -+ * Pressure readback. -+ * -+ * Set to 1 to read back pen down pressure -+ */ -+static int pressure = 0; -+module_param(pressure, int, 0); -+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); -+ -+/* -+ * AC97 touch data slot. -+ * -+ * Touch screen readback data ac97 slot -+ */ -+static int ac97_touch_slot = 5; -+module_param(ac97_touch_slot, int, 0); -+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); -+ -+ -+/* flush AC97 slot 5 FIFO on pxa machines */ -+#ifdef CONFIG_PXA27x -+void wm97xx_acc_pen_up (struct wm97xx* wm) -+{ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ -+ while (MISR & (1 << 2)) -+ MODR; -+} -+#else -+void wm97xx_acc_pen_up (struct wm97xx* wm) -+{ -+ int count = 16; -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ -+ while (count < 16) { -+ MODR; -+ count--; -+ } -+} -+#endif -+ -+int wm97xx_acc_pen_down (struct wm97xx* wm) -+{ -+ u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES; -+ int reads = 0; -+ -+ /* data is never immediately available after pen down irq */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); -+ -+ if (tries > 5){ -+ tries = 0; -+ return RC_PENUP; -+ } -+ -+ x = MODR; -+ if (x == last) { -+ tries++; -+ return RC_AGAIN; -+ } -+ last = x; -+ do { -+ if (reads) -+ x= MODR; -+ y= MODR; -+ if (pressure) -+ p = MODR; -+ -+ /* are samples valid */ -+ if ((x & 0x7000) != WM97XX_ADCSEL_X || -+ (y & 0x7000) != WM97XX_ADCSEL_Y || -+ (p & 0x7000) != WM97XX_ADCSEL_PRES) -+ goto up; -+ -+ /* coordinate is good */ -+ tries = 0; -+ //printk("x %x y %x p %x\n", x,y,p); -+ input_report_abs (wm->input_dev, ABS_X, x & 0xfff); -+ input_report_abs (wm->input_dev, ABS_Y, y & 0xfff); -+ input_report_abs (wm->input_dev, ABS_PRESSURE, p & 0xfff); -+ input_sync (wm->input_dev); -+ reads++; -+ } while (reads < cinfo[sp_idx].reads); -+up: -+ return RC_PENDOWN | RC_AGAIN; -+} -+ -+int wm97xx_acc_startup(struct wm97xx* wm) -+{ -+ int idx = 0; -+ -+ /* check we have a codec */ -+ if (wm->ac97 == NULL) -+ return -ENODEV; -+ -+ /* Go you big red fire engine */ -+ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { -+ if (wm->id != cinfo[idx].id) -+ continue; -+ sp_idx = idx; -+ if (cont_rate <= cinfo[idx].speed) -+ break; -+ } -+ wm->acc_rate = cinfo[sp_idx].code; -+ wm->acc_slot = ac97_touch_slot; -+ printk(KERN_INFO "pxa2xx accelerated touchscreen driver, %d samples (sec)\n", -+ cinfo[sp_idx].speed); -+ -+ /* codec specific irq config */ -+ if (pen_int) { -+ switch (wm->id) { -+ case WM9705_ID2: -+ wm->pen_irq = IRQ_GPIO(4); -+ set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE); -+ break; -+ case WM9712_ID2: -+ case WM9713_ID2: -+ /* enable pen down interrupt */ -+ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ -+ wm->pen_irq = MAINSTONE_AC97_IRQ; -+ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, -+ WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, WM97XX_GPIO_WAKE); -+ wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT, -+ WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE); -+ break; -+ default: -+ printk(KERN_WARNING "pen down irq not supported on this device\n"); -+ pen_int = 0; -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+void wm97xx_acc_shutdown(struct wm97xx* wm) -+{ -+ /* codec specific deconfig */ -+ if (pen_int) { -+ switch (wm->id & 0xffff) { -+ case WM9705_ID2: -+ wm->pen_irq = 0; -+ break; -+ case WM9712_ID2: -+ case WM9713_ID2: -+ /* disable interrupt */ -+ wm->pen_irq = 0; -+ break; -+ } -+ } -+} -+ -+static struct wm97xx_mach_ops pxa_mach_ops = { -+ .acc_enabled = 1, -+ .acc_pen_up = wm97xx_acc_pen_up, -+ .acc_pen_down = wm97xx_acc_pen_down, -+ .acc_startup = wm97xx_acc_startup, -+ .acc_shutdown = wm97xx_acc_shutdown, -+}; -+ -+int pxa_wm97xx_probe(struct device *dev) -+{ -+ struct wm97xx *wm = dev->driver_data; -+ return wm97xx_register_mach_ops (wm, &pxa_mach_ops); -+} -+ -+int pxa_wm97xx_remove(struct device *dev) -+{ -+ struct wm97xx *wm = dev->driver_data; -+ wm97xx_unregister_mach_ops (wm); -+ return 0; -+} -+ -+static struct device_driver pxa_wm97xx_driver = { -+ .name = "wm97xx-touchscreen", -+ .bus = &wm97xx_bus_type, -+ .owner = THIS_MODULE, -+ .probe = pxa_wm97xx_probe, -+ .remove = pxa_wm97xx_remove -+}; -+ -+static int __init pxa_wm97xx_init(void) -+{ -+ return driver_register(&pxa_wm97xx_driver); -+} -+ -+static void __exit pxa_wm97xx_exit(void) -+{ -+ driver_unregister(&pxa_wm97xx_driver); -+} -+ -+module_init(pxa_wm97xx_init); -+module_exit(pxa_wm97xx_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); -+MODULE_DESCRIPTION("wm97xx continuous touch driver for pxa2xx"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.17/drivers/input/touchscreen/wm9705.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/drivers/input/touchscreen/wm9705.c 2006-09-19 20:36:47.969052000 +0200 -@@ -0,0 +1,360 @@ -+/* -+ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. -+ * -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. -+ * Author: Liam Girdwood -+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com -+ * Parts Copyright : Ian Molton <spyro@f2s.com> -+ * Andrew Zabolotny <zap@homelink.ru> -+ * Russell King <rmk@arm.linux.org.uk> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Revision history -+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com> -+ * Added pre and post sample calls. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/version.h> -+#include <linux/kernel.h> -+#include <linux/input.h> -+#include <linux/delay.h> -+#include <linux/bitops.h> -+#include <linux/wm97xx.h> -+ -+#define TS_NAME "wm97xx" -+#define WM9705_VERSION "0.62" -+#define DEFAULT_PRESSURE 0xb0c0 -+ -+/* -+ * Debug -+ */ -+#if 0 -+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) -+#endif -+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -+ -+/* -+ * Module parameters -+ */ -+ -+/* -+ * Set current used for pressure measurement. -+ * -+ * Set pil = 2 to use 400uA -+ * pil = 1 to use 200uA and -+ * pil = 0 to disable pressure measurement. -+ * -+ * This is used to increase the range of values returned by the adc -+ * when measureing touchpanel pressure. -+ */ -+static int pil = 0; -+module_param(pil, int, 0); -+MODULE_PARM_DESC(pil, "Set current used for pressure measurement."); -+ -+/* -+ * Set threshold for pressure measurement. -+ * -+ * Pen down pressure below threshold is ignored. -+ */ -+static int pressure = DEFAULT_PRESSURE & 0xfff; -+module_param(pressure, int, 0); -+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement."); -+ -+/* -+ * Set adc sample delay. -+ * -+ * For accurate touchpanel measurements, some settling time may be -+ * required between the switch matrix applying a voltage across the -+ * touchpanel plate and the ADC sampling the signal. -+ * -+ * This delay can be set by setting delay = n, where n is the array -+ * position of the delay in the array delay_table below. -+ * Long delays > 1ms are supported for completeness, but are not -+ * recommended. -+ */ -+static int delay = 4; -+module_param(delay, int, 0); -+MODULE_PARM_DESC(delay, "Set adc sample delay."); -+ -+/* -+ * Pen detect comparator threshold. -+ * -+ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold -+ * i.e. 1 = Vmid/15 threshold -+ * 15 = Vmid/1 threshold -+ * -+ * Adjust this value if you are having problems with pen detect not -+ * detecting any down events. -+ */ -+static int pdd = 8; -+module_param(pdd, int, 0); -+MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold"); -+ -+/* -+ * Set adc mask function. -+ * -+ * Sources of glitch noise, such as signals driving an LCD display, may feed -+ * through to the touch screen plates and affect measurement accuracy. In -+ * order to minimise this, a signal may be applied to the MASK pin to delay or -+ * synchronise the sampling. -+ * -+ * 0 = No delay or sync -+ * 1 = High on pin stops conversions -+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above) -+ * 3 = Edge triggered, edge on pin starts conversion after delay param -+ */ -+static int mask = 0; -+module_param(mask, int, 0); -+MODULE_PARM_DESC(mask, "Set adc mask function."); -+ -+/* -+ * ADC sample delay times in uS -+ */ -+static const int delay_table[] = { -+ 21, // 1 AC97 Link frames -+ 42, // 2 -+ 84, // 4 -+ 167, // 8 -+ 333, // 16 -+ 667, // 32 -+ 1000, // 48 -+ 1333, // 64 -+ 2000, // 96 -+ 2667, // 128 -+ 3333, // 160 -+ 4000, // 192 -+ 4667, // 224 -+ 5333, // 256 -+ 6000, // 288 -+ 0 // No delay, switch matrix always on -+}; -+ -+/* -+ * Delay after issuing a POLL command. -+ * -+ * The delay is 3 AC97 link frames + the touchpanel settling delay -+ */ -+static inline void poll_delay(int d) -+{ -+ udelay (3 * AC97_LINK_FRAME + delay_table [d]); -+} -+ -+/* -+ * set up the physical settings of the WM9705 -+ */ -+static void init_wm9705_phy(struct wm97xx* wm) -+{ -+ u16 dig1 = 0, dig2 = WM97XX_RPR; -+ -+ /* -+ * mute VIDEO and AUX as they share X and Y touchscreen -+ * inputs on the WM9705 -+ */ -+ wm97xx_reg_write(wm, AC97_AUX, 0x8000); -+ wm97xx_reg_write(wm, AC97_VIDEO, 0x8000); -+ -+ /* touchpanel pressure current*/ -+ if (pil == 2) { -+ dig2 |= WM9705_PIL; -+ dbg("setting pressure measurement current to 400uA."); -+ } else if (pil) -+ dbg("setting pressure measurement current to 200uA."); -+ if(!pil) -+ pressure = 0; -+ -+ /* polling mode sample settling delay */ -+ if (delay!=4) { -+ if (delay < 0 || delay > 15) { -+ dbg("supplied delay out of range."); -+ delay = 4; -+ } -+ } -+ dig1 &= 0xff0f; -+ dig1 |= WM97XX_DELAY(delay); -+ dbg("setting adc sample delay to %d u Secs.", delay_table[delay]); -+ -+ /* WM9705 pdd */ -+ dig2 |= (pdd & 0x000f); -+ dbg("setting pdd to Vmid/%d", 1 - (pdd & 0x000f)); -+ -+ /* mask */ -+ dig2 |= ((mask & 0x3) << 4); -+ -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); -+} -+ -+static int wm9705_digitiser_ioctl(struct wm97xx* wm, int cmd) -+{ -+ switch(cmd) { -+ case WM97XX_DIG_START: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] | WM97XX_PRP_DET_DIG); -+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */ -+ break; -+ case WM97XX_DIG_STOP: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig[2] & ~WM97XX_PRP_DET_DIG); -+ break; -+ case WM97XX_AUX_PREPARE: -+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig)); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG); -+ break; -+ case WM97XX_DIG_RESTORE: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]); -+ break; -+ case WM97XX_PHY_INIT: -+ init_wm9705_phy(wm); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static inline int is_pden (struct wm97xx* wm) -+{ -+ return wm->dig[2] & WM9705_PDEN; -+} -+ -+/* -+ * Read a sample from the WM9705 adc in polling mode. -+ */ -+static int wm9705_poll_sample (struct wm97xx* wm, int adcsel, int *sample) -+{ -+ int timeout = 5 * delay; -+ -+ if (!wm->pen_probably_down) { -+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (!(data & WM97XX_PEN_DOWN)) -+ return RC_PENUP; -+ wm->pen_probably_down = 1; -+ } -+ -+ /* set up digitiser */ -+ if (adcsel & 0x8000) -+ adcsel = ((adcsel & 0x7fff) + 3) << 12; -+ -+ if (wm->mach_ops && wm->mach_ops->pre_sample) -+ wm->mach_ops->pre_sample(adcsel); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); -+ -+ /* wait 3 AC97 time slots + delay for conversion */ -+ poll_delay (delay); -+ -+ /* wait for POLL to go low */ -+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) { -+ udelay(AC97_LINK_FRAME); -+ timeout--; -+ } -+ -+ if (timeout <= 0) { -+ /* If PDEN is set, we can get a timeout when pen goes up */ -+ if (is_pden(wm)) -+ wm->pen_probably_down = 0; -+ else -+ dbg ("adc sample timeout"); -+ return RC_PENUP; -+ } -+ -+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (wm->mach_ops && wm->mach_ops->post_sample) -+ wm->mach_ops->post_sample(adcsel); -+ -+ /* check we have correct sample */ -+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { -+ dbg ("adc wrong sample, read %x got %x", adcsel, -+ *sample & WM97XX_ADCSEL_MASK); -+ return RC_PENUP; -+ } -+ -+ if (!(*sample & WM97XX_PEN_DOWN)) { -+ wm->pen_probably_down = 0; -+ return RC_PENUP; -+ } -+ -+ return RC_VALID; -+} -+ -+/* -+ * Sample the WM9705 touchscreen in polling mode -+ */ -+static int wm9705_poll_touch(struct wm97xx* wm, struct wm97xx_data *data) -+{ -+ int rc; -+ -+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID) -+ return rc; -+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID) -+ return rc; -+ if (pil) { -+ if ((rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID) -+ return rc; -+ } else -+ data->p = DEFAULT_PRESSURE; -+ -+ return RC_VALID; -+} -+ -+/* -+ * Enable WM9705 continuous mode, i.e. touch data is streamed across an AC97 slot -+ */ -+static int wm9705_acc_enable (struct wm97xx* wm, int enable) -+{ -+ u16 dig1, dig2; -+ int ret = 0; -+ -+ dig1 = wm->dig[1]; -+ dig2 = wm->dig[2]; -+ -+ if (enable) { -+ /* continous mode */ -+ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0) -+ return ret; -+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK | -+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK); -+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN | -+ WM97XX_DELAY (delay) | -+ WM97XX_SLT (wm->acc_slot) | -+ WM97XX_RATE (wm->acc_rate); -+ if (pil) -+ dig1 |= WM97XX_ADCSEL_PRES; -+ dig2 |= WM9705_PDEN; -+ } else { -+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN); -+ dig2 &= ~WM9705_PDEN; -+ if (wm->mach_ops->acc_shutdown) -+ wm->mach_ops->acc_shutdown(wm); -+ } -+ -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); -+ return ret; -+} -+ -+struct wm97xx_codec_drv wm97xx_codec = { -+ .id = WM9705_ID2, -+ .name = "wm9705", -+ .poll_sample = wm9705_poll_sample, -+ .poll_touch = wm9705_poll_touch, -+ .acc_enable = wm9705_acc_enable, -+ .digitiser_ioctl = wm9705_digitiser_ioctl, -+}; -+ -+EXPORT_SYMBOL_GPL(wm97xx_codec); -+ -+/* Module information */ -+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); -+MODULE_DESCRIPTION("WM9705 Touch Screen Driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.17/drivers/input/touchscreen/wm9712.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/drivers/input/touchscreen/wm9712.c 2006-09-19 20:36:47.969052000 +0200 -@@ -0,0 +1,464 @@ -+/* -+ * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. -+ * -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. -+ * Author: Liam Girdwood -+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com -+ * Parts Copyright : Ian Molton <spyro@f2s.com> -+ * Andrew Zabolotny <zap@homelink.ru> -+ * Russell King <rmk@arm.linux.org.uk> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Revision history -+ * 4th Jul 2005 Initial version. -+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com> -+ * Added pre and post sample calls. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/version.h> -+#include <linux/kernel.h> -+#include <linux/input.h> -+#include <linux/delay.h> -+#include <linux/bitops.h> -+#include <linux/wm97xx.h> -+ -+#define TS_NAME "wm97xx" -+#define WM9712_VERSION "0.61" -+#define DEFAULT_PRESSURE 0xb0c0 -+ -+/* -+ * Debug -+ */ -+#if 0 -+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) -+#endif -+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -+ -+/* -+ * Module parameters -+ */ -+ -+/* -+ * Set internal pull up for pen detect. -+ * -+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive) -+ * i.e. pull up resistance = 64k Ohms / rpu. -+ * -+ * Adjust this value if you are having problems with pen detect not -+ * detecting any down event. -+ */ -+static int rpu = 3; -+module_param(rpu, int, 0); -+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); -+ -+/* -+ * Set current used for pressure measurement. -+ * -+ * Set pil = 2 to use 400uA -+ * pil = 1 to use 200uA and -+ * pil = 0 to disable pressure measurement. -+ * -+ * This is used to increase the range of values returned by the adc -+ * when measureing touchpanel pressure. -+ */ -+static int pil = 0; -+module_param(pil, int, 0); -+MODULE_PARM_DESC(pil, "Set current used for pressure measurement."); -+ -+/* -+ * Set threshold for pressure measurement. -+ * -+ * Pen down pressure below threshold is ignored. -+ */ -+static int pressure = DEFAULT_PRESSURE & 0xfff; -+module_param(pressure, int, 0); -+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement."); -+ -+/* -+ * Set adc sample delay. -+ * -+ * For accurate touchpanel measurements, some settling time may be -+ * required between the switch matrix applying a voltage across the -+ * touchpanel plate and the ADC sampling the signal. -+ * -+ * This delay can be set by setting delay = n, where n is the array -+ * position of the delay in the array delay_table below. -+ * Long delays > 1ms are supported for completeness, but are not -+ * recommended. -+ */ -+static int delay = 3; -+module_param(delay, int, 0); -+MODULE_PARM_DESC(delay, "Set adc sample delay."); -+ -+/* -+ * Set five_wire = 1 to use a 5 wire touchscreen. -+ * -+ * NOTE: Five wire mode does not allow for readback of pressure. -+ */ -+static int five_wire; -+module_param(five_wire, int, 0); -+MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen."); -+ -+/* -+ * Set adc mask function. -+ * -+ * Sources of glitch noise, such as signals driving an LCD display, may feed -+ * through to the touch screen plates and affect measurement accuracy. In -+ * order to minimise this, a signal may be applied to the MASK pin to delay or -+ * synchronise the sampling. -+ * -+ * 0 = No delay or sync -+ * 1 = High on pin stops conversions -+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above) -+ * 3 = Edge triggered, edge on pin starts conversion after delay param -+ */ -+static int mask = 0; -+module_param(mask, int, 0); -+MODULE_PARM_DESC(mask, "Set adc mask function."); -+ -+/* -+ * Coordinate Polling Enable. -+ * -+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together -+ * for every poll. -+ */ -+static int coord = 0; -+module_param(coord, int, 0); -+MODULE_PARM_DESC(coord, "Polling coordinate mode"); -+ -+/* -+ * ADC sample delay times in uS -+ */ -+static const int delay_table[] = { -+ 21, // 1 AC97 Link frames -+ 42, // 2 -+ 84, // 4 -+ 167, // 8 -+ 333, // 16 -+ 667, // 32 -+ 1000, // 48 -+ 1333, // 64 -+ 2000, // 96 -+ 2667, // 128 -+ 3333, // 160 -+ 4000, // 192 -+ 4667, // 224 -+ 5333, // 256 -+ 6000, // 288 -+ 0 // No delay, switch matrix always on -+}; -+ -+/* -+ * Delay after issuing a POLL command. -+ * -+ * The delay is 3 AC97 link frames + the touchpanel settling delay -+ */ -+static inline void poll_delay(int d) -+{ -+ udelay (3 * AC97_LINK_FRAME + delay_table [d]); -+} -+ -+/* -+ * set up the physical settings of the WM9712 -+ */ -+static void init_wm9712_phy(struct wm97xx* wm) -+{ -+ u16 dig1 = 0; -+ u16 dig2 = WM97XX_RPR | WM9712_RPU(1); -+ -+ /* WM9712 rpu */ -+ if (rpu) { -+ dig2 &= 0xffc0; -+ dig2 |= WM9712_RPU(rpu); -+ dbg("setting pen detect pull-up to %d Ohms",64000 / rpu); -+ } -+ -+ /* touchpanel pressure current*/ -+ if (pil == 2) { -+ dig2 |= WM9712_PIL; -+ dbg("setting pressure measurement current to 400uA."); -+ } else if (pil) -+ dbg("setting pressure measurement current to 200uA."); -+ if(!pil) -+ pressure = 0; -+ -+ /* WM9712 five wire */ -+ if (five_wire) { -+ dig2 |= WM9712_45W; -+ dbg("setting 5-wire touchscreen mode."); -+ } -+ -+ /* polling mode sample settling delay */ -+ if (delay < 0 || delay > 15) { -+ dbg("supplied delay out of range."); -+ delay = 4; -+ } -+ dig1 &= 0xff0f; -+ dig1 |= WM97XX_DELAY(delay); -+ dbg("setting adc sample delay to %d u Secs.", delay_table[delay]); -+ -+ /* mask */ -+ dig2 |= ((mask & 0x3) << 6); -+ if (mask) { -+ u16 reg; -+ /* Set GPIO4 as Mask Pin*/ -+ reg = wm97xx_reg_read(wm, AC97_MISC_AFE); -+ wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG); -+ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4); -+ } -+ -+ /* wait - coord mode */ -+ if(coord) -+ dig2 |= WM9712_WAIT; -+ -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); -+} -+ -+static int wm9712_digitiser_ioctl(struct wm97xx* wm, int cmd) -+{ -+ u16 dig2 = wm->dig[2]; -+ -+ switch(cmd) { -+ case WM97XX_DIG_START: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 | WM97XX_PRP_DET_DIG); -+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */ -+ break; -+ case WM97XX_DIG_STOP: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2 & ~WM97XX_PRP_DET_DIG); -+ break; -+ case WM97XX_AUX_PREPARE: -+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig)); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG); -+ break; -+ case WM97XX_DIG_RESTORE: -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]); -+ break; -+ case WM97XX_PHY_INIT: -+ init_wm9712_phy(wm); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static inline int is_pden (struct wm97xx* wm) -+{ -+ return wm->dig[2] & WM9712_PDEN; -+} -+ -+/* -+ * Read a sample from the WM9712 adc in polling mode. -+ */ -+static int wm9712_poll_sample (struct wm97xx* wm, int adcsel, int *sample) -+{ -+ int timeout = 5 * delay; -+ -+ if (!wm->pen_probably_down) { -+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (!(data & WM97XX_PEN_DOWN)) -+ return RC_PENUP; -+ wm->pen_probably_down = 1; -+ } -+ -+ /* set up digitiser */ -+ if (adcsel & 0x8000) -+ adcsel = ((adcsel & 0x7fff) + 3) << 12; -+ -+ if (wm->mach_ops && wm->mach_ops->pre_sample) -+ wm->mach_ops->pre_sample(adcsel); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); -+ -+ /* wait 3 AC97 time slots + delay for conversion */ -+ poll_delay (delay); -+ -+ /* wait for POLL to go low */ -+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) { -+ udelay(AC97_LINK_FRAME); -+ timeout--; -+ } -+ -+ if (timeout <= 0) { -+ /* If PDEN is set, we can get a timeout when pen goes up */ -+ if (is_pden(wm)) -+ wm->pen_probably_down = 0; -+ else -+ dbg ("adc sample timeout"); -+ return RC_PENUP; -+ } -+ -+ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (wm->mach_ops && wm->mach_ops->post_sample) -+ wm->mach_ops->post_sample(adcsel); -+ -+ /* check we have correct sample */ -+ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { -+ dbg ("adc wrong sample, read %x got %x", adcsel, -+ *sample & WM97XX_ADCSEL_MASK); -+ return RC_PENUP; -+ } -+ -+ if (!(*sample & WM97XX_PEN_DOWN)) { -+ wm->pen_probably_down = 0; -+ return RC_PENUP; -+ } -+ -+ return RC_VALID; -+} -+ -+/* -+ * Read a coord from the WM9712 adc in polling mode. -+ */ -+static int wm9712_poll_coord (struct wm97xx* wm, struct wm97xx_data *data) -+{ -+ int timeout = 5 * delay; -+ -+ if (!wm->pen_probably_down) { -+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (!(data & WM97XX_PEN_DOWN)) -+ return RC_PENUP; -+ wm->pen_probably_down = 1; -+ } -+ -+ /* set up digitiser */ -+ if (wm->mach_ops && wm->mach_ops->pre_sample) -+ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); -+ -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, -+ WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay)); -+ -+ /* wait 3 AC97 time slots + delay for conversion and read x */ -+ poll_delay(delay); -+ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ /* wait for POLL to go low */ -+ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) && timeout) { -+ udelay(AC97_LINK_FRAME); -+ timeout--; -+ } -+ -+ if (timeout <= 0) { -+ /* If PDEN is set, we can get a timeout when pen goes up */ -+ if (is_pden(wm)) -+ wm->pen_probably_down = 0; -+ else -+ dbg ("adc sample timeout"); -+ return RC_PENUP; -+ } -+ -+ /* read back y data */ -+ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (pil) -+ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ else -+ data->p = DEFAULT_PRESSURE; -+ -+ if (wm->mach_ops && wm->mach_ops->post_sample) -+ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); -+ -+ /* check we have correct sample */ -+ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y)) -+ goto err; -+ if(pil && !(data->p & WM97XX_ADCSEL_PRES)) -+ goto err; -+ -+ if (!(data->x & WM97XX_PEN_DOWN)) { -+ wm->pen_probably_down = 0; -+ return RC_PENUP; -+ } -+ return RC_VALID; -+err: -+ return RC_PENUP; -+} -+ -+/* -+ * Sample the WM9712 touchscreen in polling mode -+ */ -+static int wm9712_poll_touch(struct wm97xx* wm, struct wm97xx_data *data) -+{ -+ int rc; -+ -+ if(coord) { -+ if((rc = wm9712_poll_coord(wm, data)) != RC_VALID) -+ return rc; -+ } else { -+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x)) != RC_VALID) -+ return rc; -+ -+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y)) != RC_VALID) -+ return rc; -+ -+ if (pil && !five_wire) { -+ if ((rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p)) != RC_VALID) -+ return rc; -+ } else -+ data->p = DEFAULT_PRESSURE; -+ } -+ return RC_VALID; -+} -+ -+/* -+ * Enable WM9712 continuous mode, i.e. touch data is streamed across an AC97 slot -+ */ -+static int wm9712_acc_enable (struct wm97xx* wm, int enable) -+{ -+ u16 dig1, dig2; -+ int ret = 0; -+ -+ dig1 = wm->dig[1]; -+ dig2 = wm->dig[2]; -+ -+ if (enable) { -+ /* continous mode */ -+ if (wm->mach_ops->acc_startup && (ret = wm->mach_ops->acc_startup(wm)) < 0) -+ return ret; -+ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK | -+ WM97XX_DELAY_MASK | WM97XX_SLT_MASK); -+ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN | -+ WM97XX_DELAY (delay) | -+ WM97XX_SLT (wm->acc_slot) | -+ WM97XX_RATE (wm->acc_rate); -+ if (pil) -+ dig1 |= WM97XX_ADCSEL_PRES; -+ dig2 |= WM9712_PDEN; -+ } else { -+ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN); -+ dig2 &= ~WM9712_PDEN; -+ if (wm->mach_ops->acc_shutdown) -+ wm->mach_ops->acc_shutdown(wm); -+ } -+ -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); -+ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); -+ return 0; -+} -+ -+struct wm97xx_codec_drv wm97xx_codec = { -+ .id = WM9712_ID2, -+ .name = "wm9712", -+ .poll_sample = wm9712_poll_sample, -+ .poll_touch = wm9712_poll_touch, -+ .acc_enable = wm9712_acc_enable, -+ .digitiser_ioctl = wm9712_digitiser_ioctl, -+}; -+ -+EXPORT_SYMBOL_GPL(wm97xx_codec); -+ -+/* Module information */ -+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); -+MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.17/drivers/input/touchscreen/wm9713.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/drivers/input/touchscreen/wm9713.c 2006-09-19 20:36:47.969052000 +0200 -@@ -0,0 +1,461 @@ -+/* -+ * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec. -+ * -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. -+ * Author: Liam Girdwood -+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com -+ * Parts Copyright : Ian Molton <spyro@f2s.com> -+ * Andrew Zabolotny <zap@homelink.ru> -+ * Russell King <rmk@arm.linux.org.uk> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Revision history -+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com> -+ * Added pre and post sample calls. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/version.h> -+#include <linux/kernel.h> -+#include <linux/input.h> -+#include <linux/delay.h> -+#include <linux/bitops.h> -+#include <linux/wm97xx.h> -+ -+#define TS_NAME "wm97xx" -+#define WM9713_VERSION "0.53" -+#define DEFAULT_PRESSURE 0xb0c0 -+ -+/* -+ * Debug -+ */ -+#if 0 -+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) -+#endif -+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -+ -+/* -+ * Module parameters -+ */ -+ -+/* -+ * Set internal pull up for pen detect. -+ * -+ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive) -+ * i.e. pull up resistance = 64k Ohms / rpu. -+ * -+ * Adjust this value if you are having problems with pen detect not -+ * detecting any down event. -+ */ -+static int rpu = 1; -+module_param(rpu, int, 0); -+MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); -+ -+/* -+ * Set current used for pressure measurement. -+ * -+ * Set pil = 2 to use 400uA -+ * pil = 1 to use 200uA and -+ * pil = 0 to disable pressure measurement. -+ * -+ * This is used to increase the range of values returned by the adc -+ * when measureing touchpanel pressure. -+ */ -+static int pil = 0; -+module_param(pil, int, 0); -+MODULE_PARM_DESC(pil, "Set current used for pressure measurement."); -+ -+/* -+ * Set threshold for pressure measurement. -+ * -+ * Pen down pressure below threshold is ignored. -+ */ -+static int pressure = DEFAULT_PRESSURE & 0xfff; -+module_param(pressure, int, 0); -+MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement."); -+ -+/* -+ * Set adc sample delay. -+ * -+ * For accurate touchpanel measurements, some settling time may be -+ * required between the switch matrix applying a voltage across the -+ * touchpanel plate and the ADC sampling the signal. -+ * -+ * This delay can be set by setting delay = n, where n is the array -+ * position of the delay in the array delay_table below. -+ * Long delays > 1ms are supported for completeness, but are not -+ * recommended. -+ */ -+static int delay = 4; -+module_param(delay, int, 0); -+MODULE_PARM_DESC(delay, "Set adc sample delay."); -+ -+/* -+ * Set adc mask function. -+ * -+ * Sources of glitch noise, such as signals driving an LCD display, may feed -+ * through to the touch screen plates and affect measurement accuracy. In -+ * order to minimise this, a signal may be applied to the MASK pin to delay or -+ * synchronise the sampling. -+ * -+ * 0 = No delay or sync -+ * 1 = High on pin stops conversions -+ * 2 = Edge triggered, edge on pin delays conversion by delay param (above) -+ * 3 = Edge triggered, edge on pin starts conversion after delay param -+ */ -+static int mask = 0; -+module_param(mask, int, 0); -+MODULE_PARM_DESC(mask, "Set adc mask function."); -+ -+/* -+ * Coordinate Polling Enable. -+ * -+ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together -+ * for every poll. -+ */ -+static int coord = 1; -+module_param(coord, int, 0); -+MODULE_PARM_DESC(coord, "Polling coordinate mode"); -+ -+/* -+ * ADC sample delay times in uS -+ */ -+static const int delay_table[] = { -+ 21, // 1 AC97 Link frames -+ 42, // 2 -+ 84, // 4 -+ 167, // 8 -+ 333, // 16 -+ 667, // 32 -+ 1000, // 48 -+ 1333, // 64 -+ 2000, // 96 -+ 2667, // 128 -+ 3333, // 160 -+ 4000, // 192 -+ 4667, // 224 -+ 5333, // 256 -+ 6000, // 288 -+ 0 // No delay, switch matrix always on -+}; -+ -+/* -+ * Delay after issuing a POLL command. -+ * -+ * The delay is 3 AC97 link frames + the touchpanel settling delay -+ */ -+static inline void poll_delay(int d) -+{ -+ udelay (3 * AC97_LINK_FRAME + delay_table [d]); -+} -+ -+/* -+ * set up the physical settings of the WM9713 -+ */ -+static void init_wm9713_phy(struct wm97xx* wm) -+{ -+ u16 dig1 = 0, dig2, dig3; -+ -+ /* default values */ -+ dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5); -+ dig3= WM9712_RPU(1); -+ -+ /* rpu */ -+ if (rpu) { -+ dig3 &= 0xffc0; -+ dig3 |= WM9712_RPU(rpu); -+ info("setting pen detect pull-up to %d Ohms",64000 / rpu); -+ } -+ -+ /* touchpanel pressure */ -+ if (pil == 2) { -+ dig3 |= WM9712_PIL; -+ info("setting pressure measurement current to 400uA."); -+ } else if (pil) -+ info ("setting pressure measurement current to 200uA."); -+ if(!pil) -+ pressure = 0; -+ -+ /* sample settling delay */ -+ if (delay < 0 || delay > 15) { -+ info ("supplied delay out of range."); -+ delay = 4; -+ info("setting adc sample delay to %d u Secs.", delay_table[delay]); -+ } -+ dig2 &= 0xff0f; -+ dig2 |= WM97XX_DELAY(delay); -+ -+ /* mask */ -+ dig3 |= ((mask & 0x3) << 4); -+ if(coord) -+ dig3 |= WM9713_WAIT; -+ -+ wm->misc = wm97xx_reg_read(wm, 0x5a); -+ -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3); -+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0); -+} -+ -+static int wm9713_digitiser_ioctl(struct wm97xx* wm, int cmd) -+{ -+ u16 val = 0; -+ -+ switch(cmd){ -+ case WM97XX_DIG_START: -+ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID); -+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] | WM97XX_PRP_DET_DIG); -+ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */ -+ break; -+ case WM97XX_DIG_STOP: -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] & ~WM97XX_PRP_DET_DIG); -+ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID); -+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000); -+ break; -+ case WM97XX_AUX_PREPARE: -+ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig)); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG); -+ break; -+ case WM97XX_DIG_RESTORE: -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]); -+ break; -+ case WM97XX_PHY_INIT: -+ init_wm9713_phy(wm); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static inline int is_pden (struct wm97xx* wm) -+{ -+ return wm->dig[2] & WM9713_PDEN; -+} -+ -+/* -+ * Read a sample from the WM9713 adc in polling mode. -+ */ -+static int wm9713_poll_sample (struct wm97xx* wm, int adcsel, int *sample) -+{ -+ u16 dig1; -+ int timeout = 5 * delay; -+ -+ if (!wm->pen_probably_down) { -+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (!(data & WM97XX_PEN_DOWN)) -+ return RC_PENUP; -+ wm->pen_probably_down = 1; -+ } -+ -+ /* set up digitiser */ -+ if (adcsel & 0x8000) -+ adcsel = 1 << ((adcsel & 0x7fff) + 3); -+ -+ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1); -+ dig1 &= ~WM9713_ADCSEL_MASK; -+ -+ if (wm->mach_ops && wm->mach_ops->pre_sample) -+ wm->mach_ops->pre_sample(adcsel); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel |WM9713_POLL); -+ -+ /* wait 3 AC97 time slots + delay for conversion */ -+ poll_delay(delay); -+ -+ /* wait for POLL to go low */ -+ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) { -+ udelay(AC97_LINK_FRAME); -+ timeout--; -+ } -+ -+ if (timeout <= 0) { -+ /* If PDEN is set, we can get a timeout when pen goes up */ -+ if (is_pden(wm)) -+ wm->pen_probably_down = 0; -+ else -+ dbg ("adc sample timeout"); -+ return RC_PENUP; -+ } -+ -+ *sample =wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (wm->mach_ops && wm->mach_ops->post_sample) -+ wm->mach_ops->post_sample(adcsel); -+ -+ /* check we have correct sample */ -+ if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) { -+ dbg ("adc wrong sample, read %x got %x", adcsel, -+ *sample & WM97XX_ADCSRC_MASK); -+ return RC_PENUP; -+ } -+ -+ if (!(*sample & WM97XX_PEN_DOWN)) { -+ wm->pen_probably_down = 0; -+ return RC_PENUP; -+ } -+ -+ return RC_VALID; -+} -+ -+/* -+ * Read a coordinate from the WM9713 adc in polling mode. -+ */ -+static int wm9713_poll_coord (struct wm97xx* wm, struct wm97xx_data *data) -+{ -+ u16 dig1; -+ int timeout = 5 * delay; -+ -+ if (!wm->pen_probably_down) { -+ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (!(data & WM97XX_PEN_DOWN)) -+ return RC_PENUP; -+ wm->pen_probably_down = 1; -+ } -+ -+ /* set up digitiser */ -+ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1); -+ dig1 &= ~WM9713_ADCSEL_MASK; -+ if(pil) -+ dig1 |= WM97XX_ADCSEL_PRES; -+ -+ if (wm->mach_ops && wm->mach_ops->pre_sample) -+ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL | WM9713_COO); -+ -+ /* wait 3 AC97 time slots + delay for conversion */ -+ poll_delay(delay); -+ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ /* wait for POLL to go low */ -+ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) && timeout) { -+ udelay(AC97_LINK_FRAME); -+ timeout--; -+ } -+ -+ if (timeout <= 0) { -+ /* If PDEN is set, we can get a timeout when pen goes up */ -+ if (is_pden(wm)) -+ wm->pen_probably_down = 0; -+ else -+ dbg ("adc sample timeout"); -+ return RC_PENUP; -+ } -+ -+ /* read back data */ -+ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ if (pil) -+ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); -+ else -+ data->p = DEFAULT_PRESSURE; -+ -+ if (wm->mach_ops && wm->mach_ops->post_sample) -+ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y); -+ -+ /* check we have correct sample */ -+ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y)) -+ goto err; -+ if(pil && !(data->p & WM97XX_ADCSEL_PRES)) -+ goto err; -+ -+ if (!(data->x & WM97XX_PEN_DOWN)) { -+ wm->pen_probably_down = 0; -+ return RC_PENUP; -+ } -+ return RC_VALID; -+err: -+ return RC_PENUP; -+} -+ -+/* -+ * Sample the WM9713 touchscreen in polling mode -+ */ -+static int wm9713_poll_touch(struct wm97xx* wm, struct wm97xx_data *data) -+{ -+ int rc; -+ -+ if(coord) { -+ if((rc = wm9713_poll_coord(wm, data)) != RC_VALID) -+ return rc; -+ } else { -+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x)) != RC_VALID) -+ return rc; -+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y)) != RC_VALID) -+ return rc; -+ if (pil) { -+ if ((rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, &data->p)) != RC_VALID) -+ return rc; -+ } else -+ data->p = DEFAULT_PRESSURE; -+ } -+ return RC_VALID; -+} -+ -+/* -+ * Enable WM9713 continuous mode, i.e. touch data is streamed across an AC97 slot -+ */ -+static int wm9713_acc_enable (struct wm97xx* wm, int enable) -+{ -+ u16 dig1, dig2, dig3; -+ int ret = 0; -+ -+ dig1 = wm->dig[0]; -+ dig2 = wm->dig[1]; -+ dig3 = wm->dig[2]; -+ -+ if (enable) { -+ /* continous mode */ -+ if (wm->mach_ops->acc_startup && -+ (ret = wm->mach_ops->acc_startup(wm)) < 0) -+ return ret; -+ -+ dig1 &= ~WM9713_ADCSEL_MASK; -+ dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X | WM9713_ADCSEL_Y; -+ if (pil) -+ dig1 |= WM9713_ADCSEL_PRES; -+ dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK | WM97XX_CM_RATE_MASK); -+ dig2 |= WM97XX_SLEN | WM97XX_DELAY (delay) | -+ WM97XX_SLT (wm->acc_slot) | WM97XX_RATE (wm->acc_rate); -+ dig3 |= WM9713_PDEN; -+ } else { -+ dig1 &= ~(WM9713_CTC | WM9713_COO); -+ dig2 &= ~WM97XX_SLEN; -+ dig3 &= ~WM9713_PDEN; -+ if (wm->mach_ops->acc_shutdown) -+ wm->mach_ops->acc_shutdown(wm); -+ } -+ -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3); -+ return ret; -+} -+ -+struct wm97xx_codec_drv wm97xx_codec = { -+ .id = WM9713_ID2, -+ .name = "wm9713", -+ .poll_sample = wm9713_poll_sample, -+ .poll_touch = wm9713_poll_touch, -+ .acc_enable = wm9713_acc_enable, -+ .digitiser_ioctl = wm9713_digitiser_ioctl, -+}; -+ -+EXPORT_SYMBOL_GPL(wm97xx_codec); -+ -+/* Module information */ -+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); -+MODULE_DESCRIPTION("WM9713 Touch Screen Driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/drivers/input/touchscreen/wm97xx-core.c 2006-09-19 20:36:47.969052000 +0200 -@@ -0,0 +1,912 @@ -+/* -+ * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712 -+ * and WM9713 AC97 Codecs. -+ * -+ * Copyright 2003, 2004, 2005, 2006 Wolfson Microelectronics PLC. -+ * Author: Liam Girdwood -+ * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com -+ * Parts Copyright : Ian Molton <spyro@f2s.com> -+ * Andrew Zabolotny <zap@homelink.ru> -+ * Russell King <rmk@arm.linux.org.uk> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * Notes: -+ * -+ * Features: -+ * - supports WM9705, WM9712, WM9713 -+ * - polling mode -+ * - continuous mode (arch-dependent) -+ * - adjustable rpu/dpp settings -+ * - adjustable pressure current -+ * - adjustable sample settle delay -+ * - 4 and 5 wire touchscreens (5 wire is WM9712 only) -+ * - pen down detection -+ * - battery monitor -+ * - sample AUX adc's -+ * - power management -+ * - codec GPIO -+ * - codec event notification -+ * Todo -+ * - Support for async sampling control for noisy LCD's. -+ * -+ * Revision history -+ * 7th May 2003 Initial version. -+ * 6th June 2003 Added non module support and AC97 registration. -+ * 18th June 2003 Added AUX adc sampling. -+ * 23rd June 2003 Did some minimal reformatting, fixed a couple of -+ * codec_mutexing bugs and noted a race to fix. -+ * 24th June 2003 Added power management and fixed race condition. -+ * 10th July 2003 Changed to a misc device. -+ * 31st July 2003 Moved TS_EVENT and TS_CAL to wm97xx.h -+ * 8th Aug 2003 Added option for read() calling wm97xx_sample_touch() -+ * because some ac97_read/ac_97_write call schedule() -+ * 7th Nov 2003 Added Input touch event interface, stanley.cai@intel.com -+ * 13th Nov 2003 Removed h3600 touch interface, added interrupt based -+ * pen down notification and implemented continous mode -+ * on XScale arch. -+ * 16th Nov 2003 Ian Molton <spyro@f2s.com> -+ * Modified so that it suits the new 2.6 driver model. -+ * 25th Jan 2004 Andrew Zabolotny <zap@homelink.ru> -+ * Implemented IRQ-driven pen down detection, implemented -+ * the private API meant to be exposed to platform-specific -+ * drivers, reorganized the driver so that it supports -+ * an arbitrary number of devices. -+ * 1st Feb 2004 Moved continuous mode handling to a separate -+ * architecture-dependent file. For now only PXA -+ * built-in AC97 controller is supported (pxa-ac97-wm97xx.c). -+ * 11th Feb 2004 Reduced CPU usage by keeping a cached copy of both -+ * digitizer registers instead of reading them every time. -+ * A reorganization of the whole code for better -+ * error handling. -+ * 17th Apr 2004 Added BMON support. -+ * 17th Nov 2004 Added codec GPIO, codec event handling (real and virtual -+ * GPIOs) and 2.6 power management. -+ * 29th Nov 2004 Added WM9713 support. -+ * 4th Jul 2005 Moved codec specific code out to seperate files. -+ * 6th Sep 2006 Mike Arthur <linux@wolfsonmicro.com> -+ * Added bus interface. -+ */ -+ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/version.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/string.h> -+#include <linux/proc_fs.h> -+#include <linux/pm.h> -+#include <linux/interrupt.h> -+#include <linux/bitops.h> -+#include <linux/workqueue.h> -+#include <linux/device.h> -+#include <linux/wm97xx.h> -+#include <asm/uaccess.h> -+#include <asm/io.h> -+ -+#define TS_NAME "wm97xx" -+#define WM_CORE_VERSION "0.63" -+#define DEFAULT_PRESSURE 0xb0c0 -+ -+/* -+ * WM97xx - enable/disable AUX ADC sysfs -+ */ -+static int aux_sys = 1; -+module_param(aux_sys, int, 0); -+MODULE_PARM_DESC(aux_sys, "enable AUX ADC sysfs entries"); -+ -+/* -+ * WM97xx - enable/disable codec status sysfs -+ */ -+static int status_sys = 1; -+module_param(status_sys, int, 0); -+MODULE_PARM_DESC(status_sys, "enable codec status sysfs entries"); -+ -+/* -+ * Touchscreen absolute values -+ * -+ * These parameters are used to help the input layer discard out of -+ * range readings and reduce jitter etc. -+ * -+ * o min, max:- indicate the min and max values your touch screen returns -+ * o fuzz:- use a higher number to reduce jitter -+ * -+ * The default values correspond to Mainstone II in QVGA mode -+ * -+ * Please read -+ * Documentation/input/input-programming.txt for more details. -+ */ -+ -+static int abs_x[3] = {350,3900,5}; -+module_param_array(abs_x, int, NULL, 0); -+MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz"); -+ -+static int abs_y[3] = {320,3750,40}; -+module_param_array(abs_y, int, NULL, 0); -+MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz"); -+ -+static int abs_p[3] = {0,150,4}; -+module_param_array(abs_p, int, NULL, 0); -+MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz"); -+ -+/* -+ * Debug -+ */ -+#if 0 -+#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg) -+#else -+#define dbg(format, arg...) -+#endif -+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) -+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) -+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -+ -+/* codec AC97 IO access */ -+int wm97xx_reg_read(struct wm97xx *wm, u16 reg) -+{ -+ if (wm->ac97) -+ return wm->ac97->bus->ops->read(wm->ac97, reg); -+ else -+ return -1; -+} -+ -+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val) -+{ -+ /* cache digitiser registers */ -+ if(reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3) -+ wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val; -+ -+ /* cache gpio regs */ -+ if(reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE) -+ wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val; -+ -+ /* wm9713 irq reg */ -+ if(reg == 0x5a) -+ wm->misc = val; -+ -+ if (wm->ac97) -+ wm->ac97->bus->ops->write(wm->ac97, reg, val); -+} -+ -+ -+/** -+ * wm97xx_read_aux_adc - Read the aux adc. -+ * @wm: wm97xx device. -+ * @adcsel: codec ADC to be read -+ * -+ * Reads the selected AUX ADC. -+ */ -+ -+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel) -+{ -+ int power_adc = 0, auxval; -+ u16 power = 0; -+ -+ /* get codec */ -+ mutex_lock(&wm->codec_mutex); -+ -+ /* When the touchscreen is not in use, we may have to power up the AUX ADC -+ * before we can use sample the AUX inputs-> -+ */ -+ if (wm->id == WM9713_ID2 && -+ (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) { -+ power_adc = 1; -+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff); -+ } -+ -+ /* Prepare the codec for AUX reading */ -+ wm->codec->digitiser_ioctl(wm, WM97XX_AUX_PREPARE); -+ -+ /* Turn polling mode on to read AUX ADC */ -+ wm->pen_probably_down = 1; -+ wm->codec->poll_sample(wm, adcsel, &auxval); -+ -+ if (power_adc) -+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000); -+ -+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_RESTORE); -+ -+ wm->pen_probably_down = 0; -+ -+ mutex_unlock(&wm->codec_mutex); -+ return auxval & 0xfff; -+} -+ -+#define WM97XX_AUX_ATTR(name,input) \ -+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \ -+ return sprintf(buf, "%d\n", wm97xx_read_aux_adc(wm, input)); \ -+} \ -+static DEVICE_ATTR(name, 0444, name##_show, NULL) -+ -+WM97XX_AUX_ATTR(aux1, WM97XX_AUX_ID1); -+WM97XX_AUX_ATTR(aux2, WM97XX_AUX_ID2); -+WM97XX_AUX_ATTR(aux3, WM97XX_AUX_ID3); -+WM97XX_AUX_ATTR(aux4, WM97XX_AUX_ID4); -+ -+#define WM97XX_STATUS_ATTR(name) \ -+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct wm97xx *wm = (struct wm97xx*)dev->driver_data; \ -+ return sprintf(buf, "%d\n", wm97xx_reg_read(wm, AC97_GPIO_STATUS)); \ -+} \ -+static DEVICE_ATTR(name, 0444, name##_show, NULL) -+ -+WM97XX_STATUS_ATTR(gpio); -+ -+static int wm97xx_sys_add(struct device *dev) -+{ -+ if (aux_sys) { -+ device_create_file(dev, &dev_attr_aux1); -+ device_create_file(dev, &dev_attr_aux2); -+ device_create_file(dev, &dev_attr_aux3); -+ device_create_file(dev, &dev_attr_aux4); -+ } -+ if (status_sys) -+ device_create_file(dev, &dev_attr_gpio); -+ return 0; -+} -+ -+static void wm97xx_sys_remove(struct device *dev) -+{ -+ if (status_sys) -+ device_remove_file(dev, &dev_attr_gpio); -+ if (aux_sys) { -+ device_remove_file(dev, &dev_attr_aux1); -+ device_remove_file(dev, &dev_attr_aux2); -+ device_remove_file(dev, &dev_attr_aux3); -+ device_remove_file(dev, &dev_attr_aux4); -+ } -+} -+ -+/** -+ * wm97xx_get_gpio - Get the status of a codec GPIO. -+ * @wm: wm97xx device. -+ * @gpio: gpio -+ * -+ * Get the status of a codec GPIO pin -+ */ -+ -+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio) -+{ -+ u16 status; -+ wm97xx_gpio_status_t ret; -+ -+ mutex_lock(&wm->codec_mutex); -+ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS); -+ -+ if (status & gpio) -+ ret = WM97XX_GPIO_HIGH; -+ else -+ ret = WM97XX_GPIO_LOW; -+ -+ mutex_unlock(&wm->codec_mutex); -+ return ret; -+} -+ -+/** -+ * wm97xx_set_gpio - Set the status of a codec GPIO. -+ * @wm: wm97xx device. -+ * @gpio: gpio -+ * -+ * -+ * Set the status of a codec GPIO pin -+ */ -+ -+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, -+ wm97xx_gpio_status_t status) -+{ -+ u16 reg; -+ -+ mutex_lock(&wm->codec_mutex); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); -+ -+ if (status & WM97XX_GPIO_HIGH) -+ reg |= gpio; -+ else -+ reg &= ~gpio; -+ -+ if (wm->id == WM9712_ID2) -+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); -+ else -+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); -+ mutex_unlock(&wm->codec_mutex); -+} -+ -+/* -+ * Codec GPIO pin configuration, this set's pin direction, polarity, -+ * stickyness and wake up. -+ */ -+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, wm97xx_gpio_dir_t dir, -+ wm97xx_gpio_pol_t pol, wm97xx_gpio_sticky_t sticky, -+ wm97xx_gpio_wake_t wake) -+{ -+ u16 reg; -+ -+ mutex_lock(&wm->codec_mutex); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); -+ -+ if (pol == WM97XX_GPIO_POL_HIGH) -+ reg |= gpio; -+ else -+ reg &= ~gpio; -+ -+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY); -+ -+ if (sticky == WM97XX_GPIO_STICKY) -+ reg |= gpio; -+ else -+ reg &= ~gpio; -+ -+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP); -+ -+ if (wake == WM97XX_GPIO_WAKE) -+ reg |= gpio; -+ else -+ reg &= ~gpio; -+ -+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg); -+ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG); -+ -+ if (dir == WM97XX_GPIO_IN) -+ reg |= gpio; -+ else -+ reg &= ~gpio; -+ -+ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg); -+ mutex_unlock(&wm->codec_mutex); -+} -+ -+/* -+ * Handle a pen down interrupt. -+ */ -+static void wm97xx_pen_irq_worker(void *ptr) -+{ -+ struct wm97xx *wm = (struct wm97xx *) ptr; -+ -+ /* do we need to enable the touch panel reader */ -+ if (wm->id == WM9705_ID2) { -+ if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN) -+ wm->pen_is_down = 1; -+ else -+ wm->pen_is_down = 0; -+ wake_up_interruptible(&wm->pen_irq_wait); -+ } else { -+ u16 status, pol; -+ mutex_lock(&wm->codec_mutex); -+ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS); -+ pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); -+ -+ if (WM97XX_GPIO_13 & pol & status) { -+ wm->pen_is_down = 1; -+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol & ~WM97XX_GPIO_13); -+ } else { -+ wm->pen_is_down = 0; -+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol | WM97XX_GPIO_13); -+ } -+ -+ if (wm->id == WM9712_ID2) -+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & ~WM97XX_GPIO_13) << 1); -+ else -+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, status & ~WM97XX_GPIO_13); -+ mutex_unlock(&wm->codec_mutex); -+ wake_up_interruptible(&wm->pen_irq_wait); -+ } -+ -+ if (!wm->pen_is_down && wm->mach_ops && wm->mach_ops->acc_enabled) -+ wm->mach_ops->acc_pen_up(wm); -+ enable_irq(wm->pen_irq); -+} -+ -+/* -+ * Codec PENDOWN irq handler -+ * -+ * We have to disable the codec interrupt in the handler because it can -+ * take upto 1ms to clear the interrupt source. The interrupt is then enabled -+ * again in the slow handler when the source has been cleared. -+ */ -+static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id, -+ struct pt_regs *regs) -+{ -+ struct wm97xx *wm = (struct wm97xx *) dev_id; -+ disable_irq(wm->pen_irq); -+ queue_work(wm->pen_irq_workq, &wm->pen_event_work); -+ return IRQ_HANDLED; -+} -+ -+/* -+ * initialise pen IRQ handler and workqueue -+ */ -+static int wm97xx_init_pen_irq(struct wm97xx *wm) -+{ -+ u16 reg; -+ -+ INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker, wm); -+ if ((wm->pen_irq_workq = -+ create_singlethread_workqueue("kwm97pen")) == NULL) { -+ err("could not create pen irq work queue"); -+ wm->pen_irq = 0; -+ return -EINVAL; -+ } -+ -+ if (request_irq (wm->pen_irq, wm97xx_pen_interrupt, SA_SHIRQ, "wm97xx-pen", wm)) { -+ err("could not register codec pen down interrupt, will poll for pen down"); -+ destroy_workqueue(wm->pen_irq_workq); -+ wm->pen_irq = 0; -+ return -EINVAL; -+ } -+ -+ /* enable PEN down on wm9712/13 */ -+ if (wm->id != WM9705_ID2) { -+ reg = wm97xx_reg_read(wm, AC97_MISC_AFE); -+ wm97xx_reg_write(wm, AC97_MISC_AFE, reg & 0xfffb); -+ reg = wm97xx_reg_read(wm, 0x5a); -+ wm97xx_reg_write(wm, 0x5a, reg & ~0x0001); -+ } -+ -+ return 0; -+} -+ -+/* Private struct for communication between struct wm97xx_tshread -+ * and wm97xx_read_samples */ -+struct ts_state { -+ int sleep_time; -+ int min_sleep_time; -+}; -+ -+static int wm97xx_read_samples(struct wm97xx *wm, struct ts_state *state) -+{ -+ struct wm97xx_data data; -+ int rc; -+ -+ mutex_lock(&wm->codec_mutex); -+ -+ if (wm->mach_ops && wm->mach_ops->acc_enabled) -+ rc = wm->mach_ops->acc_pen_down(wm); -+ else -+ rc = wm->codec->poll_touch(wm, &data); -+ -+ if (rc & RC_PENUP) { -+ if (wm->pen_is_down) { -+ wm->pen_is_down = 0; -+ dbg("pen up"); -+ input_report_abs(wm->input_dev, ABS_PRESSURE, 0); -+ input_sync(wm->input_dev); -+ } else if (!(rc & RC_AGAIN)) { -+ /* We need high frequency updates only while pen is down, -+ * the user never will be able to touch screen faster than -+ * a few times per second... On the other hand, when the -+ * user is actively working with the touchscreen we don't -+ * want to lose the quick response. So we will slowly -+ * increase sleep time after the pen is up and quicky -+ * restore it to ~one task switch when pen is down again. -+ */ -+ if (state->sleep_time < HZ / 10) -+ state->sleep_time++; -+ } -+ -+ } else if (rc & RC_VALID) { -+ dbg("pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n", -+ data.x >> 12, data.x & 0xfff, data.y >> 12, -+ data.y & 0xfff, data.p >> 12, data.p & 0xfff); -+ input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); -+ input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); -+ input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); -+ input_sync(wm->input_dev); -+ wm->pen_is_down = 1; -+ state->sleep_time = state->min_sleep_time; -+ } else if (rc & RC_PENDOWN) { -+ dbg("pen down"); -+ wm->pen_is_down = 1; -+ state->sleep_time = state->min_sleep_time; -+ } -+ -+ mutex_unlock(&wm->codec_mutex); -+ return rc; -+} -+ -+/* -+* The touchscreen sample reader thread. -+*/ -+static int wm97xx_ts_read(void *data) -+{ -+ int rc; -+ struct ts_state state; -+ struct wm97xx *wm = (struct wm97xx *) data; -+ -+ /* set up thread context */ -+ wm->ts_task = current; -+ daemonize("kwm97xxts"); -+ -+ if (wm->codec == NULL) { -+ wm->ts_task = NULL; -+ printk(KERN_ERR "codec is NULL, bailing\n"); -+ } -+ -+ complete(&wm->ts_init); -+ wm->pen_is_down = 0; -+ state.min_sleep_time = HZ >= 100 ? HZ / 100 : 1; -+ if (state.min_sleep_time < 1) -+ state.min_sleep_time = 1; -+ state.sleep_time = state.min_sleep_time; -+ -+ /* touch reader loop */ -+ while (wm->ts_task) { -+ do { -+ try_to_freeze(); -+ rc = wm97xx_read_samples(wm, &state); -+ } while (rc & RC_AGAIN); -+ if (!wm->pen_is_down && wm->pen_irq) { -+ /* Nice, we don't have to poll for pen down event */ -+ wait_event_interruptible(wm->pen_irq_wait, wm->pen_is_down); -+ } else { -+ set_task_state(current, TASK_INTERRUPTIBLE); -+ schedule_timeout(state.sleep_time); -+ } -+ } -+ complete_and_exit(&wm->ts_exit, 0); -+} -+ -+/** -+ * wm97xx_ts_input_open - Open the touch screen input device. -+ * @idev: Input device to be opened. -+ * -+ * Called by the input sub system to open a wm97xx touchscreen device. -+ * Starts the touchscreen thread and touch digitiser. -+ */ -+static int wm97xx_ts_input_open(struct input_dev *idev) -+{ -+ int ret = 0; -+ struct wm97xx *wm = (struct wm97xx *) idev->private; -+ -+ mutex_lock(&wm->codec_mutex); -+ /* first time opened ? */ -+ if (wm->ts_use_count++ == 0) { -+ /* start touchscreen thread */ -+ init_completion(&wm->ts_init); -+ init_completion(&wm->ts_exit); -+ ret = kernel_thread(wm97xx_ts_read, wm, CLONE_KERNEL); -+ -+ if (ret >= 0) { -+ wait_for_completion(&wm->ts_init); -+ if (wm->ts_task == NULL) -+ ret = -EINVAL; -+ } else { -+ mutex_unlock(&wm->codec_mutex); -+ return ret; -+ } -+ -+ /* start digitiser */ -+ if (wm->mach_ops && wm->mach_ops->acc_enabled) -+ wm->codec->acc_enable(wm, 1); -+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_START); -+ -+ /* init pen down/up irq handling */ -+ if (wm->pen_irq) { -+ wm97xx_init_pen_irq(wm); -+ -+ if (wm->pen_irq == 0) { -+ /* we failed to get an irq for pen down events, -+ * so we resort to polling. kickstart the reader */ -+ wm->pen_is_down = 1; -+ wake_up_interruptible(&wm->pen_irq_wait); -+ } -+ } -+ } -+ -+ mutex_unlock(&wm->codec_mutex); -+ return 0; -+} -+ -+/** -+ * wm97xx_ts_input_close - Close the touch screen input device. -+ * @idev: Input device to be closed. -+ * -+ * Called by the input sub system to close a wm97xx touchscreen device. -+ * Kills the touchscreen thread and stops the touch digitiser. -+ */ -+ -+static void wm97xx_ts_input_close(struct input_dev *idev) -+{ -+ struct wm97xx *wm = (struct wm97xx *) idev->private; -+ -+ mutex_lock(&wm->codec_mutex); -+ if (--wm->ts_use_count == 0) { -+ /* destroy workqueues and free irqs */ -+ if (wm->pen_irq) { -+ free_irq(wm->pen_irq, wm); -+ destroy_workqueue(wm->pen_irq_workq); -+ } -+ -+ /* kill thread */ -+ if (wm->ts_task) { -+ wm->ts_task = NULL; -+ wm->pen_is_down = 1; -+ wake_up_interruptible(&wm->pen_irq_wait); -+ wait_for_completion(&wm->ts_exit); -+ wm->pen_is_down = 0; -+ } -+ -+ /* stop digitiser */ -+ wm->codec->digitiser_ioctl(wm, WM97XX_DIG_STOP); -+ if (wm->mach_ops && wm->mach_ops->acc_enabled) -+ wm->codec->acc_enable(wm, 0); -+ } -+ mutex_unlock(&wm->codec_mutex); -+} -+ -+static int wm97xx_bus_match(struct device *dev, struct device_driver *drv) -+{ -+ return !(strcmp(dev->bus_id,drv->name)); -+} -+ -+/* -+ * The AC97 audio driver will do all the Codec suspend and resume -+ * tasks. This is just for anything machine specific or extra. -+ */ -+static int wm97xx_bus_suspend(struct device *dev, pm_message_t state) -+{ -+ int ret = 0; -+ -+ if (dev->driver && dev->driver->suspend) -+ ret = dev->driver->suspend(dev, state); -+ -+ return ret; -+} -+ -+static int wm97xx_bus_resume(struct device *dev) -+{ -+ int ret = 0; -+ -+ if (dev->driver && dev->driver->resume) -+ ret = dev->driver->resume(dev); -+ -+ return ret; -+} -+ -+struct bus_type wm97xx_bus_type = { -+ .name = "wm97xx", -+ .match = wm97xx_bus_match, -+ .suspend = wm97xx_bus_suspend, -+ .resume = wm97xx_bus_resume, -+}; -+ -+static void wm97xx_release(struct device *dev) -+{ -+ kfree(dev); -+} -+ -+static int wm97xx_probe(struct device *dev) -+{ -+ struct wm97xx* wm; -+ int ret = 0, id = 0; -+ -+ if (!(wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL))) -+ return -ENOMEM; -+ mutex_init(&wm->codec_mutex); -+ -+ init_waitqueue_head(&wm->pen_irq_wait); -+ wm->dev = dev; -+ dev->driver_data = wm; -+ wm->ac97 = to_ac97_t(dev); -+ -+ /* check that we have a supported codec */ -+ if ((id = wm97xx_reg_read(wm, AC97_VENDOR_ID1)) != WM97XX_ID1) { -+ err("could not find a wm97xx, found a %x instead\n", id); -+ kfree(wm); -+ return -ENODEV; -+ } -+ -+ wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); -+ if(wm->id != wm97xx_codec.id) { -+ err("could not find a the selected codec, please build for wm97%2x", wm->id & 0xff); -+ kfree(wm); -+ return -ENODEV; -+ } -+ -+ if((wm->input_dev = input_allocate_device()) == NULL) { -+ kfree(wm); -+ return -ENOMEM; -+ } -+ -+ /* set up touch configuration */ -+ info("detected a wm97%2x codec", wm->id & 0xff); -+ wm->input_dev->name = "wm97xx touchscreen"; -+ wm->input_dev->open = wm97xx_ts_input_open; -+ wm->input_dev->close = wm97xx_ts_input_close; -+ set_bit(EV_ABS, wm->input_dev->evbit); -+ set_bit(ABS_X, wm->input_dev->absbit); -+ set_bit(ABS_Y, wm->input_dev->absbit); -+ set_bit(ABS_PRESSURE, wm->input_dev->absbit); -+ wm->input_dev->absmax[ABS_X] = abs_x[1]; -+ wm->input_dev->absmax[ABS_Y] = abs_y[1]; -+ wm->input_dev->absmax[ABS_PRESSURE] = abs_p[1]; -+ wm->input_dev->absmin[ABS_X] = abs_x[0]; -+ wm->input_dev->absmin[ABS_Y] = abs_y[0]; -+ wm->input_dev->absmin[ABS_PRESSURE] = abs_p[0]; -+ wm->input_dev->absfuzz[ABS_X] = abs_x[2]; -+ wm->input_dev->absfuzz[ABS_Y] = abs_y[2]; -+ wm->input_dev->absfuzz[ABS_PRESSURE] = abs_p[2]; -+ wm->input_dev->private = wm; -+ wm->codec = &wm97xx_codec; -+ if((ret = input_register_device(wm->input_dev)) < 0) { -+ kfree(wm); -+ return -ENOMEM; -+ } -+ -+ if(aux_sys) -+ wm97xx_sys_add(dev); -+ -+ /* set up physical characteristics */ -+ wm->codec->digitiser_ioctl(wm, WM97XX_PHY_INIT); -+ -+ /* load gpio cache */ -+ wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG); -+ wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY); -+ wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY); -+ wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP); -+ wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS); -+ wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE); -+ -+ /* register our battery device */ -+ if (!(wm->battery_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) { -+ ret = -ENOMEM; -+ goto batt_err; -+ } -+ wm->battery_dev->bus = &wm97xx_bus_type; -+ strcpy(wm->battery_dev->bus_id,"wm97xx-battery"); -+ wm->battery_dev->driver_data = wm; -+ wm->battery_dev->parent = dev; -+ wm->battery_dev->release = wm97xx_release; -+ if((ret = device_register(wm->battery_dev)) < 0) -+ goto batt_reg_err; -+ -+ /* register our extended touch device (for machine specific extensions) */ -+ if (!(wm->touch_dev = kzalloc(sizeof(struct device), GFP_KERNEL))) { -+ ret = -ENOMEM; -+ goto touch_err; -+ } -+ wm->touch_dev->bus = &wm97xx_bus_type; -+ strcpy(wm->touch_dev->bus_id,"wm97xx-touchscreen"); -+ wm->touch_dev->driver_data = wm; -+ wm->touch_dev->parent = dev; -+ wm->touch_dev->release = wm97xx_release; -+ if((ret = device_register(wm->touch_dev)) < 0) -+ goto touch_reg_err; -+ -+ return ret; -+ -+touch_reg_err: -+ kfree(wm->touch_dev); -+touch_err: -+ device_unregister(wm->battery_dev); -+batt_reg_err: -+ kfree(wm->battery_dev); -+batt_err: -+ input_unregister_device(wm->input_dev); -+ kfree(wm); -+ return ret; -+} -+ -+static int wm97xx_remove(struct device *dev) -+{ -+ struct wm97xx *wm = dev_get_drvdata(dev); -+ -+ /* Stop touch reader thread */ -+ if (wm->ts_task) { -+ wm->ts_task = NULL; -+ wm->pen_is_down = 1; -+ wake_up_interruptible(&wm->pen_irq_wait); -+ wait_for_completion(&wm->ts_exit); -+ } -+ device_unregister(wm->battery_dev); -+ device_unregister(wm->touch_dev); -+ input_unregister_device(wm->input_dev); -+ -+ if(aux_sys) -+ wm97xx_sys_remove(dev); -+ -+ kfree(wm); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+int wm97xx_resume(struct device* dev) -+{ -+ struct wm97xx *wm = dev_get_drvdata(dev); -+ -+ /* restore digitiser and gpio's */ -+ if(wm->id == WM9713_ID2) { -+ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]); -+ wm97xx_reg_write(wm, 0x5a, wm->misc); -+ if(wm->ts_use_count) { -+ u16 reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff; -+ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg); -+ } -+ } -+ -+ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]); -+ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]); -+ -+ wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]); -+ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]); -+ wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]); -+ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]); -+ wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]); -+ wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]); -+ -+ return 0; -+} -+ -+#else -+#define wm97xx_resume NULL -+#endif -+ -+int wm97xx_register_mach_ops(struct wm97xx *wm, struct wm97xx_mach_ops *mach_ops) -+{ -+ mutex_lock(&wm->codec_mutex); -+ if(wm->mach_ops) { -+ mutex_unlock(&wm->codec_mutex); -+ return -EINVAL; -+ } -+ wm->mach_ops = mach_ops; -+ mutex_unlock(&wm->codec_mutex); -+ return 0; -+} -+ -+void wm97xx_unregister_mach_ops(struct wm97xx *wm) -+{ -+ mutex_lock(&wm->codec_mutex); -+ wm->mach_ops = NULL; -+ mutex_unlock(&wm->codec_mutex); -+} -+ -+static struct device_driver wm97xx_driver = { -+ .name = "ac97", -+ .bus = &ac97_bus_type, -+ .owner = THIS_MODULE, -+ .probe = wm97xx_probe, -+ .remove = wm97xx_remove, -+ .resume = wm97xx_resume, -+}; -+ -+static int __init wm97xx_init(void) -+{ -+ int ret; -+ -+ info("version %s liam.girdwood@wolfsonmicro.com", WM_CORE_VERSION); -+ if((ret = bus_register(&wm97xx_bus_type)) < 0) -+ return ret; -+ return driver_register(&wm97xx_driver); -+} -+ -+static void __exit wm97xx_exit(void) -+{ -+ driver_unregister(&wm97xx_driver); -+ bus_unregister(&wm97xx_bus_type); -+} -+ -+EXPORT_SYMBOL_GPL(wm97xx_get_gpio); -+EXPORT_SYMBOL_GPL(wm97xx_set_gpio); -+EXPORT_SYMBOL_GPL(wm97xx_config_gpio); -+EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc); -+EXPORT_SYMBOL_GPL(wm97xx_reg_read); -+EXPORT_SYMBOL_GPL(wm97xx_reg_write); -+EXPORT_SYMBOL_GPL(wm97xx_bus_type); -+EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops); -+EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops); -+ -+module_init(wm97xx_init); -+module_exit(wm97xx_exit); -+ -+/* Module information */ -+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); -+MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.17/include/linux/wm97xx.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.17/include/linux/wm97xx.h 2006-09-19 20:36:47.973052250 +0200 -@@ -0,0 +1,291 @@ -+ -+/* -+ * Register bits and API for Wolfson WM97xx series of codecs -+ */ -+ -+#ifndef _LINUX_WM97XX_H -+#define _LINUX_WM97XX_H -+ -+#include <sound/driver.h> -+#include <sound/core.h> -+#include <sound/pcm.h> -+#include <sound/ac97_codec.h> -+#include <sound/initval.h> -+#include <linux/types.h> -+#include <linux/list.h> -+#include <linux/input.h> /* Input device layer */ -+ -+/* -+ * WM97xx AC97 Touchscreen registers -+ */ -+#define AC97_WM97XX_DIGITISER1 0x76 -+#define AC97_WM97XX_DIGITISER2 0x78 -+#define AC97_WM97XX_DIGITISER_RD 0x7a -+#define AC97_WM9713_DIG1 0x74 -+#define AC97_WM9713_DIG2 AC97_WM97XX_DIGITISER1 -+#define AC97_WM9713_DIG3 AC97_WM97XX_DIGITISER2 -+ -+/* -+ * WM97xx register bits -+ */ -+#define WM97XX_POLL 0x8000 /* initiate a polling measurement */ -+#define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */ -+#define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */ -+#define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */ -+#define WM97XX_ADCSEL_MASK 0x7000 -+#define WM97XX_COO 0x0800 /* enable coordinate mode */ -+#define WM97XX_CTC 0x0400 /* enable continuous mode */ -+#define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */ -+#define WM97XX_CM_RATE_187 0x0100 /* 187.5Hz continuous rate */ -+#define WM97XX_CM_RATE_375 0x0200 /* 375Hz continuous rate */ -+#define WM97XX_CM_RATE_750 0x0300 /* 750Hz continuous rate */ -+#define WM97XX_CM_RATE_8K 0x00f0 /* 8kHz continuous rate */ -+#define WM97XX_CM_RATE_12K 0x01f0 /* 12kHz continuous rate */ -+#define WM97XX_CM_RATE_24K 0x02f0 /* 24kHz continuous rate */ -+#define WM97XX_CM_RATE_48K 0x03f0 /* 48kHz continuous rate */ -+#define WM97XX_CM_RATE_MASK 0x03f0 -+#define WM97XX_RATE(i) (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0)) -+#define WM97XX_DELAY(i) ((i << 4) & 0x00f0) /* sample delay times */ -+#define WM97XX_DELAY_MASK 0x00f0 -+#define WM97XX_SLEN 0x0008 /* slot read back enable */ -+#define WM97XX_SLT(i) ((i - 5) & 0x7) /* touchpanel slot selection (5-11) */ -+#define WM97XX_SLT_MASK 0x0007 -+#define WM97XX_PRP_DETW 0x4000 /* pen detect on, digitiser off, wake up */ -+#define WM97XX_PRP_DET 0x8000 /* pen detect on, digitiser off, no wake up */ -+#define WM97XX_PRP_DET_DIG 0xc000 /* pen detect on, digitiser on */ -+#define WM97XX_RPR 0x2000 /* wake up on pen down */ -+#define WM97XX_PEN_DOWN 0x8000 /* pen is down */ -+#define WM97XX_ADCSRC_MASK 0x7000 /* ADC source mask */ -+ -+#define WM97XX_AUX_ID1 0x8001 -+#define WM97XX_AUX_ID2 0x8002 -+#define WM97XX_AUX_ID3 0x8003 -+#define WM97XX_AUX_ID4 0x8004 -+ -+ -+/* WM9712 Bits */ -+#define WM9712_45W 0x1000 /* set for 5-wire touchscreen */ -+#define WM9712_PDEN 0x0800 /* measure only when pen down */ -+#define WM9712_WAIT 0x0200 /* wait until adc is read before next sample */ -+#define WM9712_PIL 0x0100 /* current used for pressure measurement. set 400uA else 200uA */ -+#define WM9712_MASK_HI 0x0040 /* hi on mask pin (47) stops conversions */ -+#define WM9712_MASK_EDGE 0x0080 /* rising/falling edge on pin delays sample */ -+#define WM9712_MASK_SYNC 0x00c0 /* rising/falling edge on mask initiates sample */ -+#define WM9712_RPU(i) (i&0x3f) /* internal pull up on pen detect (64k / rpu) */ -+#define WM9712_PD(i) (0x1 << i) /* power management */ -+ -+/* WM9712 Registers */ -+#define AC97_WM9712_POWER 0x24 -+#define AC97_WM9712_REV 0x58 -+ -+/* WM9705 Bits */ -+#define WM9705_PDEN 0x1000 /* measure only when pen is down */ -+#define WM9705_PINV 0x0800 /* inverts sense of pen down output */ -+#define WM9705_BSEN 0x0400 /* BUSY flag enable, pin47 is 1 when busy */ -+#define WM9705_BINV 0x0200 /* invert BUSY (pin47) output */ -+#define WM9705_WAIT 0x0100 /* wait until adc is read before next sample */ -+#define WM9705_PIL 0x0080 /* current used for pressure measurement. set 400uA else 200uA */ -+#define WM9705_PHIZ 0x0040 /* set PHONE and PCBEEP inputs to high impedance */ -+#define WM9705_MASK_HI 0x0010 /* hi on mask stops conversions */ -+#define WM9705_MASK_EDGE 0x0020 /* rising/falling edge on pin delays sample */ -+#define WM9705_MASK_SYNC 0x0030 /* rising/falling edge on mask initiates sample */ -+#define WM9705_PDD(i) (i & 0x000f) /* pen detect comparator threshold */ -+ -+ -+/* WM9713 Bits */ -+#define WM9713_PDPOL 0x0400 /* Pen down polarity */ -+#define WM9713_POLL 0x0200 /* initiate a polling measurement */ -+#define WM9713_CTC 0x0100 /* enable continuous mode */ -+#define WM9713_ADCSEL_X 0x0002 /* X measurement */ -+#define WM9713_ADCSEL_Y 0x0004 /* Y measurement */ -+#define WM9713_ADCSEL_PRES 0x0008 /* Pressure measurement */ -+#define WM9713_COO 0x0001 /* enable coordinate mode */ -+#define WM9713_PDEN 0x0800 /* measure only when pen down */ -+#define WM9713_ADCSEL_MASK 0x00fe /* ADC selection mask */ -+#define WM9713_WAIT 0x0200 /* coordinate wait */ -+ -+/* AUX ADC ID's */ -+#define TS_COMP1 0x0 -+#define TS_COMP2 0x1 -+#define TS_BMON 0x2 -+#define TS_WIPER 0x3 -+ -+/* ID numbers */ -+#define WM97XX_ID1 0x574d -+#define WM9712_ID2 0x4c12 -+#define WM9705_ID2 0x4c05 -+#define WM9713_ID2 0x4c13 -+ -+/* Codec GPIO's */ -+#define WM97XX_MAX_GPIO 16 -+#define WM97XX_GPIO_1 (1 << 1) -+#define WM97XX_GPIO_2 (1 << 2) -+#define WM97XX_GPIO_3 (1 << 3) -+#define WM97XX_GPIO_4 (1 << 4) -+#define WM97XX_GPIO_5 (1 << 5) -+#define WM97XX_GPIO_6 (1 << 6) -+#define WM97XX_GPIO_7 (1 << 7) -+#define WM97XX_GPIO_8 (1 << 8) -+#define WM97XX_GPIO_9 (1 << 9) -+#define WM97XX_GPIO_10 (1 << 10) -+#define WM97XX_GPIO_11 (1 << 11) -+#define WM97XX_GPIO_12 (1 << 12) -+#define WM97XX_GPIO_13 (1 << 13) -+#define WM97XX_GPIO_14 (1 << 14) -+#define WM97XX_GPIO_15 (1 << 15) -+ -+ -+#define AC97_LINK_FRAME 21 /* time in uS for AC97 link frame */ -+ -+ -+/*---------------- Return codes from sample reading functions ---------------*/ -+ -+/* More data is available; call the sample gathering function again */ -+#define RC_AGAIN 0x00000001 -+/* The returned sample is valid */ -+#define RC_VALID 0x00000002 -+/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */ -+#define RC_PENUP 0x00000004 -+/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful -+ to tell the handler that the pen is down but we don't know yet his coords, -+ so the handler should not sleep or wait for pendown irq) */ -+#define RC_PENDOWN 0x00000008 -+ -+/* The wm97xx driver provides a private API for writing platform-specific -+ * drivers. -+ */ -+ -+/* The structure used to return arch specific sampled data into */ -+struct wm97xx_data { -+ int x; -+ int y; -+ int p; -+}; -+ -+/* Codec GPIO status -+ */ -+typedef enum { -+ WM97XX_GPIO_HIGH, -+ WM97XX_GPIO_LOW -+} wm97xx_gpio_status_t; -+ -+/* Codec GPIO direction -+ */ -+typedef enum { -+ WM97XX_GPIO_IN, -+ WM97XX_GPIO_OUT -+} wm97xx_gpio_dir_t; -+ -+/* Codec GPIO polarity -+ */ -+typedef enum { -+ WM97XX_GPIO_POL_HIGH, -+ WM97XX_GPIO_POL_LOW -+} wm97xx_gpio_pol_t; -+ -+/* Codec GPIO sticky -+ */ -+typedef enum { -+ WM97XX_GPIO_STICKY, -+ WM97XX_GPIO_NOTSTICKY -+} wm97xx_gpio_sticky_t; -+ -+/* Codec GPIO wake -+ */ -+typedef enum { -+ WM97XX_GPIO_WAKE, -+ WM97XX_GPIO_NOWAKE -+} wm97xx_gpio_wake_t; -+ -+ -+/* -+ * Digitiser ioctl commands -+ */ -+#define WM97XX_DIG_START 0x1 -+#define WM97XX_DIG_STOP 0x2 -+#define WM97XX_PHY_INIT 0x3 -+#define WM97XX_AUX_PREPARE 0x4 -+#define WM97XX_DIG_RESTORE 0x5 -+ -+struct wm97xx; -+extern struct wm97xx_codec_drv wm97xx_codec; -+ -+/* -+ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs -+ */ -+struct wm97xx_codec_drv { -+ u16 id; -+ char *name; -+ int (*poll_sample) (struct wm97xx *, int adcsel, int *sample); /* read 1 sample */ -+ int (*poll_touch) (struct wm97xx *, struct wm97xx_data *); /* read X,Y,[P] in poll */ -+ int (*digitiser_ioctl) (struct wm97xx *, int cmd); -+ int (*acc_enable) (struct wm97xx *, int enable); -+}; -+ -+ -+/* Machine specific and accelerated touch operations */ -+struct wm97xx_mach_ops { -+ -+ /* accelerated touch readback - coords are transmited on AC97 link */ -+ int acc_enabled; -+ void (*acc_pen_up) (struct wm97xx *); -+ int (*acc_pen_down) (struct wm97xx *); -+ int (*acc_startup) (struct wm97xx *); -+ void (*acc_shutdown) (struct wm97xx *); -+ -+ /* pre and post sample - can be used to minimise any analog noise */ -+ void (*pre_sample) (int); /* function to run before sampling */ -+ void (*post_sample) (int); /* function to run after sampling */ -+}; -+ -+struct wm97xx { -+ u16 dig[3], id, gpio[6], misc; /* Cached codec registers */ -+ u16 dig_save[3]; /* saved during aux reading */ -+ struct wm97xx_codec_drv *codec; /* attached codec driver*/ -+ struct input_dev* input_dev; /* touchscreen input device */ -+ ac97_t *ac97; /* ALSA codec access */ -+ struct device *dev; /* ALSA device */ -+ struct device *battery_dev; -+ struct device *touch_dev; -+ struct wm97xx_mach_ops *mach_ops; -+ struct mutex codec_mutex; -+ struct completion ts_init; -+ struct completion ts_exit; -+ struct task_struct *ts_task; -+ unsigned int pen_irq; /* Pen IRQ number in use */ -+ wait_queue_head_t pen_irq_wait; /* Pen IRQ wait queue */ -+ struct workqueue_struct *pen_irq_workq; -+ struct work_struct pen_event_work; -+ u16 acc_slot; /* AC97 slot used for acc touch data */ -+ u16 acc_rate; /* acc touch data rate */ -+ unsigned int ts_use_count; -+ unsigned pen_is_down:1; /* Pen is down */ -+ unsigned aux_waiting:1; /* aux measurement waiting */ -+ unsigned pen_probably_down:1; /* used in polling mode */ -+}; -+ -+/* Codec GPIO access (not supported on WM9705) -+ * This can be used to set/get codec GPIO and Virtual GPIO status. -+ */ -+wm97xx_gpio_status_t wm97xx_get_gpio(struct wm97xx *wm, u32 gpio); -+void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, -+ wm97xx_gpio_status_t status); -+void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, -+ wm97xx_gpio_dir_t dir, -+ wm97xx_gpio_pol_t pol, -+ wm97xx_gpio_sticky_t sticky, -+ wm97xx_gpio_wake_t wake); -+ -+/* codec AC97 IO access */ -+int wm97xx_reg_read(struct wm97xx *wm, u16 reg); -+void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val); -+ -+/* aux adc readback */ -+int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel); -+ -+/* machine ops */ -+int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *); -+void wm97xx_unregister_mach_ops(struct wm97xx *); -+ -+extern struct bus_type wm97xx_bus_type; -+#endif |