jornada720_ts.c revision cdcc96e261909eccf596c070116c8b906a42b328
15637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson/* 25637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * drivers/input/touchscreen/jornada720_ts.c 35637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * 45637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> 55637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * 65637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl> 75637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * based on HP Jornada 56x touchscreen driver by Alex Lange <chicken@handhelds.org> 85637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * 95637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * This program is free software; you can redistribute it and/or modify 105637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * it under the terms of the GNU General Public License version 2 as 115637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * published by the Free Software Foundation. 125637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * 135637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson * HP Jornada 710/720/729 Touchscreen Driver 145637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson */ 155637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 165637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson#include <linux/platform_device.h> 175637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson#include <linux/init.h> 185637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson#include <linux/input.h> 195637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson#include <linux/interrupt.h> 205637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson#include <linux/module.h> 215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 225637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 23a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h> 24a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/jornada720.h> 255637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 265637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer EricsonMODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); 275637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer EricsonMODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); 28839cd31050096c88d929cc7c790c80cae87e2d85Al ViroMODULE_LICENSE("GPL v2"); 295637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 305637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstruct jornada_ts { 315637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct input_dev *dev; 325637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson int x_data[4]; /* X sample values */ 335637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson int y_data[4]; /* Y sample values */ 345637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson}; 355637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 365637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic void jornada720_ts_collect_data(struct jornada_ts *jornada_ts) 375637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson{ 385637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 395637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* 3 low word X samples */ 405637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY); 415637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY); 425637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY); 435637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 445637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* 3 low word Y samples */ 455637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY); 465637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY); 475637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY); 485637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 495637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* combined x samples bits */ 505637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY); 515637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 525637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* combined y samples bits */ 535637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY); 545637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson} 555637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 565637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic int jornada720_ts_average(int coords[4]) 575637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson{ 585637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson int coord, high_bits = coords[3]; 595637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 605637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson coord = coords[0] | ((high_bits & 0x03) << 8); 615637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson coord += coords[1] | ((high_bits & 0x0c) << 6); 625637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson coord += coords[2] | ((high_bits & 0x30) << 4); 635637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 645637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson return coord / 3; 655637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson} 665637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 675637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) 685637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson{ 695637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct platform_device *pdev = dev_id; 705637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); 715637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct input_dev *input = jornada_ts->dev; 725637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson int x, y; 735637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 745637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* If GPIO_GPIO9 is set to high then report pen up */ 755637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson if (GPLR & GPIO_GPIO(9)) { 765637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_report_key(input, BTN_TOUCH, 0); 775637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_sync(input); 785637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson } else { 795637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ssp_start(); 805637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 815637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson /* proper reply to request is always TXDUMMY */ 825637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) { 835637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada720_ts_collect_data(jornada_ts); 845637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 855637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson x = jornada720_ts_average(jornada_ts->x_data); 865637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson y = jornada720_ts_average(jornada_ts->y_data); 875637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 885637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_report_key(input, BTN_TOUCH, 1); 895637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_report_abs(input, ABS_X, x); 905637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_report_abs(input, ABS_Y, y); 915637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_sync(input); 925637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson } 935637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 945637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ssp_end(); 955637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson } 965637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 975637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson return IRQ_HANDLED; 985637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson} 995637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1005637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic int __devinit jornada720_ts_probe(struct platform_device *pdev) 1015637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson{ 1025637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct jornada_ts *jornada_ts; 1035637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct input_dev *input_dev; 1045637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson int error; 1055637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1065637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL); 1075637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_dev = input_allocate_device(); 1085637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1095637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson if (!jornada_ts || !input_dev) { 1105637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson error = -ENOMEM; 1115637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson goto fail1; 1125637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson } 1135637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1145637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson platform_set_drvdata(pdev, jornada_ts); 1155637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1165637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada_ts->dev = input_dev; 1175637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1185637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_dev->name = "HP Jornada 7xx Touchscreen"; 1195637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_dev->phys = "jornadats/input0"; 1205637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_dev->id.bustype = BUS_HOST; 1215637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_dev->dev.parent = &pdev->dev; 1225637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1231577e4b70a04cce39f296cc714da5ad5d272105aKristoffer Ericson input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 1241577e4b70a04cce39f296cc714da5ad5d272105aKristoffer Ericson input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1255637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); 1265637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); 1275637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1285637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson error = request_irq(IRQ_GPIO9, 1295637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson jornada720_ts_interrupt, 130ec4665c46b11f6e444911ba73dddae6044dec909Yong Zhang IRQF_TRIGGER_RISING, 1315637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson "HP7XX Touchscreen driver", pdev); 1325637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson if (error) { 1335637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); 1345637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson goto fail1; 1355637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson } 1365637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1375637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson error = input_register_device(jornada_ts->dev); 1385637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson if (error) 1395637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson goto fail2; 1405637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1415637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson return 0; 1425637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1435637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson fail2: 1445637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson free_irq(IRQ_GPIO9, pdev); 1455637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson fail1: 1465637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson platform_set_drvdata(pdev, NULL); 1475637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_free_device(input_dev); 1485637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson kfree(jornada_ts); 1495637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson return error; 1505637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson} 1515637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1525637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic int __devexit jornada720_ts_remove(struct platform_device *pdev) 1535637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson{ 1545637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); 1555637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1565637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson free_irq(IRQ_GPIO9, pdev); 1575637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson platform_set_drvdata(pdev, NULL); 1585637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson input_unregister_device(jornada_ts->dev); 1595637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson kfree(jornada_ts); 1605637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 1615637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson return 0; 1625637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson} 1635637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson 164d7b5247bbcfba2bc96d4b3dec9086a4f1a31363bKay Sievers/* work with hotplug and coldplug */ 165d7b5247bbcfba2bc96d4b3dec9086a4f1a31363bKay SieversMODULE_ALIAS("platform:jornada_ts"); 166d7b5247bbcfba2bc96d4b3dec9086a4f1a31363bKay Sievers 1675637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericsonstatic struct platform_driver jornada720_ts_driver = { 1685637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson .probe = jornada720_ts_probe, 1695637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson .remove = __devexit_p(jornada720_ts_remove), 1705637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson .driver = { 1715637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson .name = "jornada_ts", 172d7b5247bbcfba2bc96d4b3dec9086a4f1a31363bKay Sievers .owner = THIS_MODULE, 1735637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson }, 1745637f02a9cf84f2c00fd8a0f6561c375bb19103bKristoffer Ericson}; 175cdcc96e261909eccf596c070116c8b906a42b328JJ Dingmodule_platform_driver(jornada720_ts_driver); 176