aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 408379669d3c..791781ade4e7 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -24,8 +24,8 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/input.h> 26#include <linux/input.h>
27#include <linux/interrupt.h>
27#include <linux/kernel.h> 28#include <linux/kernel.h>
28#include <linux/notifier.h>
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/input/matrix_keypad.h> 31#include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
42 * @dev: Device pointer 42 * @dev: Device pointer
43 * @idev: Input device 43 * @idev: Input device
44 * @ec: Top level ChromeOS device to use to talk to EC 44 * @ec: Top level ChromeOS device to use to talk to EC
45 * @event_notifier: interrupt event notifier for transport devices
46 */ 45 */
47struct cros_ec_keyb { 46struct cros_ec_keyb {
48 unsigned int rows; 47 unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
55 struct device *dev; 54 struct device *dev;
56 struct input_dev *idev; 55 struct input_dev *idev;
57 struct cros_ec_device *ec; 56 struct cros_ec_device *ec;
58 struct notifier_block notifier;
59}; 57};
60 58
61 59
@@ -173,41 +171,55 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
173 input_sync(ckdev->idev); 171 input_sync(ckdev->idev);
174} 172}
175 173
176static int cros_ec_keyb_open(struct input_dev *dev)
177{
178 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
179
180 return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
181 &ckdev->notifier);
182}
183
184static void cros_ec_keyb_close(struct input_dev *dev)
185{
186 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
187
188 blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
189 &ckdev->notifier);
190}
191
192static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) 174static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
193{ 175{
194 return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE, 176 struct cros_ec_command msg = {
195 kb_state, ckdev->cols); 177 .version = 0,
178 .command = EC_CMD_MKBP_STATE,
179 .outdata = NULL,
180 .outsize = 0,
181 .indata = kb_state,
182 .insize = ckdev->cols,
183 };
184
185 return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
196} 186}
197 187
198static int cros_ec_keyb_work(struct notifier_block *nb, 188static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
199 unsigned long state, void *_notify)
200{ 189{
190 struct cros_ec_keyb *ckdev = data;
191 struct cros_ec_device *ec = ckdev->ec;
201 int ret; 192 int ret;
202 struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
203 notifier);
204 uint8_t kb_state[ckdev->cols]; 193 uint8_t kb_state[ckdev->cols];
205 194
195 if (device_may_wakeup(ec->dev))
196 pm_wakeup_event(ec->dev, 0);
197
206 ret = cros_ec_keyb_get_state(ckdev, kb_state); 198 ret = cros_ec_keyb_get_state(ckdev, kb_state);
207 if (ret >= 0) 199 if (ret >= 0)
208 cros_ec_keyb_process(ckdev, kb_state, ret); 200 cros_ec_keyb_process(ckdev, kb_state, ret);
201 else
202 dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
209 203
210 return NOTIFY_DONE; 204 return IRQ_HANDLED;
205}
206
207static int cros_ec_keyb_open(struct input_dev *dev)
208{
209 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
210 struct cros_ec_device *ec = ckdev->ec;
211
212 return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
213 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
214 "cros_ec_keyb", ckdev);
215}
216
217static void cros_ec_keyb_close(struct input_dev *dev)
218{
219 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
220 struct cros_ec_device *ec = ckdev->ec;
221
222 free_irq(ec->irq, ckdev);
211} 223}
212 224
213static int cros_ec_keyb_probe(struct platform_device *pdev) 225static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -238,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
238 if (!idev) 250 if (!idev)
239 return -ENOMEM; 251 return -ENOMEM;
240 252
253 if (!ec->irq) {
254 dev_err(dev, "no EC IRQ specified\n");
255 return -EINVAL;
256 }
257
241 ckdev->ec = ec; 258 ckdev->ec = ec;
242 ckdev->notifier.notifier_call = cros_ec_keyb_work;
243 ckdev->dev = dev; 259 ckdev->dev = dev;
244 dev_set_drvdata(&pdev->dev, ckdev); 260 dev_set_drvdata(&pdev->dev, ckdev);
245 261