Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc2 330 lines 8.4 kB view raw
1/* 2 * max7359_keypad.c - MAX7359 Key Switch Controller Driver 3 * 4 * Copyright (C) 2009 Samsung Electronics 5 * Kim Kyuwon <q1.kim@samsung.com> 6 * 7 * Based on pxa27x_keypad.c 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/5456 14 */ 15 16#include <linux/module.h> 17#include <linux/i2c.h> 18#include <linux/interrupt.h> 19#include <linux/input.h> 20#include <linux/input/matrix_keypad.h> 21 22#define MAX7359_MAX_KEY_ROWS 8 23#define MAX7359_MAX_KEY_COLS 8 24#define MAX7359_MAX_KEY_NUM (MAX7359_MAX_KEY_ROWS * MAX7359_MAX_KEY_COLS) 25#define MAX7359_ROW_SHIFT 3 26 27/* 28 * MAX7359 registers 29 */ 30#define MAX7359_REG_KEYFIFO 0x00 31#define MAX7359_REG_CONFIG 0x01 32#define MAX7359_REG_DEBOUNCE 0x02 33#define MAX7359_REG_INTERRUPT 0x03 34#define MAX7359_REG_PORTS 0x04 35#define MAX7359_REG_KEYREP 0x05 36#define MAX7359_REG_SLEEP 0x06 37 38/* 39 * Configuration register bits 40 */ 41#define MAX7359_CFG_SLEEP (1 << 7) 42#define MAX7359_CFG_INTERRUPT (1 << 5) 43#define MAX7359_CFG_KEY_RELEASE (1 << 3) 44#define MAX7359_CFG_WAKEUP (1 << 1) 45#define MAX7359_CFG_TIMEOUT (1 << 0) 46 47/* 48 * Autosleep register values (ms) 49 */ 50#define MAX7359_AUTOSLEEP_8192 0x01 51#define MAX7359_AUTOSLEEP_4096 0x02 52#define MAX7359_AUTOSLEEP_2048 0x03 53#define MAX7359_AUTOSLEEP_1024 0x04 54#define MAX7359_AUTOSLEEP_512 0x05 55#define MAX7359_AUTOSLEEP_256 0x06 56 57struct max7359_keypad { 58 /* matrix key code map */ 59 unsigned short keycodes[MAX7359_MAX_KEY_NUM]; 60 61 struct input_dev *input_dev; 62 struct i2c_client *client; 63}; 64 65static int max7359_write_reg(struct i2c_client *client, u8 reg, u8 val) 66{ 67 int ret = i2c_smbus_write_byte_data(client, reg, val); 68 69 if (ret < 0) 70 dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", 71 __func__, reg, val, ret); 72 return ret; 73} 74 75static int max7359_read_reg(struct i2c_client *client, int reg) 76{ 77 int ret = i2c_smbus_read_byte_data(client, reg); 78 79 if (ret < 0) 80 dev_err(&client->dev, "%s: reg 0x%x, err %d\n", 81 __func__, reg, ret); 82 return ret; 83} 84 85static void max7359_build_keycode(struct max7359_keypad *keypad, 86 const struct matrix_keymap_data *keymap_data) 87{ 88 struct input_dev *input_dev = keypad->input_dev; 89 int i; 90 91 for (i = 0; i < keymap_data->keymap_size; i++) { 92 unsigned int key = keymap_data->keymap[i]; 93 unsigned int row = KEY_ROW(key); 94 unsigned int col = KEY_COL(key); 95 unsigned int scancode = MATRIX_SCAN_CODE(row, col, 96 MAX7359_ROW_SHIFT); 97 unsigned short keycode = KEY_VAL(key); 98 99 keypad->keycodes[scancode] = keycode; 100 __set_bit(keycode, input_dev->keybit); 101 } 102 __clear_bit(KEY_RESERVED, input_dev->keybit); 103} 104 105/* runs in an IRQ thread -- can (and will!) sleep */ 106static irqreturn_t max7359_interrupt(int irq, void *dev_id) 107{ 108 struct max7359_keypad *keypad = dev_id; 109 struct input_dev *input_dev = keypad->input_dev; 110 int val, row, col, release, code; 111 112 val = max7359_read_reg(keypad->client, MAX7359_REG_KEYFIFO); 113 row = val & 0x7; 114 col = (val >> 3) & 0x7; 115 release = val & 0x40; 116 117 code = MATRIX_SCAN_CODE(row, col, MAX7359_ROW_SHIFT); 118 119 dev_dbg(&keypad->client->dev, 120 "key[%d:%d] %s\n", row, col, release ? "release" : "press"); 121 122 input_event(input_dev, EV_MSC, MSC_SCAN, code); 123 input_report_key(input_dev, keypad->keycodes[code], !release); 124 input_sync(input_dev); 125 126 return IRQ_HANDLED; 127} 128 129/* 130 * Let MAX7359 fall into a deep sleep: 131 * If no keys are pressed, enter sleep mode for 8192 ms. And if any 132 * key is pressed, the MAX7359 returns to normal operating mode. 133 */ 134static inline void max7359_fall_deepsleep(struct i2c_client *client) 135{ 136 max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_8192); 137} 138 139/* 140 * Let MAX7359 take a catnap: 141 * Autosleep just for 256 ms. 142 */ 143static inline void max7359_take_catnap(struct i2c_client *client) 144{ 145 max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_256); 146} 147 148static int max7359_open(struct input_dev *dev) 149{ 150 struct max7359_keypad *keypad = input_get_drvdata(dev); 151 152 max7359_take_catnap(keypad->client); 153 154 return 0; 155} 156 157static void max7359_close(struct input_dev *dev) 158{ 159 struct max7359_keypad *keypad = input_get_drvdata(dev); 160 161 max7359_fall_deepsleep(keypad->client); 162} 163 164static void max7359_initialize(struct i2c_client *client) 165{ 166 max7359_write_reg(client, MAX7359_REG_CONFIG, 167 MAX7359_CFG_INTERRUPT | /* Irq clears after host read */ 168 MAX7359_CFG_KEY_RELEASE | /* Key release enable */ 169 MAX7359_CFG_WAKEUP); /* Key press wakeup enable */ 170 171 /* Full key-scan functionality */ 172 max7359_write_reg(client, MAX7359_REG_DEBOUNCE, 0x1F); 173 174 /* nINT asserts every debounce cycles */ 175 max7359_write_reg(client, MAX7359_REG_INTERRUPT, 0x01); 176 177 max7359_fall_deepsleep(client); 178} 179 180static int __devinit max7359_probe(struct i2c_client *client, 181 const struct i2c_device_id *id) 182{ 183 const struct matrix_keymap_data *keymap_data = client->dev.platform_data; 184 struct max7359_keypad *keypad; 185 struct input_dev *input_dev; 186 int ret; 187 int error; 188 189 if (!client->irq) { 190 dev_err(&client->dev, "The irq number should not be zero\n"); 191 return -EINVAL; 192 } 193 194 /* Detect MAX7359: The initial Keys FIFO value is '0x3F' */ 195 ret = max7359_read_reg(client, MAX7359_REG_KEYFIFO); 196 if (ret < 0) { 197 dev_err(&client->dev, "failed to detect device\n"); 198 return -ENODEV; 199 } 200 201 dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret); 202 203 keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL); 204 input_dev = input_allocate_device(); 205 if (!keypad || !input_dev) { 206 dev_err(&client->dev, "failed to allocate memory\n"); 207 error = -ENOMEM; 208 goto failed_free_mem; 209 } 210 211 keypad->client = client; 212 keypad->input_dev = input_dev; 213 214 input_dev->name = client->name; 215 input_dev->id.bustype = BUS_I2C; 216 input_dev->open = max7359_open; 217 input_dev->close = max7359_close; 218 input_dev->dev.parent = &client->dev; 219 220 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 221 input_dev->keycodesize = sizeof(keypad->keycodes[0]); 222 input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); 223 input_dev->keycode = keypad->keycodes; 224 225 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 226 input_set_drvdata(input_dev, keypad); 227 228 max7359_build_keycode(keypad, keymap_data); 229 230 error = request_threaded_irq(client->irq, NULL, max7359_interrupt, 231 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 232 client->name, keypad); 233 if (error) { 234 dev_err(&client->dev, "failed to register interrupt\n"); 235 goto failed_free_mem; 236 } 237 238 /* Register the input device */ 239 error = input_register_device(input_dev); 240 if (error) { 241 dev_err(&client->dev, "failed to register input device\n"); 242 goto failed_free_irq; 243 } 244 245 /* Initialize MAX7359 */ 246 max7359_initialize(client); 247 248 i2c_set_clientdata(client, keypad); 249 device_init_wakeup(&client->dev, 1); 250 251 return 0; 252 253failed_free_irq: 254 free_irq(client->irq, keypad); 255failed_free_mem: 256 input_free_device(input_dev); 257 kfree(keypad); 258 return error; 259} 260 261static int __devexit max7359_remove(struct i2c_client *client) 262{ 263 struct max7359_keypad *keypad = i2c_get_clientdata(client); 264 265 free_irq(client->irq, keypad); 266 input_unregister_device(keypad->input_dev); 267 i2c_set_clientdata(client, NULL); 268 kfree(keypad); 269 270 return 0; 271} 272 273#ifdef CONFIG_PM 274static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) 275{ 276 max7359_fall_deepsleep(client); 277 278 if (device_may_wakeup(&client->dev)) 279 enable_irq_wake(client->irq); 280 281 return 0; 282} 283 284static int max7359_resume(struct i2c_client *client) 285{ 286 if (device_may_wakeup(&client->dev)) 287 disable_irq_wake(client->irq); 288 289 /* Restore the default setting */ 290 max7359_take_catnap(client); 291 292 return 0; 293} 294#else 295#define max7359_suspend NULL 296#define max7359_resume NULL 297#endif 298 299static const struct i2c_device_id max7359_ids[] = { 300 { "max7359", 0 }, 301 { } 302}; 303MODULE_DEVICE_TABLE(i2c, max7359_ids); 304 305static struct i2c_driver max7359_i2c_driver = { 306 .driver = { 307 .name = "max7359", 308 }, 309 .probe = max7359_probe, 310 .remove = __devexit_p(max7359_remove), 311 .suspend = max7359_suspend, 312 .resume = max7359_resume, 313 .id_table = max7359_ids, 314}; 315 316static int __init max7359_init(void) 317{ 318 return i2c_add_driver(&max7359_i2c_driver); 319} 320module_init(max7359_init); 321 322static void __exit max7359_exit(void) 323{ 324 i2c_del_driver(&max7359_i2c_driver); 325} 326module_exit(max7359_exit); 327 328MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); 329MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver"); 330MODULE_LICENSE("GPL v2");