diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-09 21:14:47 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-09 21:14:47 -0400 |
commit | d344c5e0856ad03278d8700b503762dbc8b86e12 (patch) | |
tree | a6d893a643470a3c2580a58f3228a55fa1fd1d82 /drivers/input/keyboard | |
parent | 010988e888a0abbe7118635c1b33d049caae6b29 (diff) | |
parent | 87fc767b832ef5a681a0ff9d203c3289bc3be2bf (diff) |
Manual merge with Linus
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/corgikbd.c | 104 |
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 | ||
83 | static 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 | */ |
106 | static inline void corgikbd_discharge_all(void) | 94 | static 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 | ||
113 | static inline void corgikbd_activate_all(void) | 101 | static 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 | ||
126 | static inline void corgikbd_activate_col(int col) | 114 | static 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 | ||
133 | static inline void corgikbd_reset_col(int col) | 121 | static 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 */ |
150 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) | 138 | static 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 | ||
263 | static 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 | |||
272 | static 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 | |||
258 | static int __init corgikbd_probe(struct device *dev) | 288 | static 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 | ||
348 | static int __devinit corgikbd_init(void) | 384 | static int __devinit corgikbd_init(void) |