aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/corgikbd.c61
1 files changed, 28 insertions, 33 deletions
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 43d6edb3cf09..767e853dd766 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -33,7 +33,6 @@
33/* zero code, 124 scancodes + 3 hinge combinations */ 33/* zero code, 124 scancodes + 3 hinge combinations */
34#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 )
35#define SCAN_INTERVAL (HZ/10) 35#define SCAN_INTERVAL (HZ/10)
36#define CORGIKBD_PRESSED 1
37 36
38#define HINGE_SCAN_INTERVAL (HZ/4) 37#define HINGE_SCAN_INTERVAL (HZ/4)
39 38
@@ -74,9 +73,7 @@ struct corgikbd {
74 struct input_dev input; 73 struct input_dev input;
75 char phys[32]; 74 char phys[32];
76 75
77 unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
78 spinlock_t lock; 76 spinlock_t lock;
79
80 struct timer_list timer; 77 struct timer_list timer;
81 struct timer_list htimer; 78 struct timer_list htimer;
82 79
@@ -84,22 +81,6 @@ struct corgikbd {
84 unsigned long suspend_jiffies; 81 unsigned long suspend_jiffies;
85}; 82};
86 83
87static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
88{
89 if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
90 corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
91 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
92 if ((corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
93 && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
94 input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
95 corgikbd_data->suspend_jiffies=jiffies;
96 }
97 } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
98 corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
99 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
100 }
101}
102
103#define KB_DISCHARGE_DELAY 10 84#define KB_DISCHARGE_DELAY 10
104#define KB_ACTIVATE_DELAY 10 85#define KB_ACTIVATE_DELAY 10
105 86
@@ -112,36 +93,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c
112 */ 93 */
113static inline void corgikbd_discharge_all(void) 94static inline void corgikbd_discharge_all(void)
114{ 95{
115 // STROBE All HiZ 96 /* STROBE All HiZ */
116 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; 97 GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
117 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; 98 GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
118} 99}
119 100
120static inline void corgikbd_activate_all(void) 101static inline void corgikbd_activate_all(void)
121{ 102{
122 // STROBE ALL -> High 103 /* STROBE ALL -> High */
123 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; 104 GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
124 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; 105 GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
125 106
126 udelay(KB_DISCHARGE_DELAY); 107 udelay(KB_DISCHARGE_DELAY);
127 108
128 // 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 */
129 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; 110 GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
130 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; 111 GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
131} 112}
132 113
133static inline void corgikbd_activate_col(int col) 114static inline void corgikbd_activate_col(int col)
134{ 115{
135 // STROBE col -> High, not col -> HiZ 116 /* STROBE col -> High, not col -> HiZ */
136 GPSR2 = CORGI_GPIO_STROBE_BIT(col); 117 GPSR2 = CORGI_GPIO_STROBE_BIT(col);
137 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);
138} 119}
139 120
140static inline void corgikbd_reset_col(int col) 121static inline void corgikbd_reset_col(int col)
141{ 122{
142 // STROBE col -> Low 123 /* STROBE col -> Low */
143 GPCR2 = CORGI_GPIO_STROBE_BIT(col); 124 GPCR2 = CORGI_GPIO_STROBE_BIT(col);
144 // STROBE col -> out, not col -> HiZ 125 /* STROBE col -> out, not col -> HiZ */
145 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);
146} 127}
147 128
@@ -156,7 +137,7 @@ static inline void corgikbd_reset_col(int col)
156/* 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 */
157static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) 138static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
158{ 139{
159 unsigned int row, col, rowd, scancode; 140 unsigned int row, col, rowd;
160 unsigned long flags; 141 unsigned long flags;
161 unsigned int num_pressed; 142 unsigned int num_pressed;
162 143
@@ -183,10 +164,21 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
183 164
184 rowd = GET_ROWS_STATUS(col); 165 rowd = GET_ROWS_STATUS(col);
185 for (row = 0; row < KB_ROWS; row++) { 166 for (row = 0; row < KB_ROWS; row++) {
167 unsigned int scancode, pressed;
168
186 scancode = SCANCODE(row, col); 169 scancode = SCANCODE(row, col);
187 handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data); 170 pressed = rowd & KB_ROWMASK(row);
188 if (rowd & KB_ROWMASK(row)) 171
172 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
173
174 if (pressed)
189 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 }
190 } 182 }
191 corgikbd_reset_col(col); 183 corgikbd_reset_col(col);
192 } 184 }
@@ -231,8 +223,11 @@ static void corgikbd_timer_callback(unsigned long data)
231 * The hinge switches generate no interrupt so they need to be 223 * The hinge switches generate no interrupt so they need to be
232 * monitored by a timer. 224 * monitored by a timer.
233 * 225 *
234 * When we detect changes, we debounce it and then pass the three 226 * We debounce the switches and pass them to the input system.
235 * 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
236 */ 231 */
237 232
238#define HINGE_STABLE_COUNT 2 233#define HINGE_STABLE_COUNT 2
@@ -254,9 +249,9 @@ static void corgikbd_hinge_timer(unsigned long data)
254 if (hinge_count >= HINGE_STABLE_COUNT) { 249 if (hinge_count >= HINGE_STABLE_COUNT) {
255 spin_lock_irqsave(&corgikbd_data->lock, flags); 250 spin_lock_irqsave(&corgikbd_data->lock, flags);
256 251
257 handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */ 252 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[125], (sharpsl_hinge_state == 0x00));
258 handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */ 253 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[126], (sharpsl_hinge_state == 0x08));
259 handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */ 254 input_report_key(&corgikbd_data->input, corgikbd_data->keycode[127], (sharpsl_hinge_state == 0x0c));
260 input_sync(&corgikbd_data->input); 255 input_sync(&corgikbd_data->input);
261 256
262 spin_unlock_irqrestore(&corgikbd_data->lock, flags); 257 spin_unlock_irqrestore(&corgikbd_data->lock, flags);