diff options
author | Magnus Damm <damm@opensource.se> | 2010-02-11 01:13:21 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-02-11 02:04:13 -0500 |
commit | 324e5ade1569111a40c349726d8a2694b28d7943 (patch) | |
tree | 27bf7ba3d3a3634ab9266ac0a160e6d16e349a28 /drivers/input/keyboard | |
parent | 2b14a808fbbb042d0de323260d939bdf95e9efdf (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/keyboard')
-rw-r--r-- | drivers/input/keyboard/sh_keysc.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 6218b2f0249..c2fc97732f0 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 { | |||
35 | struct sh_keysc_priv { | 36 | struct 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 | ||
75 | static 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 | |||
74 | static irqreturn_t sh_keysc_isr(int irq, void *dev_id) | 84 | static 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 | } |