1*61cd4822SLejun Zhu /* 2*61cd4822SLejun Zhu * Supports for the button array on SoC tablets originally running 3*61cd4822SLejun Zhu * Windows 8. 4*61cd4822SLejun Zhu * 5*61cd4822SLejun Zhu * (C) Copyright 2014 Intel Corporation 6*61cd4822SLejun Zhu * 7*61cd4822SLejun Zhu * This program is free software; you can redistribute it and/or 8*61cd4822SLejun Zhu * modify it under the terms of the GNU General Public License 9*61cd4822SLejun Zhu * as published by the Free Software Foundation; version 2 10*61cd4822SLejun Zhu * of the License. 11*61cd4822SLejun Zhu */ 12*61cd4822SLejun Zhu 13*61cd4822SLejun Zhu #include <linux/module.h> 14*61cd4822SLejun Zhu #include <linux/input.h> 15*61cd4822SLejun Zhu #include <linux/init.h> 16*61cd4822SLejun Zhu #include <linux/kernel.h> 17*61cd4822SLejun Zhu #include <linux/acpi.h> 18*61cd4822SLejun Zhu #include <linux/gpio/consumer.h> 19*61cd4822SLejun Zhu #include <linux/gpio_keys.h> 20*61cd4822SLejun Zhu #include <linux/input.h> 21*61cd4822SLejun Zhu #include <linux/platform_device.h> 22*61cd4822SLejun Zhu #include <linux/pnp.h> 23*61cd4822SLejun Zhu 24*61cd4822SLejun Zhu /* 25*61cd4822SLejun Zhu * Definition of buttons on the tablet. The ACPI index of each button 26*61cd4822SLejun Zhu * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC 27*61cd4822SLejun Zhu * Platforms" 28*61cd4822SLejun Zhu */ 29*61cd4822SLejun Zhu #define MAX_NBUTTONS 5 30*61cd4822SLejun Zhu 31*61cd4822SLejun Zhu struct soc_button_info { 32*61cd4822SLejun Zhu const char *name; 33*61cd4822SLejun Zhu int acpi_index; 34*61cd4822SLejun Zhu unsigned int event_type; 35*61cd4822SLejun Zhu unsigned int event_code; 36*61cd4822SLejun Zhu bool autorepeat; 37*61cd4822SLejun Zhu bool wakeup; 38*61cd4822SLejun Zhu }; 39*61cd4822SLejun Zhu 40*61cd4822SLejun Zhu /* 41*61cd4822SLejun Zhu * Some of the buttons like volume up/down are auto repeat, while others 42*61cd4822SLejun Zhu * are not. To support both, we register two platform devices, and put 43*61cd4822SLejun Zhu * buttons into them based on whether the key should be auto repeat. 44*61cd4822SLejun Zhu */ 45*61cd4822SLejun Zhu #define BUTTON_TYPES 2 46*61cd4822SLejun Zhu 47*61cd4822SLejun Zhu struct soc_button_data { 48*61cd4822SLejun Zhu struct platform_device *children[BUTTON_TYPES]; 49*61cd4822SLejun Zhu }; 50*61cd4822SLejun Zhu 51*61cd4822SLejun Zhu /* 52*61cd4822SLejun Zhu * Get the Nth GPIO number from the ACPI object. 53*61cd4822SLejun Zhu */ 54*61cd4822SLejun Zhu static int soc_button_lookup_gpio(struct device *dev, int acpi_index) 55*61cd4822SLejun Zhu { 56*61cd4822SLejun Zhu struct gpio_desc *desc; 57*61cd4822SLejun Zhu int gpio; 58*61cd4822SLejun Zhu 59*61cd4822SLejun Zhu desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index); 60*61cd4822SLejun Zhu if (IS_ERR(desc)) 61*61cd4822SLejun Zhu return PTR_ERR(desc); 62*61cd4822SLejun Zhu 63*61cd4822SLejun Zhu gpio = desc_to_gpio(desc); 64*61cd4822SLejun Zhu 65*61cd4822SLejun Zhu gpiod_put(desc); 66*61cd4822SLejun Zhu 67*61cd4822SLejun Zhu return gpio; 68*61cd4822SLejun Zhu } 69*61cd4822SLejun Zhu 70*61cd4822SLejun Zhu static struct platform_device * 71*61cd4822SLejun Zhu soc_button_device_create(struct pnp_dev *pdev, 72*61cd4822SLejun Zhu const struct soc_button_info *button_info, 73*61cd4822SLejun Zhu bool autorepeat) 74*61cd4822SLejun Zhu { 75*61cd4822SLejun Zhu const struct soc_button_info *info; 76*61cd4822SLejun Zhu struct platform_device *pd; 77*61cd4822SLejun Zhu struct gpio_keys_button *gpio_keys; 78*61cd4822SLejun Zhu struct gpio_keys_platform_data *gpio_keys_pdata; 79*61cd4822SLejun Zhu int n_buttons = 0; 80*61cd4822SLejun Zhu int gpio; 81*61cd4822SLejun Zhu int error; 82*61cd4822SLejun Zhu 83*61cd4822SLejun Zhu gpio_keys_pdata = devm_kzalloc(&pdev->dev, 84*61cd4822SLejun Zhu sizeof(*gpio_keys_pdata) + 85*61cd4822SLejun Zhu sizeof(*gpio_keys) * MAX_NBUTTONS, 86*61cd4822SLejun Zhu GFP_KERNEL); 87*61cd4822SLejun Zhu gpio_keys = (void *)(gpio_keys_pdata + 1); 88*61cd4822SLejun Zhu 89*61cd4822SLejun Zhu for (info = button_info; info->name; info++) { 90*61cd4822SLejun Zhu if (info->autorepeat != autorepeat) 91*61cd4822SLejun Zhu continue; 92*61cd4822SLejun Zhu 93*61cd4822SLejun Zhu gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index); 94*61cd4822SLejun Zhu if (gpio < 0) 95*61cd4822SLejun Zhu continue; 96*61cd4822SLejun Zhu 97*61cd4822SLejun Zhu gpio_keys[n_buttons].type = info->event_type; 98*61cd4822SLejun Zhu gpio_keys[n_buttons].code = info->event_code; 99*61cd4822SLejun Zhu gpio_keys[n_buttons].gpio = gpio; 100*61cd4822SLejun Zhu gpio_keys[n_buttons].active_low = 1; 101*61cd4822SLejun Zhu gpio_keys[n_buttons].desc = info->name; 102*61cd4822SLejun Zhu gpio_keys[n_buttons].wakeup = info->wakeup; 103*61cd4822SLejun Zhu n_buttons++; 104*61cd4822SLejun Zhu } 105*61cd4822SLejun Zhu 106*61cd4822SLejun Zhu if (n_buttons == 0) { 107*61cd4822SLejun Zhu error = -ENODEV; 108*61cd4822SLejun Zhu goto err_free_mem; 109*61cd4822SLejun Zhu } 110*61cd4822SLejun Zhu 111*61cd4822SLejun Zhu gpio_keys_pdata->buttons = gpio_keys; 112*61cd4822SLejun Zhu gpio_keys_pdata->nbuttons = n_buttons; 113*61cd4822SLejun Zhu gpio_keys_pdata->rep = autorepeat; 114*61cd4822SLejun Zhu 115*61cd4822SLejun Zhu pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO); 116*61cd4822SLejun Zhu if (!pd) { 117*61cd4822SLejun Zhu error = -ENOMEM; 118*61cd4822SLejun Zhu goto err_free_mem; 119*61cd4822SLejun Zhu } 120*61cd4822SLejun Zhu 121*61cd4822SLejun Zhu error = platform_device_add_data(pd, gpio_keys_pdata, 122*61cd4822SLejun Zhu sizeof(*gpio_keys_pdata)); 123*61cd4822SLejun Zhu if (error) 124*61cd4822SLejun Zhu goto err_free_pdev; 125*61cd4822SLejun Zhu 126*61cd4822SLejun Zhu error = platform_device_add(pd); 127*61cd4822SLejun Zhu if (error) 128*61cd4822SLejun Zhu goto err_free_pdev; 129*61cd4822SLejun Zhu 130*61cd4822SLejun Zhu return pd; 131*61cd4822SLejun Zhu 132*61cd4822SLejun Zhu err_free_pdev: 133*61cd4822SLejun Zhu platform_device_put(pd); 134*61cd4822SLejun Zhu err_free_mem: 135*61cd4822SLejun Zhu devm_kfree(&pdev->dev, gpio_keys_pdata); 136*61cd4822SLejun Zhu return ERR_PTR(error); 137*61cd4822SLejun Zhu } 138*61cd4822SLejun Zhu 139*61cd4822SLejun Zhu static void soc_button_remove(struct pnp_dev *pdev) 140*61cd4822SLejun Zhu { 141*61cd4822SLejun Zhu struct soc_button_data *priv = pnp_get_drvdata(pdev); 142*61cd4822SLejun Zhu int i; 143*61cd4822SLejun Zhu 144*61cd4822SLejun Zhu for (i = 0; i < BUTTON_TYPES; i++) 145*61cd4822SLejun Zhu if (priv->children[i]) 146*61cd4822SLejun Zhu platform_device_unregister(priv->children[i]); 147*61cd4822SLejun Zhu } 148*61cd4822SLejun Zhu 149*61cd4822SLejun Zhu static int soc_button_pnp_probe(struct pnp_dev *pdev, 150*61cd4822SLejun Zhu const struct pnp_device_id *id) 151*61cd4822SLejun Zhu { 152*61cd4822SLejun Zhu const struct soc_button_info *button_info = (void *)id->driver_data; 153*61cd4822SLejun Zhu struct soc_button_data *priv; 154*61cd4822SLejun Zhu struct platform_device *pd; 155*61cd4822SLejun Zhu int i; 156*61cd4822SLejun Zhu int error; 157*61cd4822SLejun Zhu 158*61cd4822SLejun Zhu priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 159*61cd4822SLejun Zhu if (!priv) 160*61cd4822SLejun Zhu return -ENOMEM; 161*61cd4822SLejun Zhu 162*61cd4822SLejun Zhu pnp_set_drvdata(pdev, priv); 163*61cd4822SLejun Zhu 164*61cd4822SLejun Zhu for (i = 0; i < BUTTON_TYPES; i++) { 165*61cd4822SLejun Zhu pd = soc_button_device_create(pdev, button_info, i == 0); 166*61cd4822SLejun Zhu if (IS_ERR(pd)) { 167*61cd4822SLejun Zhu error = PTR_ERR(pd); 168*61cd4822SLejun Zhu if (error != -ENODEV) { 169*61cd4822SLejun Zhu soc_button_remove(pdev); 170*61cd4822SLejun Zhu return error; 171*61cd4822SLejun Zhu } 172*61cd4822SLejun Zhu } 173*61cd4822SLejun Zhu 174*61cd4822SLejun Zhu priv->children[i] = pd; 175*61cd4822SLejun Zhu } 176*61cd4822SLejun Zhu 177*61cd4822SLejun Zhu if (!priv->children[0] && !priv->children[1]) 178*61cd4822SLejun Zhu return -ENODEV; 179*61cd4822SLejun Zhu 180*61cd4822SLejun Zhu return 0; 181*61cd4822SLejun Zhu } 182*61cd4822SLejun Zhu 183*61cd4822SLejun Zhu static struct soc_button_info soc_button_PNP0C40[] = { 184*61cd4822SLejun Zhu { "power", 0, EV_KEY, KEY_POWER, false, true }, 185*61cd4822SLejun Zhu { "home", 1, EV_KEY, KEY_HOME, false, true }, 186*61cd4822SLejun Zhu { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, 187*61cd4822SLejun Zhu { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, 188*61cd4822SLejun Zhu { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false }, 189*61cd4822SLejun Zhu { } 190*61cd4822SLejun Zhu }; 191*61cd4822SLejun Zhu 192*61cd4822SLejun Zhu static const struct pnp_device_id soc_button_pnp_match[] = { 193*61cd4822SLejun Zhu { .id = "PNP0C40", .driver_data = (long)soc_button_PNP0C40 }, 194*61cd4822SLejun Zhu { .id = "" } 195*61cd4822SLejun Zhu }; 196*61cd4822SLejun Zhu MODULE_DEVICE_TABLE(pnp, soc_button_pnp_match); 197*61cd4822SLejun Zhu 198*61cd4822SLejun Zhu static struct pnp_driver soc_button_pnp_driver = { 199*61cd4822SLejun Zhu .name = KBUILD_MODNAME, 200*61cd4822SLejun Zhu .id_table = soc_button_pnp_match, 201*61cd4822SLejun Zhu .probe = soc_button_pnp_probe, 202*61cd4822SLejun Zhu .remove = soc_button_remove, 203*61cd4822SLejun Zhu }; 204*61cd4822SLejun Zhu 205*61cd4822SLejun Zhu static int __init soc_button_init(void) 206*61cd4822SLejun Zhu { 207*61cd4822SLejun Zhu return pnp_register_driver(&soc_button_pnp_driver); 208*61cd4822SLejun Zhu } 209*61cd4822SLejun Zhu 210*61cd4822SLejun Zhu static void __exit soc_button_exit(void) 211*61cd4822SLejun Zhu { 212*61cd4822SLejun Zhu pnp_unregister_driver(&soc_button_pnp_driver); 213*61cd4822SLejun Zhu } 214*61cd4822SLejun Zhu 215*61cd4822SLejun Zhu module_init(soc_button_init); 216*61cd4822SLejun Zhu module_exit(soc_button_exit); 217*61cd4822SLejun Zhu 218*61cd4822SLejun Zhu MODULE_LICENSE("GPL"); 219