Message ID | 1355348028-19017-6-git-send-email-sjg@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, 12 Dec 2012 13:33:48 -0800, Simon Glass <sjg@chromium.org> wrote: > Use the key-matrix layer to interpret key scan information from the EC > and inject input based on the FDT-supplied key map. This driver registers > itself with the ChromeOS EC driver to perform communications. > > Additional FDT bindings are provided to specify rows/columns and the > auto-repeat information. > > Signed-off-by: Simon Glass <sjg@chromium.org> > Signed-off-by: Luigi Semenzato <semenzato@chromium.org> > Signed-off-by: Vincent Palatin <vpalatin@chromium.org> > --- > .../devicetree/bindings/input/cros-ec-keyb.txt | 77 ++++ > drivers/input/keyboard/Kconfig | 10 + > drivers/input/keyboard/Makefile | 1 + > drivers/input/keyboard/cros_ec_keyb.c | 413 ++++++++++++++++++++ > 4 files changed, 501 insertions(+), 0 deletions(-) > create mode 100644 Documentation/devicetree/bindings/input/cros-ec-keyb.txt > create mode 100644 drivers/input/keyboard/cros_ec_keyb.c > > diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > new file mode 100644 > index 0000000..67f51d8 > --- /dev/null > +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > @@ -0,0 +1,77 @@ > +ChromeOS EC Keyboard > + > +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on > +a separate EC (Embedded Controller) device. It provides a message for reading > +key scans from the EC. These are then converted into keycodes for processing > +by the kernel. > + > +Required properties: > +- compatible: "google,cros-ec-keyb" > +- google,key-rows: Number of keyboard rows (must be <= 8) > +- google,key-columns: Number of keyboard columns (must be <= 13) > +- google,repeat-delay-ms: Key repeat delay in milliseconds > +- google,repeat-rate-ms: Key repeat rate in milliseconds Hmmm, these should probably be in a common binding. Take a look at the other input bindings and make a proposal for properties to add to matrix-keymap.txt. > +- linux.keymap: Key map as for matrix-keypad.txt should be: linux,keymap (comma instead of period) g. -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: > On Wed, 12 Dec 2012 13:33:48 -0800, Simon Glass <sjg@chromium.org> wrote: > > Use the key-matrix layer to interpret key scan information from the EC > > and inject input based on the FDT-supplied key map. This driver registers > > itself with the ChromeOS EC driver to perform communications. > > > > Additional FDT bindings are provided to specify rows/columns and the > > auto-repeat information. > > > > Signed-off-by: Simon Glass <sjg@chromium.org> > > Signed-off-by: Luigi Semenzato <semenzato@chromium.org> > > Signed-off-by: Vincent Palatin <vpalatin@chromium.org> > > --- > > > > .../devicetree/bindings/input/cros-ec-keyb.txt | 77 ++++ > > drivers/input/keyboard/Kconfig | 10 + > > drivers/input/keyboard/Makefile | 1 + > > drivers/input/keyboard/cros_ec_keyb.c | 413 > > ++++++++++++++++++++ 4 files changed, 501 insertions(+), 0 deletions(-) > > create mode 100644 > > Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > create mode 100644 drivers/input/keyboard/cros_ec_keyb.c > > > > diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt new file mode > > 100644 > > index 0000000..67f51d8 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > @@ -0,0 +1,77 @@ > > +ChromeOS EC Keyboard > > + > > +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on > > +a separate EC (Embedded Controller) device. It provides a message for > > reading +key scans from the EC. These are then converted into keycodes > > for processing +by the kernel. > > + > > +Required properties: > > +- compatible: "google,cros-ec-keyb" > > +- google,key-rows: Number of keyboard rows (must be <= 8) > > +- google,key-columns: Number of keyboard columns (must be <= 13) > > +- google,repeat-delay-ms: Key repeat delay in milliseconds > > +- google,repeat-rate-ms: Key repeat rate in milliseconds > > Hmmm, these should probably be in a common binding. Take a look at > the other input bindings and make a proposal for properties to add to > matrix-keymap.txt. Actually these are not essentia for bringup and can be set from userspace, so I'd say simply drop them. Thanks. -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 14 Dec 2012 17:43:31 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: > > On Wed, 12 Dec 2012 13:33:48 -0800, Simon Glass <sjg@chromium.org> wrote: > > > Use the key-matrix layer to interpret key scan information from the EC > > > and inject input based on the FDT-supplied key map. This driver registers > > > itself with the ChromeOS EC driver to perform communications. > > > > > > Additional FDT bindings are provided to specify rows/columns and the > > > auto-repeat information. > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org> > > > Signed-off-by: Luigi Semenzato <semenzato@chromium.org> > > > Signed-off-by: Vincent Palatin <vpalatin@chromium.org> > > > --- > > > > > > .../devicetree/bindings/input/cros-ec-keyb.txt | 77 ++++ > > > drivers/input/keyboard/Kconfig | 10 + > > > drivers/input/keyboard/Makefile | 1 + > > > drivers/input/keyboard/cros_ec_keyb.c | 413 > > > ++++++++++++++++++++ 4 files changed, 501 insertions(+), 0 deletions(-) > > > create mode 100644 > > > Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > create mode 100644 drivers/input/keyboard/cros_ec_keyb.c > > > > > > diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt new file mode > > > 100644 > > > index 0000000..67f51d8 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > @@ -0,0 +1,77 @@ > > > +ChromeOS EC Keyboard > > > + > > > +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on > > > +a separate EC (Embedded Controller) device. It provides a message for > > > reading +key scans from the EC. These are then converted into keycodes > > > for processing +by the kernel. > > > + > > > +Required properties: > > > +- compatible: "google,cros-ec-keyb" > > > +- google,key-rows: Number of keyboard rows (must be <= 8) > > > +- google,key-columns: Number of keyboard columns (must be <= 13) > > > +- google,repeat-delay-ms: Key repeat delay in milliseconds > > > +- google,repeat-rate-ms: Key repeat rate in milliseconds > > > > Hmmm, these should probably be in a common binding. Take a look at > > the other input bindings and make a proposal for properties to add to > > matrix-keymap.txt. > > Actually these are not essentia for bringup and can be set from userspace, > so I'd say simply drop them. Aren't they needed for a working keyboard? If so, I would really think they should be set correctly without userspace intervention. g. -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Dec 19, 2012 at 12:57:22PM +0000, Grant Likely wrote: > On Fri, 14 Dec 2012 17:43:31 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > > On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: > > > On Wed, 12 Dec 2012 13:33:48 -0800, Simon Glass <sjg@chromium.org> wrote: > > > > Use the key-matrix layer to interpret key scan information from the EC > > > > and inject input based on the FDT-supplied key map. This driver registers > > > > itself with the ChromeOS EC driver to perform communications. > > > > > > > > Additional FDT bindings are provided to specify rows/columns and the > > > > auto-repeat information. > > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org> > > > > Signed-off-by: Luigi Semenzato <semenzato@chromium.org> > > > > Signed-off-by: Vincent Palatin <vpalatin@chromium.org> > > > > --- > > > > > > > > .../devicetree/bindings/input/cros-ec-keyb.txt | 77 ++++ > > > > drivers/input/keyboard/Kconfig | 10 + > > > > drivers/input/keyboard/Makefile | 1 + > > > > drivers/input/keyboard/cros_ec_keyb.c | 413 > > > > ++++++++++++++++++++ 4 files changed, 501 insertions(+), 0 deletions(-) > > > > create mode 100644 > > > > Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > > create mode 100644 drivers/input/keyboard/cros_ec_keyb.c > > > > > > > > diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > > b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt new file mode > > > > 100644 > > > > index 0000000..67f51d8 > > > > --- /dev/null > > > > +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt > > > > @@ -0,0 +1,77 @@ > > > > +ChromeOS EC Keyboard > > > > + > > > > +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on > > > > +a separate EC (Embedded Controller) device. It provides a message for > > > > reading +key scans from the EC. These are then converted into keycodes > > > > for processing +by the kernel. > > > > + > > > > +Required properties: > > > > +- compatible: "google,cros-ec-keyb" > > > > +- google,key-rows: Number of keyboard rows (must be <= 8) > > > > +- google,key-columns: Number of keyboard columns (must be <= 13) > > > > +- google,repeat-delay-ms: Key repeat delay in milliseconds > > > > +- google,repeat-rate-ms: Key repeat rate in milliseconds > > > > > > Hmmm, these should probably be in a common binding. Take a look at > > > the other input bindings and make a proposal for properties to add to > > > matrix-keymap.txt. > > > > Actually these are not essentia for bringup and can be set from userspace, > > so I'd say simply drop them. > > Aren't they needed for a working keyboard? If so, I would really think > they should be set correctly without userspace intervention. I am sorry if I was unclear, but I was actually talking about the last 2: repeat-delay-ms and repeat-rate-ms. Input core has I believe sane defaults (250 msec delay, 33 cps autorepeat) and user can adjust if other rate is preferred. Thanks.
On Wed, Dec 19, 2012 at 10:16 AM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > On Wed, Dec 19, 2012 at 12:57:22PM +0000, Grant Likely wrote: >> On Fri, 14 Dec 2012 17:43:31 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: >> > On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: >> > > On Wed, 12 Dec 2012 13:33:48 -0800, Simon Glass <sjg@chromium.org> wrote: >> > > > Use the key-matrix layer to interpret key scan information from the EC >> > > > and inject input based on the FDT-supplied key map. This driver registers >> > > > itself with the ChromeOS EC driver to perform communications. >> > > > >> > > > Additional FDT bindings are provided to specify rows/columns and the >> > > > auto-repeat information. >> > > > >> > > > Signed-off-by: Simon Glass <sjg@chromium.org> >> > > > Signed-off-by: Luigi Semenzato <semenzato@chromium.org> >> > > > Signed-off-by: Vincent Palatin <vpalatin@chromium.org> >> > > > --- >> > > > >> > > > .../devicetree/bindings/input/cros-ec-keyb.txt | 77 ++++ >> > > > drivers/input/keyboard/Kconfig | 10 + >> > > > drivers/input/keyboard/Makefile | 1 + >> > > > drivers/input/keyboard/cros_ec_keyb.c | 413 >> > > > ++++++++++++++++++++ 4 files changed, 501 insertions(+), 0 deletions(-) >> > > > create mode 100644 >> > > > Documentation/devicetree/bindings/input/cros-ec-keyb.txt >> > > > create mode 100644 drivers/input/keyboard/cros_ec_keyb.c >> > > > >> > > > diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt >> > > > b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt new file mode >> > > > 100644 >> > > > index 0000000..67f51d8 >> > > > --- /dev/null >> > > > +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt >> > > > @@ -0,0 +1,77 @@ >> > > > +ChromeOS EC Keyboard >> > > > + >> > > > +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on >> > > > +a separate EC (Embedded Controller) device. It provides a message for >> > > > reading +key scans from the EC. These are then converted into keycodes >> > > > for processing +by the kernel. >> > > > + >> > > > +Required properties: >> > > > +- compatible: "google,cros-ec-keyb" >> > > > +- google,key-rows: Number of keyboard rows (must be <= 8) >> > > > +- google,key-columns: Number of keyboard columns (must be <= 13) >> > > > +- google,repeat-delay-ms: Key repeat delay in milliseconds >> > > > +- google,repeat-rate-ms: Key repeat rate in milliseconds >> > > >> > > Hmmm, these should probably be in a common binding. Take a look at >> > > the other input bindings and make a proposal for properties to add to >> > > matrix-keymap.txt. >> > >> > Actually these are not essentia for bringup and can be set from userspace, >> > so I'd say simply drop them. >> >> Aren't they needed for a working keyboard? If so, I would really think >> they should be set correctly without userspace intervention. > > I am sorry if I was unclear, but I was actually talking about the last > 2: repeat-delay-ms and repeat-rate-ms. Input core has I believe sane > defaults (250 msec delay, 33 cps autorepeat) and user can adjust if > other rate is preferred. (resending due to mailing problem) I seems like I should remove these two, then. It would be nice if we could keep these parameters so that the keyboard doesn't require user-space set up to work, but I understand and agree they are not essential. Regarding Grant's request to come up with a common binding, if I remove these then that is not needed, right? Regards, Simon > > Thanks. > > -- > Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Dec 19, 2012 at 8:20 PM, Simon Glass <sjg@chromium.org> wrote: > On Wed, Dec 19, 2012 at 10:16 AM, Dmitry Torokhov > <dmitry.torokhov@gmail.com> wrote: >> >> On Wed, Dec 19, 2012 at 12:57:22PM +0000, Grant Likely wrote: >> > On Fri, 14 Dec 2012 17:43:31 -0800, Dmitry Torokhov >> > <dmitry.torokhov@gmail.com> wrote: >> > > On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: >> > > > > +Required properties: >> > > > > +- compatible: "google,cros-ec-keyb" >> > > > > +- google,key-rows: Number of keyboard rows (must be <= 8) >> > > > > +- google,key-columns: Number of keyboard columns (must be <= 13) >> > > > > +- google,repeat-delay-ms: Key repeat delay in milliseconds >> > > > > +- google,repeat-rate-ms: Key repeat rate in milliseconds >> > > > >> > > > Hmmm, these should probably be in a common binding. Take a look at >> > > > the other input bindings and make a proposal for properties to add >> > > > to >> > > > matrix-keymap.txt. >> > > >> > > Actually these are not essentia for bringup and can be set from >> > > userspace, >> > > so I'd say simply drop them. >> > >> > Aren't they needed for a working keyboard? If so, I would really think >> > they should be set correctly without userspace intervention. >> >> I am sorry if I was unclear, but I was actually talking about the last >> 2: repeat-delay-ms and repeat-rate-ms. Input core has I believe sane >> defaults (250 msec delay, 33 cps autorepeat) and user can adjust if >> other rate is preferred. > > > I seems like I should remove these two, then. > > It would be nice if we could keep these parameters so that the keyboard > doesn't require user-space set up to work, but I understand and agree they > are not essential. Regarding Grant's request to come up with a common > binding, if I remove these then that is not needed, right? I have no problem keeping the properties, but it does look like something applicable to all users, not just this driver. g. -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Grant, On Wed, Dec 19, 2012 at 12:42 PM, Grant Likely <grant.likely@secretlab.ca> wrote: > On Wed, Dec 19, 2012 at 8:20 PM, Simon Glass <sjg@chromium.org> wrote: >> On Wed, Dec 19, 2012 at 10:16 AM, Dmitry Torokhov >> <dmitry.torokhov@gmail.com> wrote: >>> >>> On Wed, Dec 19, 2012 at 12:57:22PM +0000, Grant Likely wrote: >>> > On Fri, 14 Dec 2012 17:43:31 -0800, Dmitry Torokhov >>> > <dmitry.torokhov@gmail.com> wrote: >>> > > On Saturday, December 15, 2012 01:13:45 AM Grant Likely wrote: >>> > > > > +Required properties: >>> > > > > +- compatible: "google,cros-ec-keyb" >>> > > > > +- google,key-rows: Number of keyboard rows (must be <= 8) >>> > > > > +- google,key-columns: Number of keyboard columns (must be <= 13) >>> > > > > +- google,repeat-delay-ms: Key repeat delay in milliseconds >>> > > > > +- google,repeat-rate-ms: Key repeat rate in milliseconds >>> > > > >>> > > > Hmmm, these should probably be in a common binding. Take a look at >>> > > > the other input bindings and make a proposal for properties to add >>> > > > to >>> > > > matrix-keymap.txt. >>> > > >>> > > Actually these are not essentia for bringup and can be set from >>> > > userspace, >>> > > so I'd say simply drop them. >>> > >>> > Aren't they needed for a working keyboard? If so, I would really think >>> > they should be set correctly without userspace intervention. >>> >>> I am sorry if I was unclear, but I was actually talking about the last >>> 2: repeat-delay-ms and repeat-rate-ms. Input core has I believe sane >>> defaults (250 msec delay, 33 cps autorepeat) and user can adjust if >>> other rate is preferred. >> >> >> I seems like I should remove these two, then. >> >> It would be nice if we could keep these parameters so that the keyboard >> doesn't require user-space set up to work, but I understand and agree they >> are not essential. Regarding Grant's request to come up with a common >> binding, if I remove these then that is not needed, right? > > I have no problem keeping the properties, but it does look like > something applicable to all users, not just this driver. I dropped keyboard repeat from the common binding and resent. If that goes in then I can try again later when Dmitry is on holiday :-), or I can put it just in our own driver. I don't mind either way, so someone should let me know which is best. > > g. Regards, Simon -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/devicetree/bindings/input/cros-ec-keyb.txt b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt new file mode 100644 index 0000000..67f51d8 --- /dev/null +++ b/Documentation/devicetree/bindings/input/cros-ec-keyb.txt @@ -0,0 +1,77 @@ +ChromeOS EC Keyboard + +Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on +a separate EC (Embedded Controller) device. It provides a message for reading +key scans from the EC. These are then converted into keycodes for processing +by the kernel. + +Required properties: +- compatible: "google,cros-ec-keyb" +- google,key-rows: Number of keyboard rows (must be <= 8) +- google,key-columns: Number of keyboard columns (must be <= 13) +- google,repeat-delay-ms: Key repeat delay in milliseconds +- google,repeat-rate-ms: Key repeat rate in milliseconds +- linux.keymap: Key map as for matrix-keypad.txt + +Optional properties: +- google,needs-ghost-filter: True to enable a ghost filter for the matrix +keyboard. This is recommended if the EC does not have its own logic or +hardware for this. + + +Example: + +cros-ec-keyb { + compatible = "google,cros-ec-keyb"; + google,key-rows = <8>; + google,key-columns = <13>; + google,repeat-delay-ms = <600>; + google,repeat-rate-ms = <60>; + google,needs-ghost-filter; + /* + * Keymap entries take the form of 0xRRCCKKKK where + * RR=Row CC=Column KKKK=Key Code + * The values below are for a US keyboard layout and + * are taken from the Linux driver. Note that the + * 102ND key is not used for US keyboards. + */ + linux,keymap = < + /* CAPSLCK F1 B F10 */ + 0x0001003a 0x0002003b 0x00030030 0x00040044 + /* N = R_ALT ESC */ + 0x00060031 0x0008000d 0x000a0064 0x01010001 + /* F4 G F7 H */ + 0x0102003e 0x01030022 0x01040041 0x01060023 + /* ' F9 BKSPACE L_CTRL */ + 0x01080028 0x01090043 0x010b000e 0x0200001d + /* TAB F3 T F6 */ + 0x0201000f 0x0202003d 0x02030014 0x02040040 + /* ] Y 102ND [ */ + 0x0205001b 0x02060015 0x02070056 0x0208001a + /* F8 GRAVE F2 5 */ + 0x02090042 0x03010029 0x0302003c 0x03030006 + /* F5 6 - \ */ + 0x0304003f 0x03060007 0x0308000c 0x030b002b + /* R_CTRL A D F */ + 0x04000061 0x0401001e 0x04020020 0x04030021 + /* S K J ; */ + 0x0404001f 0x04050025 0x04060024 0x04080027 + /* L ENTER Z C */ + 0x04090026 0x040b001c 0x0501002c 0x0502002e + /* V X , M */ + 0x0503002f 0x0504002d 0x05050033 0x05060032 + /* L_SHIFT / . SPACE */ + 0x0507002a 0x05080035 0x05090034 0x050B0039 + /* 1 3 4 2 */ + 0x06010002 0x06020004 0x06030005 0x06040003 + /* 8 7 0 9 */ + 0x06050009 0x06060008 0x0608000b 0x0609000a + /* L_ALT DOWN RIGHT Q */ + 0x060a0038 0x060b006c 0x060c006a 0x07010010 + /* E R W I */ + 0x07020012 0x07030013 0x07040011 0x07050017 + /* U R_SHIFT P O */ + 0x07060016 0x07070036 0x07080019 0x07090018 + /* UP LEFT */ + 0x070b0067 0x070c0069>; +}; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 7ccd652..eb16434 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -617,4 +617,14 @@ config KEYBOARD_W90P910 To compile this driver as a module, choose M here: the module will be called w90p910_keypad. +config KEYBOARD_CROS_EC + tristate "ChromeOS EC keyboard" + select INPUT_MATRIXKMAP + help + Say Y here to enable the matrix keyboard used by ChromeOS devices + and implemented on the ChromeOS EC. + + To compile this driver as a module, choose M here: the + module will be called cros_ec_keyb. + endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 44e7600..61b739c 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o +obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c new file mode 100644 index 0000000..d7dc9f3 --- /dev/null +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -0,0 +1,413 @@ +/* + * ChromeOS EC keyboard driver + * + * Copyright (C) 2012 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This driver uses the Chrome OS EC byte-level message-based protocol for + * communicating the keyboard state (which keys are pressed) from a keyboard EC + * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, + * but everything else (including deghosting) is done here. The main + * motivation for this is to keep the EC firmware as simple as possible, since + * it cannot be easily upgraded and EC flash/IRAM space is relatively + * expensive. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/notifier.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/input/matrix_keypad.h> +#include <linux/mfd/cros_ec.h> +#include <linux/mfd/cros_ec_commands.h> + +/* + * @rows: Number of rows in the keypad + * @cols: Number of columns in the keypad + * @row_shift: log2 or number of rows, rounded up + * @keymap_data: Matrix keymap data used to convert to keyscan values + * @ghost_filter: true to enable the matrix key-ghosting filter + * @old_state: Previous state of the keyboard matrix (used to calc deltas) + * @dev: Device pointer + * @idev: Input device + * @ec: Top level ChromeOS device to use to talk to EC + * @event_notifier: interrupt event notifier for transport devices + * @wake_notifier: wake notfier for client devices (e.g. keyboard). This + * indicates to sub-drivers that we have woken up from resume but we + * were not a wakeup source. + */ +struct cros_ec_keyb { + int rows; + int cols; + int row_shift; + const struct matrix_keymap_data *keymap_data; + bool ghost_filter; + /* + * old_state[matrix code] is 1 when the most recent (valid) + * communication with the keyboard indicated that the key at row/col + * was in the pressed state. + */ + uint8_t *old_state; + + struct device *dev; + struct input_dev *idev; + struct cros_ec_device *ec; + struct notifier_block notifier; + struct notifier_block wake_notifier; +}; + + +/* + * Sends a single key event to the input layer. + */ +static inline void cros_ec_keyb_send_key_event(struct cros_ec_keyb *ckdev, + int row, int col, int pressed) +{ + struct input_dev *idev = ckdev->idev; + int code = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); + const unsigned short *keycodes = idev->keycode; + + input_report_key(idev, keycodes[code], pressed); +} + +/* + * Returns true when there is at least one combination of pressed keys that + * results in ghosting. + */ +static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf) +{ + int col, row; + int mask; + int pressed_in_row[ckdev->rows]; + int row_has_teeth[ckdev->rows]; + + memset(pressed_in_row, '\0', sizeof(pressed_in_row)); + memset(row_has_teeth, '\0', sizeof(row_has_teeth)); + /* + * Ghosting happens if for any pressed key X there are other keys + * pressed both in the same row and column of X as, for instance, + * in the following diagram: + * + * . . Y . g . + * . . . . . . + * . . . . . . + * . . X . Z . + * + * In this case only X, Y, and Z are pressed, but g appears to be + * pressed too (see Wikipedia). + * + * We can detect ghosting in a single pass (*) over the keyboard state + * by maintaining two arrays. pressed_in_row counts how many pressed + * keys we have found in a row. row_has_teeth is true if any of the + * pressed keys for this row has other pressed keys in its column. If + * at any point of the scan we find that a row has multiple pressed + * keys, and at least one of them is at the intersection with a column + * with multiple pressed keys, we're sure there is ghosting. + * Conversely, if there is ghosting, we will detect such situation for + * at least one key during the pass. + * + * (*) This looks linear in the number of keys, but it's not. We can + * cheat because the number of rows is small. + */ + for (row = 0; row < ckdev->rows; row++) { + mask = 1 << row; + for (col = 0; col < ckdev->cols; col++) { + if (buf[col] & mask) { + pressed_in_row[row] += 1; + row_has_teeth[row] |= buf[col] & ~mask; + if (pressed_in_row[row] > 1 && + row_has_teeth[row]) { + /* ghosting */ + dev_dbg(ckdev->dev, + "ghost found at: r%d c%d," + " pressed %d, teeth 0x%x\n", + row, col, pressed_in_row[row], + row_has_teeth[row]); + return true; + } + } + } + } + return false; +} + +/* + * Compares the new keyboard state to the old one and produces key + * press/release events accordingly. The keyboard state is 13 bytes (one byte + * per column) + */ +static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, + uint8_t *kb_state, int len) +{ + int col, row; + int new_state; + int num_cols; + + num_cols = len; + + if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) { + /* + * Simple-minded solution: ignore this state. The obvious + * improvement is to only ignore changes to keys involved in + * the ghosting, but process the other changes. + */ + dev_dbg(ckdev->dev, "ghosting found\n"); + return; + } + + for (col = 0; col < ckdev->cols; col++) { + for (row = 0; row < ckdev->rows; row++) { + int code = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); + + new_state = kb_state[col] & (1 << row); + if (!!new_state != ckdev->old_state[code]) { + dev_dbg(ckdev->dev, + "changed: [r%d c%d]: byte %02x\n", + row, col, new_state); + } + if (new_state && !ckdev->old_state[code]) { + /* key press */ + cros_ec_keyb_send_key_event(ckdev, row, col, 1); + ckdev->old_state[code] = 1; + } else if (!new_state && ckdev->old_state[code]) { + /* key release */ + cros_ec_keyb_send_key_event(ckdev, row, col, 0); + ckdev->old_state[code] = 0; + } + } + } + input_sync(ckdev->idev); +} + +static int cros_ec_keyb_open(struct input_dev *dev) +{ + struct cros_ec_keyb *ckdev = input_get_drvdata(dev); + int ret; + + ret = blocking_notifier_chain_register(&ckdev->ec->event_notifier, + &ckdev->notifier); + if (ret) + return ret; + ret = blocking_notifier_chain_register(&ckdev->ec->wake_notifier, + &ckdev->wake_notifier); + if (ret) { + blocking_notifier_chain_unregister( + &ckdev->ec->event_notifier, &ckdev->notifier); + return ret; + } + + return 0; +} + +static void cros_ec_keyb_close(struct input_dev *dev) +{ + struct cros_ec_keyb *ckdev = input_get_drvdata(dev); + + blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, + &ckdev->notifier); + blocking_notifier_chain_unregister(&ckdev->ec->wake_notifier, + &ckdev->wake_notifier); +} + +static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) +{ + return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE, + kb_state, ckdev->cols); +} + +static int cros_ec_keyb_work(struct notifier_block *nb, + unsigned long state, void *_notify) +{ + int ret; + struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, + notifier); + uint8_t kb_state[ckdev->cols]; + + ret = cros_ec_keyb_get_state(ckdev, kb_state); + if (ret >= 0) + cros_ec_keyb_process(ckdev, kb_state, ret); + + return NOTIFY_DONE; +} + +/* On resume, clear any keys in the buffer */ +static int cros_ec_keyb_clear_keyboard(struct notifier_block *nb, + unsigned long state, void *_notify) +{ + struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, + wake_notifier); + uint8_t old_state[ckdev->cols]; + uint8_t new_state[ckdev->cols]; + unsigned long duration; + int i, ret; + + /* + * Keep reading until we see that the scan state does not change. + * That indicates that we are done. + * + * Assume that the EC keyscan buffer is at most 32 deep. + */ + duration = jiffies; + ret = cros_ec_keyb_get_state(ckdev, new_state); + for (i = 1; !ret && i < 32; i++) { + memcpy(old_state, new_state, sizeof(old_state)); + ret = cros_ec_keyb_get_state(ckdev, new_state); + if (0 == memcmp(old_state, new_state, sizeof(old_state))) + break; + } + duration = jiffies - duration; + dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, + jiffies_to_usecs(duration)); + + return 0; +} + +static const struct of_device_id cros_ec_kbc_of_match[] = { + { .compatible = "google,cros-ec-keyb", }, + { }, +}; + +static int __devinit cros_ec_keyb_probe(struct platform_device *pdev) +{ + struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); + struct device *dev = ec->dev; + struct cros_ec_keyb *ckdev = NULL; + struct input_dev *idev = NULL; + struct device_node *np; + u32 value; + int err; + + np = of_find_matching_node(NULL, cros_ec_kbc_of_match); + if (!np) { + dev_err(dev, "no device tree data\n"); + return -EINVAL; + } + + ckdev = kzalloc(sizeof(*ckdev), GFP_KERNEL); + if (!ckdev) { + dev_err(dev, "cannot allocate memory for ckdev\n"); + return -ENOMEM; + } + idev = input_allocate_device(); + if (!idev) { + err = -ENOMEM; + dev_err(dev, "cannot allocate memory for input device\n"); + goto fail_alloc_dev; + } + + ckdev->ec = ec; + ckdev->notifier.notifier_call = cros_ec_keyb_work; + ckdev->wake_notifier.notifier_call = cros_ec_keyb_clear_keyboard; + ckdev->dev = dev; + dev_set_drvdata(&pdev->dev, ckdev); + + idev->name = ec->get_name(ec); + idev->phys = ec->get_phys_name(ec); + __set_bit(EV_REP, idev->evbit); + + idev->id.bustype = BUS_VIRTUAL; + idev->id.version = 1; + idev->id.product = 0; + idev->dev.parent = &pdev->dev; + pdev->dev.of_node = np; + idev->open = cros_ec_keyb_open; + idev->close = cros_ec_keyb_close; + + of_property_read_u32(np, "google,key-rows", &ckdev->rows); + of_property_read_u32(np, "google,key-columns", &ckdev->cols); + if (!ckdev->rows || !ckdev->cols) { + dev_err(dev, "number of keypad rows/columns not specified\n"); + err = -EINVAL; + goto fail_props; + } + ckdev->ghost_filter = of_property_read_bool(np, + "google,needs-ghost-filter"); + + err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, + NULL, idev); + if (err) { + dev_err(dev, "cannot build key matrix\n"); + goto fail_matrix; + } + + ckdev->row_shift = get_count_order(ckdev->cols); + ckdev->old_state = kzalloc(idev->keycodemax, GFP_KERNEL); + if (!ckdev->old_state) { + dev_err(dev, "Cannot allocate memory for old_state\n"); + err = -ENOMEM; + goto fail_old_state; + } + + input_set_capability(idev, EV_MSC, MSC_SCAN); + input_set_drvdata(idev, ckdev); + ckdev->idev = idev; + err = input_register_device(ckdev->idev); + if (err) { + dev_err(dev, "cannot register input device\n"); + goto fail_register; + } + + /* + * We must change the delay after device registration, or else the + * input layer assumes that the driver does its own autorepeat. + */ + if (!of_property_read_u32(np, "google,repeat-delay-ms", &value)) + ckdev->idev->rep[REP_DELAY] = value; + if (!of_property_read_u32(np, "google,repeat-rate-ms", &value)) { + ckdev->idev->rep[REP_PERIOD] = value; + __set_bit(EV_REP, idev->evbit); + } + + return 0; + +fail_register: + kfree(ckdev->old_state); +fail_old_state: + kfree(idev->keycode); +fail_matrix: +fail_props: + input_free_device(idev); +fail_alloc_dev: + kfree(ckdev); + return err; +} + +static int __devexit cros_ec_keyb_remove(struct platform_device *pdev) +{ + struct cros_ec_keyb *ckdev = dev_get_drvdata(&pdev->dev); + struct input_dev *idev = ckdev->idev; + + /* I believe we leak a matrix_keymap here */ + input_unregister_device(idev); + kfree(ckdev->old_state); + kfree(idev->keycode); + input_free_device(idev); + kfree(ckdev); + + return 0; +} + +static struct platform_driver cros_ec_keyb_driver = { + .probe = cros_ec_keyb_probe, + .remove = cros_ec_keyb_remove, + .driver = { + .name = "cros-ec-keyb", + }, +}; + +module_platform_driver(cros_ec_keyb_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ChromeOS EC keyboard driver"); +MODULE_ALIAS("platform:cros-ec-keyb");