122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* 222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * zylonite-wm97xx.c -- Zylonite Continuous Touch screen driver 322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * 422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Copyright 2004, 2007, 2008 Wolfson Microelectronics PLC. 522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Parts Copyright : Ian Molton <spyro@f2s.com> 722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Andrew Zabolotny <zap@homelink.ru> 822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * 922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * This program is free software; you can redistribute it and/or modify it 1022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * under the terms of the GNU General Public License as published by the 1122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Free Software Foundation; either version 2 of the License, or (at your 1222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * option) any later version. 1322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * 1422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Notes: 1522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * This is a wm97xx extended touch driver supporting interrupt driven 1622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * and continuous operation on Marvell Zylonite development systems 1722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * (which have a WM9713 on board). 1822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown */ 1922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 2022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/module.h> 2122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/moduleparam.h> 2222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/kernel.h> 2322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/init.h> 2422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/delay.h> 25b5d798cc7a221aec50baf496c482280f1b809143Axel Lin#include <linux/gpio.h> 2622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/irq.h> 2722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/interrupt.h> 2822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/io.h> 2922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <linux/wm97xx.h> 3022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 3122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <mach/hardware.h> 3222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <mach/mfp.h> 3322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#include <mach/regs-ac97.h> 3422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 3522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstruct continuous { 3622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown u16 id; /* codec id */ 3722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown u8 code; /* continuous code */ 3822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown u8 reads; /* number of coord reads per read cycle */ 3922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown u32 speed; /* number of coords per second */ 4022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown}; 4122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 4222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown#define WM_READS(sp) ((sp / HZ) + 1) 4322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 4422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic const struct continuous cinfo[] = { 4522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown { WM9713_ID2, 0, WM_READS(94), 94 }, 4622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown { WM9713_ID2, 1, WM_READS(120), 120 }, 4722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown { WM9713_ID2, 2, WM_READS(154), 154 }, 4822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown { WM9713_ID2, 3, WM_READS(188), 188 }, 4922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown}; 5022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 5122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* continuous speed index */ 5222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int sp_idx; 5322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 5422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* 5522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Pen sampling frequency (Hz) in continuous mode. 5622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown */ 5722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int cont_rate = 200; 5822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownmodule_param(cont_rate, int, 0); 5922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); 6022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 6122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* 6222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Pressure readback. 6322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * 6422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Set to 1 to read back pen down pressure 6522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown */ 6622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int pressure; 6722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownmodule_param(pressure, int, 0); 6822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); 6922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 7022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* 7122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * AC97 touch data slot. 7222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * 7322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * Touch screen readback data ac97 slot 7422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown */ 7522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int ac97_touch_slot = 5; 7622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownmodule_param(ac97_touch_slot, int, 0); 7722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); 7822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 7922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 8022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* flush AC97 slot 5 FIFO machines */ 8122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic void wm97xx_acc_pen_up(struct wm97xx *wm) 8222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 8322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown int i; 8422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 8522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown msleep(1); 8622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 8722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown for (i = 0; i < 16; i++) 8822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown MODR; 8922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 9022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 9122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int wm97xx_acc_pen_down(struct wm97xx *wm) 9222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 9322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES; 9422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown int reads = 0; 9522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown static u16 last, tries; 9622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 9722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown /* When the AC97 queue has been drained we need to allow time 9822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * to buffer up samples otherwise we end up spinning polling 9922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown * for samples. The controller can't have a suitably low 100af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * threshold set to use the notifications it gives. 10122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown */ 10222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown msleep(1); 10322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 10422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (tries > 5) { 10522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown tries = 0; 10622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return RC_PENUP; 10722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown } 10822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 10922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown x = MODR; 11022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (x == last) { 11122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown tries++; 11222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return RC_AGAIN; 11322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown } 11422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown last = x; 11522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown do { 11622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (reads) 11722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown x = MODR; 11822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown y = MODR; 11922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (pressure) 12022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown p = MODR; 12122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 122dcfc32babbece923381bd3bffaf17373b5d97568Mark Brown dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", 123dcfc32babbece923381bd3bffaf17373b5d97568Mark Brown x, y, p); 124dcfc32babbece923381bd3bffaf17373b5d97568Mark Brown 12522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown /* are samples valid */ 1262456689b3b11ddecc091cd5f00b9adea6a9854cfWolfram Sang if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X || 1272456689b3b11ddecc091cd5f00b9adea6a9854cfWolfram Sang (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y || 1282456689b3b11ddecc091cd5f00b9adea6a9854cfWolfram Sang (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES) 12922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown goto up; 13022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 13122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown /* coordinate is good */ 13222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown tries = 0; 13322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown input_report_abs(wm->input_dev, ABS_X, x & 0xfff); 13422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); 13522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); 13622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); 13722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown input_sync(wm->input_dev); 13822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown reads++; 13922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown } while (reads < cinfo[sp_idx].reads); 14022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownup: 14122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return RC_PENDOWN | RC_AGAIN; 14222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 14322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 14422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int wm97xx_acc_startup(struct wm97xx *wm) 14522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 14622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown int idx; 14722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 14822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown /* check we have a codec */ 14922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (wm->ac97 == NULL) 15022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return -ENODEV; 15122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 15222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown /* Go you big red fire engine */ 15322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { 15422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (wm->id != cinfo[idx].id) 15522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown continue; 15622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown sp_idx = idx; 15722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (cont_rate <= cinfo[idx].speed) 15822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown break; 15922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown } 16022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown wm->acc_rate = cinfo[sp_idx].code; 16122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown wm->acc_slot = ac97_touch_slot; 16222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown dev_info(wm->dev, 16322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown "zylonite accelerated touchscreen driver, %d samples/sec\n", 16422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown cinfo[sp_idx].speed); 16522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 16622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return 0; 16722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 16822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 16922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic void wm97xx_irq_enable(struct wm97xx *wm, int enable) 17022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 17122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (enable) 17222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown enable_irq(wm->pen_irq); 17322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown else 17422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown disable_irq_nosync(wm->pen_irq); 17522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 17622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 17722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic struct wm97xx_mach_ops zylonite_mach_ops = { 17822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .acc_enabled = 1, 17922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .acc_pen_up = wm97xx_acc_pen_up, 18022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .acc_pen_down = wm97xx_acc_pen_down, 18122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .acc_startup = wm97xx_acc_startup, 18222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .irq_enable = wm97xx_irq_enable, 18322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .irq_gpio = WM97XX_GPIO_2, 18422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown}; 18522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 18622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int zylonite_wm97xx_probe(struct platform_device *pdev) 18722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 18822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown struct wm97xx *wm = platform_get_drvdata(pdev); 18922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown int gpio_touch_irq; 19022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 19122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown if (cpu_is_pxa320()) 19222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO15); 19322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown else 19422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); 19522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 196b5d798cc7a221aec50baf496c482280f1b809143Axel Lin wm->pen_irq = gpio_to_irq(gpio_touch_irq); 197b5d798cc7a221aec50baf496c482280f1b809143Axel Lin irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); 19822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 19922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, 20022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_POL_HIGH, 20122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_STICKY, 20222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_WAKE); 20322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT, 20422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_POL_HIGH, 20522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_NOTSTICKY, 20622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown WM97XX_GPIO_NOWAKE); 20722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 20822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return wm97xx_register_mach_ops(wm, &zylonite_mach_ops); 20922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 21022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 21122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic int zylonite_wm97xx_remove(struct platform_device *pdev) 21222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown{ 21322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown struct wm97xx *wm = platform_get_drvdata(pdev); 21422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 21522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown wm97xx_unregister_mach_ops(wm); 21622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 21722e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown return 0; 21822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown} 21922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 22022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brownstatic struct platform_driver zylonite_wm97xx_driver = { 22122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .probe = zylonite_wm97xx_probe, 22222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .remove = zylonite_wm97xx_remove, 22322e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .driver = { 22422e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown .name = "wm97xx-touch", 22522e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown }, 22622e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown}; 227cdcc96e261909eccf596c070116c8b906a42b328JJ Dingmodule_platform_driver(zylonite_wm97xx_driver); 22822e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown 22922e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark Brown/* Module information */ 23022e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 23122e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_DESCRIPTION("wm97xx continuous touch driver for Zylonite"); 23222e39d344f5f3465dffb9e2713bb8d7cf1f5aec8Mark BrownMODULE_LICENSE("GPL"); 233