Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
f59ad611 AW |
2 | /* |
3 | * Driver for the Conexant CX23885/7/8 PCIe bridge | |
4 | * | |
5 | * Infrared device support routines - non-input, non-vl42_subdev routines | |
6 | * | |
6afdeaf8 | 7 | * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> |
f59ad611 AW |
8 | */ |
9 | ||
f59ad611 | 10 | #include "cx23885.h" |
ada73eee | 11 | #include "cx23885-ir.h" |
dbda8f70 | 12 | #include "cx23885-input.h" |
f59ad611 | 13 | |
e39682b5 MCC |
14 | #include <media/v4l2-device.h> |
15 | ||
f59ad611 AW |
16 | #define CX23885_IR_RX_FIFO_SERVICE_REQ 0 |
17 | #define CX23885_IR_RX_END_OF_RX_DETECTED 1 | |
18 | #define CX23885_IR_RX_HW_FIFO_OVERRUN 2 | |
19 | #define CX23885_IR_RX_SW_FIFO_OVERRUN 3 | |
20 | ||
21 | #define CX23885_IR_TX_FIFO_SERVICE_REQ 0 | |
22 | ||
23 | ||
24 | void cx23885_ir_rx_work_handler(struct work_struct *work) | |
25 | { | |
26 | struct cx23885_dev *dev = | |
27 | container_of(work, struct cx23885_dev, ir_rx_work); | |
28 | u32 events = 0; | |
29 | unsigned long *notifications = &dev->ir_rx_notifications; | |
30 | ||
31 | if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications)) | |
32 | events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN; | |
33 | if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications)) | |
34 | events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN; | |
35 | if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications)) | |
36 | events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED; | |
37 | if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications)) | |
38 | events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; | |
39 | ||
40 | if (events == 0) | |
41 | return; | |
dbda8f70 | 42 | |
43c24078 | 43 | if (dev->kernel_ir) |
dbda8f70 | 44 | cx23885_input_rx_work_handler(dev, events); |
f59ad611 AW |
45 | } |
46 | ||
47 | void cx23885_ir_tx_work_handler(struct work_struct *work) | |
48 | { | |
49 | struct cx23885_dev *dev = | |
50 | container_of(work, struct cx23885_dev, ir_tx_work); | |
51 | u32 events = 0; | |
52 | unsigned long *notifications = &dev->ir_tx_notifications; | |
53 | ||
54 | if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications)) | |
55 | events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ; | |
56 | ||
57 | if (events == 0) | |
58 | return; | |
59 | ||
60 | } | |
61 | ||
e5514f10 | 62 | /* Possibly called in an IRQ context */ |
f59ad611 AW |
63 | void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) |
64 | { | |
65 | struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); | |
66 | unsigned long *notifications = &dev->ir_rx_notifications; | |
67 | ||
68 | if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ) | |
69 | set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications); | |
70 | if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED) | |
71 | set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications); | |
72 | if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN) | |
73 | set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); | |
74 | if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) | |
75 | set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); | |
e5514f10 AW |
76 | |
77 | /* | |
78 | * For the integrated AV core, we are already in a workqueue context. | |
79 | * For the CX23888 integrated IR, we are in an interrupt context. | |
80 | */ | |
81 | if (sd == dev->sd_cx25840) | |
82 | cx23885_ir_rx_work_handler(&dev->ir_rx_work); | |
83 | else | |
84 | schedule_work(&dev->ir_rx_work); | |
f59ad611 AW |
85 | } |
86 | ||
e5514f10 | 87 | /* Possibly called in an IRQ context */ |
f59ad611 AW |
88 | void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) |
89 | { | |
90 | struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); | |
91 | unsigned long *notifications = &dev->ir_tx_notifications; | |
92 | ||
93 | if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) | |
94 | set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); | |
e5514f10 AW |
95 | |
96 | /* | |
97 | * For the integrated AV core, we are already in a workqueue context. | |
98 | * For the CX23888 integrated IR, we are in an interrupt context. | |
99 | */ | |
100 | if (sd == dev->sd_cx25840) | |
101 | cx23885_ir_tx_work_handler(&dev->ir_tx_work); | |
102 | else | |
103 | schedule_work(&dev->ir_tx_work); | |
f59ad611 | 104 | } |