// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Driver for the Conexant CX23885/7/8 PCIe bridge
 *
 *  Infrared device support routines - non-input, non-vl42_subdev routines
 *
 *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
 */

#include "cx23885.h"
#include "cx23885-ir.h"
#include "cx23885-input.h"

#include <media/v4l2-device.h>

#define CX23885_IR_RX_FIFO_SERVICE_REQ		0
#define CX23885_IR_RX_END_OF_RX_DETECTED	1
#define CX23885_IR_RX_HW_FIFO_OVERRUN		2
#define CX23885_IR_RX_SW_FIFO_OVERRUN		3

#define CX23885_IR_TX_FIFO_SERVICE_REQ		0


void cx23885_ir_rx_work_handler(struct work_struct *work)
{
	struct cx23885_dev *dev =
			     container_of(work, struct cx23885_dev, ir_rx_work);
	u32 events = 0;
	unsigned long *notifications = &dev->ir_rx_notifications;

	if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
	if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
	if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
	if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;

	if (events == 0)
		return;

	if (dev->kernel_ir)
		cx23885_input_rx_work_handler(dev, events);
}

void cx23885_ir_tx_work_handler(struct work_struct *work)
{
	struct cx23885_dev *dev =
			     container_of(work, struct cx23885_dev, ir_tx_work);
	u32 events = 0;
	unsigned long *notifications = &dev->ir_tx_notifications;

	if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
		events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;

	if (events == 0)
		return;

}

/* Possibly called in an IRQ context */
void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
{
	struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
	unsigned long *notifications = &dev->ir_rx_notifications;

	if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
		set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
	if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
		set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
	if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
		set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
	if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
		set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);

	/*
	 * For the integrated AV core, we are already in a workqueue context.
	 * For the CX23888 integrated IR, we are in an interrupt context.
	 */
	if (sd == dev->sd_cx25840)
		cx23885_ir_rx_work_handler(&dev->ir_rx_work);
	else
		schedule_work(&dev->ir_rx_work);
}

/* Possibly called in an IRQ context */
void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
{
	struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
	unsigned long *notifications = &dev->ir_tx_notifications;

	if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
		set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);

	/*
	 * For the integrated AV core, we are already in a workqueue context.
	 * For the CX23888 integrated IR, we are in an interrupt context.
	 */
	if (sd == dev->sd_cx25840)
		cx23885_ir_tx_work_handler(&dev->ir_tx_work);
	else
		schedule_work(&dev->ir_tx_work);
}
