2009-01-09 01:50:58 +01:00
/* NXP PCF50633 Input Driver
*
* ( C ) 2006 - 2008 by Openmoko , Inc .
* Author : Balaji Rao < balajirrao @ openmoko . org >
* All rights reserved .
*
* Broken down from monstrous PCF50633 driver mainly by
* Harald Welte , Andy Green and Werner Almesberger
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/platform_device.h>
# include <linux/input.h>
# include <linux/mfd/pcf50633/core.h>
# define PCF50633_OOCSTAT_ONKEY 0x01
# define PCF50633_REG_OOCSTAT 0x12
# define PCF50633_REG_OOCMODE 0x10
struct pcf50633_input {
struct pcf50633 * pcf ;
struct input_dev * input_dev ;
} ;
static void
pcf50633_input_irq ( int irq , void * data )
{
struct pcf50633_input * input ;
int onkey_released ;
input = data ;
/* We report only one event depending on the key press status */
onkey_released = pcf50633_reg_read ( input - > pcf , PCF50633_REG_OOCSTAT )
& PCF50633_OOCSTAT_ONKEY ;
if ( irq = = PCF50633_IRQ_ONKEYF & & ! onkey_released )
input_report_key ( input - > input_dev , KEY_POWER , 1 ) ;
else if ( irq = = PCF50633_IRQ_ONKEYR & & onkey_released )
input_report_key ( input - > input_dev , KEY_POWER , 0 ) ;
input_sync ( input - > input_dev ) ;
}
static int __devinit pcf50633_input_probe ( struct platform_device * pdev )
{
struct pcf50633_input * input ;
struct input_dev * input_dev ;
int ret ;
input = kzalloc ( sizeof ( * input ) , GFP_KERNEL ) ;
if ( ! input )
return - ENOMEM ;
input_dev = input_allocate_device ( ) ;
if ( ! input_dev ) {
kfree ( input ) ;
return - ENOMEM ;
}
platform_set_drvdata ( pdev , input ) ;
2009-10-14 02:12:33 +04:00
input - > pcf = dev_to_pcf50633 ( pdev - > dev . parent ) ;
2009-01-09 01:50:58 +01:00
input - > input_dev = input_dev ;
input_dev - > name = " PCF50633 PMU events " ;
input_dev - > id . bustype = BUS_I2C ;
input_dev - > evbit [ 0 ] = BIT ( EV_KEY ) | BIT ( EV_PWR ) ;
set_bit ( KEY_POWER , input_dev - > keybit ) ;
ret = input_register_device ( input_dev ) ;
if ( ret ) {
input_free_device ( input_dev ) ;
kfree ( input ) ;
return ret ;
}
2009-10-14 02:12:33 +04:00
pcf50633_register_irq ( input - > pcf , PCF50633_IRQ_ONKEYR ,
2009-01-09 01:50:58 +01:00
pcf50633_input_irq , input ) ;
2009-10-14 02:12:33 +04:00
pcf50633_register_irq ( input - > pcf , PCF50633_IRQ_ONKEYF ,
2009-01-09 01:50:58 +01:00
pcf50633_input_irq , input ) ;
return 0 ;
}
static int __devexit pcf50633_input_remove ( struct platform_device * pdev )
{
struct pcf50633_input * input = platform_get_drvdata ( pdev ) ;
pcf50633_free_irq ( input - > pcf , PCF50633_IRQ_ONKEYR ) ;
pcf50633_free_irq ( input - > pcf , PCF50633_IRQ_ONKEYF ) ;
input_unregister_device ( input - > input_dev ) ;
kfree ( input ) ;
return 0 ;
}
static struct platform_driver pcf50633_input_driver = {
. driver = {
. name = " pcf50633-input " ,
} ,
. probe = pcf50633_input_probe ,
. remove = __devexit_p ( pcf50633_input_remove ) ,
} ;
static int __init pcf50633_input_init ( void )
{
return platform_driver_register ( & pcf50633_input_driver ) ;
}
module_init ( pcf50633_input_init ) ;
static void __exit pcf50633_input_exit ( void )
{
platform_driver_unregister ( & pcf50633_input_driver ) ;
}
module_exit ( pcf50633_input_exit ) ;
MODULE_AUTHOR ( " Balaji Rao <balajirrao@openmoko.org> " ) ;
MODULE_DESCRIPTION ( " PCF50633 input driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:pcf50633-input " ) ;