atmel-wm97xx.c revision 864fe73c312ca8e177da01207ce86fb1b80b3e54
1/* 2 * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97 3 * codecs. 4 * 5 * Copyright (C) 2008 - 2009 Atmel Corporation 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 */ 11#include <linux/module.h> 12#include <linux/moduleparam.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/delay.h> 16#include <linux/irq.h> 17#include <linux/interrupt.h> 18#include <linux/wm97xx.h> 19#include <linux/timer.h> 20#include <linux/gpio.h> 21#include <linux/io.h> 22 23#define AC97C_ICA 0x10 24#define AC97C_CBRHR 0x30 25#define AC97C_CBSR 0x38 26#define AC97C_CBMR 0x3c 27#define AC97C_IER 0x54 28#define AC97C_IDR 0x58 29 30#define AC97C_RXRDY (1 << 4) 31#define AC97C_OVRUN (1 << 5) 32 33#define AC97C_CMR_SIZE_20 (0 << 16) 34#define AC97C_CMR_SIZE_18 (1 << 16) 35#define AC97C_CMR_SIZE_16 (2 << 16) 36#define AC97C_CMR_SIZE_10 (3 << 16) 37#define AC97C_CMR_CEM_LITTLE (1 << 18) 38#define AC97C_CMR_CEM_BIG (0 << 18) 39#define AC97C_CMR_CENA (1 << 21) 40 41#define AC97C_INT_CBEVT (1 << 4) 42 43#define AC97C_SR_CAEVT (1 << 3) 44 45#define AC97C_CH_MASK(slot) \ 46 (0x7 << (3 * (slot - 3))) 47#define AC97C_CH_ASSIGN(slot, channel) \ 48 (AC97C_CHANNEL_##channel << (3 * (slot - 3))) 49#define AC97C_CHANNEL_NONE 0x0 50#define AC97C_CHANNEL_B 0x2 51 52#define ac97c_writel(chip, reg, val) \ 53 __raw_writel((val), (chip)->regs + AC97C_##reg) 54#define ac97c_readl(chip, reg) \ 55 __raw_readl((chip)->regs + AC97C_##reg) 56 57#ifdef CONFIG_CPU_AT32AP700X 58#define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800) 59#define ATMEL_WM97XX_AC97C_IRQ (29) 60#define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */ 61#else 62#error Unkown CPU, this driver only supports AT32AP700X CPUs. 63#endif 64 65struct continuous { 66 u16 id; /* codec id */ 67 u8 code; /* continuous code */ 68 u8 reads; /* number of coord reads per read cycle */ 69 u32 speed; /* number of coords per second */ 70}; 71 72#define WM_READS(sp) ((sp / HZ) + 1) 73 74static const struct continuous cinfo[] = { 75 {WM9705_ID2, 0, WM_READS(94), 94}, 76 {WM9705_ID2, 1, WM_READS(188), 188}, 77 {WM9705_ID2, 2, WM_READS(375), 375}, 78 {WM9705_ID2, 3, WM_READS(750), 750}, 79 {WM9712_ID2, 0, WM_READS(94), 94}, 80 {WM9712_ID2, 1, WM_READS(188), 188}, 81 {WM9712_ID2, 2, WM_READS(375), 375}, 82 {WM9712_ID2, 3, WM_READS(750), 750}, 83 {WM9713_ID2, 0, WM_READS(94), 94}, 84 {WM9713_ID2, 1, WM_READS(120), 120}, 85 {WM9713_ID2, 2, WM_READS(154), 154}, 86 {WM9713_ID2, 3, WM_READS(188), 188}, 87}; 88 89/* Continuous speed index. */ 90static int sp_idx; 91 92/* 93 * Pen sampling frequency (Hz) in continuous mode. 94 */ 95static int cont_rate = 188; 96module_param(cont_rate, int, 0); 97MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); 98 99/* 100 * Pen down detection. 101 * 102 * This driver can either poll or use an interrupt to indicate a pen down 103 * event. If the irq request fails then it will fall back to polling mode. 104 */ 105static int pen_int = 1; 106module_param(pen_int, int, 0); 107MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)"); 108 109/* 110 * Pressure readback. 111 * 112 * Set to 1 to read back pen down pressure. 113 */ 114static int pressure; 115module_param(pressure, int, 0); 116MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); 117 118/* 119 * AC97 touch data slot. 120 * 121 * Touch screen readback data ac97 slot. 122 */ 123static int ac97_touch_slot = 5; 124module_param(ac97_touch_slot, int, 0); 125MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); 126 127/* 128 * GPIO line number. 129 * 130 * Set to GPIO number where the signal from the WM97xx device is hooked up. 131 */ 132static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT; 133module_param(atmel_gpio_line, int, 0); 134MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx"); 135 136struct atmel_wm97xx { 137 struct wm97xx *wm; 138 struct timer_list pen_timer; 139 void __iomem *regs; 140 unsigned long ac97c_irq; 141 unsigned long gpio_pen; 142 unsigned long gpio_irq; 143 unsigned short x; 144 unsigned short y; 145}; 146 147static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id) 148{ 149 struct atmel_wm97xx *atmel_wm97xx = dev_id; 150 struct wm97xx *wm = atmel_wm97xx->wm; 151 int status = ac97c_readl(atmel_wm97xx, CBSR); 152 irqreturn_t retval = IRQ_NONE; 153 154 if (status & AC97C_OVRUN) { 155 dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n"); 156 ac97c_readl(atmel_wm97xx, CBRHR); 157 retval = IRQ_HANDLED; 158 } else if (status & AC97C_RXRDY) { 159 u16 data; 160 u16 value; 161 u16 source; 162 u16 pen_down; 163 164 data = ac97c_readl(atmel_wm97xx, CBRHR); 165 value = data & 0x0fff; 166 source = data & WM97XX_ADCSRC_MASK; 167 pen_down = (data & WM97XX_PEN_DOWN) >> 8; 168 169 if (source == WM97XX_ADCSEL_X) 170 atmel_wm97xx->x = value; 171 if (source == WM97XX_ADCSEL_Y) 172 atmel_wm97xx->y = value; 173 174 if (!pressure && source == WM97XX_ADCSEL_Y) { 175 input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x); 176 input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y); 177 input_report_key(wm->input_dev, BTN_TOUCH, pen_down); 178 input_sync(wm->input_dev); 179 } else if (pressure && source == WM97XX_ADCSEL_PRES) { 180 input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x); 181 input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y); 182 input_report_abs(wm->input_dev, ABS_PRESSURE, value); 183 input_report_key(wm->input_dev, BTN_TOUCH, value); 184 input_sync(wm->input_dev); 185 } 186 187 retval = IRQ_HANDLED; 188 } 189 190 return retval; 191} 192 193static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm) 194{ 195 struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev); 196 struct input_dev *input_dev = wm->input_dev; 197 int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen); 198 199 if (pen_down != 0) { 200 mod_timer(&atmel_wm97xx->pen_timer, 201 jiffies + msecs_to_jiffies(1)); 202 } else { 203 if (pressure) 204 input_report_abs(input_dev, ABS_PRESSURE, 0); 205 input_report_key(input_dev, BTN_TOUCH, 0); 206 input_sync(input_dev); 207 } 208} 209 210static void atmel_wm97xx_pen_timer(unsigned long data) 211{ 212 atmel_wm97xx_acc_pen_up((struct wm97xx *)data); 213} 214 215static int atmel_wm97xx_acc_startup(struct wm97xx *wm) 216{ 217 struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev); 218 int idx = 0; 219 220 if (wm->ac97 == NULL) 221 return -ENODEV; 222 223 for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { 224 if (wm->id != cinfo[idx].id) 225 continue; 226 227 sp_idx = idx; 228 229 if (cont_rate <= cinfo[idx].speed) 230 break; 231 } 232 233 wm->acc_rate = cinfo[sp_idx].code; 234 wm->acc_slot = ac97_touch_slot; 235 dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, " 236 "%d samples/sec\n", cinfo[sp_idx].speed); 237 238 if (pen_int) { 239 unsigned long reg; 240 241 wm->pen_irq = atmel_wm97xx->gpio_irq; 242 243 switch (wm->id) { 244 case WM9712_ID2: /* Fall through. */ 245 case WM9713_ID2: 246 /* 247 * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3 248 * (PENDOWN). 249 */ 250 wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, 251 WM97XX_GPIO_POL_HIGH, 252 WM97XX_GPIO_STICKY, 253 WM97XX_GPIO_WAKE); 254 wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT, 255 WM97XX_GPIO_POL_HIGH, 256 WM97XX_GPIO_NOTSTICKY, 257 WM97XX_GPIO_NOWAKE); 258 case WM9705_ID2: /* Fall through. */ 259 /* 260 * Enable touch data slot in AC97 controller channel B. 261 */ 262 reg = ac97c_readl(atmel_wm97xx, ICA); 263 reg &= ~AC97C_CH_MASK(wm->acc_slot); 264 reg |= AC97C_CH_ASSIGN(wm->acc_slot, B); 265 ac97c_writel(atmel_wm97xx, ICA, reg); 266 267 /* 268 * Enable channel and interrupt for RXRDY and OVERRUN. 269 */ 270 ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA 271 | AC97C_CMR_CEM_BIG 272 | AC97C_CMR_SIZE_16 273 | AC97C_OVRUN 274 | AC97C_RXRDY); 275 /* Dummy read to empty RXRHR. */ 276 ac97c_readl(atmel_wm97xx, CBRHR); 277 /* 278 * Enable interrupt for channel B in the AC97 279 * controller. 280 */ 281 ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT); 282 break; 283 default: 284 dev_err(&wm->touch_dev->dev, "pen down irq not " 285 "supported on this device\n"); 286 pen_int = 0; 287 break; 288 } 289 } 290 291 return 0; 292} 293 294static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm) 295{ 296 if (pen_int) { 297 struct atmel_wm97xx *atmel_wm97xx = 298 platform_get_drvdata(wm->touch_dev); 299 unsigned long ica; 300 301 switch (wm->id & 0xffff) { 302 case WM9705_ID2: /* Fall through. */ 303 case WM9712_ID2: /* Fall through. */ 304 case WM9713_ID2: 305 /* Disable slot and turn off channel B interrupts. */ 306 ica = ac97c_readl(atmel_wm97xx, ICA); 307 ica &= ~AC97C_CH_MASK(wm->acc_slot); 308 ac97c_writel(atmel_wm97xx, ICA, ica); 309 ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); 310 ac97c_writel(atmel_wm97xx, CBMR, 0); 311 wm->pen_irq = 0; 312 break; 313 default: 314 dev_err(&wm->touch_dev->dev, "unknown codec\n"); 315 break; 316 } 317 } 318} 319 320static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable) 321{ 322 /* Intentionally left empty. */ 323} 324 325static struct wm97xx_mach_ops atmel_mach_ops = { 326 .acc_enabled = 1, 327 .acc_pen_up = atmel_wm97xx_acc_pen_up, 328 .acc_startup = atmel_wm97xx_acc_startup, 329 .acc_shutdown = atmel_wm97xx_acc_shutdown, 330 .irq_enable = atmel_wm97xx_irq_enable, 331 .irq_gpio = WM97XX_GPIO_3, 332}; 333 334static int __init atmel_wm97xx_probe(struct platform_device *pdev) 335{ 336 struct wm97xx *wm = platform_get_drvdata(pdev); 337 struct atmel_wm97xx *atmel_wm97xx; 338 int ret; 339 340 atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL); 341 if (!atmel_wm97xx) { 342 dev_dbg(&pdev->dev, "out of memory\n"); 343 return -ENOMEM; 344 } 345 346 atmel_wm97xx->wm = wm; 347 atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM; 348 atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ; 349 atmel_wm97xx->gpio_pen = atmel_gpio_line; 350 atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen); 351 352 setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 353 (unsigned long)wm); 354 355 ret = request_irq(atmel_wm97xx->ac97c_irq, 356 atmel_wm97xx_channel_b_interrupt, 357 IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx); 358 if (ret) { 359 dev_dbg(&pdev->dev, "could not request ac97c irq\n"); 360 goto err; 361 } 362 363 platform_set_drvdata(pdev, atmel_wm97xx); 364 365 ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops); 366 if (ret) 367 goto err_irq; 368 369 return ret; 370 371err_irq: 372 free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); 373err: 374 platform_set_drvdata(pdev, NULL); 375 kfree(atmel_wm97xx); 376 return ret; 377} 378 379static int __exit atmel_wm97xx_remove(struct platform_device *pdev) 380{ 381 struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); 382 struct wm97xx *wm = atmel_wm97xx->wm; 383 384 ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); 385 free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); 386 del_timer_sync(&atmel_wm97xx->pen_timer); 387 wm97xx_unregister_mach_ops(wm); 388 platform_set_drvdata(pdev, NULL); 389 kfree(atmel_wm97xx); 390 391 return 0; 392} 393 394#ifdef CONFIG_PM 395static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) 396{ 397 struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); 398 399 ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); 400 disable_irq(atmel_wm97xx->gpio_irq); 401 del_timer_sync(&atmel_wm97xx->pen_timer); 402 403 return 0; 404} 405 406static int atmel_wm97xx_resume(struct platform_device *pdev) 407{ 408 struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); 409 struct wm97xx *wm = atmel_wm97xx->wm; 410 411 if (wm->input_dev->users) { 412 enable_irq(atmel_wm97xx->gpio_irq); 413 ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT); 414 } 415 416 return 0; 417} 418#else 419#define atmel_wm97xx_suspend NULL 420#define atmel_wm97xx_resume NULL 421#endif 422 423static struct platform_driver atmel_wm97xx_driver = { 424 .remove = __exit_p(atmel_wm97xx_remove), 425 .driver = { 426 .name = "wm97xx-touch", 427 }, 428 .suspend = atmel_wm97xx_suspend, 429 .resume = atmel_wm97xx_resume, 430}; 431 432static int __init atmel_wm97xx_init(void) 433{ 434 return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe); 435} 436module_init(atmel_wm97xx_init); 437 438static void __exit atmel_wm97xx_exit(void) 439{ 440 platform_driver_unregister(&atmel_wm97xx_driver); 441} 442module_exit(atmel_wm97xx_exit); 443 444MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); 445MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); 446MODULE_LICENSE("GPL"); 447