2019-05-27 08:55:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-09-27 19:51:50 -03:00
/*
* Driver for the Conexant CX23885 / 7 / 8 PCIe bridge
*
* Infrared device support routines - non - input , non - vl42_subdev routines
*
2010-05-23 18:53:35 -03:00
* Copyright ( C ) 2009 Andy Walls < awalls @ md . metrocast . net >
2009-09-27 19:51:50 -03:00
*/
# include "cx23885.h"
2012-10-27 11:29:23 -03:00
# include "cx23885-ir.h"
2009-09-27 20:55:41 -03:00
# include "cx23885-input.h"
2009-09-27 19:51:50 -03:00
2016-11-13 09:46:11 -02:00
# include <media/v4l2-device.h>
2009-09-27 19:51:50 -03:00
# 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 ;
2009-09-27 20:55:41 -03:00
2010-06-27 23:15:35 -03:00
if ( dev - > kernel_ir )
2009-09-27 20:55:41 -03:00
cx23885_input_rx_work_handler ( dev , events ) ;
2009-09-27 19:51:50 -03:00
}
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 ;
}
2010-07-19 01:35:46 -03:00
/* Possibly called in an IRQ context */
2009-09-27 19:51:50 -03:00
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 ) ;
2010-07-19 01:35:46 -03:00
/*
* 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 ) ;
2009-09-27 19:51:50 -03:00
}
2010-07-19 01:35:46 -03:00
/* Possibly called in an IRQ context */
2009-09-27 19:51:50 -03:00
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 ) ;
2010-07-19 01:35:46 -03:00
/*
* 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 ) ;
2009-09-27 19:51:50 -03:00
}