omap3-pandora-kernel: Add AUFS2 shim and keypad 'WIP' code.
authorDavid-John Willis <John.Willis@Distant-earth.com>
Tue, 17 Nov 2009 12:11:41 +0000 (12:11 +0000)
committerDavid-John Willis <John.Willis@Distant-earth.com>
Tue, 17 Nov 2009 12:11:41 +0000 (12:11 +0000)
recipes/linux/omap3-pandora-kernel/aufs2/aufs2-base.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/aufs2/aufs2-standalone.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/defconfig
recipes/linux/omap3-pandora-kernel/keypad/0001-input-remove-old-twl4030keypad-to-replace-it-with-ma.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0002-Input-add-support-for-generic-GPIO-based-matrix-keyp.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0003-Input-matrix_keypad-make-matrix-keymap-size-dynamic.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0004-Input-matrix-keypad-add-function-to-build-device-key.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0005-Input-add-twl4030_keypad-driver.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0006-input-hacks-updates-for-mainline-twl4030-driver.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel/keypad/0007-some-hackish-Fn-handling-for-testing.patch [new file with mode: 0644]
recipes/linux/omap3-pandora-kernel_2.6.27-pandora.bb

diff --git a/recipes/linux/omap3-pandora-kernel/aufs2/aufs2-base.patch b/recipes/linux/omap3-pandora-kernel/aufs2/aufs2-base.patch
new file mode 100644 (file)
index 0000000..b97a4ca
--- /dev/null
@@ -0,0 +1,81 @@
+aufs2 base patch for linux-2.6.27
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 4ea63ed..2759ad4 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1241,7 +1241,7 @@ out:
+  * needs parent already locked. Doesn't follow mounts.
+  * SMP-safe.
+  */
+-static struct dentry *lookup_hash(struct nameidata *nd)
++struct dentry *lookup_hash(struct nameidata *nd)
+ {
+       int err;
+@@ -1251,7 +1251,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
+       return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
+-static int __lookup_one_len(const char *name, struct qstr *this,
++int __lookup_one_len(const char *name, struct qstr *this,
+               struct dentry *base, int len)
+ {
+       unsigned long hash;
+diff --git a/fs/splice.c b/fs/splice.c
+index a1e701c..409245a 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -887,8 +887,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+  * Attempt to initiate a splice from pipe to file.
+  */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+-                         loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                  loff_t *ppos, size_t len, unsigned int flags)
+ {
+       int ret;
+@@ -911,9 +911,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ /*
+  * Attempt to initiate a splice from a file to a pipe.
+  */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+-                       struct pipe_inode_info *pipe, size_t len,
+-                       unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++                struct pipe_inode_info *pipe, size_t len,
++                unsigned int flags)
+ {
+       int ret;
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 68f8c32..5522432 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -71,6 +71,9 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
+ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+ extern void release_open_intent(struct nameidata *);
++extern struct dentry *lookup_hash(struct nameidata *nd);
++extern int __lookup_one_len(const char *name, struct qstr *this,
++                          struct dentry *base, int len);
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+ extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 528dcb9..5123bc6 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -71,4 +71,10 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+                                     splice_direct_actor *);
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                         loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++                       struct pipe_inode_info *pipe, size_t len,
++                       unsigned int flags);
++
+ #endif
diff --git a/recipes/linux/omap3-pandora-kernel/aufs2/aufs2-standalone.patch b/recipes/linux/omap3-pandora-kernel/aufs2/aufs2-standalone.patch
new file mode 100644 (file)
index 0000000..c40db9e
--- /dev/null
@@ -0,0 +1,138 @@
+aufs2 standalone patch for linux-2.6.27
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 2759ad4..b207821 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -354,6 +354,7 @@ int deny_write_access(struct file * file)
+       return 0;
+ }
++EXPORT_SYMBOL(deny_write_access);
+ /**
+  * path_get - get a reference to a path
+@@ -1250,6 +1251,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
+               return ERR_PTR(err);
+       return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
++EXPORT_SYMBOL(lookup_hash);
+ int __lookup_one_len(const char *name, struct qstr *this,
+               struct dentry *base, int len)
+@@ -1272,6 +1274,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
+       this->hash = end_name_hash(hash);
+       return 0;
+ }
++EXPORT_SYMBOL(__lookup_one_len);
+ /**
+  * lookup_one_len - filesystem helper to lookup single pathname component
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 6e283c9..36030e8 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -37,6 +37,7 @@
+ /* spinlock for vfsmount related operations, inplace of dcache_lock */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
++EXPORT_SYMBOL(vfsmount_lock);
+ static int event;
+ static DEFINE_IDA(mnt_id_ida);
+diff --git a/fs/open.c b/fs/open.c
+index 07da935..b8e9726 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -222,6 +222,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       return err;
+ }
++EXPORT_SYMBOL(do_truncate);
+ static long do_sys_truncate(const char __user *pathname, loff_t length)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index 409245a..48d7e72 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -907,6 +907,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+       return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL(do_splice_from);
+ /*
+  * Attempt to initiate a splice from a file to a pipe.
+@@ -929,6 +930,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
+       return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL(do_splice_to);
+ /**
+  * splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/fs/super.c b/fs/super.c
+index e931ae9..141853c 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -270,6 +270,7 @@ int fsync_super(struct super_block *sb)
+       __fsync_super(sb);
+       return sync_blockdev(sb->s_bdev);
+ }
++EXPORT_SYMBOL(fsync_super);
+ /**
+  *    generic_shutdown_super  -       common helper for ->kill_sb()
+diff --git a/fs/sync.c b/fs/sync.c
+index 2967562..34040d6 100644
+--- a/fs/sync.c
++++ b/fs/sync.c
+@@ -104,6 +104,7 @@ long do_fsync(struct file *file, int datasync)
+ out:
+       return ret;
+ }
++EXPORT_SYMBOL(do_fsync);
+ static long __do_fsync(unsigned int fd, int datasync)
+ {
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 46f2397..00ec611 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -537,6 +537,7 @@ acc_check:
+       return -EPERM;
+ }
++EXPORT_SYMBOL(devcgroup_inode_permission);
+ int devcgroup_inode_mknod(int mode, dev_t dev)
+ {
+diff --git a/security/security.c b/security/security.c
+index 3a4b4f5..79be80b 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -425,6 +425,7 @@ int security_inode_readlink(struct dentry *dentry)
+               return 0;
+       return security_ops->inode_readlink(dentry);
+ }
++EXPORT_SYMBOL(security_inode_readlink);
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+@@ -439,6 +440,7 @@ int security_inode_permission(struct inode *inode, int mask)
+               return 0;
+       return security_ops->inode_permission(inode, mask);
+ }
++EXPORT_SYMBOL(security_inode_permission);
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
+@@ -539,6 +541,7 @@ int security_file_permission(struct file *file, int mask)
+ {
+       return security_ops->file_permission(file, mask);
+ }
++EXPORT_SYMBOL(security_file_permission);
+ int security_file_alloc(struct file *file)
+ {
index 3c5f95e..937a8ab 100755 (executable)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.27-omap1
-# Sun Aug 30 18:56:27 2009
+# Fri Nov 13 10:18:13 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -277,7 +277,7 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=128
 CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
+CONFIG_OABI_COMPAT=y
 CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -310,21 +310,7 @@ CONFIG_ATAGS_PROC=y
 #
 # CPU Frequency scaling
 #
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=y
-# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+# CONFIG_CPU_FREQ is not set
 
 #
 # Floating point emulation
@@ -333,6 +319,8 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
 #
 # At least one emulation must be selected
 #
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
 CONFIG_VFP=y
 CONFIG_VFPv3=y
 CONFIG_NEON=y
@@ -385,7 +373,7 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -396,7 +384,25 @@ CONFIG_INET_TCP_DIAG=y
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
@@ -455,7 +461,7 @@ CONFIG_NET_SCH_FIFO=y
 # CONFIG_IRDA is not set
 CONFIG_BT=y
 CONFIG_BT_L2CAP=y
-# CONFIG_BT_SCO is not set
+CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=y
@@ -466,10 +472,12 @@ CONFIG_BT_HIDP=y
 #
 # Bluetooth device drivers
 #
-# CONFIG_BT_HCIUSB is not set
-# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTUSB=m
 # CONFIG_BT_HCIBTSDIO is not set
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+CONFIG_BT_HCIUART_LL=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
@@ -507,7 +515,9 @@ CONFIG_MAC80211_VERBOSE_DEBUG=y
 # CONFIG_MAC80211_LOWTX_FRAME_DUMP is not set
 # CONFIG_MAC80211_VERBOSE_SPECT_MGMT_DEBUG is not set
 # CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
+CONFIG_RFKILL=m
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_RFKILL_LEDS=y
 # CONFIG_NET_9P is not set
 
 #
@@ -735,6 +745,7 @@ CONFIG_USB_ARMLINUX=y
 CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
 CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_HSO is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 CONFIG_PPP_MULTILINK=y
@@ -814,7 +825,7 @@ CONFIG_INPUT_MISC=y
 # CONFIG_INPUT_ATI_REMOTE is not set
 # CONFIG_INPUT_ATI_REMOTE2 is not set
 # CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
+CONFIG_INPUT_POWERMATE=m
 # CONFIG_INPUT_YEALINK is not set
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_VSENSE=y
@@ -914,6 +925,7 @@ CONFIG_TWL4030_PWRBUTTON=y
 CONFIG_TWL4030_POWEROFF=y
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
 # CONFIG_LP5521 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -968,7 +980,61 @@ CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_DS2760 is not set
 # CONFIG_BATTERY_BQ27x00 is not set
 CONFIG_TWL4030_BCI_BATTERY=y
-# CONFIG_HWMON is not set
+CONFIG_HWMON=m
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+# CONFIG_SENSORS_OMAP34XX is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_WATCHDOG is not set
 
 #
@@ -1077,7 +1143,7 @@ CONFIG_USB_ZR364XX=m
 # CONFIG_VIDEO_SH_MOBILE_CEU is not set
 CONFIG_RADIO_ADAPTERS=y
 # CONFIG_RADIO_TEA5761 is not set
-# CONFIG_USB_DSBR is not set
+CONFIG_USB_DSBR=m
 # CONFIG_USB_SI470X is not set
 CONFIG_DVB_CAPTURE_DRIVERS=y
 # CONFIG_TTPCI_EEPROM is not set
@@ -1196,7 +1262,7 @@ CONFIG_DVB_LNBP21=m
 # CONFIG_DVB_ISL6405 is not set
 CONFIG_DVB_ISL6421=m
 CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+CONFIG_USB_DABUSB=m
 
 #
 # Graphics support
@@ -1546,7 +1612,7 @@ CONFIG_MMC_EMBEDDED_SDIO=y
 #
 CONFIG_MMC_BLOCK=y
 CONFIG_MMC_BLOCK_BOUNCE=y
-# CONFIG_SDIO_UART is not set
+CONFIG_SDIO_UART=m
 # CONFIG_MMC_TEST is not set
 
 #
@@ -1662,7 +1728,7 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
@@ -1744,9 +1810,13 @@ CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0001-input-remove-old-twl4030keypad-to-replace-it-with-ma.patch b/recipes/linux/omap3-pandora-kernel/keypad/0001-input-remove-old-twl4030keypad-to-replace-it-with-ma.patch
new file mode 100644 (file)
index 0000000..610dbe3
--- /dev/null
@@ -0,0 +1,566 @@
+From 917491ccf4546bbd34d999cd4878c3b10b621c1c Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Tue, 3 Nov 2009 15:15:00 +0200
+Subject: [PATCH 1/7] input: remove old twl4030keypad to replace it with mainline version
+
+---
+ drivers/input/keyboard/Kconfig              |   10 -
+ drivers/input/keyboard/Makefile             |    1 -
+ drivers/input/keyboard/omap-twl4030keypad.c |  422 ---------------------------
+ drivers/input/keyboard/twl4030-keypad.h     |   82 ------
+ 4 files changed, 0 insertions(+), 515 deletions(-)
+ delete mode 100644 drivers/input/keyboard/omap-twl4030keypad.c
+ delete mode 100644 drivers/input/keyboard/twl4030-keypad.h
+
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 616ce41..59ad05a 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -259,16 +259,6 @@ config KEYBOARD_OMAP
+         To compile this driver as a module, choose M here: the
+         module will be called omap-keypad.
+-config KEYBOARD_TWL4030
+-      tristate "TI TWL4030 keypad support"
+-      depends on TWL4030_CORE && (MACH_OMAP_2430SDP || MACH_OMAP2EVM || MACH_OMAP_3430SDP || MACH_OMAP3EVM || MACH_OMAP3_PANDORA)
+-      help
+-        Say Y here if you want to use the OMAP TWL4030 keypad.
+-
+-        To compile this driver as a module, choose M here: the
+-        module will be called omap-twl4030keypad. This driver depends on
+-        TWL4030 Core and TWL4030 GPIO I2C client driver
+-
+ config OMAP_PS2
+       tristate "TI OMAP Innovator 1510 PS/2 keyboard & mouse support"
+       depends on ARCH_OMAP15XX && MACH_OMAP_INNOVATOR
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index ae47fff..81e59f7 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -22,7 +22,6 @@ obj-$(CONFIG_KEYBOARD_OMAP)          += omap-keypad.o
+ obj-$(CONFIG_OMAP_PS2)                        += innovator_ps2.o
+ obj-$(CONFIG_KEYBOARD_TSC2301)                += tsc2301_kp.o
+ obj-$(CONFIG_KEYBOARD_LM8323)         += lm8323.o
+-obj-$(CONFIG_KEYBOARD_TWL4030)                += omap-twl4030keypad.o
+ obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keypad.o
+ obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
+ obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
+diff --git a/drivers/input/keyboard/omap-twl4030keypad.c b/drivers/input/keyboard/omap-twl4030keypad.c
+deleted file mode 100644
+index f6f1ad8..0000000
+--- a/drivers/input/keyboard/omap-twl4030keypad.c
++++ /dev/null
+@@ -1,422 +0,0 @@
+-/*
+- * drivers/input/keyboard/omap-twl4030keypad.c
+- *
+- * Copyright (C) 2007 Texas Instruments, Inc.
+- * Copyright (C) 2008 Nokia Corporation
+- *
+- * Code re-written for 2430SDP by:
+- * Syed Mohammed Khasim <x0khasim@ti.com>
+- *
+- * Initial Code:
+- * Manjunatha G K <manjugk@ti.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.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/types.h>
+-#include <linux/input.h>
+-#include <linux/kernel.h>
+-#include <linux/mutex.h>
+-#include <linux/delay.h>
+-#include <linux/bitops.h>
+-#include <linux/platform_device.h>
+-#include <linux/i2c.h>
+-#include <linux/i2c/twl4030.h>
+-#include <linux/irq.h>
+-#include "twl4030-keypad.h"
+-
+-#define PTV_PRESCALER         4
+-
+-#define MAX_ROWS              8 /* TWL4030 hardlimit */
+-#define ROWCOL_MASK           0xFF000000
+-#define KEYNUM_MASK           0x00FFFFFF
+-#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+-
+-/* Global variables */
+-
+-struct omap_keypad {
+-      int             *keymap;
+-      unsigned int    keymapsize;
+-      u16             kp_state[MAX_ROWS];
+-      int             n_rows;
+-      int             n_cols;
+-      int             irq;
+-
+-      struct device   *dbg_dev;
+-      struct input_dev *omap_twl4030kp;
+-
+-      /* sync read/write */
+-      struct mutex    mutex;
+-};
+-
+-static int twl4030_kpread(struct omap_keypad *kp,
+-              u32 module, u8 *data, u32 reg, u8 num_bytes)
+-{
+-      int ret;
+-
+-      ret = twl4030_i2c_read(module, data, reg, num_bytes);
+-      if (ret < 0) {
+-              dev_warn(kp->dbg_dev,
+-                      "Couldn't read TWL4030: %X - ret %d[%x]\n",
+-                       reg, ret, ret);
+-              return ret;
+-      }
+-      return ret;
+-}
+-
+-static int twl4030_kpwrite_u8(struct omap_keypad *kp,
+-              u32 module, u8 data, u32 reg)
+-{
+-      int ret;
+-
+-      ret = twl4030_i2c_write_u8(module, data, reg);
+-      if (ret < 0) {
+-              dev_warn(kp->dbg_dev,
+-                      "Could not write TWL4030: %X - ret %d[%x]\n",
+-                       reg, ret, ret);
+-              return ret;
+-      }
+-      return ret;
+-}
+-
+-static int omap_kp_find_key(struct omap_keypad *kp, int col, int row)
+-{
+-      int i, rc;
+-
+-      rc = KEY(col, row, 0);
+-      for (i = 0; i < kp->keymapsize; i++)
+-              if ((kp->keymap[i] & ROWCOL_MASK) == rc)
+-                      return kp->keymap[i] & KEYNUM_MASK;
+-
+-      return -EINVAL;
+-}
+-
+-static inline u16 omap_kp_col_xlate(struct omap_keypad *kp, u8 col)
+-{
+-      /* If all bits in a row are active for all coloumns then
+-       * we have that row line connected to gnd. Mark this
+-       * key on as if it was on matrix position n_cols (ie
+-       * one higher than the size of the matrix).
+-       */
+-      if (col == 0xFF)
+-              return 1 << kp->n_cols;
+-      else
+-              return col & ((1 << kp->n_cols) - 1);
+-}
+-
+-static int omap_kp_read_kp_matrix_state(struct omap_keypad *kp, u16 *state)
+-{
+-      u8 new_state[MAX_ROWS];
+-      int row;
+-      int ret = twl4030_kpread(kp, TWL4030_MODULE_KEYPAD,
+-                               new_state, KEYP_FULL_CODE_7_0, kp->n_rows);
+-      if (ret >= 0) {
+-              for (row = 0; row < kp->n_rows; row++)
+-                      state[row] = omap_kp_col_xlate(kp, new_state[row]);
+-      }
+-      return ret;
+-}
+-
+-static int omap_kp_is_in_ghost_state(struct omap_keypad *kp, u16 *key_state)
+-{
+-      int i;
+-      u16 check = 0;
+-
+-      for (i = 0; i < kp->n_rows; i++) {
+-              u16 col = key_state[i];
+-
+-              if ((col & check) && hweight16(col) > 1)
+-                      return 1;
+-              check |= col;
+-      }
+-
+-      return 0;
+-}
+-
+-static void twl4030_kp_scan(struct omap_keypad *kp, int release_all)
+-{
+-      u16 new_state[MAX_ROWS];
+-      int col, row;
+-
+-      if (release_all)
+-              memset(new_state, 0, sizeof(new_state));
+-      else {
+-              /* check for any changes */
+-              int ret = omap_kp_read_kp_matrix_state(kp, new_state);
+-              if (ret < 0)    /* panic ... */
+-                      return;
+-
+-              if (omap_kp_is_in_ghost_state(kp, new_state))
+-                      return;
+-      }
+-
+-      mutex_lock(&kp->mutex);
+-
+-      /* check for changes and print those */
+-      for (row = 0; row < kp->n_rows; row++) {
+-              int changed = new_state[row] ^ kp->kp_state[row];
+-
+-              if (!changed)
+-                      continue;
+-
+-              for (col = 0; col < kp->n_cols; col++) {
+-                      int key;
+-
+-                      if (!(changed & (1 << col)))
+-                              continue;
+-
+-                      dev_dbg(kp->dbg_dev, "key [%d:%d] %s\n", row, col,
+-                              (new_state[row] & (1 << col)) ?
+-                              "press" : "release");
+-
+-                      key = omap_kp_find_key(kp, col, row);
+-                      if (key < 0)
+-                              dev_warn(kp->dbg_dev,
+-                                      "Spurious key event %d-%d\n",
+-                                       col, row);
+-                      else
+-                              input_report_key(kp->omap_twl4030kp, key,
+-                                               new_state[row] & (1 << col));
+-              }
+-              kp->kp_state[row] = new_state[row];
+-      }
+-
+-      mutex_unlock(&kp->mutex);
+-}
+-
+-/*
+- * Keypad interrupt handler
+- */
+-static irqreturn_t do_kp_irq(int irq, void *_kp)
+-{
+-      struct omap_keypad *kp = _kp;
+-      u8 reg;
+-      int ret;
+-
+-#ifdef CONFIG_LOCKDEP
+-      /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+-       * we don't want and can't tolerate.  Although it might be
+-       * friendlier not to borrow this thread context...
+-       */
+-      local_irq_enable();
+-#endif
+-
+-      /* Read & Clear TWL4030 pending interrupt */
+-      ret = twl4030_kpread(kp, TWL4030_MODULE_KEYPAD, &reg, KEYP_ISR1, 1);
+-
+-      /* Release all keys if I2C has gone bad or
+-       * the KEYP has gone to idle state */
+-      if ((ret >= 0) && (reg & KEYP_IMR1_KP))
+-              twl4030_kp_scan(kp, 0);
+-      else
+-              twl4030_kp_scan(kp, 1);
+-
+-      return IRQ_HANDLED;
+-}
+-
+-/*
+- * Registers keypad device with input sub system
+- * and configures TWL4030 keypad registers
+- */
+-static int __init omap_kp_probe(struct platform_device *pdev)
+-{
+-      u8 reg;
+-      int i;
+-      int ret = 0;
+-      struct omap_keypad *kp;
+-      struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
+-
+-      kp = kzalloc(sizeof(*kp), GFP_KERNEL);
+-      if (!kp)
+-              return -ENOMEM;
+-
+-      if (!pdata->rows || !pdata->cols || !pdata->keymap) {
+-              dev_err(&pdev->dev, "No rows, cols or keymap from pdata\n");
+-              kfree(kp);
+-              return -EINVAL;
+-      }
+-
+-      dev_set_drvdata(&pdev->dev, kp);
+-
+-      /* Get the debug Device */
+-      kp->dbg_dev = &pdev->dev;
+-
+-      kp->omap_twl4030kp = input_allocate_device();
+-      if (!kp->omap_twl4030kp) {
+-              kfree(kp);
+-              return -ENOMEM;
+-      }
+-
+-      mutex_init(&kp->mutex);
+-
+-      kp->keymap = pdata->keymap;
+-      kp->keymapsize = pdata->keymapsize;
+-      kp->n_rows = pdata->rows;
+-      kp->n_cols = pdata->cols;
+-      kp->irq = pdata->irq;
+-
+-      /* setup input device */
+-      set_bit(EV_KEY, kp->omap_twl4030kp->evbit);
+-
+-      /* Enable auto repeat feature of Linux input subsystem */
+-      if (pdata->rep)
+-              set_bit(EV_REP, kp->omap_twl4030kp->evbit);
+-
+-      for (i = 0; i < kp->keymapsize; i++)
+-              set_bit(kp->keymap[i] & KEYNUM_MASK,
+-                              kp->omap_twl4030kp->keybit);
+-
+-      kp->omap_twl4030kp->name        = "omap_twl4030keypad";
+-      kp->omap_twl4030kp->phys        = "omap_twl4030keypad/input0";
+-      kp->omap_twl4030kp->dev.parent  = &pdev->dev;
+-
+-      kp->omap_twl4030kp->id.bustype  = BUS_HOST;
+-      kp->omap_twl4030kp->id.vendor   = 0x0001;
+-      kp->omap_twl4030kp->id.product  = 0x0001;
+-      kp->omap_twl4030kp->id.version  = 0x0003;
+-
+-      kp->omap_twl4030kp->keycode     = kp->keymap;
+-      kp->omap_twl4030kp->keycodesize = sizeof(unsigned int);
+-      kp->omap_twl4030kp->keycodemax  = kp->keymapsize;
+-
+-      ret = input_register_device(kp->omap_twl4030kp);
+-      if (ret < 0) {
+-              dev_err(kp->dbg_dev,
+-                      "Unable to register twl4030 keypad device\n");
+-              goto err2;
+-      }
+-
+-      /* Disable auto-repeat */
+-      reg = KEYP_CTRL_NOAUTORPT;
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD, reg, KEYP_CTRL);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /* Enable TO rising and KP rising and falling edge detection */
+-      reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING;
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD, reg, KEYP_EDR);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /* Set PTV prescaler Field */
+-      reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT);
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD, reg, KEYP_LK_PTV);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /* Set key debounce time to 20 ms */
+-      i = KEYP_PERIOD_US(20000, PTV_PRESCALER);
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD, i, KEYP_DEB);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /* Set timeout period to 100 ms */
+-      i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD,
+-                               (i & 0xFF), KEYP_TIMEOUT_L);
+-      if (ret < 0)
+-              goto err3;
+-
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD,
+-                               (i >> 8), KEYP_TIMEOUT_H);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /* Enable Clear-on-Read */
+-      reg = KEYP_SIH_CTRL_COR | KEYP_SIH_CTRL_PEND_DIS;
+-      ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD,
+-                               reg, KEYP_SIH_CTRL);
+-      if (ret < 0)
+-              goto err3;
+-
+-      /*
+-       * This ISR will always execute in kernel thread context because of
+-       * the need to access the TWL4030 over the I2C bus.
+-       */
+-      ret = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp);
+-      if (ret < 0) {
+-              dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
+-                      kp->irq);
+-              goto err3;
+-      } else {
+-              /* Enable KP and TO interrupts now. */
+-              reg = ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
+-              ret = twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD,
+-                                       reg, KEYP_IMR1);
+-              if (ret < 0)
+-                      goto err5;
+-      }
+-
+-      ret = omap_kp_read_kp_matrix_state(kp, kp->kp_state);
+-      if (ret < 0)
+-              goto err4;
+-
+-      return ret;
+-err5:
+-      /* mask all events - we don't care about the result */
+-      (void) twl4030_kpwrite_u8(kp, TWL4030_MODULE_KEYPAD, 0xff, KEYP_IMR1);
+-err4:
+-      free_irq(kp->irq, NULL);
+-err3:
+-      input_unregister_device(kp->omap_twl4030kp);
+-err2:
+-      input_free_device(kp->omap_twl4030kp);
+-
+-      return -ENODEV;
+-}
+-
+-static int omap_kp_remove(struct platform_device *pdev)
+-{
+-      struct omap_keypad *kp = dev_get_drvdata(&pdev->dev);
+-
+-      free_irq(kp->irq, kp);
+-      input_unregister_device(kp->omap_twl4030kp);
+-      kfree(kp);
+-
+-      return 0;
+-}
+-
+-
+-static struct platform_driver omap_kp_driver = {
+-      .probe          = omap_kp_probe,
+-      .remove         = __devexit_p(omap_kp_remove),
+-      .driver         = {
+-              .name   = "twl4030_keypad",
+-              .owner  = THIS_MODULE,
+-      },
+-};
+-
+-/*
+- * OMAP TWL4030 Keypad init
+- */
+-static int __devinit omap_kp_init(void)
+-{
+-      return platform_driver_register(&omap_kp_driver);
+-}
+-
+-static void __exit omap_kp_exit(void)
+-{
+-      platform_driver_unregister(&omap_kp_driver);
+-}
+-
+-module_init(omap_kp_init);
+-module_exit(omap_kp_exit);
+-MODULE_ALIAS("platform:twl4030_keypad");
+-MODULE_AUTHOR("Texas Instruments");
+-MODULE_DESCRIPTION("OMAP TWL4030 Keypad Driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/twl4030-keypad.h b/drivers/input/keyboard/twl4030-keypad.h
+deleted file mode 100644
+index b903a77..0000000
+--- a/drivers/input/keyboard/twl4030-keypad.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/*
+- * drivers/input/keyboard/twl4030-keypad.h
+- *
+- * Copyright (C) 2006-2007 Texas Instruments, Inc.
+- *
+- * Intial Code:
+- *    Syed Mohammed Khasim <x0khasim@ti.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.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+- */
+-#ifndef __TWL4030_KEYPAD_H__
+-#define __TWL4030_KEYPAD_H__
+-
+-/* Register Definitions */
+-#define KEYP_CTRL                             0x00
+-#define KEYP_DEB                              0x01
+-#define KEYP_LONG_KEY                         0x02
+-#define KEYP_LK_PTV                           0x03
+-#define KEYP_TIMEOUT_L                                0x04
+-#define KEYP_TIMEOUT_H                                0x05
+-#define KEYP_FULL_CODE_7_0                    0x09
+-#define KEYP_ISR1                             0x11
+-#define KEYP_IMR1                             0x12
+-#define KEYP_EDR                              0x16
+-#define KEYP_SIH_CTRL                         0x17
+-
+-/* KEYP_CTRL_REG Fields */
+-#define KEYP_CTRL_SOFT_NRST                   0x01
+-#define KEYP_CTRL_SOFTMODEN                   0x02
+-#define KEYP_CTRL_LK_EN                               0x04
+-#define KEYP_CTRL_TOE_EN                      0x08
+-#define KEYP_CTRL_TOLE_EN                     0x10
+-#define KEYP_CTRL_RP_EN                               0x20
+-#define KEYP_CTRL_KBD_ON                      0x40
+-
+-
+-#define KEYP_CTRL_NOAUTORPT                   (KEYP_CTRL_SOFT_NRST |  \
+-                                               KEYP_CTRL_SOFTMODEN |  \
+-                                               KEYP_CTRL_TOE_EN |     \
+-                                               KEYP_CTRL_KBD_ON)
+-
+-/* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/
+-#define KEYP_PERIOD_US(T, prescale)           (T / (31 << (prescale + 1)) - 1)
+-
+-/* KEYP_LK_PTV_REG Fields */
+-#define KEYP_LK_PTV_PTV_SHIFT                 5
+-
+-/* KEYP_IMR1 Fields */
+-#define KEYP_IMR1_MIS                         0x08
+-#define KEYP_IMR1_TO                          0x04
+-#define KEYP_IMR1_LK                          0x02
+-#define KEYP_IMR1_KP                          0x01
+-
+-/* KEYP_EDR Fields */
+-#define KEYP_EDR_KP_FALLING                   0x01
+-#define KEYP_EDR_KP_RISING                    0x02
+-#define KEYP_EDR_KP_BOTH                      0x03
+-#define KEYP_EDR_LK_FALLING                   0x04
+-#define KEYP_EDR_LK_RISING                    0x08
+-#define KEYP_EDR_TO_FALLING                   0x10
+-#define KEYP_EDR_TO_RISING                    0x20
+-#define KEYP_EDR_MIS_FALLING                  0x40
+-#define KEYP_EDR_MIS_RISING                   0x80
+-
+-/* KEYP_SIH_CTRL Fields */
+-#define KEYP_SIH_CTRL_COR                     0x04
+-#define KEYP_SIH_CTRL_PEND_DIS                        0x02
+-#define KEYP_SIH_CTRL_EXCL_EN                 0x01
+-
+-#endif        /* End of __TWL4030-KEYPAD_H__ */
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0002-Input-add-support-for-generic-GPIO-based-matrix-keyp.patch b/recipes/linux/omap3-pandora-kernel/keypad/0002-Input-add-support-for-generic-GPIO-based-matrix-keyp.patch
new file mode 100644 (file)
index 0000000..814a561
--- /dev/null
@@ -0,0 +1,612 @@
+From a38e5cd354ef968dc6dc0decf579243c8d473698 Mon Sep 17 00:00:00 2001
+From: Eric Miao <eric.y.miao@gmail.com>
+Date: Tue, 3 Nov 2009 15:43:49 +0200
+Subject: [PATCH 2/7] Input: add support for generic GPIO-based matrix keypad
+
+Original patch by Marek Vasut, modified by Eric in:
+
+1. use delayed work to simplify the debouncing
+2. combine col_polarity/row_polarity into a single active_low field
+3. use a generic bit array based XOR algorithm to detect key
+   press/release, which should make the column assertion time
+   shorter and code a bit cleaner
+4. remove the ALT_FN handling, which is no way generic, the ALT_FN
+   key should be treated as no different from other keys, and
+   translation will be done by user space by commands like 'loadkeys'.
+5. explicitly disable row IRQs and flush potential pending work,
+   and schedule an immediate scan after resuming as suggested
+   by Uli Luckas
+6. incorporate review comments from many others
+
+Patch tested on Littleton/PXA310 (though PXA310 has a dedicate keypad
+controller, I have to configure those pins as generic GPIO to use this
+driver, works quite well, though), and Sharp Zaurus model SL-C7x0
+and SL-C1000.
+
+[dtor@mail.ru: fix error unwinding path, support changing keymap
+ from userspace]
+Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
+Reviewed-by: Trilok Soni <soni.trilok@gmail.com>
+Reviewed-by: Uli Luckas <u.luckas@road.de>
+Reviewed-by: Russell King <linux@arm.linux.org.uk>
+Reviewed-by: Robert Jarzmik <robert.jarzmik@free.fr>
+Signed-off-by: Eric Miao <eric.miao@marvell.com>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+
+Conflicts:
+
+       drivers/input/keyboard/Kconfig
+       drivers/input/keyboard/Makefile
+---
+ drivers/input/keyboard/Kconfig         |    9 +
+ drivers/input/keyboard/Makefile        |    1 +
+ drivers/input/keyboard/matrix_keypad.c |  453 ++++++++++++++++++++++++++++++++
+ include/linux/input/matrix_keypad.h    |   65 +++++
+ 4 files changed, 528 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/input/keyboard/matrix_keypad.c
+ create mode 100644 include/linux/input/matrix_keypad.h
+
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 59ad05a..b0a3c78 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -199,6 +199,15 @@ config KEYBOARD_ATARI
+         To compile this driver as a module, choose M here: the
+         module will be called atakbd.
++config KEYBOARD_MATRIX
++      tristate "GPIO driven matrix keypad support"
++      depends on GENERIC_GPIO
++      help
++        Enable support for GPIO driven matrix keypad.
++
++        To compile this driver as a module, choose M here: the
++        module will be called matrix_keypad.
++
+ config KEYBOARD_HIL_OLD
+       tristate "HP HIL keyboard support (simple driver)"
+       depends on GSC || HP300
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index 81e59f7..7b8bc44 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -28,5 +28,6 @@ obj-$(CONFIG_KEYBOARD_GPIO)          += gpio_keys.o
+ obj-$(CONFIG_KEYBOARD_HP6XX)          += jornada680_kbd.o
+ obj-$(CONFIG_KEYBOARD_HP7XX)          += jornada720_kbd.o
+ obj-$(CONFIG_KEYBOARD_MAPLE)          += maple_keyb.o
++obj-$(CONFIG_KEYBOARD_MATRIX)         += matrix_keypad.o
+ obj-$(CONFIG_KEYBOARD_BFIN)           += bf54x-keys.o
+ obj-$(CONFIG_KEYBOARD_SH_KEYSC)               += sh_keysc.o
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+new file mode 100644
+index 0000000..e9b2e7c
+--- /dev/null
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -0,0 +1,453 @@
++/*
++ *  GPIO driven matrix keyboard driver
++ *
++ *  Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
++ *
++ *  Based on 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/types.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/gpio.h>
++#include <linux/input/matrix_keypad.h>
++
++struct matrix_keypad {
++      const struct matrix_keypad_platform_data *pdata;
++      struct input_dev *input_dev;
++      unsigned short *keycodes;
++
++      uint32_t last_key_state[MATRIX_MAX_COLS];
++      struct delayed_work work;
++      bool scan_pending;
++      bool stopped;
++      spinlock_t lock;
++};
++
++/*
++ * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
++ * minmal side effect when scanning other columns, here it is configured to
++ * be input, and it should work on most platforms.
++ */
++static void __activate_col(const struct matrix_keypad_platform_data *pdata,
++                         int col, bool on)
++{
++      bool level_on = !pdata->active_low;
++
++      if (on) {
++              gpio_direction_output(pdata->col_gpios[col], level_on);
++      } else {
++              gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
++              gpio_direction_input(pdata->col_gpios[col]);
++      }
++}
++
++static void activate_col(const struct matrix_keypad_platform_data *pdata,
++                       int col, bool on)
++{
++      __activate_col(pdata, col, on);
++
++      if (on && pdata->col_scan_delay_us)
++              udelay(pdata->col_scan_delay_us);
++}
++
++static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
++                            bool on)
++{
++      int col;
++
++      for (col = 0; col < pdata->num_col_gpios; col++)
++              __activate_col(pdata, col, on);
++}
++
++static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
++                       int row)
++{
++      return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
++                      !pdata->active_low : pdata->active_low;
++}
++
++static void enable_row_irqs(struct matrix_keypad *keypad)
++{
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i;
++
++      for (i = 0; i < pdata->num_row_gpios; i++)
++              enable_irq(gpio_to_irq(pdata->row_gpios[i]));
++}
++
++static void disable_row_irqs(struct matrix_keypad *keypad)
++{
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i;
++
++      for (i = 0; i < pdata->num_row_gpios; i++)
++              disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
++}
++
++/*
++ * This gets the keys from keyboard and reports it to input subsystem
++ */
++static void matrix_keypad_scan(struct work_struct *work)
++{
++      struct matrix_keypad *keypad =
++              container_of(work, struct matrix_keypad, work.work);
++      struct input_dev *input_dev = keypad->input_dev;
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      uint32_t new_state[MATRIX_MAX_COLS];
++      int row, col, code;
++
++      /* de-activate all columns for scanning */
++      activate_all_cols(pdata, false);
++
++      memset(new_state, 0, sizeof(new_state));
++
++      /* assert each column and read the row status out */
++      for (col = 0; col < pdata->num_col_gpios; col++) {
++
++              activate_col(pdata, col, true);
++
++              for (row = 0; row < pdata->num_row_gpios; row++)
++                      new_state[col] |=
++                              row_asserted(pdata, row) ? (1 << row) : 0;
++
++              activate_col(pdata, col, false);
++      }
++
++      for (col = 0; col < pdata->num_col_gpios; col++) {
++              uint32_t bits_changed;
++
++              bits_changed = keypad->last_key_state[col] ^ new_state[col];
++              if (bits_changed == 0)
++                      continue;
++
++              for (row = 0; row < pdata->num_row_gpios; row++) {
++                      if ((bits_changed & (1 << row)) == 0)
++                              continue;
++
++                      code = (row << 4) + col;
++                      input_event(input_dev, EV_MSC, MSC_SCAN, code);
++                      input_report_key(input_dev,
++                                       keypad->keycodes[code],
++                                       new_state[col] & (1 << row));
++              }
++      }
++      input_sync(input_dev);
++
++      memcpy(keypad->last_key_state, new_state, sizeof(new_state));
++
++      activate_all_cols(pdata, true);
++
++      /* Enable IRQs again */
++      spin_lock_irq(&keypad->lock);
++      keypad->scan_pending = false;
++      enable_row_irqs(keypad);
++      spin_unlock_irq(&keypad->lock);
++}
++
++static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
++{
++      struct matrix_keypad *keypad = id;
++      unsigned long flags;
++
++      spin_lock_irqsave(&keypad->lock, flags);
++
++      /*
++       * See if another IRQ beaten us to it and scheduled the
++       * scan already. In that case we should not try to
++       * disable IRQs again.
++       */
++      if (unlikely(keypad->scan_pending || keypad->stopped))
++              goto out;
++
++      disable_row_irqs(keypad);
++      keypad->scan_pending = true;
++      schedule_delayed_work(&keypad->work,
++              msecs_to_jiffies(keypad->pdata->debounce_ms));
++
++out:
++      spin_unlock_irqrestore(&keypad->lock, flags);
++      return IRQ_HANDLED;
++}
++
++static int matrix_keypad_start(struct input_dev *dev)
++{
++      struct matrix_keypad *keypad = input_get_drvdata(dev);
++
++      keypad->stopped = false;
++      mb();
++
++      /*
++       * Schedule an immediate key scan to capture current key state;
++       * columns will be activated and IRQs be enabled after the scan.
++       */
++      schedule_delayed_work(&keypad->work, 0);
++
++      return 0;
++}
++
++static void matrix_keypad_stop(struct input_dev *dev)
++{
++      struct matrix_keypad *keypad = input_get_drvdata(dev);
++
++      keypad->stopped = true;
++      mb();
++      flush_work(&keypad->work.work);
++      /*
++       * matrix_keypad_scan() will leave IRQs enabled;
++       * we should disable them now.
++       */
++      disable_row_irqs(keypad);
++}
++
++#ifdef CONFIG_PM
++static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct matrix_keypad *keypad = platform_get_drvdata(pdev);
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i;
++
++      matrix_keypad_stop(keypad->input_dev);
++
++      if (device_may_wakeup(&pdev->dev))
++              for (i = 0; i < pdata->num_row_gpios; i++)
++                      enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
++
++      return 0;
++}
++
++static int matrix_keypad_resume(struct platform_device *pdev)
++{
++      struct matrix_keypad *keypad = platform_get_drvdata(pdev);
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i;
++
++      if (device_may_wakeup(&pdev->dev))
++              for (i = 0; i < pdata->num_row_gpios; i++)
++                      disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
++
++      matrix_keypad_start(keypad->input_dev);
++
++      return 0;
++}
++#else
++#define matrix_keypad_suspend NULL
++#define matrix_keypad_resume  NULL
++#endif
++
++static int __devinit init_matrix_gpio(struct platform_device *pdev,
++                                      struct matrix_keypad *keypad)
++{
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i, err = -EINVAL;
++
++      /* initialized strobe lines as outputs, activated */
++      for (i = 0; i < pdata->num_col_gpios; i++) {
++              err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
++              if (err) {
++                      dev_err(&pdev->dev,
++                              "failed to request GPIO%d for COL%d\n",
++                              pdata->col_gpios[i], i);
++                      goto err_free_cols;
++              }
++
++              gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
++      }
++
++      for (i = 0; i < pdata->num_row_gpios; i++) {
++              err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
++              if (err) {
++                      dev_err(&pdev->dev,
++                              "failed to request GPIO%d for ROW%d\n",
++                              pdata->row_gpios[i], i);
++                      goto err_free_rows;
++              }
++
++              gpio_direction_input(pdata->row_gpios[i]);
++      }
++
++      for (i = 0; i < pdata->num_row_gpios; i++) {
++              err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
++                              matrix_keypad_interrupt,
++                              IRQF_DISABLED |
++                              IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
++                              "matrix-keypad", keypad);
++              if (err) {
++                      dev_err(&pdev->dev,
++                              "Unable to acquire interrupt for GPIO line %i\n",
++                              pdata->row_gpios[i]);
++                      goto err_free_irqs;
++              }
++      }
++
++      /* initialized as disabled - enabled by input->open */
++      disable_row_irqs(keypad);
++      return 0;
++
++err_free_irqs:
++      while (--i >= 0)
++              free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
++      i = pdata->num_row_gpios;
++err_free_rows:
++      while (--i >= 0)
++              gpio_free(pdata->row_gpios[i]);
++      i = pdata->num_col_gpios;
++err_free_cols:
++      while (--i >= 0)
++              gpio_free(pdata->col_gpios[i]);
++
++      return err;
++}
++
++static int __devinit matrix_keypad_probe(struct platform_device *pdev)
++{
++      const struct matrix_keypad_platform_data *pdata;
++      const struct matrix_keymap_data *keymap_data;
++      struct matrix_keypad *keypad;
++      struct input_dev *input_dev;
++      unsigned short *keycodes;
++      int i;
++      int err;
++
++      pdata = pdev->dev.platform_data;
++      if (!pdata) {
++              dev_err(&pdev->dev, "no platform data defined\n");
++              return -EINVAL;
++      }
++
++      keymap_data = pdata->keymap_data;
++      if (!keymap_data) {
++              dev_err(&pdev->dev, "no keymap data defined\n");
++              return -EINVAL;
++      }
++
++      if (!keymap_data->max_keymap_size) {
++              dev_err(&pdev->dev, "invalid keymap data supplied\n");
++              return -EINVAL;
++      }
++
++      keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
++      keycodes = kzalloc(keymap_data->max_keymap_size *
++                              sizeof(keypad->keycodes),
++                         GFP_KERNEL);
++      input_dev = input_allocate_device();
++      if (!keypad || !keycodes || !input_dev) {
++              err = -ENOMEM;
++              goto err_free_mem;
++      }
++
++      keypad->input_dev = input_dev;
++      keypad->pdata = pdata;
++      keypad->keycodes = keycodes;
++      keypad->stopped = true;
++      INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
++      spin_lock_init(&keypad->lock);
++
++      input_dev->name         = pdev->name;
++      input_dev->id.bustype   = BUS_HOST;
++      input_dev->dev.parent   = &pdev->dev;
++      input_dev->evbit[0]     = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
++      input_dev->open         = matrix_keypad_start;
++      input_dev->close        = matrix_keypad_stop;
++
++      input_dev->keycode      = keycodes;
++      input_dev->keycodesize  = sizeof(*keycodes);
++      input_dev->keycodemax   = keymap_data->max_keymap_size;
++
++      for (i = 0; i < keymap_data->keymap_size; i++) {
++              unsigned int key = keymap_data->keymap[i];
++              unsigned int row = KEY_ROW(key);
++              unsigned int col = KEY_COL(key);
++              unsigned short code = KEY_VAL(key);
++
++              keycodes[(row << 4) + col] = code;
++              __set_bit(code, input_dev->keybit);
++      }
++      __clear_bit(KEY_RESERVED, input_dev->keybit);
++
++      input_set_capability(input_dev, EV_MSC, MSC_SCAN);
++      input_set_drvdata(input_dev, keypad);
++
++      err = init_matrix_gpio(pdev, keypad);
++      if (err)
++              goto err_free_mem;
++
++      err = input_register_device(keypad->input_dev);
++      if (err)
++              goto err_free_mem;
++
++      device_init_wakeup(&pdev->dev, pdata->wakeup);
++      platform_set_drvdata(pdev, keypad);
++
++      return 0;
++
++err_free_mem:
++      input_free_device(input_dev);
++      kfree(keycodes);
++      kfree(keypad);
++      return err;
++}
++
++static int __devexit matrix_keypad_remove(struct platform_device *pdev)
++{
++      struct matrix_keypad *keypad = platform_get_drvdata(pdev);
++      const struct matrix_keypad_platform_data *pdata = keypad->pdata;
++      int i;
++
++      device_init_wakeup(&pdev->dev, 0);
++
++      for (i = 0; i < pdata->num_row_gpios; i++) {
++              free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
++              gpio_free(pdata->row_gpios[i]);
++      }
++
++      for (i = 0; i < pdata->num_col_gpios; i++)
++              gpio_free(pdata->col_gpios[i]);
++
++      input_unregister_device(keypad->input_dev);
++      platform_set_drvdata(pdev, NULL);
++      kfree(keypad->keycodes);
++      kfree(keypad);
++
++      return 0;
++}
++
++static struct platform_driver matrix_keypad_driver = {
++      .probe          = matrix_keypad_probe,
++      .remove         = __devexit_p(matrix_keypad_remove),
++      .suspend        = matrix_keypad_suspend,
++      .resume         = matrix_keypad_resume,
++      .driver         = {
++              .name   = "matrix-keypad",
++              .owner  = THIS_MODULE,
++      },
++};
++
++static int __init matrix_keypad_init(void)
++{
++      return platform_driver_register(&matrix_keypad_driver);
++}
++
++static void __exit matrix_keypad_exit(void)
++{
++      platform_driver_unregister(&matrix_keypad_driver);
++}
++
++module_init(matrix_keypad_init);
++module_exit(matrix_keypad_exit);
++
++MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
++MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:matrix-keypad");
+diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
+new file mode 100644
+index 0000000..7964516
+--- /dev/null
++++ b/include/linux/input/matrix_keypad.h
+@@ -0,0 +1,65 @@
++#ifndef _MATRIX_KEYPAD_H
++#define _MATRIX_KEYPAD_H
++
++#include <linux/types.h>
++#include <linux/input.h>
++
++#define MATRIX_MAX_ROWS               16
++#define MATRIX_MAX_COLS               16
++
++#define KEY(row, col, val)    ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
++                               (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
++                               (val & 0xffff))
++
++#define KEY_ROW(k)            (((k) >> 24) & 0xff)
++#define KEY_COL(k)            (((k) >> 16) & 0xff)
++#define KEY_VAL(k)            ((k) & 0xffff)
++
++/**
++ * struct matrix_keymap_data - keymap for matrix keyboards
++ * @keymap: pointer to array of uint32 values encoded with KEY() macro
++ *    representing keymap
++ * @keymap_size: number of entries (initialized) in this keymap
++ * @max_keymap_size: maximum size of keymap supported by the device
++ *
++ * This structure is supposed to be used by platform code to supply
++ * keymaps to drivers that implement matrix-like keypads/keyboards.
++ */
++struct matrix_keymap_data {
++      const uint32_t *keymap;
++      unsigned int    keymap_size;
++      unsigned int    max_keymap_size;
++};
++
++/**
++ * struct matrix_keypad_platform_data - platform-dependent keypad data
++ * @keymap_data: pointer to &matrix_keymap_data
++ * @row_gpios: array of gpio numbers reporesenting rows
++ * @col_gpios: array of gpio numbers reporesenting colums
++ * @num_row_gpios: actual number of row gpios used by device
++ * @num_col_gpios: actual number of col gpios used by device
++ * @col_scan_delay_us: delay, measured in microseconds, that is
++ *    needed before we can keypad after activating column gpio
++ * @debounce_ms: debounce interval in milliseconds
++ *
++ * This structure represents platform-specific data that use used by
++ * matrix_keypad driver to perform proper initialization.
++ */
++struct matrix_keypad_platform_data {
++      const struct matrix_keymap_data *keymap_data;
++
++      unsigned int    row_gpios[MATRIX_MAX_ROWS];
++      unsigned int    col_gpios[MATRIX_MAX_COLS];
++      unsigned int    num_row_gpios;
++      unsigned int    num_col_gpios;
++
++      unsigned int    col_scan_delay_us;
++
++      /* key debounce interval in milli-second */
++      unsigned int    debounce_ms;
++
++      bool            active_low;
++      bool            wakeup;
++};
++
++#endif /* _MATRIX_KEYPAD_H */
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0003-Input-matrix_keypad-make-matrix-keymap-size-dynamic.patch b/recipes/linux/omap3-pandora-kernel/keypad/0003-Input-matrix_keypad-make-matrix-keymap-size-dynamic.patch
new file mode 100644 (file)
index 0000000..8b8ee6f
--- /dev/null
@@ -0,0 +1,140 @@
+From 99250cbbae885e9535553e095c63c762d32b4325 Mon Sep 17 00:00:00 2001
+From: Eric Miao <eric.y.miao@gmail.com>
+Date: Wed, 5 Aug 2009 01:24:41 -0700
+Subject: [PATCH 3/7] Input: matrix_keypad - make matrix keymap size dynamic
+
+Remove assumption on the shift and size of rows/columns form
+matrix_keypad driver.
+
+Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+(cherry picked from commit d82f1c35348cebe2fb2d4a4d31ce0ab0769e3d93)
+---
+ drivers/input/keyboard/matrix_keypad.c |   18 +++++++++---------
+ include/linux/input/matrix_keypad.h    |   13 +++++++------
+ 2 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+index e9b2e7c..541b981 100644
+--- a/drivers/input/keyboard/matrix_keypad.c
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -27,6 +27,7 @@ struct matrix_keypad {
+       const struct matrix_keypad_platform_data *pdata;
+       struct input_dev *input_dev;
+       unsigned short *keycodes;
++      unsigned int row_shift;
+       uint32_t last_key_state[MATRIX_MAX_COLS];
+       struct delayed_work work;
+@@ -136,7 +137,7 @@ static void matrix_keypad_scan(struct work_struct *work)
+                       if ((bits_changed & (1 << row)) == 0)
+                               continue;
+-                      code = (row << 4) + col;
++                      code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+                       input_event(input_dev, EV_MSC, MSC_SCAN, code);
+                       input_report_key(input_dev,
+                                        keypad->keycodes[code],
+@@ -317,6 +318,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+       struct matrix_keypad *keypad;
+       struct input_dev *input_dev;
+       unsigned short *keycodes;
++      unsigned int row_shift;
+       int i;
+       int err;
+@@ -332,14 +334,11 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+               return -EINVAL;
+       }
+-      if (!keymap_data->max_keymap_size) {
+-              dev_err(&pdev->dev, "invalid keymap data supplied\n");
+-              return -EINVAL;
+-      }
++      row_shift = get_count_order(pdata->num_col_gpios);
+       keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
+-      keycodes = kzalloc(keymap_data->max_keymap_size *
+-                              sizeof(keypad->keycodes),
++      keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
++                              sizeof(*keycodes),
+                          GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!keypad || !keycodes || !input_dev) {
+@@ -350,6 +349,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+       keypad->input_dev = input_dev;
+       keypad->pdata = pdata;
+       keypad->keycodes = keycodes;
++      keypad->row_shift = row_shift;
+       keypad->stopped = true;
+       INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
+       spin_lock_init(&keypad->lock);
+@@ -363,7 +363,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+       input_dev->keycode      = keycodes;
+       input_dev->keycodesize  = sizeof(*keycodes);
+-      input_dev->keycodemax   = keymap_data->max_keymap_size;
++      input_dev->keycodemax   = pdata->num_row_gpios << keypad->row_shift;
+       for (i = 0; i < keymap_data->keymap_size; i++) {
+               unsigned int key = keymap_data->keymap[i];
+@@ -371,7 +371,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+               unsigned int col = KEY_COL(key);
+               unsigned short code = KEY_VAL(key);
+-              keycodes[(row << 4) + col] = code;
++              keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
+               __set_bit(code, input_dev->keybit);
+       }
+       __clear_bit(KEY_RESERVED, input_dev->keybit);
+diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
+index 7964516..15d5903 100644
+--- a/include/linux/input/matrix_keypad.h
++++ b/include/linux/input/matrix_keypad.h
+@@ -15,12 +15,13 @@
+ #define KEY_COL(k)            (((k) >> 16) & 0xff)
+ #define KEY_VAL(k)            ((k) & 0xffff)
++#define MATRIX_SCAN_CODE(row, col, row_shift) (((row) << (row_shift)) + (col))
++
+ /**
+  * struct matrix_keymap_data - keymap for matrix keyboards
+  * @keymap: pointer to array of uint32 values encoded with KEY() macro
+  *    representing keymap
+  * @keymap_size: number of entries (initialized) in this keymap
+- * @max_keymap_size: maximum size of keymap supported by the device
+  *
+  * This structure is supposed to be used by platform code to supply
+  * keymaps to drivers that implement matrix-like keypads/keyboards.
+@@ -28,14 +29,13 @@
+ struct matrix_keymap_data {
+       const uint32_t *keymap;
+       unsigned int    keymap_size;
+-      unsigned int    max_keymap_size;
+ };
+ /**
+  * struct matrix_keypad_platform_data - platform-dependent keypad data
+  * @keymap_data: pointer to &matrix_keymap_data
+- * @row_gpios: array of gpio numbers reporesenting rows
+- * @col_gpios: array of gpio numbers reporesenting colums
++ * @row_gpios: pointer to array of gpio numbers representing rows
++ * @col_gpios: pointer to array of gpio numbers reporesenting colums
+  * @num_row_gpios: actual number of row gpios used by device
+  * @num_col_gpios: actual number of col gpios used by device
+  * @col_scan_delay_us: delay, measured in microseconds, that is
+@@ -48,8 +48,9 @@ struct matrix_keymap_data {
+ struct matrix_keypad_platform_data {
+       const struct matrix_keymap_data *keymap_data;
+-      unsigned int    row_gpios[MATRIX_MAX_ROWS];
+-      unsigned int    col_gpios[MATRIX_MAX_COLS];
++      const unsigned int *row_gpios;
++      const unsigned int *col_gpios;
++
+       unsigned int    num_row_gpios;
+       unsigned int    num_col_gpios;
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0004-Input-matrix-keypad-add-function-to-build-device-key.patch b/recipes/linux/omap3-pandora-kernel/keypad/0004-Input-matrix-keypad-add-function-to-build-device-key.patch
new file mode 100644 (file)
index 0000000..0ac80a6
--- /dev/null
@@ -0,0 +1,94 @@
+From 81d264643825f8318c2e0ca39a8b5ce6a4ce3a5a Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Tue, 3 Nov 2009 15:49:37 +0200
+Subject: [PATCH 4/7] Input: matrix-keypad - add function to build device keymap
+
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+(cherry picked from commit 77a53fd21870c726b670c0d8179294ac1ea33468)
+
+Conflicts:
+
+       drivers/input/keyboard/w90p910_keypad.c
+---
+ drivers/input/keyboard/matrix_keypad.c |   15 +++------------
+ include/linux/input/matrix_keypad.h    |   32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
+index 541b981..91cfe51 100644
+--- a/drivers/input/keyboard/matrix_keypad.c
++++ b/drivers/input/keyboard/matrix_keypad.c
+@@ -319,7 +319,6 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+       struct input_dev *input_dev;
+       unsigned short *keycodes;
+       unsigned int row_shift;
+-      int i;
+       int err;
+       pdata = pdev->dev.platform_data;
+@@ -363,18 +362,10 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+       input_dev->keycode      = keycodes;
+       input_dev->keycodesize  = sizeof(*keycodes);
+-      input_dev->keycodemax   = pdata->num_row_gpios << keypad->row_shift;
+-
+-      for (i = 0; i < keymap_data->keymap_size; i++) {
+-              unsigned int key = keymap_data->keymap[i];
+-              unsigned int row = KEY_ROW(key);
+-              unsigned int col = KEY_COL(key);
+-              unsigned short code = KEY_VAL(key);
++      input_dev->keycodemax   = pdata->num_row_gpios << row_shift;
+-              keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
+-              __set_bit(code, input_dev->keybit);
+-      }
+-      __clear_bit(KEY_RESERVED, input_dev->keybit);
++      matrix_keypad_build_keymap(keymap_data, row_shift,
++                                 input_dev->keycode, input_dev->keybit);
+       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+       input_set_drvdata(input_dev, keypad);
+diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
+index 15d5903..b3cd42d 100644
+--- a/include/linux/input/matrix_keypad.h
++++ b/include/linux/input/matrix_keypad.h
+@@ -63,4 +63,36 @@ struct matrix_keypad_platform_data {
+       bool            wakeup;
+ };
++/**
++ * matrix_keypad_build_keymap - convert platform keymap into matrix keymap
++ * @keymap_data: keymap supplied by the platform code
++ * @row_shift: number of bits to shift row value by to advance to the next
++ * line in the keymap
++ * @keymap: expanded version of keymap that is suitable for use by
++ * matrix keyboad driver
++ * @keybit: pointer to bitmap of keys supported by input device
++ *
++ * This function converts platform keymap (encoded with KEY() macro) into
++ * an array of keycodes that is suitable for using in a standard matrix
++ * keyboard driver that uses row and col as indices.
++ */
++static inline void
++matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
++                         unsigned int row_shift,
++                         unsigned short *keymap, unsigned long *keybit)
++{
++      int i;
++
++      for (i = 0; i < keymap_data->keymap_size; i++) {
++              unsigned int key = keymap_data->keymap[i];
++              unsigned int row = KEY_ROW(key);
++              unsigned int col = KEY_COL(key);
++              unsigned short code = KEY_VAL(key);
++
++              keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
++              __set_bit(code, keybit);
++      }
++      __clear_bit(KEY_RESERVED, keybit);
++}
++
+ #endif /* _MATRIX_KEYPAD_H */
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0005-Input-add-twl4030_keypad-driver.patch b/recipes/linux/omap3-pandora-kernel/keypad/0005-Input-add-twl4030_keypad-driver.patch
new file mode 100644 (file)
index 0000000..c47b00e
--- /dev/null
@@ -0,0 +1,583 @@
+From 0958f20b0237ef414371c3ff967a5e26649c30fe Mon Sep 17 00:00:00 2001
+From: David Brownell <dbrownell@users.sourceforge.net>
+Date: Tue, 3 Nov 2009 15:53:51 +0200
+Subject: [PATCH 5/7] Input: add twl4030_keypad driver
+
+Add a driver for the keypad controller on TWL4030 family chips.
+These support up to an 8x8 key matrix.  The TWL4030 multifunction
+chips are mostly used on OMAP3 (or OMAP 2430) based boards.
+
+[dtor@mail.ru: switch to matrix-keypad framework, fix changing
+keymap from userspace]
+Reviewed-by: Trilok Soni <soni.trilok@gmail.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+
+Conflicts:
+
+       drivers/input/keyboard/Kconfig
+       drivers/input/keyboard/Makefile
+---
+ drivers/input/keyboard/Kconfig          |   11 +
+ drivers/input/keyboard/Makefile         |    1 +
+ drivers/input/keyboard/twl4030_keypad.c |  480 +++++++++++++++++++++++++++++++
+ include/linux/i2c/twl4030.h             |   19 +-
+ 4 files changed, 505 insertions(+), 6 deletions(-)
+ create mode 100644 drivers/input/keyboard/twl4030_keypad.c
+
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index b0a3c78..e6a0584 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -355,4 +355,15 @@ config KEYBOARD_SH_KEYSC
+         To compile this driver as a module, choose M here: the
+         module will be called sh_keysc.
++
++config KEYBOARD_TWL4030
++      tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
++      depends on TWL4030_CORE
++      help
++        Say Y here if your board use the keypad controller on
++        TWL4030 family chips.  It's safe to say enable this
++        even on boards that don't use the keypad controller.
++
++        To compile this driver as a module, choose M here: the
++        module will be called twl4030_keypad.
+ endif
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index 7b8bc44..2085127 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -31,3 +31,4 @@ obj-$(CONFIG_KEYBOARD_MAPLE)         += maple_keyb.o
+ obj-$(CONFIG_KEYBOARD_MATRIX)         += matrix_keypad.o
+ obj-$(CONFIG_KEYBOARD_BFIN)           += bf54x-keys.o
+ obj-$(CONFIG_KEYBOARD_SH_KEYSC)               += sh_keysc.o
++obj-$(CONFIG_KEYBOARD_TWL4030)                += twl4030_keypad.o
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+new file mode 100644
+index 0000000..9a2977c
+--- /dev/null
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -0,0 +1,480 @@
++/*
++ * twl4030_keypad.c - driver for 8x8 keypad controller in twl4030 chips
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ *
++ * Code re-written for 2430SDP by:
++ * Syed Mohammed Khasim <x0khasim@ti.com>
++ *
++ * Initial Code:
++ * Manjunatha G K <manjugk@ti.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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/platform_device.h>
++#include <linux/i2c/twl4030.h>
++
++
++/*
++ * The TWL4030 family chips include a keypad controller that supports
++ * up to an 8x8 switch matrix.  The controller can issue system wakeup
++ * events, since it uses only the always-on 32KiHz oscillator, and has
++ * an internal state machine that decodes pressed keys, including
++ * multi-key combinations.
++ *
++ * This driver lets boards define what keycodes they wish to report for
++ * which scancodes, as part of the "struct twl4030_keypad_data" used in
++ * the probe() routine.
++ *
++ * See the TPS65950 documentation; that's the general availability
++ * version of the TWL5030 second generation part.
++ */
++#define TWL4030_MAX_ROWS      8       /* TWL4030 hard limit */
++#define TWL4030_MAX_COLS      8
++#define TWL4030_ROW_SHIFT     3
++#define TWL4030_KEYMAP_SIZE   (TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
++
++struct twl4030_keypad {
++      unsigned short  keymap[TWL4030_KEYMAP_SIZE];
++      u16             kp_state[TWL4030_MAX_ROWS];
++      unsigned        n_rows;
++      unsigned        n_cols;
++      unsigned        irq;
++
++      struct device *dbg_dev;
++      struct input_dev *input;
++};
++
++/*----------------------------------------------------------------------*/
++
++/* arbitrary prescaler value 0..7 */
++#define PTV_PRESCALER                 4
++
++/* Register Offsets */
++#define KEYP_CTRL                     0x00
++#define KEYP_DEB                      0x01
++#define KEYP_LONG_KEY                 0x02
++#define KEYP_LK_PTV                   0x03
++#define KEYP_TIMEOUT_L                        0x04
++#define KEYP_TIMEOUT_H                        0x05
++#define KEYP_KBC                      0x06
++#define KEYP_KBR                      0x07
++#define KEYP_SMS                      0x08
++#define KEYP_FULL_CODE_7_0            0x09    /* row 0 column status */
++#define KEYP_FULL_CODE_15_8           0x0a    /* ... row 1 ... */
++#define KEYP_FULL_CODE_23_16          0x0b
++#define KEYP_FULL_CODE_31_24          0x0c
++#define KEYP_FULL_CODE_39_32          0x0d
++#define KEYP_FULL_CODE_47_40          0x0e
++#define KEYP_FULL_CODE_55_48          0x0f
++#define KEYP_FULL_CODE_63_56          0x10
++#define KEYP_ISR1                     0x11
++#define KEYP_IMR1                     0x12
++#define KEYP_ISR2                     0x13
++#define KEYP_IMR2                     0x14
++#define KEYP_SIR                      0x15
++#define KEYP_EDR                      0x16    /* edge triggers */
++#define KEYP_SIH_CTRL                 0x17
++
++/* KEYP_CTRL_REG Fields */
++#define KEYP_CTRL_SOFT_NRST           BIT(0)
++#define KEYP_CTRL_SOFTMODEN           BIT(1)
++#define KEYP_CTRL_LK_EN                       BIT(2)
++#define KEYP_CTRL_TOE_EN              BIT(3)
++#define KEYP_CTRL_TOLE_EN             BIT(4)
++#define KEYP_CTRL_RP_EN                       BIT(5)
++#define KEYP_CTRL_KBD_ON              BIT(6)
++
++/* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/
++#define KEYP_PERIOD_US(t, prescale)   ((t) / (31 << (prescale + 1)) - 1)
++
++/* KEYP_LK_PTV_REG Fields */
++#define KEYP_LK_PTV_PTV_SHIFT         5
++
++/* KEYP_{IMR,ISR,SIR} Fields */
++#define KEYP_IMR1_MIS                 BIT(3)
++#define KEYP_IMR1_TO                  BIT(2)
++#define KEYP_IMR1_LK                  BIT(1)
++#define KEYP_IMR1_KP                  BIT(0)
++
++/* KEYP_EDR Fields */
++#define KEYP_EDR_KP_FALLING           0x01
++#define KEYP_EDR_KP_RISING            0x02
++#define KEYP_EDR_KP_BOTH              0x03
++#define KEYP_EDR_LK_FALLING           0x04
++#define KEYP_EDR_LK_RISING            0x08
++#define KEYP_EDR_TO_FALLING           0x10
++#define KEYP_EDR_TO_RISING            0x20
++#define KEYP_EDR_MIS_FALLING          0x40
++#define KEYP_EDR_MIS_RISING           0x80
++
++
++/*----------------------------------------------------------------------*/
++
++static int twl4030_kpread(struct twl4030_keypad *kp,
++              u8 *data, u32 reg, u8 num_bytes)
++{
++      int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes);
++
++      if (ret < 0)
++              dev_warn(kp->dbg_dev,
++                      "Couldn't read TWL4030: %X - ret %d[%x]\n",
++                       reg, ret, ret);
++
++      return ret;
++}
++
++static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg)
++{
++      int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg);
++
++      if (ret < 0)
++              dev_warn(kp->dbg_dev,
++                      "Could not write TWL4030: %X - ret %d[%x]\n",
++                       reg, ret, ret);
++
++      return ret;
++}
++
++static inline u16 twl4030_col_xlate(struct twl4030_keypad *kp, u8 col)
++{
++      /* If all bits in a row are active for all coloumns then
++       * we have that row line connected to gnd. Mark this
++       * key on as if it was on matrix position n_cols (ie
++       * one higher than the size of the matrix).
++       */
++      if (col == 0xFF)
++              return 1 << kp->n_cols;
++      else
++              return col & ((1 << kp->n_cols) - 1);
++}
++
++static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state)
++{
++      u8 new_state[TWL4030_MAX_ROWS];
++      int row;
++      int ret = twl4030_kpread(kp, new_state,
++                               KEYP_FULL_CODE_7_0, kp->n_rows);
++      if (ret >= 0)
++              for (row = 0; row < kp->n_rows; row++)
++                      state[row] = twl4030_col_xlate(kp, new_state[row]);
++
++      return ret;
++}
++
++static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
++{
++      int i;
++      u16 check = 0;
++
++      for (i = 0; i < kp->n_rows; i++) {
++              u16 col = key_state[i];
++
++              if ((col & check) && hweight16(col) > 1)
++                      return 1;
++
++              check |= col;
++      }
++
++      return 0;
++}
++
++static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
++{
++      struct input_dev *input = kp->input;
++      u16 new_state[TWL4030_MAX_ROWS];
++      int col, row;
++
++      if (release_all)
++              memset(new_state, 0, sizeof(new_state));
++      else {
++              /* check for any changes */
++              int ret = twl4030_read_kp_matrix_state(kp, new_state);
++
++              if (ret < 0)    /* panic ... */
++                      return;
++
++              if (twl4030_is_in_ghost_state(kp, new_state))
++                      return;
++      }
++
++      /* check for changes and print those */
++      for (row = 0; row < kp->n_rows; row++) {
++              int changed = new_state[row] ^ kp->kp_state[row];
++
++              if (!changed)
++                      continue;
++
++              for (col = 0; col < kp->n_cols; col++) {
++                      int code;
++
++                      if (!(changed & (1 << col)))
++                              continue;
++
++                      dev_dbg(kp->dbg_dev, "key [%d:%d] %s\n", row, col,
++                              (new_state[row] & (1 << col)) ?
++                              "press" : "release");
++
++                      code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT);
++                      input_event(input, EV_MSC, MSC_SCAN, code);
++                      input_report_key(input, kp->keymap[code],
++                                       new_state[row] & (1 << col));
++              }
++              kp->kp_state[row] = new_state[row];
++      }
++      input_sync(input);
++}
++
++/*
++ * Keypad interrupt handler
++ */
++static irqreturn_t do_kp_irq(int irq, void *_kp)
++{
++      struct twl4030_keypad *kp = _kp;
++      u8 reg;
++      int ret;
++
++#ifdef CONFIG_LOCKDEP
++      /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
++       * we don't want and can't tolerate.  Although it might be
++       * friendlier not to borrow this thread context...
++       */
++      local_irq_enable();
++#endif
++
++      /* Read & Clear TWL4030 pending interrupt */
++      ret = twl4030_kpread(kp, &reg, KEYP_ISR1, 1);
++
++      /* Release all keys if I2C has gone bad or
++       * the KEYP has gone to idle state */
++      if (ret >= 0 && (reg & KEYP_IMR1_KP))
++              twl4030_kp_scan(kp, false);
++      else
++              twl4030_kp_scan(kp, true);
++
++      return IRQ_HANDLED;
++}
++
++static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
++{
++      u8 reg;
++      int i;
++
++      /* Enable controller, with hardware decoding but not autorepeat */
++      reg = KEYP_CTRL_SOFT_NRST | KEYP_CTRL_SOFTMODEN
++              | KEYP_CTRL_TOE_EN | KEYP_CTRL_KBD_ON;
++      if (twl4030_kpwrite_u8(kp, reg, KEYP_CTRL) < 0)
++              return -EIO;
++
++      /* NOTE:  we could use sih_setup() here to package keypad
++       * event sources as four different IRQs ... but we don't.
++       */
++
++      /* Enable TO rising and KP rising and falling edge detection */
++      reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING;
++      if (twl4030_kpwrite_u8(kp, reg, KEYP_EDR) < 0)
++              return -EIO;
++
++      /* Set PTV prescaler Field */
++      reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT);
++      if (twl4030_kpwrite_u8(kp, reg, KEYP_LK_PTV) < 0)
++              return -EIO;
++
++      /* Set key debounce time to 20 ms */
++      i = KEYP_PERIOD_US(20000, PTV_PRESCALER);
++      if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)
++              return -EIO;
++
++      /* Set timeout period to 100 ms */
++      i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
++      if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)
++              return -EIO;
++
++      if (twl4030_kpwrite_u8(kp, (i >> 8), KEYP_TIMEOUT_H) < 0)
++              return -EIO;
++
++      /*
++       * Enable Clear-on-Read; disable remembering events that fire
++       * after the IRQ but before our handler acks (reads) them,
++       */
++      reg = TWL4030_SIH_CTRL_COR_MASK | TWL4030_SIH_CTRL_PENDDIS_MASK;
++      if (twl4030_kpwrite_u8(kp, reg, KEYP_SIH_CTRL) < 0)
++              return -EIO;
++
++      /* initialize key state; irqs update it from here on */
++      if (twl4030_read_kp_matrix_state(kp, kp->kp_state) < 0)
++              return -EIO;
++
++      return 0;
++}
++
++/*
++ * Registers keypad device with input subsystem
++ * and configures TWL4030 keypad registers
++ */
++static int __devinit twl4030_kp_probe(struct platform_device *pdev)
++{
++      struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
++      const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
++      struct twl4030_keypad *kp;
++      struct input_dev *input;
++      u8 reg;
++      int error;
++
++      if (!pdata || !pdata->rows || !pdata->cols ||
++          pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) {
++              dev_err(&pdev->dev, "Invalid platform_data\n");
++              return -EINVAL;
++      }
++
++      kp = kzalloc(sizeof(*kp), GFP_KERNEL);
++      input = input_allocate_device();
++      if (!kp || !input) {
++              error = -ENOMEM;
++              goto err1;
++      }
++
++      /* Get the debug Device */
++      kp->dbg_dev = &pdev->dev;
++      kp->input = input;
++
++      kp->n_rows = pdata->rows;
++      kp->n_cols = pdata->cols;
++      kp->irq = platform_get_irq(pdev, 0);
++
++      /* setup input device */
++      __set_bit(EV_KEY, input->evbit);
++
++      /* Enable auto repeat feature of Linux input subsystem */
++      if (pdata->rep)
++              __set_bit(EV_REP, input->evbit);
++
++      input_set_capability(input, EV_MSC, MSC_SCAN);
++
++      input->name             = "TWL4030 Keypad";
++      input->phys             = "twl4030_keypad/input0";
++      input->dev.parent       = &pdev->dev;
++
++      input->id.bustype       = BUS_HOST;
++      input->id.vendor        = 0x0001;
++      input->id.product       = 0x0001;
++      input->id.version       = 0x0003;
++
++      input->keycode          = kp->keymap;
++      input->keycodesize      = sizeof(kp->keymap[0]);
++      input->keycodemax       = ARRAY_SIZE(kp->keymap);
++
++      matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT,
++                                 input->keycode, input->keybit);
++
++      error = input_register_device(input);
++      if (error) {
++              dev_err(kp->dbg_dev,
++                      "Unable to register twl4030 keypad device\n");
++              goto err1;
++      }
++
++      error = twl4030_kp_program(kp);
++      if (error)
++              goto err2;
++
++      /*
++       * This ISR will always execute in kernel thread context because of
++       * the need to access the TWL4030 over the I2C bus.
++       *
++       * NOTE:  we assume this host is wired to TWL4040 INT1, not INT2 ...
++       */
++      error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp);
++      if (error) {
++              dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
++                      kp->irq);
++              goto err3;
++      }
++
++      /* Enable KP and TO interrupts now. */
++      reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
++      if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) {
++              error = -EIO;
++              goto err4;
++      }
++
++      platform_set_drvdata(pdev, kp);
++      return 0;
++
++err4:
++      /* mask all events - we don't care about the result */
++      (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1);
++err3:
++      free_irq(kp->irq, NULL);
++err2:
++      input_unregister_device(input);
++      input = NULL;
++err1:
++      input_free_device(input);
++      kfree(kp);
++      return error;
++}
++
++static int __devexit twl4030_kp_remove(struct platform_device *pdev)
++{
++      struct twl4030_keypad *kp = platform_get_drvdata(pdev);
++
++      free_irq(kp->irq, kp);
++      input_unregister_device(kp->input);
++      platform_set_drvdata(pdev, NULL);
++      kfree(kp);
++
++      return 0;
++}
++
++/*
++ * NOTE: twl4030 are multi-function devices connected via I2C.
++ * So this device is a child of an I2C parent, thus it needs to
++ * support unplug/replug (which most platform devices don't).
++ */
++
++static struct platform_driver twl4030_kp_driver = {
++      .probe          = twl4030_kp_probe,
++      .remove         = __devexit_p(twl4030_kp_remove),
++      .driver         = {
++              .name   = "twl4030_keypad",
++              .owner  = THIS_MODULE,
++      },
++};
++
++static int __init twl4030_kp_init(void)
++{
++      return platform_driver_register(&twl4030_kp_driver);
++}
++module_init(twl4030_kp_init);
++
++static void __exit twl4030_kp_exit(void)
++{
++      platform_driver_unregister(&twl4030_kp_driver);
++}
++module_exit(twl4030_kp_exit);
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_DESCRIPTION("TWL4030 Keypad Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:twl4030_keypad");
++
+diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
+index dc40f95..3d6321e 100644
+--- a/include/linux/i2c/twl4030.h
++++ b/include/linux/i2c/twl4030.h
+@@ -25,6 +25,9 @@
+ #ifndef __TWL4030_H_
+ #define __TWL4030_H_
++#include <linux/types.h>
++#include <linux/input/matrix_keypad.h>
++
+ /*
+  * Using the twl4030 core we address registers using a pair
+  *    { module id, relative register offset }
+@@ -254,13 +257,17 @@ struct twl4030_madc_platform_data {
+       int             irq_line;
+ };
++/* Boards have uniqe mappings of {col, row} --> keycode.
++ * Column and row are 4 bits, but range only from 0..7.
++ * a PERSISTENT_KEY is "always on" and never reported.
++ */
++#define PERSISTENT_KEY(c, r)  KEY((c), (r), KEY_RESERVED)
++
+ struct twl4030_keypad_data {
+-      int rows;
+-      int cols;
+-      int *keymap;
+-      int irq;
+-      unsigned int keymapsize;
+-      unsigned int rep:1;
++      const struct matrix_keymap_data *keymap_data;
++      unsigned rows;
++      unsigned cols;
++      bool rep;
+ };
+ enum twl4030_usb_mode {
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0006-input-hacks-updates-for-mainline-twl4030-driver.patch b/recipes/linux/omap3-pandora-kernel/keypad/0006-input-hacks-updates-for-mainline-twl4030-driver.patch
new file mode 100644 (file)
index 0000000..753404f
--- /dev/null
@@ -0,0 +1,182 @@
+From 9416a510c6939bc6da62cf12de665fd11b89a9f6 Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Thu, 5 Nov 2009 12:44:01 +0200
+Subject: [PATCH 6/7] input: hacks+updates for mainline twl4030 driver
+
+This includes some differing #includes and col/row swap
+in the KEY() macro.
+---
+ arch/arm/mach-omap2/board-omap3pandora-input.c |   89 ++++++++++++-----------
+ drivers/input/keyboard/twl4030_keypad.c        |    1 +
+ drivers/mfd/twl4030-core.c                     |    8 ++
+ include/linux/i2c/twl4030.h                    |    3 -
+ 4 files changed, 55 insertions(+), 46 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3pandora-input.c b/arch/arm/mach-omap2/board-omap3pandora-input.c
+index 6ca69ce..ce9df0e 100644
+--- a/arch/arm/mach-omap2/board-omap3pandora-input.c
++++ b/arch/arm/mach-omap2/board-omap3pandora-input.c
+@@ -23,68 +23,71 @@
+ #include <linux/platform_device.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
++#include <linux/input/matrix_keypad.h>
+ #include <mach/hardware.h>
+-#include <mach/keypad.h>
+ #include <mach/gpio.h>
+ /* hardware debounce, (value + 1) * 31us */
+ #define GPIO_DEBOUNCE_TIME 0x7f
+ static int omap3pandora_keymap[] = {
+-      /* col, row, code */
++      /* row, col, code */
+       KEY(0, 0, KEY_9),
+-      KEY(0, 1, KEY_0),
+-      KEY(0, 2, KEY_BACKSPACE),
+-      KEY(0, 3, KEY_O),
+-      KEY(0, 4, KEY_P),
+-      KEY(0, 5, KEY_K),
+-      KEY(0, 6, KEY_L),
+-      KEY(0, 7, KEY_ENTER),
+-      KEY(1, 0, KEY_8),
++      KEY(0, 1, KEY_8),
++      KEY(0, 2, KEY_I),
++      KEY(0, 3, KEY_J),
++      KEY(0, 4, KEY_N),
++      KEY(0, 5, KEY_M),
++      KEY(1, 0, KEY_0),
+       KEY(1, 1, KEY_7),
+-      KEY(1, 2, KEY_6),
+-      KEY(1, 3, KEY_5),
+-      KEY(1, 4, KEY_4),
+-      KEY(1, 5, KEY_3),
+-      KEY(1, 6, KEY_2),
+-      KEY(1, 7, KEY_1),
+-      KEY(2, 0, KEY_I),
+-      KEY(2, 1, KEY_U),
++      KEY(1, 2, KEY_U),
++      KEY(1, 3, KEY_H),
++      KEY(1, 4, KEY_B),
++      KEY(1, 5, KEY_SPACE),
++      KEY(2, 0, KEY_BACKSPACE),
++      KEY(2, 1, KEY_6),
+       KEY(2, 2, KEY_Y),
+-      KEY(2, 3, KEY_T),
+-      KEY(2, 4, KEY_R),
+-      KEY(2, 5, KEY_E),
+-      KEY(2, 6, KEY_W),
+-      KEY(2, 7, KEY_Q),
+-      KEY(3, 0, KEY_J),
+-      KEY(3, 1, KEY_H),
+-      KEY(3, 2, KEY_G),
++      KEY(2, 3, KEY_G),
++      KEY(2, 4, KEY_V),
++      KEY(2, 5, KEY_FN),
++      KEY(3, 0, KEY_O),
++      KEY(3, 1, KEY_5),
++      KEY(3, 2, KEY_T),
+       KEY(3, 3, KEY_F),
+-      KEY(3, 4, KEY_D),
+-      KEY(3, 5, KEY_S),
+-      KEY(3, 6, KEY_A),
+-      KEY(3, 7, KEY_LEFTSHIFT),
+-      KEY(4, 0, KEY_N),
+-      KEY(4, 1, KEY_B),
+-      KEY(4, 2, KEY_V),
+-      KEY(4, 3, KEY_C),
++      KEY(3, 4, KEY_C),
++      KEY(4, 0, KEY_P),
++      KEY(4, 1, KEY_4),
++      KEY(4, 2, KEY_R),
++      KEY(4, 3, KEY_D),
+       KEY(4, 4, KEY_X),
+-      KEY(4, 5, KEY_Z),
+-      KEY(4, 6, KEY_DOT),
+-      KEY(4, 7, KEY_COMMA),
+-      KEY(5, 0, KEY_M),
+-      KEY(5, 1, KEY_SPACE),
+-      KEY(5, 2, KEY_FN),
++      KEY(5, 0, KEY_K),
++      KEY(5, 1, KEY_3),
++      KEY(5, 2, KEY_E),
++      KEY(5, 3, KEY_S),
++      KEY(5, 4, KEY_Z),
++      KEY(6, 0, KEY_L),
++      KEY(6, 1, KEY_2),
++      KEY(6, 2, KEY_W),
++      KEY(6, 3, KEY_A),
++      KEY(6, 4, KEY_DOT),
++      KEY(7, 0, KEY_ENTER),
++      KEY(7, 1, KEY_1),
++      KEY(7, 2, KEY_Q),
++      KEY(7, 3, KEY_LEFTSHIFT),
++      KEY(7, 4, KEY_COMMA),
++};
++
++static struct matrix_keymap_data board_map_data = {
++      .keymap         = omap3pandora_keymap,
++      .keymap_size    = ARRAY_SIZE(omap3pandora_keymap),
+ };
+ struct twl4030_keypad_data omap3pandora_kp_data = {
++      .keymap_data    = &board_map_data,
+       .rows           = 8,
+       .cols           = 6,
+-      .keymap         = omap3pandora_keymap,
+-      .keymapsize     = ARRAY_SIZE(omap3pandora_keymap),
+       .rep            = 1,
+-      .irq            = TWL4030_MODIRQ_KEYPAD,
+ };
+ static struct gpio_keys_button gpio_buttons[] = {
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index 9a2977c..99bb58d 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -32,6 +32,7 @@
+ #include <linux/input.h>
+ #include <linux/platform_device.h>
+ #include <linux/i2c/twl4030.h>
++#include <linux/input/matrix_keypad.h>
+ /*
+diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
+index dd843c4..4c502d7 100644
+--- a/drivers/mfd/twl4030-core.c
++++ b/drivers/mfd/twl4030-core.c
+@@ -468,7 +468,15 @@ static int add_children(struct twl4030_platform_data *pdata)
+                                       status);
+                               platform_device_put(pdev);
+                               goto err;
++                      } else {
++                              struct resource r = {
++                                      .start = pdata->irq_base + 1,
++                                      .flags = IORESOURCE_IRQ,
++                              };
++
++                              status = platform_device_add_resources(pdev, &r, 1);
+                       }
++
+                       status = platform_device_add(pdev);
+                       if (status < 0) {
+                               platform_device_put(pdev);
+diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
+index 3d6321e..4a31016 100644
+--- a/include/linux/i2c/twl4030.h
++++ b/include/linux/i2c/twl4030.h
+@@ -25,9 +25,6 @@
+ #ifndef __TWL4030_H_
+ #define __TWL4030_H_
+-#include <linux/types.h>
+-#include <linux/input/matrix_keypad.h>
+-
+ /*
+  * Using the twl4030 core we address registers using a pair
+  *    { module id, relative register offset }
+-- 
+1.6.3.1
+
diff --git a/recipes/linux/omap3-pandora-kernel/keypad/0007-some-hackish-Fn-handling-for-testing.patch b/recipes/linux/omap3-pandora-kernel/keypad/0007-some-hackish-Fn-handling-for-testing.patch
new file mode 100644 (file)
index 0000000..be0a2a4
--- /dev/null
@@ -0,0 +1,157 @@
+From fc359f9dd7efd346c070950320dda62ae671519f Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Thu, 5 Nov 2009 12:52:23 +0200
+Subject: [PATCH 7/7] some hackish Fn handling for testing
+
+---
+ arch/arm/mach-omap2/board-omap3pandora-input.c |   47 ++++++++++++++++++++++++
+ drivers/input/keyboard/twl4030_keypad.c        |   39 +++++++++++++++++---
+ 2 files changed, 81 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3pandora-input.c b/arch/arm/mach-omap2/board-omap3pandora-input.c
+index ce9df0e..3d530cf 100644
+--- a/arch/arm/mach-omap2/board-omap3pandora-input.c
++++ b/arch/arm/mach-omap2/board-omap3pandora-input.c
+@@ -31,6 +31,9 @@
+ /* hardware debounce, (value + 1) * 31us */
+ #define GPIO_DEBOUNCE_TIME 0x7f
++/* HACK: this requires patched twl4030_keypad driver */
++#define FNKEY(row, col, code) KEY((row + 8), col, code)
++
+ static int omap3pandora_keymap[] = {
+       /* row, col, code */
+       KEY(0, 0, KEY_9),
+@@ -76,6 +79,50 @@ static int omap3pandora_keymap[] = {
+       KEY(7, 2, KEY_Q),
+       KEY(7, 3, KEY_LEFTSHIFT),
+       KEY(7, 4, KEY_COMMA),
++      /* Fn keys */
++      FNKEY(0, 0, KEY_F9),
++      FNKEY(0, 1, KEY_F8),
++      FNKEY(0, 2, KEY_BRIGHTNESSUP),
++      FNKEY(0, 3, KEY_F13),           /* apostrophe, differs from Fn-A? */
++      FNKEY(0, 4, KEY_DOLLAR),
++      FNKEY(0, 5, KEY_EURO),
++      FNKEY(1, 0, KEY_F10),
++      FNKEY(1, 1, KEY_F7),
++      FNKEY(1, 2, KEY_BRIGHTNESSDOWN),
++      FNKEY(1, 3, KEY_GRAVE),
++      FNKEY(1, 4, KEY_F14),           /* pipe/bar */
++      FNKEY(1, 5, KEY_TAB),
++      FNKEY(2, 0, KEY_INSERT),
++      FNKEY(2, 1, KEY_F6),
++      FNKEY(2, 2, KEY_F15),           /* dash */
++      FNKEY(2, 3, KEY_EQUAL),
++      FNKEY(2, 4, KEY_F16),           /* # (pound/hash) */
++      FNKEY(2, 5, KEY_FN),
++      FNKEY(3, 0, KEY_F11),
++      FNKEY(3, 1, KEY_F5),
++      FNKEY(3, 2, KEY_F17),           /* ! */
++      FNKEY(3, 3, KEY_KPPLUS),
++      FNKEY(3, 4, KEY_BACKSLASH),
++      FNKEY(4, 0, KEY_F12),
++      FNKEY(4, 1, KEY_F4),
++      FNKEY(4, 2, KEY_RIGHTBRACE),
++      FNKEY(4, 3, KEY_KPMINUS),
++      FNKEY(4, 4, KEY_QUESTION),
++      FNKEY(5, 0, KEY_F18),           /* £ (pound) */
++      FNKEY(5, 1, KEY_F3),
++      FNKEY(5, 2, KEY_LEFTBRACE),
++      FNKEY(5, 3, KEY_F19),           /* " */
++      FNKEY(5, 4, KEY_SLASH),
++      FNKEY(6, 0, KEY_YEN),
++      FNKEY(6, 1, KEY_F2),
++      FNKEY(6, 2, KEY_F20),           /* @ */
++      FNKEY(6, 3, KEY_APOSTROPHE),
++      FNKEY(6, 4, KEY_F21),           /* : */
++      FNKEY(7, 0, KEY_ENTER),
++      FNKEY(7, 1, KEY_F1),
++      FNKEY(7, 2, KEY_ESC),
++      FNKEY(7, 3, KEY_CAPSLOCK),
++      FNKEY(7, 4, KEY_SEMICOLON),
+ };
+ static struct matrix_keymap_data board_map_data = {
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index 99bb58d..74485d6 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -52,7 +52,7 @@
+ #define TWL4030_MAX_ROWS      8       /* TWL4030 hard limit */
+ #define TWL4030_MAX_COLS      8
+ #define TWL4030_ROW_SHIFT     3
+-#define TWL4030_KEYMAP_SIZE   (TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
++#define TWL4030_KEYMAP_SIZE   (TWL4030_MAX_ROWS * 2 * TWL4030_MAX_COLS)
+ struct twl4030_keypad {
+       unsigned short  keymap[TWL4030_KEYMAP_SIZE];
+@@ -61,6 +61,9 @@ struct twl4030_keypad {
+       unsigned        n_cols;
+       unsigned        irq;
++      unsigned        fn_down:1;
++      unsigned        fn_sticked:1;
++
+       struct device *dbg_dev;
+       struct input_dev *input;
+ };
+@@ -226,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
+                       continue;
+               for (col = 0; col < kp->n_cols; col++) {
+-                      int code;
++                      int code, kcode, is_down;
++                      int code2;
+                       if (!(changed & (1 << col)))
+                               continue;
+@@ -236,9 +240,34 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
+                               "press" : "release");
+                       code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT);
++                      kcode = kp->keymap[code];
++                      is_down = (new_state[row] & (1 << col)) ? 1 : 0;
++
++                      dev_dbg(kp->dbg_dev, "code:     %d %d\n", code, kcode);
++                      /* Fn handling */
++                      if (kcode == KEY_FN) {
++                              kp->fn_down = is_down;
++                              kp->fn_sticked |= is_down;
++                      } else if (kp->fn_down || kp->fn_sticked) {
++                              /* make sure other function is up */
++                              input_event(input, EV_MSC, MSC_SCAN, code);
++                              input_report_key(input, kcode, 0);
++
++                              code = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
++                                      col, TWL4030_ROW_SHIFT);
++                              kcode = kp->keymap[code];
++
++                              kp->fn_sticked = 0;
++                      } else {
++                              code2 = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
++                                      col, TWL4030_ROW_SHIFT);
++                              input_event(input, EV_MSC, MSC_SCAN, code2);
++                              input_report_key(input, kp->keymap[code2], 0);
++                      }
++
++                      dev_dbg(kp->dbg_dev, "code(fn): %d %d\n", code, kcode);
+                       input_event(input, EV_MSC, MSC_SCAN, code);
+-                      input_report_key(input, kp->keymap[code],
+-                                       new_state[row] & (1 << col));
++                      input_report_key(input, kcode, is_down);
+               }
+               kp->kp_state[row] = new_state[row];
+       }
+@@ -371,7 +400,7 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
+       input_set_capability(input, EV_MSC, MSC_SCAN);
+-      input->name             = "TWL4030 Keypad";
++      input->name             = "omap_twl4030keypad";
+       input->phys             = "twl4030_keypad/input0";
+       input->dev.parent       = &pdev->dev;
+-- 
+1.6.3.1
+
index 3079525..6a6a824 100755 (executable)
@@ -5,23 +5,6 @@ KERNEL_IMAGETYPE = "uImage"
 
 COMPATIBLE_MACHINE = "omap3-pandora"
 
-# ----- Revision 2 Boards -----
-
-#GIT HEAD for Rev2 - Same as Rev3 without Batt Fuel Guage and Nub/Button changes.
-
-#SRCREV = "45dce3afbd5c2d2af899ae7e7a107d01a5c15558"
-
-#SRC_URI = " \
-#           git://git.openpandora.org/pandora-kernel.git;protocol=git;branch=rev2 \
-#"
-
-# -----------------------------
-
-
-# ----- Revision 3 > Boards -----
-
-#GIT HEAD for Rev3 > (i.e. Shipping units) - Will run on Rev2 boards without Nubs and an incorrect Start button.
-
 SRCREV = "b7075725f109114e144c5534cd519ffa2b9780d9"
 
 SRC_URI = " \
@@ -61,5 +44,24 @@ SRC_URI_append = " \
            file://0002-Add-a-very-basic-platform-driver-module-to-bring-up-.patch;patch=1 \
            file://0003-Remove-old-msm_wifi-hack-as-the-temp-platform-driver.patch;patch=1 \
 "
+
+# AUFS2 Patches - Used by ausf2-27 recipe to build as a module.
+
+SRC_URI_append = " \
+           file://aufs2/aufs2-base.patch;patch=1 \
+           file://aufs2/aufs2-standalone.patch;patch=1 \
+"           
+
+# Temp Keypad Patches for FN.
+
+SRC_URI_append = " \
+           file://keypad/0001-input-remove-old-twl4030keypad-to-replace-it-with-ma.patch;patch=1 \
+           file://keypad/0002-Input-add-support-for-generic-GPIO-based-matrix-keyp.patch;patch=1 \
+           file://keypad/0003-Input-matrix_keypad-make-matrix-keymap-size-dynamic.patch;patch=1 \
+           file://keypad/0004-Input-matrix-keypad-add-function-to-build-device-key.patch;patch=1 \
+           file://keypad/0005-Input-add-twl4030_keypad-driver.patch;patch=1 \
+           file://keypad/0006-input-hacks-updates-for-mainline-twl4030-driver.patch;patch=1 \
+           file://keypad/0007-some-hackish-Fn-handling-for-testing.patch;patch=1 \           
+"       
        
 S = "${WORKDIR}/git"