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