1/* 2 * Driver for tilt switches connected via GPIO lines 3 * not capable of generating interrupts 4 * 5 * Copyright (C) 2011 Heiko Stuebner <heiko@sntech.de> 6 * 7 * based on: drivers/input/keyboard/gpio_keys_polled.c 8 * 9 * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org> 10 * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/slab.h> 20#include <linux/input.h> 21#include <linux/input-polldev.h> 22#include <linux/ioport.h> 23#include <linux/platform_device.h> 24#include <linux/gpio.h> 25#include <linux/input/gpio_tilt.h> 26 27#define DRV_NAME "gpio-tilt-polled" 28 29struct gpio_tilt_polled_dev { 30 struct input_polled_dev *poll_dev; 31 struct device *dev; 32 const struct gpio_tilt_platform_data *pdata; 33 34 int last_state; 35 36 int threshold; 37 int count; 38}; 39 40static void gpio_tilt_polled_poll(struct input_polled_dev *dev) 41{ 42 struct gpio_tilt_polled_dev *tdev = dev->private; 43 const struct gpio_tilt_platform_data *pdata = tdev->pdata; 44 struct input_dev *input = dev->input; 45 struct gpio_tilt_state *tilt_state = NULL; 46 int state, i; 47 48 if (tdev->count < tdev->threshold) { 49 tdev->count++; 50 } else { 51 state = 0; 52 for (i = 0; i < pdata->nr_gpios; i++) 53 state |= (!!gpio_get_value(pdata->gpios[i].gpio) << i); 54 55 if (state != tdev->last_state) { 56 for (i = 0; i < pdata->nr_states; i++) 57 if (pdata->states[i].gpios == state) 58 tilt_state = &pdata->states[i]; 59 60 if (tilt_state) { 61 for (i = 0; i < pdata->nr_axes; i++) 62 input_report_abs(input, 63 pdata->axes[i].axis, 64 tilt_state->axes[i]); 65 66 input_sync(input); 67 } 68 69 tdev->count = 0; 70 tdev->last_state = state; 71 } 72 } 73} 74 75static void gpio_tilt_polled_open(struct input_polled_dev *dev) 76{ 77 struct gpio_tilt_polled_dev *tdev = dev->private; 78 const struct gpio_tilt_platform_data *pdata = tdev->pdata; 79 80 if (pdata->enable) 81 pdata->enable(tdev->dev); 82 83 /* report initial state of the axes */ 84 tdev->last_state = -1; 85 tdev->count = tdev->threshold; 86 gpio_tilt_polled_poll(tdev->poll_dev); 87} 88 89static void gpio_tilt_polled_close(struct input_polled_dev *dev) 90{ 91 struct gpio_tilt_polled_dev *tdev = dev->private; 92 const struct gpio_tilt_platform_data *pdata = tdev->pdata; 93 94 if (pdata->disable) 95 pdata->disable(tdev->dev); 96} 97 98static int gpio_tilt_polled_probe(struct platform_device *pdev) 99{ 100 const struct gpio_tilt_platform_data *pdata = 101 dev_get_platdata(&pdev->dev); 102 struct device *dev = &pdev->dev; 103 struct gpio_tilt_polled_dev *tdev; 104 struct input_polled_dev *poll_dev; 105 struct input_dev *input; 106 int error, i; 107 108 if (!pdata || !pdata->poll_interval) 109 return -EINVAL; 110 111 tdev = kzalloc(sizeof(struct gpio_tilt_polled_dev), GFP_KERNEL); 112 if (!tdev) { 113 dev_err(dev, "no memory for private data\n"); 114 return -ENOMEM; 115 } 116 117 error = gpio_request_array(pdata->gpios, pdata->nr_gpios); 118 if (error) { 119 dev_err(dev, 120 "Could not request tilt GPIOs: %d\n", error); 121 goto err_free_tdev; 122 } 123 124 poll_dev = input_allocate_polled_device(); 125 if (!poll_dev) { 126 dev_err(dev, "no memory for polled device\n"); 127 error = -ENOMEM; 128 goto err_free_gpios; 129 } 130 131 poll_dev->private = tdev; 132 poll_dev->poll = gpio_tilt_polled_poll; 133 poll_dev->poll_interval = pdata->poll_interval; 134 poll_dev->open = gpio_tilt_polled_open; 135 poll_dev->close = gpio_tilt_polled_close; 136 137 input = poll_dev->input; 138 139 input->name = pdev->name; 140 input->phys = DRV_NAME"/input0"; 141 input->dev.parent = &pdev->dev; 142 143 input->id.bustype = BUS_HOST; 144 input->id.vendor = 0x0001; 145 input->id.product = 0x0001; 146 input->id.version = 0x0100; 147 148 __set_bit(EV_ABS, input->evbit); 149 for (i = 0; i < pdata->nr_axes; i++) 150 input_set_abs_params(input, pdata->axes[i].axis, 151 pdata->axes[i].min, pdata->axes[i].max, 152 pdata->axes[i].fuzz, pdata->axes[i].flat); 153 154 tdev->threshold = DIV_ROUND_UP(pdata->debounce_interval, 155 pdata->poll_interval); 156 157 tdev->poll_dev = poll_dev; 158 tdev->dev = dev; 159 tdev->pdata = pdata; 160 161 error = input_register_polled_device(poll_dev); 162 if (error) { 163 dev_err(dev, "unable to register polled device, err=%d\n", 164 error); 165 goto err_free_polldev; 166 } 167 168 platform_set_drvdata(pdev, tdev); 169 170 return 0; 171 172err_free_polldev: 173 input_free_polled_device(poll_dev); 174err_free_gpios: 175 gpio_free_array(pdata->gpios, pdata->nr_gpios); 176err_free_tdev: 177 kfree(tdev); 178 179 return error; 180} 181 182static int gpio_tilt_polled_remove(struct platform_device *pdev) 183{ 184 struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev); 185 const struct gpio_tilt_platform_data *pdata = tdev->pdata; 186 187 input_unregister_polled_device(tdev->poll_dev); 188 input_free_polled_device(tdev->poll_dev); 189 190 gpio_free_array(pdata->gpios, pdata->nr_gpios); 191 192 kfree(tdev); 193 194 return 0; 195} 196 197static struct platform_driver gpio_tilt_polled_driver = { 198 .probe = gpio_tilt_polled_probe, 199 .remove = gpio_tilt_polled_remove, 200 .driver = { 201 .name = DRV_NAME, 202 }, 203}; 204 205module_platform_driver(gpio_tilt_polled_driver); 206 207MODULE_LICENSE("GPL v2"); 208MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 209MODULE_DESCRIPTION("Polled GPIO tilt driver"); 210MODULE_ALIAS("platform:" DRV_NAME); 211