diff options
Diffstat (limited to 'drivers/media/rc/gpio-ir-recv.c')
-rw-r--r-- | drivers/media/rc/gpio-ir-recv.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 4f71a7d1f019..8b82ae9bd686 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/of_gpio.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
21 | #include <media/rc-core.h> | 22 | #include <media/rc-core.h> |
@@ -30,6 +31,45 @@ struct gpio_rc_dev { | |||
30 | bool active_low; | 31 | bool active_low; |
31 | }; | 32 | }; |
32 | 33 | ||
34 | #ifdef CONFIG_OF | ||
35 | /* | ||
36 | * Translate OpenFirmware node properties into platform_data | ||
37 | */ | ||
38 | static int gpio_ir_recv_get_devtree_pdata(struct device *dev, | ||
39 | struct gpio_ir_recv_platform_data *pdata) | ||
40 | { | ||
41 | struct device_node *np = dev->of_node; | ||
42 | enum of_gpio_flags flags; | ||
43 | int gpio; | ||
44 | |||
45 | gpio = of_get_gpio_flags(np, 0, &flags); | ||
46 | if (gpio < 0) { | ||
47 | if (gpio != -EPROBE_DEFER) | ||
48 | dev_err(dev, "Failed to get gpio flags (%d)\n", gpio); | ||
49 | return gpio; | ||
50 | } | ||
51 | |||
52 | pdata->gpio_nr = gpio; | ||
53 | pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW); | ||
54 | /* probe() takes care of map_name == NULL or allowed_protos == 0 */ | ||
55 | pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL); | ||
56 | pdata->allowed_protos = 0; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static struct of_device_id gpio_ir_recv_of_match[] = { | ||
62 | { .compatible = "gpio-ir-receiver", }, | ||
63 | { }, | ||
64 | }; | ||
65 | MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); | ||
66 | |||
67 | #else /* !CONFIG_OF */ | ||
68 | |||
69 | #define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS) | ||
70 | |||
71 | #endif | ||
72 | |||
33 | static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) | 73 | static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) |
34 | { | 74 | { |
35 | struct gpio_rc_dev *gpio_dev = dev_id; | 75 | struct gpio_rc_dev *gpio_dev = dev_id; |
@@ -66,6 +106,17 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) | |||
66 | pdev->dev.platform_data; | 106 | pdev->dev.platform_data; |
67 | int rc; | 107 | int rc; |
68 | 108 | ||
109 | if (pdev->dev.of_node) { | ||
110 | struct gpio_ir_recv_platform_data *dtpdata = | ||
111 | devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL); | ||
112 | if (!dtpdata) | ||
113 | return -ENOMEM; | ||
114 | rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata); | ||
115 | if (rc) | ||
116 | return rc; | ||
117 | pdata = dtpdata; | ||
118 | } | ||
119 | |||
69 | if (!pdata) | 120 | if (!pdata) |
70 | return -EINVAL; | 121 | return -EINVAL; |
71 | 122 | ||
@@ -129,12 +180,12 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) | |||
129 | err_request_irq: | 180 | err_request_irq: |
130 | platform_set_drvdata(pdev, NULL); | 181 | platform_set_drvdata(pdev, NULL); |
131 | rc_unregister_device(rcdev); | 182 | rc_unregister_device(rcdev); |
183 | rcdev = NULL; | ||
132 | err_register_rc_device: | 184 | err_register_rc_device: |
133 | err_gpio_direction_input: | 185 | err_gpio_direction_input: |
134 | gpio_free(pdata->gpio_nr); | 186 | gpio_free(pdata->gpio_nr); |
135 | err_gpio_request: | 187 | err_gpio_request: |
136 | rc_free_device(rcdev); | 188 | rc_free_device(rcdev); |
137 | rcdev = NULL; | ||
138 | err_allocate_device: | 189 | err_allocate_device: |
139 | kfree(gpio_dev); | 190 | kfree(gpio_dev); |
140 | return rc; | 191 | return rc; |
@@ -148,7 +199,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) | |||
148 | platform_set_drvdata(pdev, NULL); | 199 | platform_set_drvdata(pdev, NULL); |
149 | rc_unregister_device(gpio_dev->rcdev); | 200 | rc_unregister_device(gpio_dev->rcdev); |
150 | gpio_free(gpio_dev->gpio_nr); | 201 | gpio_free(gpio_dev->gpio_nr); |
151 | rc_free_device(gpio_dev->rcdev); | ||
152 | kfree(gpio_dev); | 202 | kfree(gpio_dev); |
153 | return 0; | 203 | return 0; |
154 | } | 204 | } |
@@ -192,6 +242,7 @@ static struct platform_driver gpio_ir_recv_driver = { | |||
192 | .driver = { | 242 | .driver = { |
193 | .name = GPIO_IR_DRIVER_NAME, | 243 | .name = GPIO_IR_DRIVER_NAME, |
194 | .owner = THIS_MODULE, | 244 | .owner = THIS_MODULE, |
245 | .of_match_table = of_match_ptr(gpio_ir_recv_of_match), | ||
195 | #ifdef CONFIG_PM | 246 | #ifdef CONFIG_PM |
196 | .pm = &gpio_ir_recv_pm_ops, | 247 | .pm = &gpio_ir_recv_pm_ops, |
197 | #endif | 248 | #endif |