aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r--drivers/input/keyboard/corgikbd.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index a8551711e8d6..cd4b6e795013 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/input.h> 17#include <linux/input.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/jiffies.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <asm/irq.h> 22#include <asm/irq.h>
@@ -32,7 +33,6 @@
32/* zero code, 124 scancodes + 3 hinge combinations */ 33/* zero code, 124 scancodes + 3 hinge combinations */
33#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) 34#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
34#define SCAN_INTERVAL (HZ/10) 35#define SCAN_INTERVAL (HZ/10)
35#define CORGIKBD_PRESSED 1
36 36
37#define HINGE_SCAN_INTERVAL (HZ/4) 37#define HINGE_SCAN_INTERVAL (HZ/4)
38 38
@@ -73,25 +73,13 @@ struct corgikbd {
73 struct input_dev input; 73 struct input_dev input;
74 char phys[32]; 74 char phys[32];
75 75
76 unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
77 spinlock_t lock; 76 spinlock_t lock;
78
79 struct timer_list timer; 77 struct timer_list timer;
80 struct timer_list htimer; 78 struct timer_list htimer;
81};
82 79
83static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) 80 unsigned int suspended;
84{ 81 unsigned long suspend_jiffies;
85 if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { 82};
86 corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
87 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
88 if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
89 input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
90 } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
91 corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
92 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
93 }
94}
95 83
96#define KB_DISCHARGE_DELAY 10 84#define KB_DISCHARGE_DELAY 10
97#define KB_ACTIVATE_DELAY 10 85#define KB_ACTIVATE_DELAY 10
@@ -105,36 +93,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c
105 */ 93 */
106static inline void corgikbd_discharge_all(void) 94static inline void corgikbd_discharge_all(void)
107{ 95{
108 // STROBE All HiZ 96 /* STROBE All HiZ */
109 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; 97 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
110 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; 98 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
111} 99}
112 100
113static inline void corgikbd_activate_all(void) 101static inline void corgikbd_activate_all(void)
114{ 102{
115 // STROBE ALL -> High 103 /* STROBE ALL -> High */
116 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; 104 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
117 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; 105 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
118 106
119 udelay(KB_DISCHARGE_DELAY); 107 udelay(KB_DISCHARGE_DELAY);
120 108
121 // Clear any interrupts we may have triggered when altering the GPIO lines 109 /* Clear any interrupts we may have triggered when altering the GPIO lines */
122 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; 110 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
123 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; 111 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
124} 112}
125 113
126static inline void corgikbd_activate_col(int col) 114static inline void corgikbd_activate_col(int col)
127{ 115{
128 // STROBE col -> High, not col -> HiZ 116 /* STROBE col -> High, not col -> HiZ */
129 GPSR2 = CORGI_GPIO_STROBE_BIT(col); 117 GPSR2 = CORGI_GPIO_STROBE_BIT(col);
130 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); 118 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
131} 119}
132 120
133static inline void corgikbd_reset_col(int col) 121static inline void corgikbd_reset_col(int col)
134{ 122{
135 // STROBE col -> Low 123 /* STROBE col -> Low */
136 GPCR2 = CORGI_GPIO_STROBE_BIT(col); 124 GPCR2 = CORGI_GPIO_STROBE_BIT(col);
137 // STROBE col -> out, not col -> HiZ 125 /* STROBE col -> out, not col -> HiZ */
138 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); 126 GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
139} 127}
140 128
@@ -149,10 +137,13 @@ static inline void corgikbd_reset_col(int col)
149/* Scan the hardware keyboard and push any changes up through the input layer */ 137/* Scan the hardware keyboard and push any changes up through the input layer */
150static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) 138static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
151{ 139{
152 unsigned int row, col, rowd, scancode; 140 unsigned int row, col, rowd;
153 unsigned long flags; 141 unsigned long flags;
154 unsigned int num_pressed; 142 unsigned int num_pressed;
155 143
144 if (corgikbd_data->suspended)
145 return;
146
156 spin_lock_irqsave(&corgikbd_data->lock, flags); 147 spin_lock_irqsave(&corgikbd_data->lock, flags);
157 148
158 if (regs) 149 if (regs)
@@ -173,10 +164,21 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
173 164
174 rowd = GET_ROWS_STATUS(col); 165 rowd = GET_ROWS_STATUS(col);
175 for (row = 0; row < KB_ROWS; row++) { 166 for (row = 0; row < KB_ROWS; row++) {
167 unsigned int scancode, pressed;
168
176 scancode = SCANCODE(row, col); 169 scancode = SCANCODE(row, col);
177 handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data); 170 pressed = rowd & KB_ROWMASK(row);
178 if (rowd & KB_ROWMASK(row)) 171
172 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
173
174 if (pressed)
179 num_pressed++; 175 num_pressed++;
176
177 if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
178 && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
179 input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
180 corgikbd_data->suspend_jiffies=jiffies;
181 }
180 } 182 }
181 corgikbd_reset_col(col); 183 corgikbd_reset_col(col);
182 } 184 }
@@ -221,8 +223,11 @@ static void corgikbd_timer_callback(unsigned long data)
221 * The hinge switches generate no interrupt so they need to be 223 * The hinge switches generate no interrupt so they need to be
222 * monitored by a timer. 224 * monitored by a timer.
223 * 225 *
224 * When we detect changes, we debounce it and then pass the three 226 * We debounce the switches and pass them to the input system.
225 * positions the system can take as keypresses to the input system. 227 *
228 * gprr == 0x00 - Keyboard with Landscape Screen
229 * 0x08 - No Keyboard with Portrait Screen
230 * 0x0c - Keyboard and Screen Closed
226 */ 231 */
227 232
228#define HINGE_STABLE_COUNT 2 233#define HINGE_STABLE_COUNT 2
@@ -235,7 +240,7 @@ static void corgikbd_hinge_timer(unsigned long data)
235 unsigned long gprr; 240 unsigned long gprr;
236 unsigned long flags; 241 unsigned long flags;
237 242
238 gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); 243 gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
239 if (gprr != sharpsl_hinge_state) { 244 if (gprr != sharpsl_hinge_state) {
240 hinge_count = 0; 245 hinge_count = 0;
241 sharpsl_hinge_state = gprr; 246 sharpsl_hinge_state = gprr;
@@ -244,9 +249,8 @@ static void corgikbd_hinge_timer(unsigned long data)
244 if (hinge_count >= HINGE_STABLE_COUNT) { 249 if (hinge_count >= HINGE_STABLE_COUNT) {
245 spin_lock_irqsave(&corgikbd_data->lock, flags); 250 spin_lock_irqsave(&corgikbd_data->lock, flags);
246 251
247 handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */ 252 input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
248 handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */ 253 input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
249 handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
250 input_sync(&corgikbd_data->input); 254 input_sync(&corgikbd_data->input);
251 255
252 spin_unlock_irqrestore(&corgikbd_data->lock, flags); 256 spin_unlock_irqrestore(&corgikbd_data->lock, flags);
@@ -255,19 +259,45 @@ static void corgikbd_hinge_timer(unsigned long data)
255 mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); 259 mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
256} 260}
257 261
262#ifdef CONFIG_PM
263static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
264{
265 if (level == SUSPEND_POWER_DOWN) {
266 struct corgikbd *corgikbd = dev_get_drvdata(dev);
267 corgikbd->suspended = 1;
268 }
269 return 0;
270}
271
272static int corgikbd_resume(struct device *dev, uint32_t level)
273{
274 if (level == RESUME_POWER_ON) {
275 struct corgikbd *corgikbd = dev_get_drvdata(dev);
276
277 /* Upon resume, ignore the suspend key for a short while */
278 corgikbd->suspend_jiffies=jiffies;
279 corgikbd->suspended = 0;
280 }
281 return 0;
282}
283#else
284#define corgikbd_suspend NULL
285#define corgikbd_resume NULL
286#endif
287
258static int __init corgikbd_probe(struct device *dev) 288static int __init corgikbd_probe(struct device *dev)
259{ 289{
260 int i; 290 int i;
261 struct corgikbd *corgikbd; 291 struct corgikbd *corgikbd;
262 292
263 corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL); 293 corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
264 if (!corgikbd) 294 if (!corgikbd)
265 return -ENOMEM; 295 return -ENOMEM;
266 296
267 dev_set_drvdata(dev,corgikbd); 297 dev_set_drvdata(dev,corgikbd);
268 strcpy(corgikbd->phys, "corgikbd/input0"); 298 strcpy(corgikbd->phys, "corgikbd/input0");
269 299
270 spin_lock_init(corgikbd->lock); 300 spin_lock_init(&corgikbd->lock);
271 301
272 /* Init Keyboard rescan timer */ 302 /* Init Keyboard rescan timer */
273 init_timer(&corgikbd->timer); 303 init_timer(&corgikbd->timer);
@@ -279,6 +309,8 @@ static int __init corgikbd_probe(struct device *dev)
279 corgikbd->htimer.function = corgikbd_hinge_timer; 309 corgikbd->htimer.function = corgikbd_hinge_timer;
280 corgikbd->htimer.data = (unsigned long) corgikbd; 310 corgikbd->htimer.data = (unsigned long) corgikbd;
281 311
312 corgikbd->suspend_jiffies=jiffies;
313
282 init_input_dev(&corgikbd->input); 314 init_input_dev(&corgikbd->input);
283 corgikbd->input.private = corgikbd; 315 corgikbd->input.private = corgikbd;
284 corgikbd->input.name = "Corgi Keyboard"; 316 corgikbd->input.name = "Corgi Keyboard";
@@ -288,7 +320,7 @@ static int __init corgikbd_probe(struct device *dev)
288 corgikbd->input.id.vendor = 0x0001; 320 corgikbd->input.id.vendor = 0x0001;
289 corgikbd->input.id.product = 0x0001; 321 corgikbd->input.id.product = 0x0001;
290 corgikbd->input.id.version = 0x0100; 322 corgikbd->input.id.version = 0x0100;
291 corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR); 323 corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
292 corgikbd->input.keycode = corgikbd->keycode; 324 corgikbd->input.keycode = corgikbd->keycode;
293 corgikbd->input.keycodesize = sizeof(unsigned char); 325 corgikbd->input.keycodesize = sizeof(unsigned char);
294 corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode); 326 corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
@@ -297,6 +329,8 @@ static int __init corgikbd_probe(struct device *dev)
297 for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) 329 for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
298 set_bit(corgikbd->keycode[i], corgikbd->input.keybit); 330 set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
299 clear_bit(0, corgikbd->input.keybit); 331 clear_bit(0, corgikbd->input.keybit);
332 set_bit(SW_0, corgikbd->input.swbit);
333 set_bit(SW_1, corgikbd->input.swbit);
300 334
301 input_register_device(&corgikbd->input); 335 input_register_device(&corgikbd->input);
302 mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); 336 mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
@@ -343,6 +377,8 @@ static struct device_driver corgikbd_driver = {
343 .bus = &platform_bus_type, 377 .bus = &platform_bus_type,
344 .probe = corgikbd_probe, 378 .probe = corgikbd_probe,
345 .remove = corgikbd_remove, 379 .remove = corgikbd_remove,
380 .suspend = corgikbd_suspend,
381 .resume = corgikbd_resume,
346}; 382};
347 383
348static int __devinit corgikbd_init(void) 384static int __devinit corgikbd_init(void)