2019-05-29 07:17:58 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-02-28 01:51:40 -03:00
/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/interrupt.h>
2017-10-05 09:11:06 -03:00
# include <linux/gpio/consumer.h>
2012-02-28 01:51:40 -03:00
# 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 ;
2017-09-07 20:41:32 -03:00
struct gpio_desc * gpiod ;
int irq ;
2012-02-28 01:51:40 -03:00
} ;
static irqreturn_t gpio_ir_recv_irq ( int irq , void * dev_id )
{
2017-09-07 20:41:32 -03:00
int val ;
2012-02-28 01:51:40 -03:00
struct gpio_rc_dev * gpio_dev = dev_id ;
2017-09-07 20:41:32 -03:00
val = gpiod_get_value ( gpio_dev - > gpiod ) ;
if ( val > = 0 )
ir_raw_event_store_edge ( gpio_dev - > rcdev , val = = 1 ) ;
2012-02-28 01:51:40 -03:00
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 ;
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:41:32 -03:00
gpio_dev - > gpiod = devm_gpiod_get ( dev , NULL , GPIOD_IN ) ;
if ( IS_ERR ( gpio_dev - > gpiod ) ) {
rc = PTR_ERR ( gpio_dev - > gpiod ) ;
/* Just try again if this happens */
2017-09-07 20:39:45 -03:00
if ( rc ! = - EPROBE_DEFER )
2017-09-07 20:41:32 -03:00
dev_err ( dev , " error getting gpio (%d) \n " , rc ) ;
2017-09-07 20:39:45 -03:00
return rc ;
}
2017-09-07 20:41:32 -03:00
gpio_dev - > irq = gpiod_to_irq ( gpio_dev - > gpiod ) ;
if ( gpio_dev - > irq < 0 )
return gpio_dev - > irq ;
2017-09-07 20:39:45 -03:00
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: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:41:32 -03:00
return devm_request_irq ( dev , gpio_dev - > irq , gpio_ir_recv_irq ,
2017-09-07 20:38:20 -03:00
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 )
{
2017-09-07 20:41:32 -03:00
struct gpio_rc_dev * gpio_dev = dev_get_drvdata ( dev ) ;
2012-02-28 01:51:40 -03:00
if ( device_may_wakeup ( dev ) )
2017-09-07 20:41:32 -03:00
enable_irq_wake ( gpio_dev - > irq ) ;
2012-02-28 01:51:40 -03:00
else
2017-09-07 20:41:32 -03:00
disable_irq ( gpio_dev - > irq ) ;
2012-02-28 01:51:40 -03:00
return 0 ;
}
static int gpio_ir_recv_resume ( struct device * dev )
{
2017-09-07 20:41:32 -03:00
struct gpio_rc_dev * gpio_dev = dev_get_drvdata ( dev ) ;
2012-02-28 01:51:40 -03:00
if ( device_may_wakeup ( dev ) )
2017-09-07 20:41:32 -03:00
disable_irq_wake ( gpio_dev - > irq ) ;
2012-02-28 01:51:40 -03:00
else
2017-09-07 20:41:32 -03:00
enable_irq ( gpio_dev - > irq ) ;
2012-02-28 01:51:40 -03:00
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 " ) ;