^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 = ®,
^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) }