aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-18 18:08:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-18 18:08:02 -0500
commita310410f616c78f24490de1274487a7b7b137d97 (patch)
treedbc2fc187800e6e7014263bf83e10d0155620029 /drivers/media/rc
parentcdd278db0e3dd714e8076e58f723f3c59547591b (diff)
parent80f93c7b0f4599ffbdac8d964ecd1162b8b618b9 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "This series include: - a new Remote Controller driver for ST SoC with the corresponding DT bindings - a new frontend (cx24117) - a new I2C camera flash driver (lm3560) - a new mem2mem driver for TI SoC (ti-vpe) - support for Raphael r828d added to r820t driver - some improvements on buffer allocation at VB2 core - usual driver fixes and improvements PS this time, we have a smaller number of patches. While it is hard to pinpoint to the reasons, I believe that it is mainly due to: 1) there are several patch series ready, but depending on DT review. I decided to grant some extra time for DT maintainers to look on it, as they're expecting to have more time with the changes agreed during ARM mini-summit and KS. If they can't review in time for 3.14, I'll review myself and apply for the next merge window. 2) I suspect that having both LinuxCon EU and LinuxCon NA happening during the same merge window affected the development productivity, as several core media developers participated on both events" * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (151 commits) [media] media: st-rc: Add ST remote control driver [media] gpio-ir-recv: Include linux/of.h header [media] tvp7002: Include linux/of.h header [media] tvp514x: Include linux/of.h header [media] ths8200: Include linux/of.h header [media] adv7343: Include linux/of.h header [media] v4l: Fix typo in v4l2_subdev_get_try_crop() [media] media: i2c: add driver for dual LED Flash, lm3560 [media] rtl28xxu: add 15f4:0131 Astrometa DVB-T2 [media] rtl28xxu: add RTL2832P + R828D support [media] rtl2832: add new tuner R828D [media] r820t: add support for R828D [media] media/i2c: ths8200: fix build failure with gcc 4.5.4 [media] Add support for KWorld UB435-Q V2 [media] staging/media: fix msi3101 build errors [media] ddbridge: Remove casting the return value which is a void pointer [media] ngene: Remove casting the return value which is a void pointer [media] dm1105: remove unneeded not-null test [media] sh_mobile_ceu_camera: remove deprecated IRQF_DISABLED [media] media: rcar_vin: Add preliminary r8a7790 support ...
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/gpio-ir-recv.c1
-rw-r--r--drivers/media/rc/ir-rx51.c3
-rw-r--r--drivers/media/rc/st_rc.c395
-rw-r--r--drivers/media/rc/winbond-cir.c2
6 files changed, 409 insertions, 3 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 11e84bcc23a1..904f11367c29 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -322,4 +322,14 @@ config IR_GPIO_CIR
322 To compile this driver as a module, choose M here: the module will 322 To compile this driver as a module, choose M here: the module will
323 be called gpio-ir-recv. 323 be called gpio-ir-recv.
324 324
325config RC_ST
326 tristate "ST remote control receiver"
327 depends on ARCH_STI && RC_CORE
328 help
329 Say Y here if you want support for ST remote control driver
330 which allows both IR and UHF RX.
331 The driver passes raw pulse and space information to the LIRC decoder.
332
333 If you're not sure, select N here.
334
325endif #RC_DEVICES 335endif #RC_DEVICES
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 56bacf07b361..f4eb32c0a455 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
30obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o 30obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
31obj-$(CONFIG_IR_IGUANA) += iguanair.o 31obj-$(CONFIG_IR_IGUANA) += iguanair.o
32obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o 32obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
33obj-$(CONFIG_RC_ST) += st_rc.o
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 07aacfa5903d..80c611c2e8c2 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.h>
19#include <linux/of_gpio.h> 20#include <linux/of_gpio.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/irq.h> 22#include <linux/irq.h>
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 31b955bf7664..b1e19a26208d 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -201,8 +201,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
201 201
202 lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer); 202 lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
203 retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler, 203 retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
204 IRQF_DISABLED | IRQF_SHARED, 204 IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
205 "lirc_pulse_timer", lirc_rx51);
206 if (retval) { 205 if (retval) {
207 dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n"); 206 dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
208 goto err2; 207 goto err2;
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
new file mode 100644
index 000000000000..65120c2d47ad
--- /dev/null
+++ b/drivers/media/rc/st_rc.c
@@ -0,0 +1,395 @@
1/*
2 * Copyright (C) 2013 STMicroelectronics Limited
3 * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10#include <linux/kernel.h>
11#include <linux/clk.h>
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/of.h>
15#include <linux/platform_device.h>
16#include <media/rc-core.h>
17#include <linux/pinctrl/consumer.h>
18
19struct st_rc_device {
20 struct device *dev;
21 int irq;
22 int irq_wake;
23 struct clk *sys_clock;
24 void *base; /* Register base address */
25 void *rx_base;/* RX Register base address */
26 struct rc_dev *rdev;
27 bool overclocking;
28 int sample_mult;
29 int sample_div;
30 bool rxuhfmode;
31};
32
33/* Registers */
34#define IRB_SAMPLE_RATE_COMM 0x64 /* sample freq divisor*/
35#define IRB_CLOCK_SEL 0x70 /* clock select */
36#define IRB_CLOCK_SEL_STATUS 0x74 /* clock status */
37/* IRB IR/UHF receiver registers */
38#define IRB_RX_ON 0x40 /* pulse time capture */
39#define IRB_RX_SYS 0X44 /* sym period capture */
40#define IRB_RX_INT_EN 0x48 /* IRQ enable (R/W) */
41#define IRB_RX_INT_STATUS 0x4c /* IRQ status (R/W) */
42#define IRB_RX_EN 0x50 /* Receive enable */
43#define IRB_MAX_SYM_PERIOD 0x54 /* max sym value */
44#define IRB_RX_INT_CLEAR 0x58 /* overrun status */
45#define IRB_RX_STATUS 0x6c /* receive status */
46#define IRB_RX_NOISE_SUPPR 0x5c /* noise suppression */
47#define IRB_RX_POLARITY_INV 0x68 /* polarity inverter */
48
49/**
50 * IRQ set: Enable full FIFO 1 -> bit 3;
51 * Enable overrun IRQ 1 -> bit 2;
52 * Enable last symbol IRQ 1 -> bit 1:
53 * Enable RX interrupt 1 -> bit 0;
54 */
55#define IRB_RX_INTS 0x0f
56#define IRB_RX_OVERRUN_INT 0x04
57 /* maximum symbol period (microsecs),timeout to detect end of symbol train */
58#define MAX_SYMB_TIME 0x5000
59#define IRB_SAMPLE_FREQ 10000000
60#define IRB_FIFO_NOT_EMPTY 0xff00
61#define IRB_OVERFLOW 0x4
62#define IRB_TIMEOUT 0xffff
63#define IR_ST_NAME "st-rc"
64
65static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
66{
67 DEFINE_IR_RAW_EVENT(ev);
68 ev.timeout = true;
69 ir_raw_event_store(rdev, &ev);
70}
71
72/**
73 * RX graphical example to better understand the difference between ST IR block
74 * output and standard definition used by LIRC (and most of the world!)
75 *
76 * mark mark
77 * |-IRB_RX_ON-| |-IRB_RX_ON-|
78 * ___ ___ ___ ___ ___ ___ _
79 * | | | | | | | | | | | | |
80 * | | | | | | space 0 | | | | | | space 1 |
81 * _____| |__| |__| |____________________________| |__| |__| |_____________|
82 *
83 * |--------------- IRB_RX_SYS -------------|------ IRB_RX_SYS -------|
84 *
85 * |------------- encoding bit 0 -----------|---- encoding bit 1 -----|
86 *
87 * ST hardware returns mark (IRB_RX_ON) and total symbol time (IRB_RX_SYS), so
88 * convert to standard mark/space we have to calculate space=(IRB_RX_SYS-mark)
89 * The mark time represents the amount of time the carrier (usually 36-40kHz)
90 * is detected.The above examples shows Pulse Width Modulation encoding where
91 * bit 0 is represented by space>mark.
92 */
93
94static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
95{
96 unsigned int symbol, mark = 0;
97 struct st_rc_device *dev = data;
98 int last_symbol = 0;
99 u32 status;
100 DEFINE_IR_RAW_EVENT(ev);
101
102 if (dev->irq_wake)
103 pm_wakeup_event(dev->dev, 0);
104
105 status = readl(dev->rx_base + IRB_RX_STATUS);
106
107 while (status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)) {
108 u32 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
109 if (unlikely(int_status & IRB_RX_OVERRUN_INT)) {
110 /* discard the entire collection in case of errors! */
111 ir_raw_event_reset(dev->rdev);
112 dev_info(dev->dev, "IR RX overrun\n");
113 writel(IRB_RX_OVERRUN_INT,
114 dev->rx_base + IRB_RX_INT_CLEAR);
115 continue;
116 }
117
118 symbol = readl(dev->rx_base + IRB_RX_SYS);
119 mark = readl(dev->rx_base + IRB_RX_ON);
120
121 if (symbol == IRB_TIMEOUT)
122 last_symbol = 1;
123
124 /* Ignore any noise */
125 if ((mark > 2) && (symbol > 1)) {
126 symbol -= mark;
127 if (dev->overclocking) { /* adjustments to timings */
128 symbol *= dev->sample_mult;
129 symbol /= dev->sample_div;
130 mark *= dev->sample_mult;
131 mark /= dev->sample_div;
132 }
133
134 ev.duration = US_TO_NS(mark);
135 ev.pulse = true;
136 ir_raw_event_store(dev->rdev, &ev);
137
138 if (!last_symbol) {
139 ev.duration = US_TO_NS(symbol);
140 ev.pulse = false;
141 ir_raw_event_store(dev->rdev, &ev);
142 } else {
143 st_rc_send_lirc_timeout(dev->rdev);
144 }
145
146 }
147 last_symbol = 0;
148 status = readl(dev->rx_base + IRB_RX_STATUS);
149 }
150
151 writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR);
152
153 /* Empty software fifo */
154 ir_raw_event_handle(dev->rdev);
155 return IRQ_HANDLED;
156}
157
158static void st_rc_hardware_init(struct st_rc_device *dev)
159{
160 int baseclock, freqdiff;
161 unsigned int rx_max_symbol_per = MAX_SYMB_TIME;
162 unsigned int rx_sampling_freq_div;
163
164 clk_prepare_enable(dev->sys_clock);
165 baseclock = clk_get_rate(dev->sys_clock);
166
167 /* IRB input pins are inverted internally from high to low. */
168 writel(1, dev->rx_base + IRB_RX_POLARITY_INV);
169
170 rx_sampling_freq_div = baseclock / IRB_SAMPLE_FREQ;
171 writel(rx_sampling_freq_div, dev->base + IRB_SAMPLE_RATE_COMM);
172
173 freqdiff = baseclock - (rx_sampling_freq_div * IRB_SAMPLE_FREQ);
174 if (freqdiff) { /* over clocking, workout the adjustment factors */
175 dev->overclocking = true;
176 dev->sample_mult = 1000;
177 dev->sample_div = baseclock / (10000 * rx_sampling_freq_div);
178 rx_max_symbol_per = (rx_max_symbol_per * 1000)/dev->sample_div;
179 }
180
181 writel(rx_max_symbol_per, dev->rx_base + IRB_MAX_SYM_PERIOD);
182}
183
184static int st_rc_remove(struct platform_device *pdev)
185{
186 struct st_rc_device *rc_dev = platform_get_drvdata(pdev);
187 clk_disable_unprepare(rc_dev->sys_clock);
188 rc_unregister_device(rc_dev->rdev);
189 return 0;
190}
191
192static int st_rc_open(struct rc_dev *rdev)
193{
194 struct st_rc_device *dev = rdev->priv;
195 unsigned long flags;
196 local_irq_save(flags);
197 /* enable interrupts and receiver */
198 writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_EN);
199 writel(0x01, dev->rx_base + IRB_RX_EN);
200 local_irq_restore(flags);
201
202 return 0;
203}
204
205static void st_rc_close(struct rc_dev *rdev)
206{
207 struct st_rc_device *dev = rdev->priv;
208 /* disable interrupts and receiver */
209 writel(0x00, dev->rx_base + IRB_RX_EN);
210 writel(0x00, dev->rx_base + IRB_RX_INT_EN);
211}
212
213static int st_rc_probe(struct platform_device *pdev)
214{
215 int ret = -EINVAL;
216 struct rc_dev *rdev;
217 struct device *dev = &pdev->dev;
218 struct resource *res;
219 struct st_rc_device *rc_dev;
220 struct device_node *np = pdev->dev.of_node;
221 const char *rx_mode;
222
223 rc_dev = devm_kzalloc(dev, sizeof(struct st_rc_device), GFP_KERNEL);
224
225 if (!rc_dev)
226 return -ENOMEM;
227
228 rdev = rc_allocate_device();
229
230 if (!rdev)
231 return -ENOMEM;
232
233 if (np && !of_property_read_string(np, "rx-mode", &rx_mode)) {
234
235 if (!strcmp(rx_mode, "uhf")) {
236 rc_dev->rxuhfmode = true;
237 } else if (!strcmp(rx_mode, "infrared")) {
238 rc_dev->rxuhfmode = false;
239 } else {
240 dev_err(dev, "Unsupported rx mode [%s]\n", rx_mode);
241 goto err;
242 }
243
244 } else {
245 goto err;
246 }
247
248 rc_dev->sys_clock = devm_clk_get(dev, NULL);
249 if (IS_ERR(rc_dev->sys_clock)) {
250 dev_err(dev, "System clock not found\n");
251 ret = PTR_ERR(rc_dev->sys_clock);
252 goto err;
253 }
254
255 rc_dev->irq = platform_get_irq(pdev, 0);
256 if (rc_dev->irq < 0) {
257 ret = rc_dev->irq;
258 goto err;
259 }
260
261 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
262
263 rc_dev->base = devm_ioremap_resource(dev, res);
264 if (IS_ERR(rc_dev->base)) {
265 ret = PTR_ERR(rc_dev->base);
266 goto err;
267 }
268
269 if (rc_dev->rxuhfmode)
270 rc_dev->rx_base = rc_dev->base + 0x40;
271 else
272 rc_dev->rx_base = rc_dev->base;
273
274 rc_dev->dev = dev;
275 platform_set_drvdata(pdev, rc_dev);
276 st_rc_hardware_init(rc_dev);
277
278 rdev->driver_type = RC_DRIVER_IR_RAW;
279 rdev->allowed_protos = RC_BIT_ALL;
280 /* rx sampling rate is 10Mhz */
281 rdev->rx_resolution = 100;
282 rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
283 rdev->priv = rc_dev;
284 rdev->open = st_rc_open;
285 rdev->close = st_rc_close;
286 rdev->driver_name = IR_ST_NAME;
287 rdev->map_name = RC_MAP_LIRC;
288 rdev->input_name = "ST Remote Control Receiver";
289
290 /* enable wake via this device */
291 device_set_wakeup_capable(dev, true);
292 device_set_wakeup_enable(dev, true);
293
294 ret = rc_register_device(rdev);
295 if (ret < 0)
296 goto clkerr;
297
298 rc_dev->rdev = rdev;
299 if (devm_request_irq(dev, rc_dev->irq, st_rc_rx_interrupt,
300 IRQF_NO_SUSPEND, IR_ST_NAME, rc_dev) < 0) {
301 dev_err(dev, "IRQ %d register failed\n", rc_dev->irq);
302 ret = -EINVAL;
303 goto rcerr;
304 }
305
306 /**
307 * for LIRC_MODE_MODE2 or LIRC_MODE_PULSE or LIRC_MODE_RAW
308 * lircd expects a long space first before a signal train to sync.
309 */
310 st_rc_send_lirc_timeout(rdev);
311
312 dev_info(dev, "setup in %s mode\n", rc_dev->rxuhfmode ? "UHF" : "IR");
313
314 return ret;
315rcerr:
316 rc_unregister_device(rdev);
317 rdev = NULL;
318clkerr:
319 clk_disable_unprepare(rc_dev->sys_clock);
320err:
321 rc_free_device(rdev);
322 dev_err(dev, "Unable to register device (%d)\n", ret);
323 return ret;
324}
325
326#ifdef CONFIG_PM
327static int st_rc_suspend(struct device *dev)
328{
329 struct st_rc_device *rc_dev = dev_get_drvdata(dev);
330
331 if (device_may_wakeup(dev)) {
332 if (!enable_irq_wake(rc_dev->irq))
333 rc_dev->irq_wake = 1;
334 else
335 return -EINVAL;
336 } else {
337 pinctrl_pm_select_sleep_state(dev);
338 writel(0x00, rc_dev->rx_base + IRB_RX_EN);
339 writel(0x00, rc_dev->rx_base + IRB_RX_INT_EN);
340 clk_disable_unprepare(rc_dev->sys_clock);
341 }
342
343 return 0;
344}
345
346static int st_rc_resume(struct device *dev)
347{
348 struct st_rc_device *rc_dev = dev_get_drvdata(dev);
349 struct rc_dev *rdev = rc_dev->rdev;
350
351 if (rc_dev->irq_wake) {
352 disable_irq_wake(rc_dev->irq);
353 rc_dev->irq_wake = 0;
354 } else {
355 pinctrl_pm_select_default_state(dev);
356 st_rc_hardware_init(rc_dev);
357 if (rdev->users) {
358 writel(IRB_RX_INTS, rc_dev->rx_base + IRB_RX_INT_EN);
359 writel(0x01, rc_dev->rx_base + IRB_RX_EN);
360 }
361 }
362
363 return 0;
364}
365
366static SIMPLE_DEV_PM_OPS(st_rc_pm_ops, st_rc_suspend, st_rc_resume);
367#endif
368
369#ifdef CONFIG_OF
370static struct of_device_id st_rc_match[] = {
371 { .compatible = "st,comms-irb", },
372 {},
373};
374
375MODULE_DEVICE_TABLE(of, st_rc_match);
376#endif
377
378static struct platform_driver st_rc_driver = {
379 .driver = {
380 .name = IR_ST_NAME,
381 .owner = THIS_MODULE,
382 .of_match_table = of_match_ptr(st_rc_match),
383#ifdef CONFIG_PM
384 .pm = &st_rc_pm_ops,
385#endif
386 },
387 .probe = st_rc_probe,
388 .remove = st_rc_remove,
389};
390
391module_platform_driver(st_rc_driver);
392
393MODULE_DESCRIPTION("RC Transceiver driver for STMicroelectronics platforms");
394MODULE_AUTHOR("STMicroelectronics (R&D) Ltd");
395MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 98bd4960c75e..904baf4eec28 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1110,7 +1110,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
1110 } 1110 }
1111 1111
1112 err = request_irq(data->irq, wbcir_irq_handler, 1112 err = request_irq(data->irq, wbcir_irq_handler,
1113 IRQF_DISABLED, DRVNAME, device); 1113 0, DRVNAME, device);
1114 if (err) { 1114 if (err) {
1115 dev_err(dev, "Failed to claim IRQ %u\n", data->irq); 1115 dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
1116 err = -EBUSY; 1116 err = -EBUSY;