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)  * cimax2.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright (C) 2009 NetUP Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "cx23885.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "cimax2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <media/dvb_ca_en50221.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /* Max transfer size done by I2C transfer functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define MAX_XFER_SIZE  64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)   bits 31-16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) +-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) | Reserved  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) +-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)   bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) +-------+-------+-------+-------+-------+-------+-------+-------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) |  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) +-------+-------+-------+-------+-------+-------+-------+-------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) +-------+-------+-------+-------+-------+-------+-------+-------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) +-------+-------+-------+-------+-------+-------+-------+-------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /* MC417 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define NETUP_DATA		0x000000ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define NETUP_WR		0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define NETUP_RD		0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define NETUP_ACK		0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define NETUP_ADHI		0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define NETUP_ADLO		0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define NETUP_CS1		0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define NETUP_CS0		0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define NETUP_EN_ALL		0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define NETUP_CTRL_OFF		(NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define NETUP_CI_CTL		0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define NETUP_CI_RD		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define NETUP_IRQ_DETAM		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define NETUP_IRQ_IRQAM		0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static unsigned int ci_dbg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) module_param(ci_dbg, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static unsigned int ci_irq_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) module_param(ci_irq_enable, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define ci_dbg_print(fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		if (ci_dbg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			printk(KERN_DEBUG pr_fmt("%s: " fmt), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 			       __func__, ##args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) /* stores all private variables for communication with CI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) struct netup_ci_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct dvb_ca_en50221 ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	struct mutex ca_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct i2c_adapter *i2c_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	u8 ci_i2c_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	u8 current_irq_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int current_ci_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	unsigned long next_status_checked_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 						u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			.addr	= addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			.flags	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			.buf	= &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			.len	= 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			.addr	= addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			.flags	= I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			.buf	= buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			.len	= len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	ret = i2c_transfer(i2c_adap, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 						__func__, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 						__func__, addr, reg, buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 						u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	u8 buffer[MAX_XFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		.addr	= addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		.flags	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		.buf	= &buffer[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		.len	= len + 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (1 + len > sizeof(buffer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		       KBUILD_MODNAME, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	buffer[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	memcpy(&buffer[1], buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	ret = i2c_transfer(i2c_adap, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (ret != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 						__func__, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^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 int netup_ci_get_mem(struct cx23885_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	int mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	unsigned long timeout = jiffies + msecs_to_jiffies(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		mem = cx_read(MC417_RWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if ((mem & NETUP_ACK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	cx_set(MC417_RWD, NETUP_CTRL_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return mem & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				u8 flag, u8 read, int addr, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct netup_ci_state *state = en50221->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	struct cx23885_tsport *port = state->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	struct cx23885_dev *dev = port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	u8 store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	int mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (state->current_ci_flag != flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 				0, &store, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		store &= ~0x0c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		store |= flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 				0, &store, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	state->current_ci_flag = flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	mutex_lock(&dev->gpio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	/* write addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	cx_write(MC417_OEN, NETUP_EN_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	cx_write(MC417_RWD, NETUP_CTRL_OFF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 				NETUP_ADLO | (0xff & addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	cx_clear(MC417_RWD, NETUP_ADLO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	cx_write(MC417_RWD, NETUP_CTRL_OFF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 				NETUP_ADHI | (0xff & (addr >> 8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	cx_clear(MC417_RWD, NETUP_ADHI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	if (read) { /* data in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	} else /* data out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	/* choose chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	cx_clear(MC417_RWD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			(state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	/* read/write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	mem = netup_ci_get_mem(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	mutex_unlock(&dev->gpio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (!read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		if (mem < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			(read) ? "read" : "write", state->ci_i2c_addr, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			(flag == NETUP_CI_CTL) ? "ctl" : "mem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			(read) ? mem : data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		return mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	return 0;
^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) int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 						int slot, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 						int slot, int addr, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 				 u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 							NETUP_CI_RD, addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 							u8 addr, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	struct netup_ci_state *state = en50221->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	u8 buf =  0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 							0, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	buf = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 							0, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	dvb_ca_en50221_camready_irq(&state->ca, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	/* not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	struct netup_ci_state *state = en50221->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	if (irq_mode == state->current_irq_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			__func__, state->ci_i2c_addr, irq_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 							0x1b, &irq_mode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	state->current_irq_mode = irq_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	return 0;
^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) int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	struct netup_ci_state *state = en50221->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	u8 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			0, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	buf |= 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 							0, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* work handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void netup_read_ci_status(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	struct netup_ci_state *state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			container_of(work, struct netup_ci_state, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	u8 buf[33];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	/* CAM module IRQ processing. fast operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	dvb_ca_en50221_frda_irq(&state->ca, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	/* CAM module INSERT/REMOVE processing. slow operation because of i2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	 * transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	if (time_after(jiffies, state->next_status_checked_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			|| !state->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 				0, &buf[0], 33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		state->next_status_checked_time = jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			+ msecs_to_jiffies(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, TS config = %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			     __func__,	state->ci_i2c_addr, 0, buf[0], buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		if (buf[0] & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 				DVB_CA_EN50221_POLL_CAM_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			state->status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* CI irq handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	struct cx23885_tsport *port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	struct netup_ci_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	ci_dbg_print("%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (pci_status & PCI_MSK_GPIO0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		port = &dev->ts1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		state = port->port_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		schedule_work(&state->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		ci_dbg_print("%s: Wakeup CI0\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (pci_status & PCI_MSK_GPIO1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		port = &dev->ts2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		state = port->port_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		schedule_work(&state->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		ci_dbg_print("%s: Wakeup CI1\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 				     int slot, int open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	struct netup_ci_state *state = en50221->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			: NETUP_IRQ_DETAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	return state->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int netup_ci_init(struct cx23885_tsport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	struct netup_ci_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	u8 cimax_init[34] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		0x00, /* module A control*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		0x00, /* auto select mask high A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		0x00, /* auto select mask low A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		0x00, /* auto select pattern high A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		0x00, /* auto select pattern low A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		0x44, /* memory access time A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		0x00, /* invert input A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		0x00, /* module B control*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		0x00, /* auto select mask high B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		0x00, /* auto select mask low B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		0x00, /* auto select pattern high B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		0x00, /* auto select pattern low B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		0x44, /* memory access time B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		0x00, /* invert input B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		0x00, /* auto select mask high Ext */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		0x00, /* auto select mask low Ext */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		0x00, /* auto select pattern high Ext */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		0x00, /* auto select pattern low Ext */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		0x02, /* destination - module A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		0x01, /* power on (use it like store place) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		0x00, /* RFU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		0x00, /* int status read only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		0x05, /* EXTINT=active-high, INT=push-pull */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		0x00, /* USCG1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		0x04, /* ack active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		0x00, /* LOCK = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		0x33, /* serial mode, rising in, rising out, MSB first*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		0x31, /* synchronization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	ci_dbg_print("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		ci_dbg_print("%s: Unable create CI structure!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	port->port_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	switch (port->nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		state->ci_i2c_addr = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		state->ci_i2c_addr = 0x41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		break;
^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) 	state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	state->ca.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	state->ca.read_attribute_mem = netup_ci_read_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	state->ca.write_attribute_mem = netup_ci_write_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	state->ca.read_cam_control = netup_ci_read_cam_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	state->ca.write_cam_control = netup_ci_write_cam_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	state->ca.slot_reset = netup_ci_slot_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	state->ca.slot_shutdown = netup_ci_slot_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	state->ca.poll_slot_status = netup_poll_ci_slot_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	state->ca.data = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	state->priv = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 						0, &cimax_init[0], 34);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	/* lock registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 						0x1f, &cimax_init[0x18], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	/* power on slots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 						0x18, &cimax_init[0x18], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	ret = dvb_ca_en50221_init(&port->frontends.adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 				   &state->ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 				   /* flags */ 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 				   /* n_slots */ 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	INIT_WORK(&state->work, netup_read_ci_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	schedule_work(&state->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	ci_dbg_print("%s: CI initialized!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) void netup_ci_exit(struct cx23885_tsport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	struct netup_ci_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	if (NULL == port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	state = (struct netup_ci_state *)port->port_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	if (NULL == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	if (NULL == state->ca.data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	dvb_ca_en50221_release(&state->ca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }