linux/drivers/staging/dream/gpio_matrix.c
<<
>>
Prefs
   1/* drivers/input/misc/gpio_matrix.c
   2 *
   3 * Copyright (C) 2007 Google, Inc.
   4 *
   5 * This software is licensed under the terms of the GNU General Public
   6 * License version 2, as published by the Free Software Foundation, and
   7 * may be copied, distributed, and modified under those terms.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/gpio.h>
  18#include <linux/gpio_event.h>
  19#include <linux/hrtimer.h>
  20#include <linux/interrupt.h>
  21#include <linux/wakelock.h>
  22
  23struct gpio_kp {
  24        struct input_dev *input_dev;
  25        struct gpio_event_matrix_info *keypad_info;
  26        struct hrtimer timer;
  27        struct wake_lock wake_lock;
  28        int current_output;
  29        unsigned int use_irq:1;
  30        unsigned int key_state_changed:1;
  31        unsigned int last_key_state_changed:1;
  32        unsigned int some_keys_pressed:2;
  33        unsigned long keys_pressed[0];
  34};
  35
  36static void clear_phantom_key(struct gpio_kp *kp, int out, int in)
  37{
  38        struct gpio_event_matrix_info *mi = kp->keypad_info;
  39        int key_index = out * mi->ninputs + in;
  40        unsigned short keycode = mi->keymap[key_index];;
  41
  42        if (!test_bit(keycode, kp->input_dev->key)) {
  43                if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
  44                        pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
  45                                "cleared\n", keycode, out, in,
  46                                mi->output_gpios[out], mi->input_gpios[in]);
  47                __clear_bit(key_index, kp->keys_pressed);
  48        } else {
  49                if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
  50                        pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
  51                                "not cleared\n", keycode, out, in,
  52                                mi->output_gpios[out], mi->input_gpios[in]);
  53        }
  54}
  55
  56static int restore_keys_for_input(struct gpio_kp *kp, int out, int in)
  57{
  58        int rv = 0;
  59        int key_index;
  60
  61        key_index = out * kp->keypad_info->ninputs + in;
  62        while (out < kp->keypad_info->noutputs) {
  63                if (test_bit(key_index, kp->keys_pressed)) {
  64                        rv = 1;
  65                        clear_phantom_key(kp, out, in);
  66                }
  67                key_index += kp->keypad_info->ninputs;
  68                out++;
  69        }
  70        return rv;
  71}
  72
  73static void remove_phantom_keys(struct gpio_kp *kp)
  74{
  75        int out, in, inp;
  76        int key_index;
  77
  78        if (kp->some_keys_pressed < 3)
  79                return;
  80
  81        for (out = 0; out < kp->keypad_info->noutputs; out++) {
  82                inp = -1;
  83                key_index = out * kp->keypad_info->ninputs;
  84                for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) {
  85                        if (test_bit(key_index, kp->keys_pressed)) {
  86                                if (inp == -1) {
  87                                        inp = in;
  88                                        continue;
  89                                }
  90                                if (inp >= 0) {
  91                                        if (!restore_keys_for_input(kp, out + 1,
  92                                                                        inp))
  93                                                break;
  94                                        clear_phantom_key(kp, out, inp);
  95                                        inp = -2;
  96                                }
  97                                restore_keys_for_input(kp, out, in);
  98                        }
  99                }
 100        }
 101}
 102
 103static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
 104{
 105        struct gpio_event_matrix_info *mi = kp->keypad_info;
 106        int pressed = test_bit(key_index, kp->keys_pressed);
 107        unsigned short keycode = mi->keymap[key_index];
 108        if (pressed != test_bit(keycode, kp->input_dev->key)) {
 109                if (keycode == KEY_RESERVED) {
 110                        if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
 111                                pr_info("gpiomatrix: unmapped key, %d-%d "
 112                                        "(%d-%d) changed to %d\n",
 113                                        out, in, mi->output_gpios[out],
 114                                        mi->input_gpios[in], pressed);
 115                } else {
 116                        if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS)
 117                                pr_info("gpiomatrix: key %x, %d-%d (%d-%d) "
 118                                        "changed to %d\n", keycode,
 119                                        out, in, mi->output_gpios[out],
 120                                        mi->input_gpios[in], pressed);
 121                        input_report_key(kp->input_dev, keycode, pressed);
 122                }
 123        }
 124}
 125
 126static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
 127{
 128        int out, in;
 129        int key_index;
 130        int gpio;
 131        struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer);
 132        struct gpio_event_matrix_info *mi = kp->keypad_info;
 133        unsigned gpio_keypad_flags = mi->flags;
 134        unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH);
 135
 136        out = kp->current_output;
 137        if (out == mi->noutputs) {
 138                out = 0;
 139                kp->last_key_state_changed = kp->key_state_changed;
 140                kp->key_state_changed = 0;
 141                kp->some_keys_pressed = 0;
 142        } else {
 143                key_index = out * mi->ninputs;
 144                for (in = 0; in < mi->ninputs; in++, key_index++) {
 145                        gpio = mi->input_gpios[in];
 146                        if (gpio_get_value(gpio) ^ !polarity) {
 147                                if (kp->some_keys_pressed < 3)
 148                                        kp->some_keys_pressed++;
 149                                kp->key_state_changed |= !__test_and_set_bit(
 150                                                key_index, kp->keys_pressed);
 151                        } else
 152                                kp->key_state_changed |= __test_and_clear_bit(
 153                                                key_index, kp->keys_pressed);
 154                }
 155                gpio = mi->output_gpios[out];
 156                if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
 157                        gpio_set_value(gpio, !polarity);
 158                else
 159                        gpio_direction_input(gpio);
 160                out++;
 161        }
 162        kp->current_output = out;
 163        if (out < mi->noutputs) {
 164                gpio = mi->output_gpios[out];
 165                if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
 166                        gpio_set_value(gpio, polarity);
 167                else
 168                        gpio_direction_output(gpio, polarity);
 169                hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL);
 170                return HRTIMER_NORESTART;
 171        }
 172        if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) {
 173                if (kp->key_state_changed) {
 174                        hrtimer_start(&kp->timer, mi->debounce_delay,
 175                                      HRTIMER_MODE_REL);
 176                        return HRTIMER_NORESTART;
 177                }
 178                kp->key_state_changed = kp->last_key_state_changed;
 179        }
 180        if (kp->key_state_changed) {
 181                if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS)
 182                        remove_phantom_keys(kp);
 183                key_index = 0;
 184                for (out = 0; out < mi->noutputs; out++)
 185                        for (in = 0; in < mi->ninputs; in++, key_index++)
 186                                report_key(kp, key_index, out, in);
 187        }
 188        if (!kp->use_irq || kp->some_keys_pressed) {
 189                hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL);
 190                return HRTIMER_NORESTART;
 191        }
 192
 193        /* No keys are pressed, reenable interrupt */
 194        for (out = 0; out < mi->noutputs; out++) {
 195                if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
 196                        gpio_set_value(mi->output_gpios[out], polarity);
 197                else
 198                        gpio_direction_output(mi->output_gpios[out], polarity);
 199        }
 200        for (in = 0; in < mi->ninputs; in++)
 201                enable_irq(gpio_to_irq(mi->input_gpios[in]));
 202        wake_unlock(&kp->wake_lock);
 203        return HRTIMER_NORESTART;
 204}
 205
 206static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
 207{
 208        int i;
 209        struct gpio_kp *kp = dev_id;
 210        struct gpio_event_matrix_info *mi = kp->keypad_info;
 211        unsigned gpio_keypad_flags = mi->flags;
 212
 213        if (!kp->use_irq) /* ignore interrupt while registering the handler */
 214                return IRQ_HANDLED;
 215
 216        for (i = 0; i < mi->ninputs; i++)
 217                disable_irq(gpio_to_irq(mi->input_gpios[i]));
 218        for (i = 0; i < mi->noutputs; i++) {
 219                if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
 220                        gpio_set_value(mi->output_gpios[i],
 221                                !(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH));
 222                else
 223                        gpio_direction_input(mi->output_gpios[i]);
 224        }
 225        wake_lock(&kp->wake_lock);
 226        hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
 227        return IRQ_HANDLED;
 228}
 229
 230static int gpio_keypad_request_irqs(struct gpio_kp *kp)
 231{
 232        int i;
 233        int err;
 234        unsigned int irq;
 235        unsigned long request_flags;
 236        struct gpio_event_matrix_info *mi = kp->keypad_info;
 237
 238        switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
 239        default:
 240                request_flags = IRQF_TRIGGER_FALLING;
 241                break;
 242        case GPIOKPF_ACTIVE_HIGH:
 243                request_flags = IRQF_TRIGGER_RISING;
 244                break;
 245        case GPIOKPF_LEVEL_TRIGGERED_IRQ:
 246                request_flags = IRQF_TRIGGER_LOW;
 247                break;
 248        case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
 249                request_flags = IRQF_TRIGGER_HIGH;
 250                break;
 251        }
 252
 253        for (i = 0; i < mi->ninputs; i++) {
 254                err = irq = gpio_to_irq(mi->input_gpios[i]);
 255                if (err < 0)
 256                        goto err_gpio_get_irq_num_failed;
 257                err = request_irq(irq, gpio_keypad_irq_handler, request_flags,
 258                                  "gpio_kp", kp);
 259                if (err) {
 260                        pr_err("gpiomatrix: request_irq failed for input %d, "
 261                                "irq %d\n", mi->input_gpios[i], irq);
 262                        goto err_request_irq_failed;
 263                }
 264                err = set_irq_wake(irq, 1);
 265                if (err) {
 266                        pr_err("gpiomatrix: set_irq_wake failed for input %d, "
 267                                "irq %d\n", mi->input_gpios[i], irq);
 268                }
 269                disable_irq(irq);
 270        }
 271        return 0;
 272
 273        for (i = mi->noutputs - 1; i >= 0; i--) {
 274                free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
 275err_request_irq_failed:
 276err_gpio_get_irq_num_failed:
 277                ;
 278        }
 279        return err;
 280}
 281
 282int gpio_event_matrix_func(struct input_dev *input_dev,
 283        struct gpio_event_info *info, void **data, int func)
 284{
 285        int i;
 286        int err;
 287        int key_count;
 288        struct gpio_kp *kp;
 289        struct gpio_event_matrix_info *mi;
 290
 291        mi = container_of(info, struct gpio_event_matrix_info, info);
 292        if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
 293                /* TODO: disable scanning */
 294                return 0;
 295        }
 296
 297        if (func == GPIO_EVENT_FUNC_INIT) {
 298                if (mi->keymap == NULL ||
 299                   mi->input_gpios == NULL ||
 300                   mi->output_gpios == NULL) {
 301                        err = -ENODEV;
 302                        pr_err("gpiomatrix: Incomplete pdata\n");
 303                        goto err_invalid_platform_data;
 304                }
 305                key_count = mi->ninputs * mi->noutputs;
 306
 307                *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
 308                                     BITS_TO_LONGS(key_count), GFP_KERNEL);
 309                if (kp == NULL) {
 310                        err = -ENOMEM;
 311                        pr_err("gpiomatrix: Failed to allocate private data\n");
 312                        goto err_kp_alloc_failed;
 313                }
 314                kp->input_dev = input_dev;
 315                kp->keypad_info = mi;
 316                set_bit(EV_KEY, input_dev->evbit);
 317                for (i = 0; i < key_count; i++) {
 318                        if (mi->keymap[i])
 319                                set_bit(mi->keymap[i] & KEY_MAX,
 320                                        input_dev->keybit);
 321                }
 322
 323                for (i = 0; i < mi->noutputs; i++) {
 324                        if (gpio_cansleep(mi->output_gpios[i])) {
 325                                pr_err("gpiomatrix: unsupported output gpio %d,"
 326                                        " can sleep\n", mi->output_gpios[i]);
 327                                err = -EINVAL;
 328                                goto err_request_output_gpio_failed;
 329                        }
 330                        err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
 331                        if (err) {
 332                                pr_err("gpiomatrix: gpio_request failed for "
 333                                        "output %d\n", mi->output_gpios[i]);
 334                                goto err_request_output_gpio_failed;
 335                        }
 336                        if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
 337                                err = gpio_direction_output(mi->output_gpios[i],
 338                                        !(mi->flags & GPIOKPF_ACTIVE_HIGH));
 339                        else
 340                                err = gpio_direction_input(mi->output_gpios[i]);
 341                        if (err) {
 342                                pr_err("gpiomatrix: gpio_configure failed for "
 343                                        "output %d\n", mi->output_gpios[i]);
 344                                goto err_output_gpio_configure_failed;
 345                        }
 346                }
 347                for (i = 0; i < mi->ninputs; i++) {
 348                        err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
 349                        if (err) {
 350                                pr_err("gpiomatrix: gpio_request failed for "
 351                                        "input %d\n", mi->input_gpios[i]);
 352                                goto err_request_input_gpio_failed;
 353                        }
 354                        err = gpio_direction_input(mi->input_gpios[i]);
 355                        if (err) {
 356                                pr_err("gpiomatrix: gpio_direction_input failed"
 357                                        " for input %d\n", mi->input_gpios[i]);
 358                                goto err_gpio_direction_input_failed;
 359                        }
 360                }
 361                kp->current_output = mi->noutputs;
 362                kp->key_state_changed = 1;
 363
 364                hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 365                kp->timer.function = gpio_keypad_timer_func;
 366                wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
 367                err = gpio_keypad_request_irqs(kp);
 368                kp->use_irq = err == 0;
 369
 370                pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for %s "
 371                        "in %s mode\n", input_dev->name,
 372                        kp->use_irq ? "interrupt" : "polling");
 373
 374                if (kp->use_irq)
 375                        wake_lock(&kp->wake_lock);
 376                hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
 377
 378                return 0;
 379        }
 380
 381        err = 0;
 382        kp = *data;
 383
 384        if (kp->use_irq)
 385                for (i = mi->noutputs - 1; i >= 0; i--)
 386                        free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
 387
 388        hrtimer_cancel(&kp->timer);
 389        wake_lock_destroy(&kp->wake_lock);
 390        for (i = mi->noutputs - 1; i >= 0; i--) {
 391err_gpio_direction_input_failed:
 392                gpio_free(mi->input_gpios[i]);
 393err_request_input_gpio_failed:
 394                ;
 395        }
 396        for (i = mi->noutputs - 1; i >= 0; i--) {
 397err_output_gpio_configure_failed:
 398                gpio_free(mi->output_gpios[i]);
 399err_request_output_gpio_failed:
 400                ;
 401        }
 402        kfree(kp);
 403err_kp_alloc_failed:
 404err_invalid_platform_data:
 405        return err;
 406}
 407