1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2786baecfSMauro Carvalho Chehab /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones 3786baecfSMauro Carvalho Chehab * (e.g. Pinnacle 400e DVB-S USB2.0). 4786baecfSMauro Carvalho Chehab * 5786baecfSMauro Carvalho Chehab * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. 6786baecfSMauro Carvalho Chehab * 7786baecfSMauro Carvalho Chehab * TDA8263 + TDA10086 8786baecfSMauro Carvalho Chehab * 9786baecfSMauro Carvalho Chehab * I2C addresses: 10786baecfSMauro Carvalho Chehab * 0x08 - LNBP21PD - LNB power supply 11786baecfSMauro Carvalho Chehab * 0x0e - TDA10086 - Demodulator 12786baecfSMauro Carvalho Chehab * 0x50 - FX2 eeprom 13786baecfSMauro Carvalho Chehab * 0x60 - TDA8263 - Tuner 14786baecfSMauro Carvalho Chehab * 0x78 ??? 15786baecfSMauro Carvalho Chehab * 16786baecfSMauro Carvalho Chehab * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> 17786baecfSMauro Carvalho Chehab * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> 18786baecfSMauro Carvalho Chehab * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org> 19786baecfSMauro Carvalho Chehab * 20*577a7ad3SMauro Carvalho Chehab * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 21786baecfSMauro Carvalho Chehab */ 22786baecfSMauro Carvalho Chehab #define DVB_USB_LOG_PREFIX "ttusb2" 23786baecfSMauro Carvalho Chehab #include "dvb-usb.h" 24786baecfSMauro Carvalho Chehab 25786baecfSMauro Carvalho Chehab #include "ttusb2.h" 26786baecfSMauro Carvalho Chehab 27786baecfSMauro Carvalho Chehab #include "tda826x.h" 28786baecfSMauro Carvalho Chehab #include "tda10086.h" 29786baecfSMauro Carvalho Chehab #include "tda1002x.h" 30786baecfSMauro Carvalho Chehab #include "tda10048.h" 31786baecfSMauro Carvalho Chehab #include "tda827x.h" 32786baecfSMauro Carvalho Chehab #include "lnbp21.h" 33786baecfSMauro Carvalho Chehab /* CA */ 34fada1935SMauro Carvalho Chehab #include <media/dvb_ca_en50221.h> 35786baecfSMauro Carvalho Chehab 36786baecfSMauro Carvalho Chehab /* debug */ 37786baecfSMauro Carvalho Chehab static int dvb_usb_ttusb2_debug; 38786baecfSMauro Carvalho Chehab #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) 39786baecfSMauro Carvalho Chehab module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); 40786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); 41786baecfSMauro Carvalho Chehab static int dvb_usb_ttusb2_debug_ci; 42786baecfSMauro Carvalho Chehab module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644); 43786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS); 44786baecfSMauro Carvalho Chehab 45786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 46786baecfSMauro Carvalho Chehab 47786baecfSMauro Carvalho Chehab #define ci_dbg(format, arg...) \ 48786baecfSMauro Carvalho Chehab do { \ 49786baecfSMauro Carvalho Chehab if (dvb_usb_ttusb2_debug_ci) \ 50786baecfSMauro Carvalho Chehab printk(KERN_DEBUG DVB_USB_LOG_PREFIX \ 51786baecfSMauro Carvalho Chehab ": %s " format "\n" , __func__, ## arg); \ 52786baecfSMauro Carvalho Chehab } while (0) 53786baecfSMauro Carvalho Chehab 54786baecfSMauro Carvalho Chehab enum { 55786baecfSMauro Carvalho Chehab TT3650_CMD_CI_TEST = 0x40, 56786baecfSMauro Carvalho Chehab TT3650_CMD_CI_RD_CTRL, 57786baecfSMauro Carvalho Chehab TT3650_CMD_CI_WR_CTRL, 58786baecfSMauro Carvalho Chehab TT3650_CMD_CI_RD_ATTR, 59786baecfSMauro Carvalho Chehab TT3650_CMD_CI_WR_ATTR, 60786baecfSMauro Carvalho Chehab TT3650_CMD_CI_RESET, 61786baecfSMauro Carvalho Chehab TT3650_CMD_CI_SET_VIDEO_PORT 62786baecfSMauro Carvalho Chehab }; 63786baecfSMauro Carvalho Chehab 64786baecfSMauro Carvalho Chehab struct ttusb2_state { 65786baecfSMauro Carvalho Chehab struct dvb_ca_en50221 ca; 66786baecfSMauro Carvalho Chehab struct mutex ca_mutex; 67786baecfSMauro Carvalho Chehab u8 id; 68786baecfSMauro Carvalho Chehab u16 last_rc_key; 69786baecfSMauro Carvalho Chehab }; 70786baecfSMauro Carvalho Chehab 71786baecfSMauro Carvalho Chehab static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, 72786baecfSMauro Carvalho Chehab u8 *wbuf, int wlen, u8 *rbuf, int rlen) 73786baecfSMauro Carvalho Chehab { 74786baecfSMauro Carvalho Chehab struct ttusb2_state *st = d->priv; 75786baecfSMauro Carvalho Chehab u8 *s, *r = NULL; 76786baecfSMauro Carvalho Chehab int ret = 0; 77786baecfSMauro Carvalho Chehab 78a12b8ab8SAlyssa Milburn if (4 + rlen > 64) 79a12b8ab8SAlyssa Milburn return -EIO; 80a12b8ab8SAlyssa Milburn 81786baecfSMauro Carvalho Chehab s = kzalloc(wlen+4, GFP_KERNEL); 82786baecfSMauro Carvalho Chehab if (!s) 83786baecfSMauro Carvalho Chehab return -ENOMEM; 84786baecfSMauro Carvalho Chehab 85786baecfSMauro Carvalho Chehab r = kzalloc(64, GFP_KERNEL); 86786baecfSMauro Carvalho Chehab if (!r) { 87786baecfSMauro Carvalho Chehab kfree(s); 88786baecfSMauro Carvalho Chehab return -ENOMEM; 89786baecfSMauro Carvalho Chehab } 90786baecfSMauro Carvalho Chehab 91786baecfSMauro Carvalho Chehab s[0] = 0xaa; 92786baecfSMauro Carvalho Chehab s[1] = ++st->id; 93786baecfSMauro Carvalho Chehab s[2] = cmd; 94786baecfSMauro Carvalho Chehab s[3] = wlen; 95786baecfSMauro Carvalho Chehab memcpy(&s[4],wbuf,wlen); 96786baecfSMauro Carvalho Chehab 97786baecfSMauro Carvalho Chehab ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); 98786baecfSMauro Carvalho Chehab 99786baecfSMauro Carvalho Chehab if (ret != 0 || 100786baecfSMauro Carvalho Chehab r[0] != 0x55 || 101786baecfSMauro Carvalho Chehab r[1] != s[1] || 102786baecfSMauro Carvalho Chehab r[2] != cmd || 103786baecfSMauro Carvalho Chehab (rlen > 0 && r[3] != rlen)) { 104786baecfSMauro Carvalho Chehab warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); 105786baecfSMauro Carvalho Chehab kfree(s); 106786baecfSMauro Carvalho Chehab kfree(r); 107786baecfSMauro Carvalho Chehab return -EIO; 108786baecfSMauro Carvalho Chehab } 109786baecfSMauro Carvalho Chehab 110786baecfSMauro Carvalho Chehab if (rlen > 0) 111786baecfSMauro Carvalho Chehab memcpy(rbuf, &r[4], rlen); 112786baecfSMauro Carvalho Chehab 113786baecfSMauro Carvalho Chehab kfree(s); 114786baecfSMauro Carvalho Chehab kfree(r); 115786baecfSMauro Carvalho Chehab 116786baecfSMauro Carvalho Chehab return 0; 117786baecfSMauro Carvalho Chehab } 118786baecfSMauro Carvalho Chehab 119786baecfSMauro Carvalho Chehab /* ci */ 120786baecfSMauro Carvalho Chehab static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) 121786baecfSMauro Carvalho Chehab { 122786baecfSMauro Carvalho Chehab int ret; 123786baecfSMauro Carvalho Chehab u8 rx[60];/* (64 -4) */ 124786baecfSMauro Carvalho Chehab ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len); 125786baecfSMauro Carvalho Chehab if (!ret) 126786baecfSMauro Carvalho Chehab memcpy(data, rx, read_len); 127786baecfSMauro Carvalho Chehab return ret; 128786baecfSMauro Carvalho Chehab } 129786baecfSMauro Carvalho Chehab 130786baecfSMauro Carvalho Chehab static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) 131786baecfSMauro Carvalho Chehab { 132786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = ca->data; 133786baecfSMauro Carvalho Chehab struct ttusb2_state *state = d->priv; 134786baecfSMauro Carvalho Chehab int ret; 135786baecfSMauro Carvalho Chehab 136786baecfSMauro Carvalho Chehab mutex_lock(&state->ca_mutex); 137786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg(d, cmd, data, write_len, read_len); 138786baecfSMauro Carvalho Chehab mutex_unlock(&state->ca_mutex); 139786baecfSMauro Carvalho Chehab 140786baecfSMauro Carvalho Chehab return ret; 141786baecfSMauro Carvalho Chehab } 142786baecfSMauro Carvalho Chehab 143786baecfSMauro Carvalho Chehab static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) 144786baecfSMauro Carvalho Chehab { 145786baecfSMauro Carvalho Chehab u8 buf[3]; 146786baecfSMauro Carvalho Chehab int ret = 0; 147786baecfSMauro Carvalho Chehab 148786baecfSMauro Carvalho Chehab if (slot) 149786baecfSMauro Carvalho Chehab return -EINVAL; 150786baecfSMauro Carvalho Chehab 151786baecfSMauro Carvalho Chehab buf[0] = (address >> 8) & 0x0F; 152786baecfSMauro Carvalho Chehab buf[1] = address; 153786baecfSMauro Carvalho Chehab 154786baecfSMauro Carvalho Chehab 155786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3); 156786baecfSMauro Carvalho Chehab 157786baecfSMauro Carvalho Chehab ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]); 158786baecfSMauro Carvalho Chehab 159786baecfSMauro Carvalho Chehab if (ret < 0) 160786baecfSMauro Carvalho Chehab return ret; 161786baecfSMauro Carvalho Chehab 162786baecfSMauro Carvalho Chehab return buf[2]; 163786baecfSMauro Carvalho Chehab } 164786baecfSMauro Carvalho Chehab 165786baecfSMauro Carvalho Chehab static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) 166786baecfSMauro Carvalho Chehab { 167786baecfSMauro Carvalho Chehab u8 buf[3]; 168786baecfSMauro Carvalho Chehab 169786baecfSMauro Carvalho Chehab ci_dbg("%d 0x%04x 0x%02x", slot, address, value); 170786baecfSMauro Carvalho Chehab 171786baecfSMauro Carvalho Chehab if (slot) 172786baecfSMauro Carvalho Chehab return -EINVAL; 173786baecfSMauro Carvalho Chehab 174786baecfSMauro Carvalho Chehab buf[0] = (address >> 8) & 0x0F; 175786baecfSMauro Carvalho Chehab buf[1] = address; 176786baecfSMauro Carvalho Chehab buf[2] = value; 177786baecfSMauro Carvalho Chehab 178786baecfSMauro Carvalho Chehab return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3); 179786baecfSMauro Carvalho Chehab } 180786baecfSMauro Carvalho Chehab 181786baecfSMauro Carvalho Chehab static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) 182786baecfSMauro Carvalho Chehab { 183786baecfSMauro Carvalho Chehab u8 buf[2]; 184786baecfSMauro Carvalho Chehab int ret; 185786baecfSMauro Carvalho Chehab 186786baecfSMauro Carvalho Chehab if (slot) 187786baecfSMauro Carvalho Chehab return -EINVAL; 188786baecfSMauro Carvalho Chehab 189786baecfSMauro Carvalho Chehab buf[0] = address & 3; 190786baecfSMauro Carvalho Chehab 191786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2); 192786baecfSMauro Carvalho Chehab 193786baecfSMauro Carvalho Chehab ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]); 194786baecfSMauro Carvalho Chehab 195786baecfSMauro Carvalho Chehab if (ret < 0) 196786baecfSMauro Carvalho Chehab return ret; 197786baecfSMauro Carvalho Chehab 198786baecfSMauro Carvalho Chehab return buf[1]; 199786baecfSMauro Carvalho Chehab } 200786baecfSMauro Carvalho Chehab 201786baecfSMauro Carvalho Chehab static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) 202786baecfSMauro Carvalho Chehab { 203786baecfSMauro Carvalho Chehab u8 buf[2]; 204786baecfSMauro Carvalho Chehab 205786baecfSMauro Carvalho Chehab ci_dbg("%d 0x%02x 0x%02x", slot, address, value); 206786baecfSMauro Carvalho Chehab 207786baecfSMauro Carvalho Chehab if (slot) 208786baecfSMauro Carvalho Chehab return -EINVAL; 209786baecfSMauro Carvalho Chehab 210786baecfSMauro Carvalho Chehab buf[0] = address; 211786baecfSMauro Carvalho Chehab buf[1] = value; 212786baecfSMauro Carvalho Chehab 213786baecfSMauro Carvalho Chehab return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2); 214786baecfSMauro Carvalho Chehab } 215786baecfSMauro Carvalho Chehab 216786baecfSMauro Carvalho Chehab static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable) 217786baecfSMauro Carvalho Chehab { 218786baecfSMauro Carvalho Chehab u8 buf[1]; 219786baecfSMauro Carvalho Chehab int ret; 220786baecfSMauro Carvalho Chehab 221786baecfSMauro Carvalho Chehab ci_dbg("%d %d", slot, enable); 222786baecfSMauro Carvalho Chehab 223786baecfSMauro Carvalho Chehab if (slot) 224786baecfSMauro Carvalho Chehab return -EINVAL; 225786baecfSMauro Carvalho Chehab 226786baecfSMauro Carvalho Chehab buf[0] = enable; 227786baecfSMauro Carvalho Chehab 228786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1); 229786baecfSMauro Carvalho Chehab if (ret < 0) 230786baecfSMauro Carvalho Chehab return ret; 231786baecfSMauro Carvalho Chehab 232786baecfSMauro Carvalho Chehab if (enable != buf[0]) { 233786baecfSMauro Carvalho Chehab err("CI not %sabled.", enable ? "en" : "dis"); 234786baecfSMauro Carvalho Chehab return -EIO; 235786baecfSMauro Carvalho Chehab } 236786baecfSMauro Carvalho Chehab 237786baecfSMauro Carvalho Chehab return 0; 238786baecfSMauro Carvalho Chehab } 239786baecfSMauro Carvalho Chehab 240786baecfSMauro Carvalho Chehab static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) 241786baecfSMauro Carvalho Chehab { 242786baecfSMauro Carvalho Chehab return tt3650_ci_set_video_port(ca, slot, 0); 243786baecfSMauro Carvalho Chehab } 244786baecfSMauro Carvalho Chehab 245786baecfSMauro Carvalho Chehab static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) 246786baecfSMauro Carvalho Chehab { 247786baecfSMauro Carvalho Chehab return tt3650_ci_set_video_port(ca, slot, 1); 248786baecfSMauro Carvalho Chehab } 249786baecfSMauro Carvalho Chehab 250786baecfSMauro Carvalho Chehab static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) 251786baecfSMauro Carvalho Chehab { 252786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = ca->data; 253786baecfSMauro Carvalho Chehab struct ttusb2_state *state = d->priv; 254786baecfSMauro Carvalho Chehab u8 buf[1]; 255786baecfSMauro Carvalho Chehab int ret; 256786baecfSMauro Carvalho Chehab 257786baecfSMauro Carvalho Chehab ci_dbg("%d", slot); 258786baecfSMauro Carvalho Chehab 259786baecfSMauro Carvalho Chehab if (slot) 260786baecfSMauro Carvalho Chehab return -EINVAL; 261786baecfSMauro Carvalho Chehab 262786baecfSMauro Carvalho Chehab buf[0] = 0; 263786baecfSMauro Carvalho Chehab 264786baecfSMauro Carvalho Chehab mutex_lock(&state->ca_mutex); 265786baecfSMauro Carvalho Chehab 266786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1); 267786baecfSMauro Carvalho Chehab if (ret) 268786baecfSMauro Carvalho Chehab goto failed; 269786baecfSMauro Carvalho Chehab 270786baecfSMauro Carvalho Chehab msleep(500); 271786baecfSMauro Carvalho Chehab 272786baecfSMauro Carvalho Chehab buf[0] = 1; 273786baecfSMauro Carvalho Chehab 274786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1); 275786baecfSMauro Carvalho Chehab if (ret) 276786baecfSMauro Carvalho Chehab goto failed; 277786baecfSMauro Carvalho Chehab 278786baecfSMauro Carvalho Chehab msleep(500); 279786baecfSMauro Carvalho Chehab 280786baecfSMauro Carvalho Chehab buf[0] = 0; /* FTA */ 281786baecfSMauro Carvalho Chehab 282786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1); 283786baecfSMauro Carvalho Chehab 284786baecfSMauro Carvalho Chehab msleep(1100); 285786baecfSMauro Carvalho Chehab 286786baecfSMauro Carvalho Chehab failed: 287786baecfSMauro Carvalho Chehab mutex_unlock(&state->ca_mutex); 288786baecfSMauro Carvalho Chehab 289786baecfSMauro Carvalho Chehab return ret; 290786baecfSMauro Carvalho Chehab } 291786baecfSMauro Carvalho Chehab 292786baecfSMauro Carvalho Chehab static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) 293786baecfSMauro Carvalho Chehab { 294786baecfSMauro Carvalho Chehab u8 buf[1]; 295786baecfSMauro Carvalho Chehab int ret; 296786baecfSMauro Carvalho Chehab 297786baecfSMauro Carvalho Chehab if (slot) 298786baecfSMauro Carvalho Chehab return -EINVAL; 299786baecfSMauro Carvalho Chehab 300786baecfSMauro Carvalho Chehab ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1); 301786baecfSMauro Carvalho Chehab if (ret) 302786baecfSMauro Carvalho Chehab return ret; 303786baecfSMauro Carvalho Chehab 304786baecfSMauro Carvalho Chehab if (1 == buf[0]) { 305786baecfSMauro Carvalho Chehab return DVB_CA_EN50221_POLL_CAM_PRESENT | 306786baecfSMauro Carvalho Chehab DVB_CA_EN50221_POLL_CAM_READY; 307786baecfSMauro Carvalho Chehab } 308786baecfSMauro Carvalho Chehab return 0; 309786baecfSMauro Carvalho Chehab } 310786baecfSMauro Carvalho Chehab 311786baecfSMauro Carvalho Chehab static void tt3650_ci_uninit(struct dvb_usb_device *d) 312786baecfSMauro Carvalho Chehab { 313786baecfSMauro Carvalho Chehab struct ttusb2_state *state; 314786baecfSMauro Carvalho Chehab 315786baecfSMauro Carvalho Chehab ci_dbg(""); 316786baecfSMauro Carvalho Chehab 317786baecfSMauro Carvalho Chehab if (NULL == d) 318786baecfSMauro Carvalho Chehab return; 319786baecfSMauro Carvalho Chehab 320786baecfSMauro Carvalho Chehab state = d->priv; 321786baecfSMauro Carvalho Chehab if (NULL == state) 322786baecfSMauro Carvalho Chehab return; 323786baecfSMauro Carvalho Chehab 324786baecfSMauro Carvalho Chehab if (NULL == state->ca.data) 325786baecfSMauro Carvalho Chehab return; 326786baecfSMauro Carvalho Chehab 327786baecfSMauro Carvalho Chehab dvb_ca_en50221_release(&state->ca); 328786baecfSMauro Carvalho Chehab 329786baecfSMauro Carvalho Chehab memset(&state->ca, 0, sizeof(state->ca)); 330786baecfSMauro Carvalho Chehab } 331786baecfSMauro Carvalho Chehab 332786baecfSMauro Carvalho Chehab static int tt3650_ci_init(struct dvb_usb_adapter *a) 333786baecfSMauro Carvalho Chehab { 334786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = a->dev; 335786baecfSMauro Carvalho Chehab struct ttusb2_state *state = d->priv; 336786baecfSMauro Carvalho Chehab int ret; 337786baecfSMauro Carvalho Chehab 338786baecfSMauro Carvalho Chehab ci_dbg(""); 339786baecfSMauro Carvalho Chehab 340786baecfSMauro Carvalho Chehab mutex_init(&state->ca_mutex); 341786baecfSMauro Carvalho Chehab 342786baecfSMauro Carvalho Chehab state->ca.owner = THIS_MODULE; 343786baecfSMauro Carvalho Chehab state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem; 344786baecfSMauro Carvalho Chehab state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem; 345786baecfSMauro Carvalho Chehab state->ca.read_cam_control = tt3650_ci_read_cam_control; 346786baecfSMauro Carvalho Chehab state->ca.write_cam_control = tt3650_ci_write_cam_control; 347786baecfSMauro Carvalho Chehab state->ca.slot_reset = tt3650_ci_slot_reset; 348786baecfSMauro Carvalho Chehab state->ca.slot_shutdown = tt3650_ci_slot_shutdown; 349786baecfSMauro Carvalho Chehab state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable; 350786baecfSMauro Carvalho Chehab state->ca.poll_slot_status = tt3650_ci_poll_slot_status; 351786baecfSMauro Carvalho Chehab state->ca.data = d; 352786baecfSMauro Carvalho Chehab 353786baecfSMauro Carvalho Chehab ret = dvb_ca_en50221_init(&a->dvb_adap, 354786baecfSMauro Carvalho Chehab &state->ca, 355786baecfSMauro Carvalho Chehab /* flags */ 0, 356786baecfSMauro Carvalho Chehab /* n_slots */ 1); 357786baecfSMauro Carvalho Chehab if (ret) { 358786baecfSMauro Carvalho Chehab err("Cannot initialize CI: Error %d.", ret); 359786baecfSMauro Carvalho Chehab memset(&state->ca, 0, sizeof(state->ca)); 360786baecfSMauro Carvalho Chehab return ret; 361786baecfSMauro Carvalho Chehab } 362786baecfSMauro Carvalho Chehab 363786baecfSMauro Carvalho Chehab info("CI initialized."); 364786baecfSMauro Carvalho Chehab 365786baecfSMauro Carvalho Chehab return 0; 366786baecfSMauro Carvalho Chehab } 367786baecfSMauro Carvalho Chehab 368786baecfSMauro Carvalho Chehab static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) 369786baecfSMauro Carvalho Chehab { 370786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 371786baecfSMauro Carvalho Chehab static u8 obuf[60], ibuf[60]; 372786baecfSMauro Carvalho Chehab int i, write_read, read; 373786baecfSMauro Carvalho Chehab 374786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 375786baecfSMauro Carvalho Chehab return -EAGAIN; 376786baecfSMauro Carvalho Chehab 377786baecfSMauro Carvalho Chehab if (num > 2) 378786baecfSMauro Carvalho Chehab warn("more than 2 i2c messages at a time is not handled yet. TODO."); 379786baecfSMauro Carvalho Chehab 380786baecfSMauro Carvalho Chehab for (i = 0; i < num; i++) { 381786baecfSMauro Carvalho Chehab write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD); 382786baecfSMauro Carvalho Chehab read = msg[i].flags & I2C_M_RD; 383786baecfSMauro Carvalho Chehab 384a12b8ab8SAlyssa Milburn if (3 + msg[i].len > sizeof(obuf)) { 385a12b8ab8SAlyssa Milburn err("i2c wr len=%d too high", msg[i].len); 386a12b8ab8SAlyssa Milburn break; 387a12b8ab8SAlyssa Milburn } 388a12b8ab8SAlyssa Milburn if (write_read) { 389a12b8ab8SAlyssa Milburn if (3 + msg[i+1].len > sizeof(ibuf)) { 390a12b8ab8SAlyssa Milburn err("i2c rd len=%d too high", msg[i+1].len); 391a12b8ab8SAlyssa Milburn break; 392a12b8ab8SAlyssa Milburn } 393a12b8ab8SAlyssa Milburn } else if (read) { 394a12b8ab8SAlyssa Milburn if (3 + msg[i].len > sizeof(ibuf)) { 395a12b8ab8SAlyssa Milburn err("i2c rd len=%d too high", msg[i].len); 396a12b8ab8SAlyssa Milburn break; 397a12b8ab8SAlyssa Milburn } 398a12b8ab8SAlyssa Milburn } 399a12b8ab8SAlyssa Milburn 400786baecfSMauro Carvalho Chehab obuf[0] = (msg[i].addr << 1) | (write_read | read); 401786baecfSMauro Carvalho Chehab if (read) 402786baecfSMauro Carvalho Chehab obuf[1] = 0; 403786baecfSMauro Carvalho Chehab else 404786baecfSMauro Carvalho Chehab obuf[1] = msg[i].len; 405786baecfSMauro Carvalho Chehab 406786baecfSMauro Carvalho Chehab /* read request */ 407786baecfSMauro Carvalho Chehab if (write_read) 408786baecfSMauro Carvalho Chehab obuf[2] = msg[i+1].len; 409786baecfSMauro Carvalho Chehab else if (read) 410786baecfSMauro Carvalho Chehab obuf[2] = msg[i].len; 411786baecfSMauro Carvalho Chehab else 412786baecfSMauro Carvalho Chehab obuf[2] = 0; 413786baecfSMauro Carvalho Chehab 414786baecfSMauro Carvalho Chehab memcpy(&obuf[3], msg[i].buf, msg[i].len); 415786baecfSMauro Carvalho Chehab 416786baecfSMauro Carvalho Chehab if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) { 417786baecfSMauro Carvalho Chehab err("i2c transfer failed."); 418786baecfSMauro Carvalho Chehab break; 419786baecfSMauro Carvalho Chehab } 420786baecfSMauro Carvalho Chehab 421786baecfSMauro Carvalho Chehab if (write_read) { 422786baecfSMauro Carvalho Chehab memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len); 423786baecfSMauro Carvalho Chehab i++; 424786baecfSMauro Carvalho Chehab } else if (read) 425786baecfSMauro Carvalho Chehab memcpy(msg[i].buf, &ibuf[3], msg[i].len); 426786baecfSMauro Carvalho Chehab } 427786baecfSMauro Carvalho Chehab 428786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 429786baecfSMauro Carvalho Chehab return i; 430786baecfSMauro Carvalho Chehab } 431786baecfSMauro Carvalho Chehab 432786baecfSMauro Carvalho Chehab static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) 433786baecfSMauro Carvalho Chehab { 434786baecfSMauro Carvalho Chehab return I2C_FUNC_I2C; 435786baecfSMauro Carvalho Chehab } 436786baecfSMauro Carvalho Chehab 437786baecfSMauro Carvalho Chehab static struct i2c_algorithm ttusb2_i2c_algo = { 438786baecfSMauro Carvalho Chehab .master_xfer = ttusb2_i2c_xfer, 439786baecfSMauro Carvalho Chehab .functionality = ttusb2_i2c_func, 440786baecfSMauro Carvalho Chehab }; 441786baecfSMauro Carvalho Chehab 442786baecfSMauro Carvalho Chehab /* command to poll IR receiver (copied from pctv452e.c) */ 443786baecfSMauro Carvalho Chehab #define CMD_GET_IR_CODE 0x1b 444786baecfSMauro Carvalho Chehab 445786baecfSMauro Carvalho Chehab /* IR */ 446786baecfSMauro Carvalho Chehab static int tt3650_rc_query(struct dvb_usb_device *d) 447786baecfSMauro Carvalho Chehab { 448786baecfSMauro Carvalho Chehab int ret; 449786baecfSMauro Carvalho Chehab u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */ 450786baecfSMauro Carvalho Chehab struct ttusb2_state *st = d->priv; 451786baecfSMauro Carvalho Chehab ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx)); 452786baecfSMauro Carvalho Chehab if (ret != 0) 453786baecfSMauro Carvalho Chehab return ret; 454786baecfSMauro Carvalho Chehab 455786baecfSMauro Carvalho Chehab if (rx[8] & 0x01) { 456786baecfSMauro Carvalho Chehab /* got a "press" event */ 457120703f9SDavid Härdeman st->last_rc_key = RC_SCANCODE_RC5(rx[3], rx[2]); 458786baecfSMauro Carvalho Chehab deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); 4596d741bfeSSean Young rc_keydown(d->rc_dev, RC_PROTO_RC5, st->last_rc_key, rx[1]); 460786baecfSMauro Carvalho Chehab } else if (st->last_rc_key) { 461786baecfSMauro Carvalho Chehab rc_keyup(d->rc_dev); 462786baecfSMauro Carvalho Chehab st->last_rc_key = 0; 463786baecfSMauro Carvalho Chehab } 464786baecfSMauro Carvalho Chehab 465786baecfSMauro Carvalho Chehab return 0; 466786baecfSMauro Carvalho Chehab } 467786baecfSMauro Carvalho Chehab 468786baecfSMauro Carvalho Chehab 469786baecfSMauro Carvalho Chehab /* Callbacks for DVB USB */ 470786baecfSMauro Carvalho Chehab static int ttusb2_identify_state (struct usb_device *udev, struct 471786baecfSMauro Carvalho Chehab dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, 472786baecfSMauro Carvalho Chehab int *cold) 473786baecfSMauro Carvalho Chehab { 474786baecfSMauro Carvalho Chehab *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; 475786baecfSMauro Carvalho Chehab return 0; 476786baecfSMauro Carvalho Chehab } 477786baecfSMauro Carvalho Chehab 478786baecfSMauro Carvalho Chehab static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) 479786baecfSMauro Carvalho Chehab { 480786baecfSMauro Carvalho Chehab u8 b = onoff; 481786baecfSMauro Carvalho Chehab ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); 482786baecfSMauro Carvalho Chehab return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); 483786baecfSMauro Carvalho Chehab } 484786baecfSMauro Carvalho Chehab 485786baecfSMauro Carvalho Chehab 486786baecfSMauro Carvalho Chehab static struct tda10086_config tda10086_config = { 487786baecfSMauro Carvalho Chehab .demod_address = 0x0e, 488786baecfSMauro Carvalho Chehab .invert = 0, 489786baecfSMauro Carvalho Chehab .diseqc_tone = 1, 490786baecfSMauro Carvalho Chehab .xtal_freq = TDA10086_XTAL_16M, 491786baecfSMauro Carvalho Chehab }; 492786baecfSMauro Carvalho Chehab 493786baecfSMauro Carvalho Chehab static struct tda10023_config tda10023_config = { 494786baecfSMauro Carvalho Chehab .demod_address = 0x0c, 495786baecfSMauro Carvalho Chehab .invert = 0, 496786baecfSMauro Carvalho Chehab .xtal = 16000000, 497786baecfSMauro Carvalho Chehab .pll_m = 11, 498786baecfSMauro Carvalho Chehab .pll_p = 3, 499786baecfSMauro Carvalho Chehab .pll_n = 1, 500786baecfSMauro Carvalho Chehab .deltaf = 0xa511, 501786baecfSMauro Carvalho Chehab }; 502786baecfSMauro Carvalho Chehab 503786baecfSMauro Carvalho Chehab static struct tda10048_config tda10048_config = { 504786baecfSMauro Carvalho Chehab .demod_address = 0x10 >> 1, 505786baecfSMauro Carvalho Chehab .output_mode = TDA10048_PARALLEL_OUTPUT, 506786baecfSMauro Carvalho Chehab .inversion = TDA10048_INVERSION_ON, 507786baecfSMauro Carvalho Chehab .dtv6_if_freq_khz = TDA10048_IF_4000, 508786baecfSMauro Carvalho Chehab .dtv7_if_freq_khz = TDA10048_IF_4500, 509786baecfSMauro Carvalho Chehab .dtv8_if_freq_khz = TDA10048_IF_5000, 510786baecfSMauro Carvalho Chehab .clk_freq_khz = TDA10048_CLK_16000, 511786baecfSMauro Carvalho Chehab .no_firmware = 1, 512786baecfSMauro Carvalho Chehab .set_pll = true , 513786baecfSMauro Carvalho Chehab .pll_m = 5, 514786baecfSMauro Carvalho Chehab .pll_n = 3, 515786baecfSMauro Carvalho Chehab .pll_p = 0, 516786baecfSMauro Carvalho Chehab }; 517786baecfSMauro Carvalho Chehab 518786baecfSMauro Carvalho Chehab static struct tda827x_config tda827x_config = { 519786baecfSMauro Carvalho Chehab .config = 0, 520786baecfSMauro Carvalho Chehab }; 521786baecfSMauro Carvalho Chehab 522786baecfSMauro Carvalho Chehab static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap) 523786baecfSMauro Carvalho Chehab { 524786baecfSMauro Carvalho Chehab if (usb_set_interface(adap->dev->udev,0,3) < 0) 525786baecfSMauro Carvalho Chehab err("set interface to alts=3 failed"); 526786baecfSMauro Carvalho Chehab 527786baecfSMauro Carvalho Chehab if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { 528786baecfSMauro Carvalho Chehab deb_info("TDA10086 attach failed\n"); 529786baecfSMauro Carvalho Chehab return -ENODEV; 530786baecfSMauro Carvalho Chehab } 531786baecfSMauro Carvalho Chehab 532786baecfSMauro Carvalho Chehab return 0; 533786baecfSMauro Carvalho Chehab } 534786baecfSMauro Carvalho Chehab 535786baecfSMauro Carvalho Chehab static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 536786baecfSMauro Carvalho Chehab { 537786baecfSMauro Carvalho Chehab struct dvb_usb_adapter *adap = fe->dvb->priv; 538786baecfSMauro Carvalho Chehab 539786baecfSMauro Carvalho Chehab return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable); 540786baecfSMauro Carvalho Chehab } 541786baecfSMauro Carvalho Chehab 542786baecfSMauro Carvalho Chehab static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap) 543786baecfSMauro Carvalho Chehab { 544786baecfSMauro Carvalho Chehab if (usb_set_interface(adap->dev->udev, 0, 3) < 0) 545786baecfSMauro Carvalho Chehab err("set interface to alts=3 failed"); 546786baecfSMauro Carvalho Chehab 547786baecfSMauro Carvalho Chehab if (adap->fe_adap[0].fe == NULL) { 548786baecfSMauro Carvalho Chehab /* FE 0 DVB-C */ 549786baecfSMauro Carvalho Chehab adap->fe_adap[0].fe = dvb_attach(tda10023_attach, 550786baecfSMauro Carvalho Chehab &tda10023_config, &adap->dev->i2c_adap, 0x48); 551786baecfSMauro Carvalho Chehab 552786baecfSMauro Carvalho Chehab if (adap->fe_adap[0].fe == NULL) { 553786baecfSMauro Carvalho Chehab deb_info("TDA10023 attach failed\n"); 554786baecfSMauro Carvalho Chehab return -ENODEV; 555786baecfSMauro Carvalho Chehab } 556786baecfSMauro Carvalho Chehab tt3650_ci_init(adap); 557786baecfSMauro Carvalho Chehab } else { 558786baecfSMauro Carvalho Chehab adap->fe_adap[1].fe = dvb_attach(tda10048_attach, 559786baecfSMauro Carvalho Chehab &tda10048_config, &adap->dev->i2c_adap); 560786baecfSMauro Carvalho Chehab 561786baecfSMauro Carvalho Chehab if (adap->fe_adap[1].fe == NULL) { 562786baecfSMauro Carvalho Chehab deb_info("TDA10048 attach failed\n"); 563786baecfSMauro Carvalho Chehab return -ENODEV; 564786baecfSMauro Carvalho Chehab } 565786baecfSMauro Carvalho Chehab 566786baecfSMauro Carvalho Chehab /* tuner is behind TDA10023 I2C-gate */ 567786baecfSMauro Carvalho Chehab adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl; 568786baecfSMauro Carvalho Chehab 569786baecfSMauro Carvalho Chehab } 570786baecfSMauro Carvalho Chehab 571786baecfSMauro Carvalho Chehab return 0; 572786baecfSMauro Carvalho Chehab } 573786baecfSMauro Carvalho Chehab 574786baecfSMauro Carvalho Chehab static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap) 575786baecfSMauro Carvalho Chehab { 576786baecfSMauro Carvalho Chehab struct dvb_frontend *fe; 577786baecfSMauro Carvalho Chehab 578786baecfSMauro Carvalho Chehab /* MFE: select correct FE to attach tuner since that's called twice */ 579786baecfSMauro Carvalho Chehab if (adap->fe_adap[1].fe == NULL) 580786baecfSMauro Carvalho Chehab fe = adap->fe_adap[0].fe; 581786baecfSMauro Carvalho Chehab else 582786baecfSMauro Carvalho Chehab fe = adap->fe_adap[1].fe; 583786baecfSMauro Carvalho Chehab 584786baecfSMauro Carvalho Chehab /* attach tuner */ 585786baecfSMauro Carvalho Chehab if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) { 586786baecfSMauro Carvalho Chehab printk(KERN_ERR "%s: No tda827x found!\n", __func__); 587786baecfSMauro Carvalho Chehab return -ENODEV; 588786baecfSMauro Carvalho Chehab } 589786baecfSMauro Carvalho Chehab return 0; 590786baecfSMauro Carvalho Chehab } 591786baecfSMauro Carvalho Chehab 592786baecfSMauro Carvalho Chehab static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap) 593786baecfSMauro Carvalho Chehab { 594786baecfSMauro Carvalho Chehab if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { 595786baecfSMauro Carvalho Chehab deb_info("TDA8263 attach failed\n"); 596786baecfSMauro Carvalho Chehab return -ENODEV; 597786baecfSMauro Carvalho Chehab } 598786baecfSMauro Carvalho Chehab 599786baecfSMauro Carvalho Chehab if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) { 600786baecfSMauro Carvalho Chehab deb_info("LNBP21 attach failed\n"); 601786baecfSMauro Carvalho Chehab return -ENODEV; 602786baecfSMauro Carvalho Chehab } 603786baecfSMauro Carvalho Chehab return 0; 604786baecfSMauro Carvalho Chehab } 605786baecfSMauro Carvalho Chehab 606786baecfSMauro Carvalho Chehab /* DVB USB Driver stuff */ 607786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties; 608786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties_s2400; 609786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties_ct3650; 610786baecfSMauro Carvalho Chehab 611786baecfSMauro Carvalho Chehab static void ttusb2_usb_disconnect(struct usb_interface *intf) 612786baecfSMauro Carvalho Chehab { 613786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = usb_get_intfdata(intf); 614786baecfSMauro Carvalho Chehab 615786baecfSMauro Carvalho Chehab tt3650_ci_uninit(d); 616786baecfSMauro Carvalho Chehab dvb_usb_device_exit(intf); 617786baecfSMauro Carvalho Chehab } 618786baecfSMauro Carvalho Chehab 619786baecfSMauro Carvalho Chehab static int ttusb2_probe(struct usb_interface *intf, 620786baecfSMauro Carvalho Chehab const struct usb_device_id *id) 621786baecfSMauro Carvalho Chehab { 622786baecfSMauro Carvalho Chehab if (0 == dvb_usb_device_init(intf, &ttusb2_properties, 623786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 624786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, 625786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr) || 626786baecfSMauro Carvalho Chehab 0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650, 627786baecfSMauro Carvalho Chehab THIS_MODULE, NULL, adapter_nr)) 628786baecfSMauro Carvalho Chehab return 0; 629786baecfSMauro Carvalho Chehab return -ENODEV; 630786baecfSMauro Carvalho Chehab } 631786baecfSMauro Carvalho Chehab 632786baecfSMauro Carvalho Chehab static struct usb_device_id ttusb2_table [] = { 633786baecfSMauro Carvalho Chehab { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, 634786baecfSMauro Carvalho Chehab { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, 635786baecfSMauro Carvalho Chehab { USB_DEVICE(USB_VID_TECHNOTREND, 636786baecfSMauro Carvalho Chehab USB_PID_TECHNOTREND_CONNECT_S2400) }, 637786baecfSMauro Carvalho Chehab { USB_DEVICE(USB_VID_TECHNOTREND, 638786baecfSMauro Carvalho Chehab USB_PID_TECHNOTREND_CONNECT_CT3650) }, 639ed72d37aSChristoph Nuscheler { USB_DEVICE(USB_VID_TECHNOTREND, 640ed72d37aSChristoph Nuscheler USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM) }, 641786baecfSMauro Carvalho Chehab {} /* Terminating entry */ 642786baecfSMauro Carvalho Chehab }; 643786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE (usb, ttusb2_table); 644786baecfSMauro Carvalho Chehab 645786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties = { 646786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 647786baecfSMauro Carvalho Chehab 648786baecfSMauro Carvalho Chehab .usb_ctrl = CYPRESS_FX2, 649786baecfSMauro Carvalho Chehab .firmware = "dvb-usb-pctv-400e-01.fw", 650786baecfSMauro Carvalho Chehab 651786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct ttusb2_state), 652786baecfSMauro Carvalho Chehab 653786baecfSMauro Carvalho Chehab .num_adapters = 1, 654786baecfSMauro Carvalho Chehab .adapter = { 655786baecfSMauro Carvalho Chehab { 656786baecfSMauro Carvalho Chehab .num_frontends = 1, 657786baecfSMauro Carvalho Chehab .fe = {{ 658786baecfSMauro Carvalho Chehab .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, 659786baecfSMauro Carvalho Chehab 660786baecfSMauro Carvalho Chehab .frontend_attach = ttusb2_frontend_tda10086_attach, 661786baecfSMauro Carvalho Chehab .tuner_attach = ttusb2_tuner_tda826x_attach, 662786baecfSMauro Carvalho Chehab 663786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 664786baecfSMauro Carvalho Chehab .stream = { 665786baecfSMauro Carvalho Chehab .type = USB_ISOC, 666786baecfSMauro Carvalho Chehab .count = 5, 667786baecfSMauro Carvalho Chehab .endpoint = 0x02, 668786baecfSMauro Carvalho Chehab .u = { 669786baecfSMauro Carvalho Chehab .isoc = { 670786baecfSMauro Carvalho Chehab .framesperurb = 4, 671786baecfSMauro Carvalho Chehab .framesize = 940, 672786baecfSMauro Carvalho Chehab .interval = 1, 673786baecfSMauro Carvalho Chehab } 674786baecfSMauro Carvalho Chehab } 675786baecfSMauro Carvalho Chehab } 676786baecfSMauro Carvalho Chehab }}, 677786baecfSMauro Carvalho Chehab } 678786baecfSMauro Carvalho Chehab }, 679786baecfSMauro Carvalho Chehab 680786baecfSMauro Carvalho Chehab .power_ctrl = ttusb2_power_ctrl, 681786baecfSMauro Carvalho Chehab .identify_state = ttusb2_identify_state, 682786baecfSMauro Carvalho Chehab 683786baecfSMauro Carvalho Chehab .i2c_algo = &ttusb2_i2c_algo, 684786baecfSMauro Carvalho Chehab 685786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x01, 686786baecfSMauro Carvalho Chehab 687786baecfSMauro Carvalho Chehab .num_device_descs = 2, 688786baecfSMauro Carvalho Chehab .devices = { 689786baecfSMauro Carvalho Chehab { "Pinnacle 400e DVB-S USB2.0", 690786baecfSMauro Carvalho Chehab { &ttusb2_table[0], NULL }, 691786baecfSMauro Carvalho Chehab { NULL }, 692786baecfSMauro Carvalho Chehab }, 693786baecfSMauro Carvalho Chehab { "Pinnacle 450e DVB-S USB2.0", 694786baecfSMauro Carvalho Chehab { &ttusb2_table[1], NULL }, 695786baecfSMauro Carvalho Chehab { NULL }, 696786baecfSMauro Carvalho Chehab }, 697786baecfSMauro Carvalho Chehab } 698786baecfSMauro Carvalho Chehab }; 699786baecfSMauro Carvalho Chehab 700786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties_s2400 = { 701786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 702786baecfSMauro Carvalho Chehab 703786baecfSMauro Carvalho Chehab .usb_ctrl = CYPRESS_FX2, 704786baecfSMauro Carvalho Chehab .firmware = "dvb-usb-tt-s2400-01.fw", 705786baecfSMauro Carvalho Chehab 706786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct ttusb2_state), 707786baecfSMauro Carvalho Chehab 708786baecfSMauro Carvalho Chehab .num_adapters = 1, 709786baecfSMauro Carvalho Chehab .adapter = { 710786baecfSMauro Carvalho Chehab { 711786baecfSMauro Carvalho Chehab .num_frontends = 1, 712786baecfSMauro Carvalho Chehab .fe = {{ 713786baecfSMauro Carvalho Chehab .streaming_ctrl = NULL, 714786baecfSMauro Carvalho Chehab 715786baecfSMauro Carvalho Chehab .frontend_attach = ttusb2_frontend_tda10086_attach, 716786baecfSMauro Carvalho Chehab .tuner_attach = ttusb2_tuner_tda826x_attach, 717786baecfSMauro Carvalho Chehab 718786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 719786baecfSMauro Carvalho Chehab .stream = { 720786baecfSMauro Carvalho Chehab .type = USB_ISOC, 721786baecfSMauro Carvalho Chehab .count = 5, 722786baecfSMauro Carvalho Chehab .endpoint = 0x02, 723786baecfSMauro Carvalho Chehab .u = { 724786baecfSMauro Carvalho Chehab .isoc = { 725786baecfSMauro Carvalho Chehab .framesperurb = 4, 726786baecfSMauro Carvalho Chehab .framesize = 940, 727786baecfSMauro Carvalho Chehab .interval = 1, 728786baecfSMauro Carvalho Chehab } 729786baecfSMauro Carvalho Chehab } 730786baecfSMauro Carvalho Chehab } 731786baecfSMauro Carvalho Chehab }}, 732786baecfSMauro Carvalho Chehab } 733786baecfSMauro Carvalho Chehab }, 734786baecfSMauro Carvalho Chehab 735786baecfSMauro Carvalho Chehab .power_ctrl = ttusb2_power_ctrl, 736786baecfSMauro Carvalho Chehab .identify_state = ttusb2_identify_state, 737786baecfSMauro Carvalho Chehab 738786baecfSMauro Carvalho Chehab .i2c_algo = &ttusb2_i2c_algo, 739786baecfSMauro Carvalho Chehab 740786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x01, 741786baecfSMauro Carvalho Chehab 742ed72d37aSChristoph Nuscheler .num_device_descs = 2, 743786baecfSMauro Carvalho Chehab .devices = { 744786baecfSMauro Carvalho Chehab { "Technotrend TT-connect S-2400", 745786baecfSMauro Carvalho Chehab { &ttusb2_table[2], NULL }, 746786baecfSMauro Carvalho Chehab { NULL }, 747786baecfSMauro Carvalho Chehab }, 748ed72d37aSChristoph Nuscheler { "Technotrend TT-connect S-2400 (8kB EEPROM)", 749ed72d37aSChristoph Nuscheler { &ttusb2_table[4], NULL }, 750ed72d37aSChristoph Nuscheler { NULL }, 751ed72d37aSChristoph Nuscheler }, 752786baecfSMauro Carvalho Chehab } 753786baecfSMauro Carvalho Chehab }; 754786baecfSMauro Carvalho Chehab 755786baecfSMauro Carvalho Chehab static struct dvb_usb_device_properties ttusb2_properties_ct3650 = { 756786baecfSMauro Carvalho Chehab .caps = DVB_USB_IS_AN_I2C_ADAPTER, 757786baecfSMauro Carvalho Chehab 758786baecfSMauro Carvalho Chehab .usb_ctrl = CYPRESS_FX2, 759786baecfSMauro Carvalho Chehab 760786baecfSMauro Carvalho Chehab .size_of_priv = sizeof(struct ttusb2_state), 761786baecfSMauro Carvalho Chehab 762786baecfSMauro Carvalho Chehab .rc.core = { 763786baecfSMauro Carvalho Chehab .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */ 764786baecfSMauro Carvalho Chehab .rc_codes = RC_MAP_TT_1500, 765786baecfSMauro Carvalho Chehab .rc_query = tt3650_rc_query, 7666d741bfeSSean Young .allowed_protos = RC_PROTO_BIT_RC5, 767786baecfSMauro Carvalho Chehab }, 768786baecfSMauro Carvalho Chehab 769786baecfSMauro Carvalho Chehab .num_adapters = 1, 770786baecfSMauro Carvalho Chehab .adapter = { 771786baecfSMauro Carvalho Chehab { 772786baecfSMauro Carvalho Chehab .num_frontends = 2, 773786baecfSMauro Carvalho Chehab .fe = {{ 774786baecfSMauro Carvalho Chehab .streaming_ctrl = NULL, 775786baecfSMauro Carvalho Chehab 776786baecfSMauro Carvalho Chehab .frontend_attach = ttusb2_frontend_tda10023_attach, 777786baecfSMauro Carvalho Chehab .tuner_attach = ttusb2_tuner_tda827x_attach, 778786baecfSMauro Carvalho Chehab 779786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 780786baecfSMauro Carvalho Chehab .stream = { 781786baecfSMauro Carvalho Chehab .type = USB_ISOC, 782786baecfSMauro Carvalho Chehab .count = 5, 783786baecfSMauro Carvalho Chehab .endpoint = 0x02, 784786baecfSMauro Carvalho Chehab .u = { 785786baecfSMauro Carvalho Chehab .isoc = { 786786baecfSMauro Carvalho Chehab .framesperurb = 4, 787786baecfSMauro Carvalho Chehab .framesize = 940, 788786baecfSMauro Carvalho Chehab .interval = 1, 789786baecfSMauro Carvalho Chehab } 790786baecfSMauro Carvalho Chehab } 791786baecfSMauro Carvalho Chehab } 792786baecfSMauro Carvalho Chehab }, { 793786baecfSMauro Carvalho Chehab .streaming_ctrl = NULL, 794786baecfSMauro Carvalho Chehab 795786baecfSMauro Carvalho Chehab .frontend_attach = ttusb2_frontend_tda10023_attach, 796786baecfSMauro Carvalho Chehab .tuner_attach = ttusb2_tuner_tda827x_attach, 797786baecfSMauro Carvalho Chehab 798786baecfSMauro Carvalho Chehab /* parameter for the MPEG2-data transfer */ 799786baecfSMauro Carvalho Chehab .stream = { 800786baecfSMauro Carvalho Chehab .type = USB_ISOC, 801786baecfSMauro Carvalho Chehab .count = 5, 802786baecfSMauro Carvalho Chehab .endpoint = 0x02, 803786baecfSMauro Carvalho Chehab .u = { 804786baecfSMauro Carvalho Chehab .isoc = { 805786baecfSMauro Carvalho Chehab .framesperurb = 4, 806786baecfSMauro Carvalho Chehab .framesize = 940, 807786baecfSMauro Carvalho Chehab .interval = 1, 808786baecfSMauro Carvalho Chehab } 809786baecfSMauro Carvalho Chehab } 810786baecfSMauro Carvalho Chehab } 811786baecfSMauro Carvalho Chehab }}, 812786baecfSMauro Carvalho Chehab }, 813786baecfSMauro Carvalho Chehab }, 814786baecfSMauro Carvalho Chehab 815786baecfSMauro Carvalho Chehab .power_ctrl = ttusb2_power_ctrl, 816786baecfSMauro Carvalho Chehab .identify_state = ttusb2_identify_state, 817786baecfSMauro Carvalho Chehab 818786baecfSMauro Carvalho Chehab .i2c_algo = &ttusb2_i2c_algo, 819786baecfSMauro Carvalho Chehab 820786baecfSMauro Carvalho Chehab .generic_bulk_ctrl_endpoint = 0x01, 821786baecfSMauro Carvalho Chehab 822786baecfSMauro Carvalho Chehab .num_device_descs = 1, 823786baecfSMauro Carvalho Chehab .devices = { 824786baecfSMauro Carvalho Chehab { "Technotrend TT-connect CT-3650", 825786baecfSMauro Carvalho Chehab .warm_ids = { &ttusb2_table[3], NULL }, 826786baecfSMauro Carvalho Chehab }, 827786baecfSMauro Carvalho Chehab } 828786baecfSMauro Carvalho Chehab }; 829786baecfSMauro Carvalho Chehab 830786baecfSMauro Carvalho Chehab static struct usb_driver ttusb2_driver = { 831786baecfSMauro Carvalho Chehab .name = "dvb_usb_ttusb2", 832786baecfSMauro Carvalho Chehab .probe = ttusb2_probe, 833786baecfSMauro Carvalho Chehab .disconnect = ttusb2_usb_disconnect, 834786baecfSMauro Carvalho Chehab .id_table = ttusb2_table, 835786baecfSMauro Carvalho Chehab }; 836786baecfSMauro Carvalho Chehab 837786baecfSMauro Carvalho Chehab module_usb_driver(ttusb2_driver); 838786baecfSMauro Carvalho Chehab 83999e44da7SPatrick Boettcher MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 840786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); 841786baecfSMauro Carvalho Chehab MODULE_VERSION("1.0"); 842786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 843