aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2010-02-11 01:13:21 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-02-11 02:04:13 -0500
commit324e5ade1569111a40c349726d8a2694b28d7943 (patch)
tree27bf7ba3d3a3634ab9266ac0a160e6d16e349a28 /drivers/input
parent2b14a808fbbb042d0de323260d939bdf95e9efdf (diff)
Input: sh_keysc - switch to using bitmaps
Use bitmaps instead of using 32-bit integers to keep track of the key states. With this change in place the driver supports key pads with more than 32 keys. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/sh_keysc.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 6218b2f02495..c2fc97732f0c 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -19,6 +19,7 @@
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/input.h> 20#include <linux/input.h>
21#include <linux/input/sh_keysc.h> 21#include <linux/input/sh_keysc.h>
22#include <linux/bitmap.h>
22#include <linux/clk.h> 23#include <linux/clk.h>
23#include <linux/io.h> 24#include <linux/io.h>
24 25
@@ -35,7 +36,7 @@ static const struct {
35struct sh_keysc_priv { 36struct sh_keysc_priv {
36 void __iomem *iomem_base; 37 void __iomem *iomem_base;
37 struct clk *clk; 38 struct clk *clk;
38 unsigned long last_keys; 39 DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS);
39 struct input_dev *input; 40 struct input_dev *input;
40 struct sh_keysc_info pdata; 41 struct sh_keysc_info pdata;
41}; 42};
@@ -71,69 +72,87 @@ static void sh_keysc_level_mode(struct sh_keysc_priv *p,
71 udelay(pdata->kycr2_delay); 72 udelay(pdata->kycr2_delay);
72} 73}
73 74
75static void sh_keysc_map_dbg(struct device *dev, unsigned long *map,
76 const char *str)
77{
78 int k;
79
80 for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++)
81 dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]);
82}
83
74static irqreturn_t sh_keysc_isr(int irq, void *dev_id) 84static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
75{ 85{
76 struct platform_device *pdev = dev_id; 86 struct platform_device *pdev = dev_id;
77 struct sh_keysc_priv *priv = platform_get_drvdata(pdev); 87 struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
78 struct sh_keysc_info *pdata = &priv->pdata; 88 struct sh_keysc_info *pdata = &priv->pdata;
79 unsigned long keys, keys1, keys0, mask; 89 int keyout_nr = sh_keysc_mode[pdata->mode].keyout;
90 int keyin_nr = sh_keysc_mode[pdata->mode].keyin;
91 DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS);
92 DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS);
93 DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS);
80 unsigned char keyin_set, tmp; 94 unsigned char keyin_set, tmp;
81 int i, k; 95 int i, k, n;
82 96
83 dev_dbg(&pdev->dev, "isr!\n"); 97 dev_dbg(&pdev->dev, "isr!\n");
84 98
85 keys1 = ~0; 99 bitmap_fill(keys1, SH_KEYSC_MAXKEYS);
86 keys0 = 0; 100 bitmap_zero(keys0, SH_KEYSC_MAXKEYS);
87 101
88 do { 102 do {
89 keys = 0; 103 bitmap_zero(keys, SH_KEYSC_MAXKEYS);
90 keyin_set = 0; 104 keyin_set = 0;
91 105
92 sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); 106 sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED);
93 107
94 for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { 108 for (i = 0; i < keyout_nr; i++) {
109 n = keyin_nr * i;
110
111 /* drive one KEYOUT pin low, read KEYIN pins */
95 sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2))); 112 sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2)));
96 udelay(pdata->delay); 113 udelay(pdata->delay);
97 tmp = sh_keysc_read(priv, KYINDR); 114 tmp = sh_keysc_read(priv, KYINDR);
98 115
99 keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); 116 /* set bit if key press has been detected */
100 tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; 117 for (k = 0; k < keyin_nr; k++) {
101 keyin_set |= tmp; 118 if (tmp & (1 << k))
119 __set_bit(n + k, keys);
120 }
121
122 /* keep track of which KEYIN bits that have been set */
123 keyin_set |= tmp ^ ((1 << keyin_nr) - 1);
102 } 124 }
103 125
104 sh_keysc_level_mode(priv, keyin_set); 126 sh_keysc_level_mode(priv, keyin_set);
105 127
106 keys ^= ~0; 128 bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS);
107 keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * 129 bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS);
108 sh_keysc_mode[pdata->mode].keyout)) - 1; 130 bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS);
109 keys1 &= keys;
110 keys0 |= keys;
111 131
112 dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); 132 sh_keysc_map_dbg(&pdev->dev, keys, "keys");
113 133
114 } while (sh_keysc_read(priv, KYCR2) & 0x01); 134 } while (sh_keysc_read(priv, KYCR2) & 0x01);
115 135
116 dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", 136 sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys");
117 priv->last_keys, keys0, keys1); 137 sh_keysc_map_dbg(&pdev->dev, keys0, "keys0");
138 sh_keysc_map_dbg(&pdev->dev, keys1, "keys1");
118 139
119 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { 140 for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
120 k = pdata->keycodes[i]; 141 k = pdata->keycodes[i];
121 if (!k) 142 if (!k)
122 continue; 143 continue;
123 144
124 mask = 1 << i; 145 if (test_bit(i, keys0) == test_bit(i, priv->last_keys))
125
126 if (!((priv->last_keys ^ keys0) & mask))
127 continue; 146 continue;
128 147
129 if ((keys1 | keys0) & mask) { 148 if (test_bit(i, keys1) || test_bit(i, keys0)) {
130 input_event(priv->input, EV_KEY, k, 1); 149 input_event(priv->input, EV_KEY, k, 1);
131 priv->last_keys |= mask; 150 __set_bit(i, priv->last_keys);
132 } 151 }
133 152
134 if (!(keys1 & mask)) { 153 if (!test_bit(i, keys1)) {
135 input_event(priv->input, EV_KEY, k, 0); 154 input_event(priv->input, EV_KEY, k, 0);
136 priv->last_keys &= ~mask; 155 __clear_bit(i, priv->last_keys);
137 } 156 }
138 157
139 } 158 }