2012-02-28 01:51:40 -03:00
/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/gpio.h>
# include <linux/slab.h>
2013-10-18 00:07:15 -03:00
# include <linux/of.h>
2013-02-08 18:47:30 -03:00
# include <linux/of_gpio.h>
2012-02-28 01:51:40 -03:00
# include <linux/platform_device.h>
# include <linux/irq.h>
# include <media/rc-core.h>
# define GPIO_IR_DEVICE_NAME "gpio_ir_recv"
struct gpio_rc_dev {
struct rc_dev * rcdev ;
2012-03-10 04:58:18 -03:00
int gpio_nr ;
2012-02-28 01:51:40 -03:00
bool active_low ;
} ;
static irqreturn_t gpio_ir_recv_irq ( int irq , void * dev_id )
{
struct gpio_rc_dev * gpio_dev = dev_id ;
2012-03-10 04:58:18 -03:00
int gval ;
2012-02-28 01:51:40 -03:00
int rc = 0 ;
2015-06-02 11:43:50 -03:00
gval = gpio_get_value ( gpio_dev - > gpio_nr ) ;
2012-02-28 01:51:40 -03:00
if ( gval < 0 )
goto err_get_value ;
if ( gpio_dev - > active_low )
gval = ! gval ;
2017-08-07 08:38:10 -04:00
rc = ir_raw_event_store_edge ( gpio_dev - > rcdev , gval = = 1 ) ;
2012-02-28 01:51:40 -03:00
if ( rc < 0 )
goto err_get_value ;
err_get_value :
return IRQ_HANDLED ;
}
2012-12-21 13:17:53 -08:00
static int gpio_ir_recv_probe ( struct platform_device * pdev )
2012-02-28 01:51:40 -03:00
{
2017-09-07 20:34:35 -03:00
struct device * dev = & pdev - > dev ;
2017-09-07 20:39:45 -03:00
struct device_node * np = dev - > of_node ;
2012-02-28 01:51:40 -03:00
struct gpio_rc_dev * gpio_dev ;
2017-09-07 20:39:45 -03:00
enum of_gpio_flags flags ;
2012-02-28 01:51:40 -03:00
struct rc_dev * rcdev ;
int rc ;
2017-09-07 20:39:45 -03:00
if ( ! np )
return - ENODEV ;
2012-02-28 01:51:40 -03:00
2017-09-07 20:35:22 -03:00
gpio_dev = devm_kzalloc ( dev , sizeof ( * gpio_dev ) , GFP_KERNEL ) ;
2012-02-28 01:51:40 -03:00
if ( ! gpio_dev )
return - ENOMEM ;
2017-09-07 20:39:45 -03:00
rc = of_get_gpio_flags ( np , 0 , & flags ) ;
if ( rc < 0 ) {
if ( rc ! = - EPROBE_DEFER )
dev_err ( dev , " Failed to get gpio flags (%d) \n " , rc ) ;
return rc ;
}
gpio_dev - > gpio_nr = rc ;
gpio_dev - > active_low = ( flags & OF_GPIO_ACTIVE_LOW ) ;
2017-09-07 20:36:11 -03:00
rcdev = devm_rc_allocate_device ( dev , RC_DRIVER_IR_RAW ) ;
2017-09-07 20:35:22 -03:00
if ( ! rcdev )
return - ENOMEM ;
2012-02-28 01:51:40 -03:00
2012-06-18 15:02:20 -03:00
rcdev - > priv = gpio_dev ;
2017-07-01 12:13:19 -04:00
rcdev - > device_name = GPIO_IR_DEVICE_NAME ;
2012-06-18 15:02:20 -03:00
rcdev - > input_phys = GPIO_IR_DEVICE_NAME " /input0 " ;
2012-02-28 01:51:40 -03:00
rcdev - > input_id . bustype = BUS_HOST ;
2012-06-18 15:02:20 -03:00
rcdev - > input_id . vendor = 0x0001 ;
rcdev - > input_id . product = 0x0001 ;
rcdev - > input_id . version = 0x0100 ;
2017-09-07 20:34:35 -03:00
rcdev - > dev . parent = dev ;
2017-09-07 20:39:14 -03:00
rcdev - > driver_name = KBUILD_MODNAME ;
2017-01-26 14:37:33 -02:00
rcdev - > min_timeout = 1 ;
2015-09-23 11:07:08 -03:00
rcdev - > timeout = IR_DEFAULT_TIMEOUT ;
rcdev - > max_timeout = 10 * IR_DEFAULT_TIMEOUT ;
2017-09-07 20:39:45 -03:00
rcdev - > allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER ;
rcdev - > map_name = of_get_property ( np , " linux,rc-map-name " , NULL ) ;
if ( ! rcdev - > map_name )
rcdev - > map_name = RC_MAP_EMPTY ;
2012-02-28 01:51:40 -03:00
gpio_dev - > rcdev = rcdev ;
2017-09-07 20:39:45 -03:00
rc = devm_gpio_request_one ( dev , gpio_dev - > gpio_nr , GPIOF_DIR_IN ,
2017-09-07 20:36:39 -03:00
" gpio-ir-recv " ) ;
2012-02-28 01:51:40 -03:00
if ( rc < 0 )
2017-09-07 20:36:11 -03:00
return rc ;
2012-02-28 01:51:40 -03:00
2017-09-07 20:37:07 -03:00
rc = devm_rc_register_device ( dev , rcdev ) ;
2012-02-28 01:51:40 -03:00
if ( rc < 0 ) {
2017-09-07 20:34:35 -03:00
dev_err ( dev , " failed to register rc device (%d) \n " , rc ) ;
2017-09-07 20:37:07 -03:00
return rc ;
2012-02-28 01:51:40 -03:00
}
platform_set_drvdata ( pdev , gpio_dev ) ;
2017-09-07 20:39:45 -03:00
return devm_request_irq ( dev , gpio_to_irq ( gpio_dev - > gpio_nr ) ,
2017-09-07 20:38:20 -03:00
gpio_ir_recv_irq ,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING ,
" gpio-ir-recv-irq " , gpio_dev ) ;
2012-02-28 01:51:40 -03:00
}
# ifdef CONFIG_PM
static int gpio_ir_recv_suspend ( struct device * dev )
{
struct platform_device * pdev = to_platform_device ( dev ) ;
struct gpio_rc_dev * gpio_dev = platform_get_drvdata ( pdev ) ;
if ( device_may_wakeup ( dev ) )
enable_irq_wake ( gpio_to_irq ( gpio_dev - > gpio_nr ) ) ;
else
disable_irq ( gpio_to_irq ( gpio_dev - > gpio_nr ) ) ;
return 0 ;
}
static int gpio_ir_recv_resume ( struct device * dev )
{
struct platform_device * pdev = to_platform_device ( dev ) ;
struct gpio_rc_dev * gpio_dev = platform_get_drvdata ( pdev ) ;
if ( device_may_wakeup ( dev ) )
disable_irq_wake ( gpio_to_irq ( gpio_dev - > gpio_nr ) ) ;
else
enable_irq ( gpio_to_irq ( gpio_dev - > gpio_nr ) ) ;
return 0 ;
}
static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
. suspend = gpio_ir_recv_suspend ,
. resume = gpio_ir_recv_resume ,
} ;
# endif
2017-09-07 20:39:45 -03:00
static const struct of_device_id gpio_ir_recv_of_match [ ] = {
{ . compatible = " gpio-ir-receiver " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , gpio_ir_recv_of_match ) ;
2012-02-28 01:51:40 -03:00
static struct platform_driver gpio_ir_recv_driver = {
. probe = gpio_ir_recv_probe ,
. driver = {
2017-09-07 20:39:14 -03:00
. name = KBUILD_MODNAME ,
2013-02-08 18:47:30 -03:00
. of_match_table = of_match_ptr ( gpio_ir_recv_of_match ) ,
2012-02-28 01:51:40 -03:00
# ifdef CONFIG_PM
. pm = & gpio_ir_recv_pm_ops ,
# endif
} ,
} ;
2012-06-18 15:03:06 -03:00
module_platform_driver ( gpio_ir_recv_driver ) ;
2012-02-28 01:51:40 -03:00
MODULE_DESCRIPTION ( " GPIO IR Receiver driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;