2007-09-26 00:02:56 -04:00
/*
* drivers / input / touchscreen / jornada720_ts . c
*
* Copyright ( C ) 2007 Kristoffer Ericson < Kristoffer . Ericson @ gmail . com >
*
* Copyright ( C ) 2006 Filip Zyzniewski < filip . zyzniewski @ tefnet . pl >
* based on HP Jornada 56 x touchscreen driver by Alex Lange < chicken @ handhelds . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* HP Jornada 710 / 720 / 729 Touchscreen Driver
*/
# include <linux/platform_device.h>
# include <linux/init.h>
# include <linux/input.h>
# include <linux/interrupt.h>
# include <linux/module.h>
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
# include <mach/jornada720.h>
2007-09-26 00:02:56 -04:00
MODULE_AUTHOR ( " Kristoffer Ericson <kristoffer.ericson@gmail.com> " ) ;
MODULE_DESCRIPTION ( " HP Jornada 710/720/728 touchscreen driver " ) ;
2008-05-21 06:32:11 +01:00
MODULE_LICENSE ( " GPL v2 " ) ;
2007-09-26 00:02:56 -04:00
struct jornada_ts {
struct input_dev * dev ;
int x_data [ 4 ] ; /* X sample values */
int y_data [ 4 ] ; /* Y sample values */
} ;
static void jornada720_ts_collect_data ( struct jornada_ts * jornada_ts )
{
/* 3 low word X samples */
jornada_ts - > x_data [ 0 ] = jornada_ssp_byte ( TXDUMMY ) ;
jornada_ts - > x_data [ 1 ] = jornada_ssp_byte ( TXDUMMY ) ;
jornada_ts - > x_data [ 2 ] = jornada_ssp_byte ( TXDUMMY ) ;
/* 3 low word Y samples */
jornada_ts - > y_data [ 0 ] = jornada_ssp_byte ( TXDUMMY ) ;
jornada_ts - > y_data [ 1 ] = jornada_ssp_byte ( TXDUMMY ) ;
jornada_ts - > y_data [ 2 ] = jornada_ssp_byte ( TXDUMMY ) ;
/* combined x samples bits */
jornada_ts - > x_data [ 3 ] = jornada_ssp_byte ( TXDUMMY ) ;
/* combined y samples bits */
jornada_ts - > y_data [ 3 ] = jornada_ssp_byte ( TXDUMMY ) ;
}
static int jornada720_ts_average ( int coords [ 4 ] )
{
int coord , high_bits = coords [ 3 ] ;
coord = coords [ 0 ] | ( ( high_bits & 0x03 ) < < 8 ) ;
coord + = coords [ 1 ] | ( ( high_bits & 0x0c ) < < 6 ) ;
coord + = coords [ 2 ] | ( ( high_bits & 0x30 ) < < 4 ) ;
return coord / 3 ;
}
static irqreturn_t jornada720_ts_interrupt ( int irq , void * dev_id )
{
struct platform_device * pdev = dev_id ;
struct jornada_ts * jornada_ts = platform_get_drvdata ( pdev ) ;
struct input_dev * input = jornada_ts - > dev ;
int x , y ;
/* If GPIO_GPIO9 is set to high then report pen up */
if ( GPLR & GPIO_GPIO ( 9 ) ) {
input_report_key ( input , BTN_TOUCH , 0 ) ;
input_sync ( input ) ;
} else {
jornada_ssp_start ( ) ;
/* proper reply to request is always TXDUMMY */
if ( jornada_ssp_inout ( GETTOUCHSAMPLES ) = = TXDUMMY ) {
jornada720_ts_collect_data ( jornada_ts ) ;
x = jornada720_ts_average ( jornada_ts - > x_data ) ;
y = jornada720_ts_average ( jornada_ts - > y_data ) ;
input_report_key ( input , BTN_TOUCH , 1 ) ;
input_report_abs ( input , ABS_X , x ) ;
input_report_abs ( input , ABS_Y , y ) ;
input_sync ( input ) ;
}
jornada_ssp_end ( ) ;
}
return IRQ_HANDLED ;
}
static int __devinit jornada720_ts_probe ( struct platform_device * pdev )
{
struct jornada_ts * jornada_ts ;
struct input_dev * input_dev ;
int error ;
jornada_ts = kzalloc ( sizeof ( struct jornada_ts ) , GFP_KERNEL ) ;
input_dev = input_allocate_device ( ) ;
if ( ! jornada_ts | | ! input_dev ) {
error = - ENOMEM ;
goto fail1 ;
}
platform_set_drvdata ( pdev , jornada_ts ) ;
jornada_ts - > dev = input_dev ;
input_dev - > name = " HP Jornada 7xx Touchscreen " ;
input_dev - > phys = " jornadats/input0 " ;
input_dev - > id . bustype = BUS_HOST ;
input_dev - > dev . parent = & pdev - > dev ;
2008-09-16 14:19:25 -04:00
input_dev - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input_dev - > keybit [ BIT_WORD ( BTN_TOUCH ) ] = BIT_MASK ( BTN_TOUCH ) ;
2007-09-26 00:02:56 -04:00
input_set_abs_params ( input_dev , ABS_X , 270 , 3900 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_Y , 180 , 3700 , 0 , 0 ) ;
error = request_irq ( IRQ_GPIO9 ,
jornada720_ts_interrupt ,
IRQF_DISABLED | IRQF_TRIGGER_RISING ,
" HP7XX Touchscreen driver " , pdev ) ;
if ( error ) {
printk ( KERN_INFO " HP7XX TS : Unable to acquire irq! \n " ) ;
goto fail1 ;
}
error = input_register_device ( jornada_ts - > dev ) ;
if ( error )
goto fail2 ;
return 0 ;
fail2 :
free_irq ( IRQ_GPIO9 , pdev ) ;
fail1 :
platform_set_drvdata ( pdev , NULL ) ;
input_free_device ( input_dev ) ;
kfree ( jornada_ts ) ;
return error ;
}
static int __devexit jornada720_ts_remove ( struct platform_device * pdev )
{
struct jornada_ts * jornada_ts = platform_get_drvdata ( pdev ) ;
free_irq ( IRQ_GPIO9 , pdev ) ;
platform_set_drvdata ( pdev , NULL ) ;
input_unregister_device ( jornada_ts - > dev ) ;
kfree ( jornada_ts ) ;
return 0 ;
}
2008-04-18 00:24:42 -04:00
/* work with hotplug and coldplug */
MODULE_ALIAS ( " platform:jornada_ts " ) ;
2007-09-26 00:02:56 -04:00
static struct platform_driver jornada720_ts_driver = {
. probe = jornada720_ts_probe ,
. remove = __devexit_p ( jornada720_ts_remove ) ,
. driver = {
. name = " jornada_ts " ,
2008-04-18 00:24:42 -04:00
. owner = THIS_MODULE ,
2007-09-26 00:02:56 -04:00
} ,
} ;
static int __init jornada720_ts_init ( void )
{
return platform_driver_register ( & jornada720_ts_driver ) ;
}
static void __exit jornada720_ts_exit ( void )
{
platform_driver_unregister ( & jornada720_ts_driver ) ;
}
module_init ( jornada720_ts_init ) ;
module_exit ( jornada720_ts_exit ) ;