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