Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / rc / gpio-ir-recv.c
1 /* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/interrupt.h>
17 #include <linux/gpio.h>
18 #include <linux/slab.h>
19 #include <linux/of.h>
20 #include <linux/of_gpio.h>
21 #include <linux/platform_device.h>
22 #include <linux/irq.h>
23 #include <media/rc-core.h>
24 #include <media/gpio-ir-recv.h>
25
26 #define GPIO_IR_DRIVER_NAME     "gpio-rc-recv"
27 #define GPIO_IR_DEVICE_NAME     "gpio_ir_recv"
28
29 struct gpio_rc_dev {
30         struct rc_dev *rcdev;
31         int gpio_nr;
32         bool active_low;
33 };
34
35 #ifdef CONFIG_OF
36 /*
37  * Translate OpenFirmware node properties into platform_data
38  */
39 static int gpio_ir_recv_get_devtree_pdata(struct device *dev,
40                                   struct gpio_ir_recv_platform_data *pdata)
41 {
42         struct device_node *np = dev->of_node;
43         enum of_gpio_flags flags;
44         int gpio;
45
46         gpio = of_get_gpio_flags(np, 0, &flags);
47         if (gpio < 0) {
48                 if (gpio != -EPROBE_DEFER)
49                         dev_err(dev, "Failed to get gpio flags (%d)\n", gpio);
50                 return gpio;
51         }
52
53         pdata->gpio_nr = gpio;
54         pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW);
55         /* probe() takes care of map_name == NULL or allowed_protos == 0 */
56         pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL);
57         pdata->allowed_protos = 0;
58
59         return 0;
60 }
61
62 static struct of_device_id gpio_ir_recv_of_match[] = {
63         { .compatible = "gpio-ir-receiver", },
64         { },
65 };
66 MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);
67
68 #else /* !CONFIG_OF */
69
70 #define gpio_ir_recv_get_devtree_pdata(dev, pdata)      (-ENOSYS)
71
72 #endif
73
74 static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
75 {
76         struct gpio_rc_dev *gpio_dev = dev_id;
77         int gval;
78         int rc = 0;
79         enum raw_event_type type = IR_SPACE;
80
81         gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
82
83         if (gval < 0)
84                 goto err_get_value;
85
86         if (gpio_dev->active_low)
87                 gval = !gval;
88
89         if (gval == 1)
90                 type = IR_PULSE;
91
92         rc = ir_raw_event_store_edge(gpio_dev->rcdev, type);
93         if (rc < 0)
94                 goto err_get_value;
95
96         ir_raw_event_handle(gpio_dev->rcdev);
97
98 err_get_value:
99         return IRQ_HANDLED;
100 }
101
102 static int gpio_ir_recv_probe(struct platform_device *pdev)
103 {
104         struct gpio_rc_dev *gpio_dev;
105         struct rc_dev *rcdev;
106         const struct gpio_ir_recv_platform_data *pdata =
107                                         pdev->dev.platform_data;
108         int rc;
109
110         if (pdev->dev.of_node) {
111                 struct gpio_ir_recv_platform_data *dtpdata =
112                         devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL);
113                 if (!dtpdata)
114                         return -ENOMEM;
115                 rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata);
116                 if (rc)
117                         return rc;
118                 pdata = dtpdata;
119         }
120
121         if (!pdata)
122                 return -EINVAL;
123
124         if (pdata->gpio_nr < 0)
125                 return -EINVAL;
126
127         gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);
128         if (!gpio_dev)
129                 return -ENOMEM;
130
131         rcdev = rc_allocate_device();
132         if (!rcdev) {
133                 rc = -ENOMEM;
134                 goto err_allocate_device;
135         }
136
137         rcdev->priv = gpio_dev;
138         rcdev->driver_type = RC_DRIVER_IR_RAW;
139         rcdev->input_name = GPIO_IR_DEVICE_NAME;
140         rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
141         rcdev->input_id.bustype = BUS_HOST;
142         rcdev->input_id.vendor = 0x0001;
143         rcdev->input_id.product = 0x0001;
144         rcdev->input_id.version = 0x0100;
145         rcdev->dev.parent = &pdev->dev;
146         rcdev->driver_name = GPIO_IR_DRIVER_NAME;
147         if (pdata->allowed_protos)
148                 rcdev->allowed_protocols = pdata->allowed_protos;
149         else
150                 rcdev->allowed_protocols = RC_BIT_ALL;
151         rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
152
153         gpio_dev->rcdev = rcdev;
154         gpio_dev->gpio_nr = pdata->gpio_nr;
155         gpio_dev->active_low = pdata->active_low;
156
157         rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
158         if (rc < 0)
159                 goto err_gpio_request;
160         rc  = gpio_direction_input(pdata->gpio_nr);
161         if (rc < 0)
162                 goto err_gpio_direction_input;
163
164         rc = rc_register_device(rcdev);
165         if (rc < 0) {
166                 dev_err(&pdev->dev, "failed to register rc device\n");
167                 goto err_register_rc_device;
168         }
169
170         platform_set_drvdata(pdev, gpio_dev);
171
172         rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),
173                                 gpio_ir_recv_irq,
174                         IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
175                                         "gpio-ir-recv-irq", gpio_dev);
176         if (rc < 0)
177                 goto err_request_irq;
178
179         return 0;
180
181 err_request_irq:
182         rc_unregister_device(rcdev);
183         rcdev = NULL;
184 err_register_rc_device:
185 err_gpio_direction_input:
186         gpio_free(pdata->gpio_nr);
187 err_gpio_request:
188         rc_free_device(rcdev);
189 err_allocate_device:
190         kfree(gpio_dev);
191         return rc;
192 }
193
194 static int gpio_ir_recv_remove(struct platform_device *pdev)
195 {
196         struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
197
198         free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
199         rc_unregister_device(gpio_dev->rcdev);
200         gpio_free(gpio_dev->gpio_nr);
201         kfree(gpio_dev);
202         return 0;
203 }
204
205 #ifdef CONFIG_PM
206 static int gpio_ir_recv_suspend(struct device *dev)
207 {
208         struct platform_device *pdev = to_platform_device(dev);
209         struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
210
211         if (device_may_wakeup(dev))
212                 enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
213         else
214                 disable_irq(gpio_to_irq(gpio_dev->gpio_nr));
215
216         return 0;
217 }
218
219 static int gpio_ir_recv_resume(struct device *dev)
220 {
221         struct platform_device *pdev = to_platform_device(dev);
222         struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
223
224         if (device_may_wakeup(dev))
225                 disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
226         else
227                 enable_irq(gpio_to_irq(gpio_dev->gpio_nr));
228
229         return 0;
230 }
231
232 static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
233         .suspend        = gpio_ir_recv_suspend,
234         .resume         = gpio_ir_recv_resume,
235 };
236 #endif
237
238 static struct platform_driver gpio_ir_recv_driver = {
239         .probe  = gpio_ir_recv_probe,
240         .remove = gpio_ir_recv_remove,
241         .driver = {
242                 .name   = GPIO_IR_DRIVER_NAME,
243                 .of_match_table = of_match_ptr(gpio_ir_recv_of_match),
244 #ifdef CONFIG_PM
245                 .pm     = &gpio_ir_recv_pm_ops,
246 #endif
247         },
248 };
249 module_platform_driver(gpio_ir_recv_driver);
250
251 MODULE_DESCRIPTION("GPIO IR Receiver driver");
252 MODULE_LICENSE("GPL v2");