^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) }