// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PCTV 452e DVB driver
*
* Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
*
* TT connect S2-3650-CI Common Interface support, MAC readout
* Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
*/
/* dvb usb framework */
#define DVB_USB_LOG_PREFIX "pctv452e"
#include "dvb-usb.h"
/* Demodulator */
#include "stb0899_drv.h"
#include "stb0899_reg.h"
#include "stb0899_cfg.h"
/* Tuner */
#include "stb6100.h"
#include "stb6100_cfg.h"
/* FE Power */
#include "isl6423.h"
#include "lnbp22.h"
#include <media/dvb_ca_en50221.h>
#include "ttpci-eeprom.h"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define ISOC_INTERFACE_ALTERNATIVE 3
#define SYNC_BYTE_OUT 0xaa
#define SYNC_BYTE_IN 0x55
/* guessed: (copied from ttusb-budget) */
#define PCTV_CMD_RESET 0x15
/* command to poll IR receiver */
#define PCTV_CMD_IR 0x1b
/* command to send I2C */
#define PCTV_CMD_I2C 0x31
#define I2C_ADDR_STB0899 (0xd0 >> 1)
#define I2C_ADDR_STB6100 (0xc0 >> 1)
#define I2C_ADDR_LNBP22 (0x10 >> 1)
#define I2C_ADDR_24C16 (0xa0 >> 1)
#define I2C_ADDR_24C64 (0xa2 >> 1)
/* pctv452e sends us this amount of data for each issued usb-command */
#define PCTV_ANSWER_LEN 64
/* Wait up to 1000ms for device */
#define PCTV_TIMEOUT 1000
#define PCTV_LED_GPIO STB0899_GPIO01
#define PCTV_LED_GREEN 0x82
#define PCTV_LED_ORANGE 0x02
#define ci_dbg(format, arg...) \
do { \
if (0) \
printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
": " format "\n" , ## arg); \
} while (0)
enum {
TT3650_CMD_CI_TEST = 0x40,
TT3650_CMD_CI_RD_CTRL,
TT3650_CMD_CI_WR_CTRL,
TT3650_CMD_CI_RD_ATTR,
TT3650_CMD_CI_WR_ATTR,
TT3650_CMD_CI_RESET,
TT3650_CMD_CI_SET_VIDEO_PORT
};
static struct stb0899_postproc pctv45e_postproc[] = {
{ PCTV_LED_GPIO, STB0899_GPIOPULLUP },
{ 0, 0 }
};
static struct isl6423_config pctv452e_isl6423_config = {
.current_max = SEC_CURRENT_515m,
.curlim = SEC_CURRENT_LIM_ON,
.mod_extern = 1,
.addr = 0x08,
};
/*
* stores all private variables for communication with the PCTV452e DVB-S2
*/
struct pctv452e_state {
struct dvb_ca_en50221 ca;
struct mutex ca_mutex;
u8 c; /* transaction counter, wraps around... */
u8 initialized; /* set to 1 if 0x15 has been sent */
u16 last_rc_key;
};
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
unsigned int write_len, unsigned int read_len)
{
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 *buf;
u8 id;
unsigned int rlen;
int ret;
if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) {
err("%s: transfer data invalid", __func__);
return -EIO;
}
buf = kmalloc(64, GFP_KERNEL);
if (!buf)
return -ENOMEM;
id = state->c++;
buf[0] = SYNC_BYTE_OUT;
buf[1] = id;
buf[2] = cmd;
buf[3] = write_len;
memcpy(buf + 4, data, write_len);
rlen = (read_len > 0) ? 64 : 0;
ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
buf, rlen, /* delay_ms */ 0);
if (0 != ret)
goto failed;
ret = -EIO;
if (SYNC_BYTE_IN != buf[0] || id != buf[1])
goto failed;
memcpy(data, buf + 4, read_len);
kfree(buf);
return 0;
failed:
err("CI error %d; %02X %02X %02X -> %*ph.",
ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
kfree(buf);
return ret;
}
static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
u8 cmd, u8 *data, unsigned int write_len,
unsigned int read_len)
{
struct dvb_usb_device *d