Path: blob/master/drivers/input/touchscreen/ucb1400_ts.c
15111 views
/*1* Philips UCB1400 touchscreen driver2*3* Author: Nicolas Pitre4* Created: September 25, 20065* Copyright: MontaVista Software, Inc.6*7* Spliting done by: Marek Vasut <[email protected]>8* If something doesn't work and it worked before spliting, e-mail me,9* dont bother Nicolas please ;-)10*11* This program is free software; you can redistribute it and/or modify12* it under the terms of the GNU General Public License version 2 as13* published by the Free Software Foundation.14*15* This code is heavily based on ucb1x00-*.c copyrighted by Russell King16* covering the UCB1100, UCB1200 and UCB1300.. Support for the UCB1400 has17* been made separate from ucb1x00-core/ucb1x00-ts on Russell's request.18*/1920#include <linux/module.h>21#include <linux/init.h>22#include <linux/completion.h>23#include <linux/delay.h>24#include <linux/input.h>25#include <linux/device.h>26#include <linux/interrupt.h>27#include <linux/suspend.h>28#include <linux/kthread.h>29#include <linux/freezer.h>30#include <linux/ucb1400.h>3132static int adcsync;33static int ts_delay = 55; /* us */34static int ts_delay_pressure; /* us */3536/* Switch to interrupt mode. */37static inline void ucb1400_ts_mode_int(struct snd_ac97 *ac97)38{39ucb1400_reg_write(ac97, UCB_TS_CR,40UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |41UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |42UCB_TS_CR_MODE_INT);43}4445/*46* Switch to pressure mode, and read pressure. We don't need to wait47* here, since both plates are being driven.48*/49static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400_ts *ucb)50{51ucb1400_reg_write(ucb->ac97, UCB_TS_CR,52UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |53UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |54UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);55udelay(ts_delay_pressure);56return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync);57}5859/*60* Switch to X position mode and measure Y plate. We switch the plate61* configuration in pressure mode, then switch to position mode. This62* gives a faster response time. Even so, we need to wait about 55us63* for things to stabilise.64*/65static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400_ts *ucb)66{67ucb1400_reg_write(ucb->ac97, UCB_TS_CR,68UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |69UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);70ucb1400_reg_write(ucb->ac97, UCB_TS_CR,71UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |72UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);73ucb1400_reg_write(ucb->ac97, UCB_TS_CR,74UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |75UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);7677udelay(ts_delay);7879return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync);80}8182/*83* Switch to Y position mode and measure X plate. We switch the plate84* configuration in pressure mode, then switch to position mode. This85* gives a faster response time. Even so, we need to wait about 55us86* for things to stabilise.87*/88static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400_ts *ucb)89{90ucb1400_reg_write(ucb->ac97, UCB_TS_CR,91UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |92UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);93ucb1400_reg_write(ucb->ac97, UCB_TS_CR,94UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |95UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);96ucb1400_reg_write(ucb->ac97, UCB_TS_CR,97UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |98UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);99100udelay(ts_delay);101102return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPX, adcsync);103}104105/*106* Switch to X plate resistance mode. Set MX to ground, PX to107* supply. Measure current.108*/109static inline unsigned int ucb1400_ts_read_xres(struct ucb1400_ts *ucb)110{111ucb1400_reg_write(ucb->ac97, UCB_TS_CR,112UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |113UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);114return ucb1400_adc_read(ucb->ac97, 0, adcsync);115}116117/*118* Switch to Y plate resistance mode. Set MY to ground, PY to119* supply. Measure current.120*/121static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb)122{123ucb1400_reg_write(ucb->ac97, UCB_TS_CR,124UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |125UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);126return ucb1400_adc_read(ucb->ac97, 0, adcsync);127}128129static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97)130{131unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR);132133return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW);134}135136static inline void ucb1400_ts_irq_enable(struct snd_ac97 *ac97)137{138ucb1400_reg_write(ac97, UCB_IE_CLEAR, UCB_IE_TSPX);139ucb1400_reg_write(ac97, UCB_IE_CLEAR, 0);140ucb1400_reg_write(ac97, UCB_IE_FAL, UCB_IE_TSPX);141}142143static inline void ucb1400_ts_irq_disable(struct snd_ac97 *ac97)144{145ucb1400_reg_write(ac97, UCB_IE_FAL, 0);146}147148static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y)149{150input_report_abs(idev, ABS_X, x);151input_report_abs(idev, ABS_Y, y);152input_report_abs(idev, ABS_PRESSURE, pressure);153input_report_key(idev, BTN_TOUCH, 1);154input_sync(idev);155}156157static void ucb1400_ts_event_release(struct input_dev *idev)158{159input_report_abs(idev, ABS_PRESSURE, 0);160input_report_key(idev, BTN_TOUCH, 0);161input_sync(idev);162}163164static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb)165{166unsigned int isr;167168isr = ucb1400_reg_read(ucb->ac97, UCB_IE_STATUS);169ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr);170ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);171172if (isr & UCB_IE_TSPX)173ucb1400_ts_irq_disable(ucb->ac97);174else175dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr);176enable_irq(ucb->irq);177}178179static int ucb1400_ts_thread(void *_ucb)180{181struct ucb1400_ts *ucb = _ucb;182struct task_struct *tsk = current;183int valid = 0;184struct sched_param param = { .sched_priority = 1 };185186sched_setscheduler(tsk, SCHED_FIFO, ¶m);187188set_freezable();189while (!kthread_should_stop()) {190unsigned int x, y, p;191long timeout;192193ucb->ts_restart = 0;194195if (ucb->irq_pending) {196ucb->irq_pending = 0;197ucb1400_handle_pending_irq(ucb);198}199200ucb1400_adc_enable(ucb->ac97);201x = ucb1400_ts_read_xpos(ucb);202y = ucb1400_ts_read_ypos(ucb);203p = ucb1400_ts_read_pressure(ucb);204ucb1400_adc_disable(ucb->ac97);205206/* Switch back to interrupt mode. */207ucb1400_ts_mode_int(ucb->ac97);208209msleep(10);210211if (ucb1400_ts_pen_up(ucb->ac97)) {212ucb1400_ts_irq_enable(ucb->ac97);213214/*215* If we spat out a valid sample set last time,216* spit out a "pen off" sample here.217*/218if (valid) {219ucb1400_ts_event_release(ucb->ts_idev);220valid = 0;221}222223timeout = MAX_SCHEDULE_TIMEOUT;224} else {225valid = 1;226ucb1400_ts_evt_add(ucb->ts_idev, p, x, y);227timeout = msecs_to_jiffies(10);228}229230wait_event_freezable_timeout(ucb->ts_wait,231ucb->irq_pending || ucb->ts_restart ||232kthread_should_stop(), timeout);233}234235/* Send the "pen off" if we are stopping with the pen still active */236if (valid)237ucb1400_ts_event_release(ucb->ts_idev);238239ucb->ts_task = NULL;240return 0;241}242243/*244* A restriction with interrupts exists when using the ucb1400, as245* the codec read/write routines may sleep while waiting for codec246* access completion and uses semaphores for access control to the247* AC97 bus. A complete codec read cycle could take anywhere from248* 60 to 100uSec so we *definitely* don't want to spin inside the249* interrupt handler waiting for codec access. So, we handle the250* interrupt by scheduling a RT kernel thread to run in process251* context instead of interrupt context.252*/253static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)254{255struct ucb1400_ts *ucb = devid;256257if (irqnr == ucb->irq) {258disable_irq_nosync(ucb->irq);259ucb->irq_pending = 1;260wake_up(&ucb->ts_wait);261return IRQ_HANDLED;262}263return IRQ_NONE;264}265266static int ucb1400_ts_open(struct input_dev *idev)267{268struct ucb1400_ts *ucb = input_get_drvdata(idev);269int ret = 0;270271BUG_ON(ucb->ts_task);272273ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts");274if (IS_ERR(ucb->ts_task)) {275ret = PTR_ERR(ucb->ts_task);276ucb->ts_task = NULL;277}278279return ret;280}281282static void ucb1400_ts_close(struct input_dev *idev)283{284struct ucb1400_ts *ucb = input_get_drvdata(idev);285286if (ucb->ts_task)287kthread_stop(ucb->ts_task);288289ucb1400_ts_irq_disable(ucb->ac97);290ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0);291}292293#ifndef NO_IRQ294#define NO_IRQ 0295#endif296297/*298* Try to probe our interrupt, rather than relying on lots of299* hard-coded machine dependencies.300*/301static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb)302{303unsigned long mask, timeout;304305mask = probe_irq_on();306307/* Enable the ADC interrupt. */308ucb1400_reg_write(ucb->ac97, UCB_IE_RIS, UCB_IE_ADC);309ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, UCB_IE_ADC);310ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0xffff);311ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);312313/* Cause an ADC interrupt. */314ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, UCB_ADC_ENA);315ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);316317/* Wait for the conversion to complete. */318timeout = jiffies + HZ/2;319while (!(ucb1400_reg_read(ucb->ac97, UCB_ADC_DATA) &320UCB_ADC_DAT_VALID)) {321cpu_relax();322if (time_after(jiffies, timeout)) {323printk(KERN_ERR "ucb1400: timed out in IRQ probe\n");324probe_irq_off(mask);325return -ENODEV;326}327}328ucb1400_reg_write(ucb->ac97, UCB_ADC_CR, 0);329330/* Disable and clear interrupt. */331ucb1400_reg_write(ucb->ac97, UCB_IE_RIS, 0);332ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, 0);333ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0xffff);334ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);335336/* Read triggered interrupt. */337ucb->irq = probe_irq_off(mask);338if (ucb->irq < 0 || ucb->irq == NO_IRQ)339return -ENODEV;340341return 0;342}343344static int ucb1400_ts_probe(struct platform_device *dev)345{346int error, x_res, y_res;347u16 fcsr;348struct ucb1400_ts *ucb = dev->dev.platform_data;349350ucb->ts_idev = input_allocate_device();351if (!ucb->ts_idev) {352error = -ENOMEM;353goto err;354}355356/* Only in case the IRQ line wasn't supplied, try detecting it */357if (ucb->irq < 0) {358error = ucb1400_ts_detect_irq(ucb);359if (error) {360printk(KERN_ERR "UCB1400: IRQ probe failed\n");361goto err_free_devs;362}363}364365init_waitqueue_head(&ucb->ts_wait);366367error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING,368"UCB1400", ucb);369if (error) {370printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n",371ucb->irq, error);372goto err_free_devs;373}374printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);375376input_set_drvdata(ucb->ts_idev, ucb);377378ucb->ts_idev->dev.parent = &dev->dev;379ucb->ts_idev->name = "UCB1400 touchscreen interface";380ucb->ts_idev->id.vendor = ucb1400_reg_read(ucb->ac97,381AC97_VENDOR_ID1);382ucb->ts_idev->id.product = ucb->id;383ucb->ts_idev->open = ucb1400_ts_open;384ucb->ts_idev->close = ucb1400_ts_close;385ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);386ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);387388/*389* Enable ADC filter to prevent horrible jitter on Colibri.390* This also further reduces jitter on boards where ADCSYNC391* pin is connected.392*/393fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR);394ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE);395396ucb1400_adc_enable(ucb->ac97);397x_res = ucb1400_ts_read_xres(ucb);398y_res = ucb1400_ts_read_yres(ucb);399ucb1400_adc_disable(ucb->ac97);400printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res);401402input_set_abs_params(ucb->ts_idev, ABS_X, 0, x_res, 0, 0);403input_set_abs_params(ucb->ts_idev, ABS_Y, 0, y_res, 0, 0);404input_set_abs_params(ucb->ts_idev, ABS_PRESSURE, 0, 0, 0, 0);405406error = input_register_device(ucb->ts_idev);407if (error)408goto err_free_irq;409410return 0;411412err_free_irq:413free_irq(ucb->irq, ucb);414err_free_devs:415input_free_device(ucb->ts_idev);416err:417return error;418419}420421static int ucb1400_ts_remove(struct platform_device *dev)422{423struct ucb1400_ts *ucb = dev->dev.platform_data;424425free_irq(ucb->irq, ucb);426input_unregister_device(ucb->ts_idev);427return 0;428}429430#ifdef CONFIG_PM431static int ucb1400_ts_resume(struct platform_device *dev)432{433struct ucb1400_ts *ucb = dev->dev.platform_data;434435if (ucb->ts_task) {436/*437* Restart the TS thread to ensure the438* TS interrupt mode is set up again439* after sleep.440*/441ucb->ts_restart = 1;442wake_up(&ucb->ts_wait);443}444return 0;445}446#else447#define ucb1400_ts_resume NULL448#endif449450static struct platform_driver ucb1400_ts_driver = {451.probe = ucb1400_ts_probe,452.remove = ucb1400_ts_remove,453.resume = ucb1400_ts_resume,454.driver = {455.name = "ucb1400_ts",456},457};458459static int __init ucb1400_ts_init(void)460{461return platform_driver_register(&ucb1400_ts_driver);462}463464static void __exit ucb1400_ts_exit(void)465{466platform_driver_unregister(&ucb1400_ts_driver);467}468469module_param(adcsync, bool, 0444);470MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");471472module_param(ts_delay, int, 0444);473MODULE_PARM_DESC(ts_delay, "Delay between panel setup and"474" position read. Default = 55us.");475476module_param(ts_delay_pressure, int, 0444);477MODULE_PARM_DESC(ts_delay_pressure,478"delay between panel setup and pressure read."479" Default = 0us.");480481module_init(ucb1400_ts_init);482module_exit(ucb1400_ts_exit);483484MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver");485MODULE_LICENSE("GPL");486487488