^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) * PCTV 452e DVB driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * TT connect S2-3650-CI Common Interface support, MAC readout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /* dvb usb framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define DVB_USB_LOG_PREFIX "pctv452e"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "dvb-usb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* Demodulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "stb0899_drv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "stb0899_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "stb0899_cfg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "stb6100.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "stb6100_cfg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* FE Power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "isl6423.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "lnbp22.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <media/dvb_ca_en50221.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "ttpci-eeprom.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ISOC_INTERFACE_ALTERNATIVE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SYNC_BYTE_OUT 0xaa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SYNC_BYTE_IN 0x55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* guessed: (copied from ttusb-budget) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define PCTV_CMD_RESET 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* command to poll IR receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define PCTV_CMD_IR 0x1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* command to send I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PCTV_CMD_I2C 0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define I2C_ADDR_STB0899 (0xd0 >> 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define I2C_ADDR_STB6100 (0xc0 >> 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define I2C_ADDR_LNBP22 (0x10 >> 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define I2C_ADDR_24C16 (0xa0 >> 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define I2C_ADDR_24C64 (0xa2 >> 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* pctv452e sends us this amount of data for each issued usb-command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define PCTV_ANSWER_LEN 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Wait up to 1000ms for device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define PCTV_TIMEOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define PCTV_LED_GPIO STB0899_GPIO01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define PCTV_LED_GREEN 0x82
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PCTV_LED_ORANGE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ci_dbg(format, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ": " format "\n" , ## arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) TT3650_CMD_CI_TEST = 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) TT3650_CMD_CI_RD_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) TT3650_CMD_CI_WR_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) TT3650_CMD_CI_RD_ATTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) TT3650_CMD_CI_WR_ATTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) TT3650_CMD_CI_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) TT3650_CMD_CI_SET_VIDEO_PORT
^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 struct stb0899_postproc pctv45e_postproc[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { PCTV_LED_GPIO, STB0899_GPIOPULLUP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct isl6423_config pctv452e_isl6423_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .current_max = SEC_CURRENT_515m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .curlim = SEC_CURRENT_LIM_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .mod_extern = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .addr = 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * stores all private variables for communication with the PCTV452e DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct pctv452e_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct dvb_ca_en50221 ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct mutex ca_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 c; /* transaction counter, wraps around... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 initialized; /* set to 1 if 0x15 has been sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u16 last_rc_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned int write_len, unsigned int read_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned int rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) err("%s: transfer data invalid", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) buf = kmalloc(64, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) id = state->c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) buf[0] = SYNC_BYTE_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) buf[1] = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) buf[2] = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) buf[3] = write_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) memcpy(buf + 4, data, write_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rlen = (read_len > 0) ? 64 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) buf, rlen, /* delay_ms */ 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (SYNC_BYTE_IN != buf[0] || id != buf[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) memcpy(data, buf + 4, read_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) err("CI error %d; %02X %02X %02X -> %*ph.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) u8 cmd, u8 *data, unsigned int write_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned int read_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int slot, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) buf[0] = (address >> 8) & 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) buf[1] = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ci_dbg("%s %04x -> %d 0x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) __func__, address, ret, buf[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int slot, int address, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ci_dbg("%s %d 0x%04x 0x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) __func__, slot, address, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) buf[0] = (address >> 8) & 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) buf[1] = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) buf[2] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
^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 int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) buf[0] = address & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ci_dbg("%s 0x%02x -> %d 0x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) __func__, address, ret, buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ci_dbg("%s %d 0x%02x 0x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) __func__, slot, address, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) buf[0] = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) buf[1] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ci_dbg("%s %d %d", __func__, slot, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) enable = !!enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) buf[0] = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (enable != buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) err("CI not %sabled.", enable ? "en" : "dis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -EIO;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return tt3650_ci_set_video_port(ca, slot, /* enable */ 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return tt3650_ci_set_video_port(ca, slot, /* enable */ 1);
^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) static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ci_dbg("%s %d", __func__, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) buf[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) mutex_lock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) buf[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) buf[0] = 0; /* FTA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mutex_unlock(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (0 != slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (1 == buf[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return DVB_CA_EN50221_POLL_CAM_PRESENT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) DVB_CA_EN50221_POLL_CAM_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static void tt3650_ci_uninit(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct pctv452e_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ci_dbg("%s", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (NULL == d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (NULL == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (NULL == state->ca.data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Error ignored. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) dvb_ca_en50221_release(&state->ca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) memset(&state->ca, 0, sizeof(state->ca));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static int tt3650_ci_init(struct dvb_usb_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct dvb_usb_device *d = a->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ci_dbg("%s", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) mutex_init(&state->ca_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) state->ca.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) state->ca.read_cam_control = tt3650_ci_read_cam_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) state->ca.write_cam_control = tt3650_ci_write_cam_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) state->ca.slot_reset = tt3650_ci_slot_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) state->ca.data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = dvb_ca_en50221_init(&a->dvb_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) &state->ca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* flags */ 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* n_slots */ 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (0 != ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) err("Cannot initialize CI: Error %d.", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) memset(&state->ca, 0, sizeof(state->ca));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ret;
^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) info("CI initialized.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #define CMD_BUFFER_SIZE 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) const u8 *snd_buf, u8 snd_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u8 *rcv_buf, u8 rcv_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) buf = kmalloc(64, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) id = state->c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (snd_len > 64 - 7 || rcv_len > 64 - 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) buf[0] = SYNC_BYTE_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) buf[1] = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) buf[2] = PCTV_CMD_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) buf[3] = snd_len + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) buf[4] = addr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) buf[5] = snd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) buf[6] = rcv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) memcpy(buf + 7, snd_buf, snd_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) buf, /* rcv_len */ 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* delay_ms */ 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* TT USB protocol error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (SYNC_BYTE_IN != buf[0] || id != buf[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* I2C device didn't respond as expected. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (buf[5] < snd_len || buf[6] < rcv_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) memcpy(rcv_buf, buf + 7, rcv_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return rcv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 7, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct dvb_usb_device *d = i2c_get_adapdata(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (msg[i].flags & I2C_M_RD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) addr = msg[i].addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) snd_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) snd_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) rcv_buf = msg[i].buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rcv_len = msg[i].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) addr = msg[i].addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) snd_buf = msg[i].buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) snd_len = msg[i].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) rcv_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) rcv_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) rcv_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (ret < rcv_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) mutex_unlock(&d->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return I2C_FUNC_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u8 *b0, *rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) info("%s: %d\n", __func__, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (state->initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!b0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) rx = b0 + 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* hmm where should this should go? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) info("%s: Warning set interface returned: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /* this is a one-time initialization, don't know where to put */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) b0[0] = 0xaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) b0[1] = state->c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) b0[2] = PCTV_CMD_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) b0[3] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) b0[4] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* reset board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) goto ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) b0[1] = state->c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) b0[4] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* reset board (again?) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) state->initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) kfree(b0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static int pctv452e_rc_query(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) u8 *b, *rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) rx = b + CMD_BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) id = state->c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* prepare command header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) b[0] = SYNC_BYTE_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) b[1] = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) b[2] = PCTV_CMD_IR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) b[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* send ir request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) goto ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (debug > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) info(" %02x", rx[i+3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) info("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if ((rx[3] == 9) && (rx[12] & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* got a "press" event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) info("%s: cmd=0x%02x sys=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) __func__, rx[6], rx[7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) rc_keydown(d->rc_dev, RC_PROTO_RC5, state->last_rc_key, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) } else if (state->last_rc_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) rc_keyup(d->rc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) state->last_rc_key = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) const u8 mem_addr[] = { 0x1f, 0xcc };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) u8 encoded_mac[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) mem_addr + 1, /* snd_len */ 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) encoded_mac, /* rcv_len */ 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (-EREMOTEIO == ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) byte write if /WC is low. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mem_addr, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) encoded_mac, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) mutex_unlock(&d->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (20 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ret = ttpci_eeprom_decode_mac(mac, encoded_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (0 != ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) eth_zero_addr(mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static const struct stb0899_s1_reg pctv452e_init_dev[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) { STB0899_DISCNTRL1, 0x26 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) { STB0899_DISCNTRL2, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) { STB0899_DISRX_ST0, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) { STB0899_DISRX_ST1, 0x20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) { STB0899_DISPARITY, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) { STB0899_DISFIFO, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) { STB0899_DISF22, 0x99 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) { STB0899_DISF22RX, 0x85 }, /* 0xa8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) { STB0899_ACRPRESC, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) { STB0899_ACRDIV1, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) { STB0899_ACRDIV2, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) { STB0899_DACR1 , 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) { STB0899_DACR2 , 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) { STB0899_OUTCFG, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) { STB0899_MODECFG, 0x00 }, /* Inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) { STB0899_IRQMSK_3, 0xf3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) { STB0899_IRQMSK_2, 0xfc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) { STB0899_IRQMSK_1, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) { STB0899_IRQMSK_0, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) { STB0899_I2CCFG, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) { STB0899_I2CRPT, 0x58 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) { STB0899_GPIO00CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) { STB0899_GPIO01CFG, 0x82 }, /* LED: 0x02 green, 0x82 orange */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) { STB0899_GPIO02CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) { STB0899_GPIO03CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) { STB0899_GPIO04CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) { STB0899_GPIO05CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) { STB0899_GPIO06CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) { STB0899_GPIO07CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) { STB0899_GPIO08CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) { STB0899_GPIO09CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) { STB0899_GPIO10CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) { STB0899_GPIO11CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) { STB0899_GPIO12CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) { STB0899_GPIO13CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) { STB0899_GPIO14CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) { STB0899_GPIO15CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) { STB0899_GPIO16CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) { STB0899_GPIO17CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) { STB0899_GPIO18CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) { STB0899_GPIO19CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) { STB0899_GPIO20CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) { STB0899_SDATCFG, 0xb8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) { STB0899_SCLTCFG, 0xba },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) { STB0899_AGCRFCFG, 0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) { STB0899_GPIO22, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) { STB0899_GPIO21, 0x91 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) { STB0899_DIRCLKCFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) { STB0899_CLKOUT27CFG, 0x7e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) { STB0899_STDBYCFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) { STB0899_CS0CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) { STB0899_CS1CFG, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) { STB0899_DISEQCOCFG, 0x20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) { STB0899_NCOARSE, 0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) { STB0899_SYNTCTRL, 0x00 }, /* 0x00 CLKI, 0x02 XTALI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) { STB0899_FILTCTRL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) { STB0899_SYSCTRL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) { STB0899_STOPCLK1, 0x20 }, /* orig: 0x00 budget-ci: 0x20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) { STB0899_STOPCLK2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) { STB0899_INTBUFCTRL, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) { STB0899_AGC2I1, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) { STB0899_AGC2I2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) { STB0899_AGCIQIN, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) { STB0899_TSTRES, 0x40 }, /* rjkm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) { 0xffff, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) { STB0899_DEMOD, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) { STB0899_RCOMPC, 0xc9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) { STB0899_AGC1CN, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) { STB0899_AGC1REF, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) { STB0899_RTC, 0x23 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) { STB0899_TMGCFG, 0x4e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) { STB0899_AGC2REF, 0x34 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) { STB0899_TLSR, 0x84 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) { STB0899_CFD, 0xf7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) { STB0899_ACLC, 0x87 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) { STB0899_BCLC, 0x94 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) { STB0899_EQON, 0x41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) { STB0899_LDT, 0xf1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) { STB0899_LDT2, 0xe3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) { STB0899_EQUALREF, 0xb4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) { STB0899_TMGRAMP, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) { STB0899_TMGTHD, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) { STB0899_IDCCOMP, 0xfd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) { STB0899_QDCCOMP, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) { STB0899_POWERI, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) { STB0899_POWERQ, 0x0f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) { STB0899_RCOMP, 0x6c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) { STB0899_AGCIQIN, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) { STB0899_AGC2I1, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) { STB0899_AGC2I2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) { STB0899_TLIR, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) { STB0899_RTF, 0x7f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) { STB0899_DSTATUS, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) { STB0899_LDI, 0xbc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) { STB0899_CFRM, 0xea },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) { STB0899_CFRL, 0x31 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) { STB0899_NIRM, 0x2b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) { STB0899_NIRL, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) { STB0899_ISYMB, 0x1d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) { STB0899_QSYMB, 0xa6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) { STB0899_SFRH, 0x2f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) { STB0899_SFRM, 0x68 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) { STB0899_SFRL, 0x40 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) { STB0899_SFRUPH, 0x2f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) { STB0899_SFRUPM, 0x68 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) { STB0899_SFRUPL, 0x40 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) { STB0899_EQUAI1, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) { STB0899_EQUAQ1, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) { STB0899_EQUAI2, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) { STB0899_EQUAQ2, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) { STB0899_EQUAI3, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) { STB0899_EQUAQ3, 0xfd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) { STB0899_EQUAI4, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) { STB0899_EQUAQ4, 0x07 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) { STB0899_EQUAI5, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) { STB0899_EQUAQ5, 0xf5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) { STB0899_DSTATUS2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) { STB0899_VSTATUS, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { STB0899_VERROR, 0x86 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) { STB0899_IQSWAP, 0x2a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) { STB0899_ECNT1M, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) { STB0899_ECNT1L, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) { STB0899_ECNT2M, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) { STB0899_ECNT2L, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) { STB0899_ECNT3M, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) { STB0899_ECNT3L, 0xad },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) { STB0899_FECAUTO1, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) { STB0899_FECM, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) { STB0899_VTH12, 0xb0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) { STB0899_VTH23, 0x7a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) { STB0899_VTH34, 0x58 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) { STB0899_VTH56, 0x38 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) { STB0899_VTH67, 0x34 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) { STB0899_VTH78, 0x24 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) { STB0899_PRVIT, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) { STB0899_VITSYNC, 0x19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) { STB0899_RSULC, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) { STB0899_TSULC, 0x42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) { STB0899_RSLLC, 0x41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) { STB0899_TSLPL, 0x12 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) { STB0899_TSCFGH, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) { STB0899_TSCFGM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) { STB0899_TSCFGL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) { STB0899_TSOUT, 0x69 }, /* 0x0d for CAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) { STB0899_RSSYNCDEL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) { STB0899_TSINHDELH, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) { STB0899_TSINHDELM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) { STB0899_TSINHDELL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) { STB0899_TSLLSTKM, 0x1b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) { STB0899_TSLLSTKL, 0xb3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) { STB0899_TSULSTKM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) { STB0899_TSULSTKL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) { STB0899_PCKLENUL, 0xbc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) { STB0899_PCKLENLL, 0xcc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) { STB0899_RSPCKLEN, 0xbd },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) { STB0899_TSSTATUS, 0x90 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) { STB0899_ERRCTRL1, 0xb6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) { STB0899_ERRCTRL2, 0x95 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) { STB0899_ERRCTRL3, 0x8d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) { STB0899_DMONMSK1, 0x27 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) { STB0899_DMONMSK0, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) { STB0899_DEMAPVIT, 0x5c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) { STB0899_PLPARM, 0x19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) { STB0899_PDELCTRL, 0x48 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) { STB0899_PDELCTRL2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) { STB0899_BBHCTRL1, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) { STB0899_BBHCTRL2, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) { STB0899_HYSTTHRESH, 0x77 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) { STB0899_MATCSTM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) { STB0899_MATCSTL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) { STB0899_UPLCSTM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) { STB0899_UPLCSTL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) { STB0899_DFLCSTM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) { STB0899_DFLCSTL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) { STB0899_SYNCCST, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) { STB0899_SYNCDCSTM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) { STB0899_SYNCDCSTL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) { STB0899_ISI_ENTRY, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) { STB0899_ISI_BIT_EN, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) { STB0899_MATSTRM, 0xf0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) { STB0899_MATSTRL, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) { STB0899_UPLSTRM, 0x45 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) { STB0899_UPLSTRL, 0x60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) { STB0899_DFLSTRM, 0xe3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) { STB0899_DFLSTRL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) { STB0899_SYNCSTR, 0x47 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) { STB0899_SYNCDSTRM, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) { STB0899_SYNCDSTRL, 0x18 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) { STB0899_CFGPDELSTATUS1, 0x19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) { STB0899_CFGPDELSTATUS2, 0x2b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) { STB0899_BBFERRORM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) { STB0899_BBFERRORL, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) { STB0899_UPKTERRORM, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) { STB0899_UPKTERRORL, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) { 0xffff, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static struct stb0899_config stb0899_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .init_dev = pctv452e_init_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .init_s2_demod = stb0899_s2_init_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .init_s1_demod = pctv452e_init_s1_demod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .init_s2_fec = stb0899_s2_init_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .init_tst = stb0899_s1_init_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .demod_address = I2C_ADDR_STB0899, /* I2C Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .block_sync_mode = STB0899_SYNC_FORCED, /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .xtal_freq = 27000000, /* Assume Hz ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .inversion = IQ_SWAP_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) .lo_clk = 76500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .hi_clk = 99000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .ts_output_mode = 0, /* Use parallel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .clock_polarity = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .data_clk_parity = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .fec_mode = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .esno_ave = STB0899_DVBS2_ESNO_AVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .esno_quant = STB0899_DVBS2_ESNO_QUANT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .tuner_get_frequency = stb6100_get_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .tuner_set_frequency = stb6100_set_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .tuner_set_bandwidth = stb6100_set_bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) .tuner_get_bandwidth = stb6100_get_bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .tuner_set_rfsiggain = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* helper for switching LED green/orange */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) .postproc = pctv45e_postproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static struct stb6100_config stb6100_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .tuner_address = I2C_ADDR_STB6100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .refclock = 27000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static struct i2c_algorithm pctv452e_i2c_algo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .master_xfer = pctv452e_i2c_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .functionality = pctv452e_i2c_func
^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) static int pctv452e_frontend_attach(struct dvb_usb_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct usb_device_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) &a->dev->i2c_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (!a->fe_adap[0].fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) id = a->dev->desc->warm_ids[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (id->idVendor == USB_VID_TECHNOTREND &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) id->idProduct == USB_PID_TECHNOTREND_CONNECT_S2_3650_CI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (dvb_attach(lnbp22_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) a->fe_adap[0].fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) &a->dev->i2c_adap) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) err("Cannot attach lnbp22\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* Error ignored. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) tt3650_ci_init(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) } else if (dvb_attach(isl6423_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) a->fe_adap[0].fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) &a->dev->i2c_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) &pctv452e_isl6423_config) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) err("Cannot attach isl6423\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int pctv452e_tuner_attach(struct dvb_usb_adapter *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (!a->fe_adap[0].fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) &a->dev->i2c_adap) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) err("%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static struct usb_device_id pctv452e_usb_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {USB_DEVICE(USB_VID_TECHNOTREND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) MODULE_DEVICE_TABLE(usb, pctv452e_usb_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static struct dvb_usb_device_properties pctv452e_properties = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .usb_ctrl = DEVICE_SPECIFIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .size_of_priv = sizeof(struct pctv452e_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .power_ctrl = pctv452e_power_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .rc.core = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .allowed_protos = RC_PROTO_BIT_RC5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .rc_query = pctv452e_rc_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .rc_interval = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .num_adapters = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .adapter = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .num_frontends = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .fe = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .frontend_attach = pctv452e_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .tuner_attach = pctv452e_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) /* parameter for the MPEG2-data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) .stream = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) .type = USB_ISOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) .count = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) .endpoint = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .u = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .isoc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .framesperurb = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .framesize = 940,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .interval = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .i2c_algo = &pctv452e_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) .num_device_descs = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) .devices = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) { .name = "PCTV HDTV USB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) .cold_ids = { NULL, NULL }, /* this is a warm only device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) .warm_ids = { &pctv452e_usb_table[0], NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) { NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) .usb_ctrl = DEVICE_SPECIFIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) .size_of_priv = sizeof(struct pctv452e_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .power_ctrl = pctv452e_power_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .read_mac_address = pctv452e_read_mac_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) .rc.core = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .rc_codes = RC_MAP_TT_1500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .allowed_protos = RC_PROTO_BIT_RC5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) .rc_query = pctv452e_rc_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) .rc_interval = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .num_adapters = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .adapter = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .num_frontends = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .fe = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .frontend_attach = pctv452e_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) .tuner_attach = pctv452e_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* parameter for the MPEG2-data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .stream = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) .type = USB_ISOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) .count = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) .endpoint = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) .u = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) .isoc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) .framesperurb = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) .framesize = 940,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) .interval = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) .i2c_algo = &pctv452e_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) .generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) .num_device_descs = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .devices = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) { .name = "Technotrend TT Connect S2-3600",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .cold_ids = { NULL, NULL }, /* this is a warm only device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .warm_ids = { &pctv452e_usb_table[1], NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) { .name = "Technotrend TT Connect S2-3650-CI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) .cold_ids = { NULL, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .warm_ids = { &pctv452e_usb_table[2], NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) { NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static void pctv452e_usb_disconnect(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct dvb_usb_device *d = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) tt3650_ci_uninit(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) dvb_usb_device_exit(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static int pctv452e_usb_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (0 == dvb_usb_device_init(intf, &pctv452e_properties,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) THIS_MODULE, NULL, adapter_nr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) THIS_MODULE, NULL, adapter_nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static struct usb_driver pctv452e_usb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) .name = "pctv452e",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) .probe = pctv452e_usb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) .disconnect = pctv452e_usb_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) .id_table = pctv452e_usb_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) module_usb_driver(pctv452e_usb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) MODULE_LICENSE("GPL");