Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  *  CX23888 Integrated Consumer Infrared Controller
^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 "cx23888-ir.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/kfifo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <media/rc-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) static unsigned int ir_888_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) module_param(ir_888_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #define CX23888_IR_REG_BASE	0x170000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  * These CX23888 register offsets have a straightforward one to one mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  * to the CX23885 register offsets of 0x200 through 0x218
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #define CX23888_IR_CNTRL_REG	0x170000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #define CNTRL_WIN_3_3	0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define CNTRL_WIN_4_3	0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #define CNTRL_WIN_3_4	0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #define CNTRL_WIN_4_4	0x00000003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #define CNTRL_WIN	0x00000003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define CNTRL_EDG_NONE	0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #define CNTRL_EDG_FALL	0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #define CNTRL_EDG_RISE	0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define CNTRL_EDG_BOTH	0x0000000C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define CNTRL_EDG	0x0000000C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define CNTRL_DMD	0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #define CNTRL_MOD	0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #define CNTRL_RFE	0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define CNTRL_TFE	0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define CNTRL_RXE	0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #define CNTRL_TXE	0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define CNTRL_RIC	0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #define CNTRL_TIC	0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define CNTRL_CPL	0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define CNTRL_LBM	0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define CNTRL_R		0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) /* CX23888 specific control flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define CNTRL_IVO	0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define CX23888_IR_TXCLK_REG	0x170004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define TXCLK_TCD	0x0000FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define CX23888_IR_RXCLK_REG	0x170008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define RXCLK_RCD	0x0000FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define CX23888_IR_CDUTY_REG	0x17000C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define CDUTY_CDC	0x0000000F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define CX23888_IR_STATS_REG	0x170010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define STATS_RTO	0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define STATS_ROR	0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define STATS_RBY	0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define STATS_TBY	0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define STATS_RSR	0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define STATS_TSR	0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define CX23888_IR_IRQEN_REG	0x170014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #define IRQEN_RTE	0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define IRQEN_ROE	0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define IRQEN_RSE	0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define IRQEN_TSE	0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #define CX23888_IR_FILTR_REG	0x170018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define FILTR_LPF	0x0000FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) /* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define CX23888_IR_FIFO_REG	0x170040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define FIFO_RXTX	0x0000FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define FIFO_RXTX_LVL	0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define FIFO_RXTX_RTO	0x0001FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define FIFO_RX_NDV	0x00020000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define FIFO_RX_DEPTH	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define FIFO_TX_DEPTH	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) /* CX23888 unique registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define CX23888_IR_SEEDP_REG	0x17001C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define CX23888_IR_TIMOL_REG	0x170020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define CX23888_IR_WAKE0_REG	0x170024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define CX23888_IR_WAKE1_REG	0x170028
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define CX23888_IR_WAKE2_REG	0x17002C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) #define CX23888_IR_MASK0_REG	0x170030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define CX23888_IR_MASK1_REG	0x170034
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define CX23888_IR_MAKS2_REG	0x170038
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define CX23888_IR_DPIPG_REG	0x17003C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define CX23888_IR_LEARN_REG	0x170044
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #define CX23888_VIDCLK_FREQ	108000000 /* 108 MHz, BT.656 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) #define CX23888_IR_REFCLK_FREQ	(CX23888_VIDCLK_FREQ / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  * We use this union internally for convenience, but callers to tx_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * and rx_read will be expecting records of type struct ir_raw_event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  * Always ensure the size of this union is dictated by struct ir_raw_event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) union cx23888_ir_fifo_rec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	u32 hw_fifo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	struct ir_raw_event ir_core_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) #define CX23888_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) #define CX23888_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) struct cx23888_ir_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	struct cx23885_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	struct v4l2_subdev_ir_parameters rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	struct mutex rx_params_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	atomic_t rxclk_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	atomic_t rx_invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	struct kfifo rx_kfifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	spinlock_t rx_kfifo_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	struct v4l2_subdev_ir_parameters tx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	struct mutex tx_params_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	atomic_t txclk_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	return v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  * IR register block read and write functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	cx_write(addr, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	return cx_read(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 				     u32 and_mask, u32 or_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	cx_andor(addr, ~and_mask, or_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  * Rx and Tx Clock Divider register computations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  * Note the largest clock divider value of 0xffff corresponds to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)  *	(0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  * which fits in 21 bits, so we'll use unsigned int for time arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) static inline u16 count_to_clock_divider(unsigned int d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	if (d > RXCLK_RCD + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		d = RXCLK_RCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	else if (d < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		d = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		d--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	return (u16) d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	return count_to_clock_divider(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 			  DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) static inline unsigned int clock_divider_to_freq(unsigned int divider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 						 unsigned int rollovers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 				 (divider + 1) * rollovers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197)  * Low Pass Filter register calculations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199)  * Note the largest count value of 0xffff corresponds to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)  *	0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  * which fits in 21 bits, so we'll use unsigned int for time arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) static inline u16 count_to_lpf_count(unsigned int d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	if (d > FILTR_LPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 		d = FILTR_LPF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	else if (d < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		d = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	return (u16) d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) static inline u16 ns_to_lpf_count(unsigned int ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	return count_to_lpf_count(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) static inline unsigned int lpf_count_to_ns(unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	/* Duration of the Low Pass Filter rejection window in ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	return DIV_ROUND_CLOSEST(count * 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 				 CX23888_IR_REFCLK_FREQ / 1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) static inline unsigned int lpf_count_to_us(unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	/* Duration of the Low Pass Filter rejection window in us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  * FIFO register pulse width count computations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) static u32 clock_divider_to_resolution(u16 divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	 * Resolution is the duration of 1 tick of the readable portion of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	 * of the pulse width counter as read from the FIFO.  The two lsb's are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	 * not readable, hence the << 2.  This function returns ns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	return DIV_ROUND_CLOSEST((1 << 2)  * ((u32) divider + 1) * 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 				 CX23888_IR_REFCLK_FREQ / 1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) static u64 pulse_width_count_to_ns(u16 count, u16 divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	u64 n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	u32 rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	 * The 2 lsb's of the pulse width timer count are not readable, hence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	 * the (count << 2) | 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000);     /* / MHz => ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	u64 n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	u32 rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	 * The 2 lsb's of the pulse width timer count are not readable, hence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	 * the (count << 2) | 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	n = (((u64) count << 2) | 0x3) * (divider + 1);    /* cycles      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 		n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	return (unsigned int) n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278)  * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280)  * The total pulse clock count is an 18 bit pulse width timer count as the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281)  * significant part and (up to) 16 bit clock divider count as a modulus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282)  * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)  * width timer count's least significant bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) static u64 ns_to_pulse_clocks(u32 ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	u64 clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	u32 rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	rem = do_div(clocks, 1000);                         /* /1000 = cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	if (rem >= 1000 / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		clocks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	return clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) static u16 pulse_clocks_to_clock_divider(u64 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	do_div(count, (FIFO_RXTX << 2) | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	/* net result needs to be rounded down and decremented by 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	if (count > RXCLK_RCD + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		count = RXCLK_RCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	else if (count < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	return (u16) count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311)  * IR Control Register helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) enum tx_fifo_watermark {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	TX_FIFO_HALF_EMPTY = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	TX_FIFO_EMPTY      = CNTRL_TIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) enum rx_fifo_watermark {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	RX_FIFO_HALF_FULL = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	RX_FIFO_NOT_EMPTY = CNTRL_RIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 					    enum tx_fifo_watermark level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 					    enum rx_fifo_watermark level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 			   enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 			   enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 						bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 			   enable ? CNTRL_MOD : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 						  bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			   enable ? CNTRL_DMD : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 					       u32 edge_types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 			   edge_types & CNTRL_EDG_BOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) static void control_rx_s_carrier_window(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 					unsigned int carrier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 					unsigned int *carrier_range_low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 					unsigned int *carrier_range_high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	unsigned int c16 = carrier * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		v = CNTRL_WIN_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		v = CNTRL_WIN_3_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		v |= CNTRL_WIN_4_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		v |= CNTRL_WIN_3_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 					      bool invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 			   invert ? CNTRL_CPL : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) static inline void control_tx_level_invert(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 					  bool invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 			   invert ? CNTRL_IVO : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409)  * IR Rx & Tx Clock Register helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 				       unsigned int freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 				       u16 *divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	*divider = carrier_freq_to_clock_divider(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	return clock_divider_to_carrier_freq(*divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 				       unsigned int freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 				       u16 *divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	*divider = carrier_freq_to_clock_divider(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	return clock_divider_to_carrier_freq(*divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 				      u16 *divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	u64 pulse_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	if (ns > IR_MAX_DURATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		ns = IR_MAX_DURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	pulse_clocks = ns_to_pulse_clocks(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 				      u16 *divider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	u64 pulse_clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	if (ns > IR_MAX_DURATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		ns = IR_MAX_DURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	pulse_clocks = ns_to_pulse_clocks(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456)  * IR Tx Carrier Duty Cycle register helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 					  unsigned int duty_cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	u32 n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	if (n != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		n--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	if (n > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		n = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472)  * IR Filter Register helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	u32 count = ns_to_lpf_count(min_width_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	return lpf_count_to_ns(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482)  * IR IRQ Enable Register helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 			   ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	mask &= IRQEN_TSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  * V4L2 Subdevice IR Ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 				  bool *handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	unsigned int i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	u32 events, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	ror = stats & STATS_ROR; /* Rx FIFO Over Run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	rse = irqen & IRQEN_RSE; /* Rx FIFO Service Request IRQ Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	*handled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	v4l2_dbg(2, ir_888_debug, sd, "IRQ Status:  %s %s %s %s %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		 tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		 rto ? "rto" : "   ", ror ? "ror" : "   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		 stats & STATS_TBY ? "tby" : "   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		 stats & STATS_RBY ? "rby" : "   ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		 tse ? "tse" : "   ", rse ? "rse" : "   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		 rte ? "rte" : "   ", roe ? "roe" : "   ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	 * Transmitter interrupt service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	if (tse && tsr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		 * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		 * Check the watermark threshold setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		 * Push the data to the hardware FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		 * If there was nothing more to send in the tx_kfifo, disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		 *	the TSR IRQ and notify the v4l2_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		 * If there was something in the tx_kfifo, check the tx_kfifo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		 *      level and notify the v4l2_device, if it is low.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		/* For now, inhibit TSR interrupt until Tx is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		irqenable_tx(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		*handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	 * Receiver interrupt service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	kror = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if ((rse && rsr) || (rte && rto)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 		 * Receive data on RSR to clear the STATS_RSR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		 * Receive data on RTO, since we may not have yet hit the RSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		 * watermark when we receive the RTO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		for (i = 0, v = FIFO_RX_NDV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		     (v & FIFO_RX_NDV) && !kror; i = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 			for (j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			     (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 				v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 				rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 				i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 			if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 			j = i * sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			k = kfifo_in_locked(&state->rx_kfifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 				      (unsigned char *) rx_data, j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 				      &state->rx_kfifo_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			if (k != j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 				kror++; /* rx_kfifo over run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		*handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	if (kror) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		v4l2_err(sd, "IR receiver software FIFO overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	if (roe && ror) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		 * the Rx FIFO Over Run status (STATS_ROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		v |= CNTRL_RFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	if (rte && rto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		 * the Rx Pulse Width Timer Time Out (STATS_RTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		v |= CNTRL_RXE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	if (v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		/* Clear STATS_ROR & STATS_RTO as needed by resetting hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 		*handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	spin_lock_irqsave(&state->rx_kfifo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	if (events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) /* Receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 			      ssize_t *num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	bool invert = (bool) atomic_read(&state->rx_invert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	u16 divider = (u16) atomic_read(&state->rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	unsigned int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	union cx23888_ir_fifo_rec *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	unsigned u, v, w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	n = count / sizeof(union cx23888_ir_fifo_rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		* sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	if (n == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		*num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	n /= sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	*num = n * sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 			/* Assume RTO was because of no IR light input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			u = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			w = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 			if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 				u = u ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			w = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		v = (unsigned) pulse_width_count_to_ns(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 				  (u16)(p->hw_fifo_data & FIFO_RXTX), divider) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		if (v > IR_MAX_DURATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 			v = IR_MAX_DURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		p->ir_core_data = (struct ir_raw_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			{ .pulse = u, .duration = v, .timeout = w };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			 v, u ? "mark" : "space", w ? "(timed out)" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		if (w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 				      struct v4l2_subdev_ir_parameters *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	mutex_lock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	mutex_unlock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	mutex_lock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	/* Disable or slow down all IR Rx circuits and counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	irqenable_rx(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	control_rx_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	control_rx_demodulation_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	filter_rx_s_min_width(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	state->rx_params.shutdown = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	mutex_unlock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 				      struct v4l2_subdev_ir_parameters *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	struct v4l2_subdev_ir_parameters *o = &state->rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	u16 rxclk_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	if (p->shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		return cx23888_ir_rx_shutdown(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	mutex_lock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	o->shutdown = p->shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	o->bytes_per_data_element = p->bytes_per_data_element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 				  = sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	/* Before we tweak the hardware, we have to disable the receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	irqenable_rx(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	control_rx_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	control_rx_demodulation_enable(dev, p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	o->modulation = p->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	if (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 						     &rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		o->carrier_freq = p->carrier_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		o->duty_cycle = p->duty_cycle = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 		control_rx_s_carrier_window(dev, p->carrier_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 					    &p->carrier_range_lower,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 					    &p->carrier_range_upper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		o->carrier_range_lower = p->carrier_range_lower;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		o->carrier_range_upper = p->carrier_range_upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		p->max_pulse_width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 			(u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 		p->max_pulse_width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 			    rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 						       &rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	o->max_pulse_width = p->max_pulse_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	atomic_set(&state->rxclk_divider, rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	p->noise_filter_min_width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			  filter_rx_s_min_width(dev, p->noise_filter_min_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	o->noise_filter_min_width = p->noise_filter_min_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	p->resolution = clock_divider_to_resolution(rxclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	o->resolution = p->resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	/* FIXME - make this dependent on resolution for better performance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	o->invert_level = p->invert_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	atomic_set(&state->rx_invert, p->invert_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	o->interrupt_enable = p->interrupt_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	o->enable = p->enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	if (p->enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		spin_lock_irqsave(&state->rx_kfifo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		kfifo_reset(&state->rx_kfifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		/* reset tx_fifo too if there is one... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		if (p->interrupt_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		control_rx_enable(dev, p->enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	mutex_unlock(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) /* Transmitter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			       ssize_t *num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	/* For now enable the Tx FIFO Service interrupt & pretend we did work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	irqenable_tx(dev, IRQEN_TSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	*num = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 				      struct v4l2_subdev_ir_parameters *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	mutex_lock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	mutex_unlock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	mutex_lock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	/* Disable or slow down all IR Tx circuits and counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	irqenable_tx(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	control_tx_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	control_tx_modulation_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	state->tx_params.shutdown = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	mutex_unlock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 				      struct v4l2_subdev_ir_parameters *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	struct v4l2_subdev_ir_parameters *o = &state->tx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	u16 txclk_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	if (p->shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		return cx23888_ir_tx_shutdown(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	mutex_lock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	o->shutdown = p->shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	o->bytes_per_data_element = p->bytes_per_data_element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 				  = sizeof(union cx23888_ir_fifo_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	/* Before we tweak the hardware, we have to disable the transmitter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	irqenable_tx(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	control_tx_enable(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	control_tx_modulation_enable(dev, p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	o->modulation = p->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	if (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 						     &txclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		o->carrier_freq = p->carrier_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		o->duty_cycle = p->duty_cycle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 		p->max_pulse_width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			(u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		p->max_pulse_width =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 			    txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 						       &txclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	o->max_pulse_width = p->max_pulse_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	atomic_set(&state->txclk_divider, txclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	p->resolution = clock_divider_to_resolution(txclk_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	o->resolution = p->resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	/* FIXME - make this dependent on resolution for better performance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	control_tx_polarity_invert(dev, p->invert_carrier_sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	o->invert_carrier_sense = p->invert_carrier_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	control_tx_level_invert(dev, p->invert_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	o->invert_level = p->invert_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	o->interrupt_enable = p->interrupt_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	o->enable = p->enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	if (p->enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		if (p->interrupt_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 			irqenable_tx(dev, IRQEN_TSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		control_tx_enable(dev, p->enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	mutex_unlock(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914)  * V4L2 Subdevice Core Ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) static int cx23888_ir_log_status(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	struct cx23885_dev *dev = state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	v4l2_info(sd, "IR Receiver:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	v4l2_info(sd, "\tEnabled:                           %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		  cntrl & CNTRL_RXE ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	v4l2_info(sd, "\tDemodulation from a carrier:       %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		  cntrl & CNTRL_DMD ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	v4l2_info(sd, "\tFIFO:                              %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		  cntrl & CNTRL_RFE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	switch (cntrl & CNTRL_EDG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	case CNTRL_EDG_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		s = "disabled";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	case CNTRL_EDG_FALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		s = "falling edge";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	case CNTRL_EDG_RISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		s = "rising edge";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	case CNTRL_EDG_BOTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		s = "rising & falling edges";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		s = "??? edge";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	v4l2_info(sd, "\tPulse timers' start/stop trigger:  %s\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		  cntrl & CNTRL_R ? "not loaded" : "overflow marker");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		  cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	v4l2_info(sd, "\tLoopback mode:                     %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		  cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	if (cntrl & CNTRL_DMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		v4l2_info(sd, "\tExpected carrier (16 clocks):      %u Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 			  clock_divider_to_carrier_freq(rxclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		switch (cntrl & CNTRL_WIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		case CNTRL_WIN_3_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			i = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 			j = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		case CNTRL_WIN_4_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 			i = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 			j = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		case CNTRL_WIN_3_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			i = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			j = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		case CNTRL_WIN_4_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			i = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 			j = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 			j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		v4l2_info(sd, "\tNext carrier edge window:	    16 clocks -%1d/+%1d, %u to %u Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 			  i, j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 			  clock_divider_to_freq(rxclk, 16 + j),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 			  clock_divider_to_freq(rxclk, 16 - i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	v4l2_info(sd, "\tMax measurable pulse width:        %u us, %llu ns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		  pulse_width_count_to_us(FIFO_RXTX, rxclk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		  pulse_width_count_to_ns(FIFO_RXTX, rxclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	v4l2_info(sd, "\tLow pass filter:                   %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		  filtr ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (filtr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, %u ns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 			  lpf_count_to_us(filtr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 			  lpf_count_to_ns(filtr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		  stats & STATS_RTO ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	v4l2_info(sd, "\tPulse width timer time-out intr:   %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		  irqen & IRQEN_RTE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	v4l2_info(sd, "\tFIFO overrun:                      %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 		  stats & STATS_ROR ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	v4l2_info(sd, "\tFIFO overrun interrupt:            %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		  irqen & IRQEN_ROE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	v4l2_info(sd, "\tBusy:                              %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		  stats & STATS_RBY ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	v4l2_info(sd, "\tFIFO service requested:            %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		  stats & STATS_RSR ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		  irqen & IRQEN_RSE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	v4l2_info(sd, "IR Transmitter:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	v4l2_info(sd, "\tEnabled:                           %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		  cntrl & CNTRL_TXE ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	v4l2_info(sd, "\tModulation onto a carrier:         %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		  cntrl & CNTRL_MOD ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	v4l2_info(sd, "\tFIFO:                              %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		  cntrl & CNTRL_TFE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		  cntrl & CNTRL_TIC ? "not empty" : "half full or less");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	v4l2_info(sd, "\tOutput pin level inversion         %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		  cntrl & CNTRL_IVO ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	v4l2_info(sd, "\tCarrier polarity:                  %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		  cntrl & CNTRL_CPL ? "space:burst mark:noburst"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 				    : "space:noburst mark:burst");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	if (cntrl & CNTRL_MOD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		v4l2_info(sd, "\tCarrier (16 clocks):               %u Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 			  clock_divider_to_carrier_freq(txclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		v4l2_info(sd, "\tCarrier duty cycle:                %2u/16\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 			  cduty + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	v4l2_info(sd, "\tMax pulse width:                   %u us, %llu ns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		  pulse_width_count_to_us(FIFO_RXTX, txclk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		  pulse_width_count_to_ns(FIFO_RXTX, txclk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	v4l2_info(sd, "\tBusy:                              %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		  stats & STATS_TBY ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	v4l2_info(sd, "\tFIFO service requested:            %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		  stats & STATS_TSR ? "yes" : "no");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		  irqen & IRQEN_TSE ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static int cx23888_ir_g_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 				 struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	if ((addr & 0x3) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	reg->size = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	reg->val = cx23888_ir_read4(state->dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int cx23888_ir_s_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 				 const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	struct cx23888_ir_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	if ((addr & 0x3) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	cx23888_ir_write4(state->dev, addr, reg->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	.log_status = cx23888_ir_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	.g_register = cx23888_ir_g_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	.s_register = cx23888_ir_s_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	.interrupt_service_routine = cx23888_ir_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	.rx_read = cx23888_ir_rx_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	.rx_g_parameters = cx23888_ir_rx_g_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	.rx_s_parameters = cx23888_ir_rx_s_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	.tx_write = cx23888_ir_tx_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	.tx_g_parameters = cx23888_ir_tx_g_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	.tx_s_parameters = cx23888_ir_tx_s_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	.core = &cx23888_ir_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	.ir = &cx23888_ir_ir_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) static const struct v4l2_subdev_ir_parameters default_rx_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	.bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	.enable = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	.interrupt_enable = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	.shutdown = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	.modulation = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	.carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	/* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	/* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	.noise_filter_min_width = 333333, /* ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	.carrier_range_lower = 35000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	.carrier_range_upper = 37000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	.invert_level = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static const struct v4l2_subdev_ir_parameters default_tx_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	.bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	.enable = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	.interrupt_enable = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	.shutdown = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	.modulation = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	.carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	.duty_cycle = 25,      /* 25 %   - RC-5 carrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	.invert_level = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	.invert_carrier_sense = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int cx23888_ir_probe(struct cx23885_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	struct cx23888_ir_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	struct v4l2_subdev_ir_parameters default_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	spin_lock_init(&state->rx_kfifo_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 			GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	state->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	v4l2_set_subdevdata(sd, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	/* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	sd->grp_id = CX23885_HW_888_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		 * Ensure no interrupts arrive from '888 specific conditions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		 * since we ignore them in this driver to have commonality with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		 * similar IR controller cores.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		mutex_init(&state->rx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		default_params = default_rx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 		v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		mutex_init(&state->tx_params_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		default_params = default_tx_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		kfifo_free(&state->rx_kfifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int cx23888_ir_remove(struct cx23885_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	struct cx23888_ir_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	if (sd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	cx23888_ir_rx_shutdown(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	cx23888_ir_tx_shutdown(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	v4l2_device_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	kfifo_free(&state->rx_kfifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	/* Nothing more to free() as state held the actual v4l2_subdev object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }