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