1bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
2bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * (e.g. Pinnacle 400e DVB-S USB2.0).
3bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
4bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
5bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
6bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * TDA8263 + TDA10086
7bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
8bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * I2C addresses:
9bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * 0x08 - LNBP21PD   - LNB power supply
10bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * 0x0e - TDA10086   - Demodulator
11bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * 0x50 - FX2 eeprom
12bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * 0x60 - TDA8263    - Tuner
13bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * 0x78 ???
14bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
15bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
16bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
17bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org>
18bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
19bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *	This program is free software; you can redistribute it and/or modify it
20bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *	under the terms of the GNU General Public License as published by the Free
21bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *	Software Foundation, version 2.
22bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher *
23bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher * see Documentation/dvb/README.dvb-usb for more information
24bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher */
25bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#define DVB_USB_LOG_PREFIX "ttusb2"
26bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#include "dvb-usb.h"
27bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
28bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#include "ttusb2.h"
29bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
30bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#include "tda826x.h"
31bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#include "tda10086.h"
3276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin#include "tda1002x.h"
33c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero#include "tda10048.h"
3476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin#include "tda827x.h"
35bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#include "lnbp21.h"
368c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero/* CA */
378c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero#include "dvb_ca_en50221.h"
38bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
39bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher/* debug */
40bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int dvb_usb_ttusb2_debug;
41bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher#define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
42bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettchermodule_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
43bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
448c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int dvb_usb_ttusb2_debug_ci;
458c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Regueromodule_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
468c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto RegueroMODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
47bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
4878e92006f410a4044f8c1760c25ac9d11d259aa2Janne GrunauDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
4978e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau
508c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero#define ci_dbg(format, arg...)                \
518c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerodo {                                          \
528c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (dvb_usb_ttusb2_debug_ci)                                    \
538c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
548c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero			": %s " format "\n" , __func__, ## arg);       \
558c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero} while (0)
568c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
578c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Regueroenum {
588c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_TEST = 0x40,
598c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_RD_CTRL,
608c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_WR_CTRL,
618c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_RD_ATTR,
628c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_WR_ATTR,
638c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_RESET,
648c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	TT3650_CMD_CI_SET_VIDEO_PORT
658c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero};
668c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
67bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstruct ttusb2_state {
688c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct dvb_ca_en50221 ca;
698c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct mutex ca_mutex;
70bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	u8 id;
719d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	u16 last_rc_key;
72bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
73bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
74bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
75bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
76bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
77bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	struct ttusb2_state *st = d->priv;
78ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	u8 *s, *r = NULL;
79bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	int ret = 0;
80bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
81ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	s = kzalloc(wlen+4, GFP_KERNEL);
82ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	if (!s)
83ff17999184ed13829bc14c3be412d980173dff40Josh Boyer		return -ENOMEM;
84ff17999184ed13829bc14c3be412d980173dff40Josh Boyer
85ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	r = kzalloc(64, GFP_KERNEL);
86ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	if (!r) {
87ff17999184ed13829bc14c3be412d980173dff40Josh Boyer		kfree(s);
88ff17999184ed13829bc14c3be412d980173dff40Josh Boyer		return -ENOMEM;
89ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	}
90bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
91bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	s[0] = 0xaa;
92bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	s[1] = ++st->id;
93bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	s[2] = cmd;
94bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	s[3] = wlen;
95bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	memcpy(&s[4],wbuf,wlen);
96bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
97bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
98bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
99bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	if (ret  != 0 ||
100bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		r[0] != 0x55 ||
101bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		r[1] != s[1] ||
102bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		r[2] != cmd ||
103bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		(rlen > 0 && r[3] != rlen)) {
104bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
105ff17999184ed13829bc14c3be412d980173dff40Josh Boyer		kfree(s);
106ff17999184ed13829bc14c3be412d980173dff40Josh Boyer		kfree(r);
107bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		return -EIO;
108bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
109bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
110bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	if (rlen > 0)
111bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		memcpy(rbuf, &r[4], rlen);
112bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
113ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	kfree(s);
114ff17999184ed13829bc14c3be412d980173dff40Josh Boyer	kfree(r);
115ff17999184ed13829bc14c3be412d980173dff40Josh Boyer
116bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return 0;
117bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
118bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
1198c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero/* ci */
1208c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
1218c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
1228c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
1238c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 rx[60];/* (64 -4) */
1248c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
1258c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (!ret)
1268c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		memcpy(data, rx, read_len);
1278c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return ret;
1288c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
1298c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1308c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
1318c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
1328c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct dvb_usb_device *d = ca->data;
1338c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct ttusb2_state *state = d->priv;
1348c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
1358c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1368c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	mutex_lock(&state->ca_mutex);
1378c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
1388c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	mutex_unlock(&state->ca_mutex);
1398c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1408c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return ret;
1418c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
1428c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1438c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
1448c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
1458c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[3];
1468c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret = 0;
1478c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1488c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
1498c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
1508c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1518c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = (address >> 8) & 0x0F;
1528c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[1] = address;
1538c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1548c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1558c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
1568c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1578c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
1588c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1598c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret < 0)
1608c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return ret;
1618c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1628c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return buf[2];
1638c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
1648c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1658c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
1668c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
1678c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[3];
1688c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1698c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
1708c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1718c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
1728c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
1738c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1748c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = (address >> 8) & 0x0F;
1758c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[1] = address;
1768c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[2] = value;
1778c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1788c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
1798c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
1808c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1818c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
1828c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
1838c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[2];
1848c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
1858c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1868c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
1878c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
1888c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1898c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = address & 3;
1908c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1918c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
1928c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1938c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
1948c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1958c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret < 0)
1968c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return ret;
1978c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
1988c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return buf[1];
1998c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2008c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2018c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
2028c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2038c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[2];
2048c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2058c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
2068c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2078c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
2088c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
2098c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2108c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = address;
2118c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[1] = value;
2128c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2138c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
2148c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2158c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2168c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
2178c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2188c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[1];
2198c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
2208c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2218c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("%d %d", slot, enable);
2228c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2238c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
2248c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
2258c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2268c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = enable;
2278c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2288c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
2298c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret < 0)
2308c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return ret;
2318c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2328c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (enable != buf[0]) {
2338c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		err("CI not %sabled.", enable ? "en" : "dis");
2348c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EIO;
2358c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	}
2368c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2378c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return 0;
2388c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2398c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2408c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
2418c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2428c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return tt3650_ci_set_video_port(ca, slot, 0);
2438c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2448c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2458c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
2468c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2478c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return tt3650_ci_set_video_port(ca, slot, 1);
2488c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2498c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2508c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
2518c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2528c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct dvb_usb_device *d = ca->data;
2538c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct ttusb2_state *state = d->priv;
2548c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[1];
2558c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
2568c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2578c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("%d", slot);
2588c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2598c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
2608c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
2618c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2628c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = 0;
2638c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2648c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	mutex_lock(&state->ca_mutex);
2658c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2668c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
2678c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret)
2688c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		goto failed;
2698c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2708c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	msleep(500);
2718c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2728c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = 1;
2738c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2748c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
2758c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret)
2768c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		goto failed;
2778c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2788c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	msleep(500);
2798c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2808c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	buf[0] = 0; /* FTA */
2818c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2828c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
2838c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2848c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	msleep(1100);
2858c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2868c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero failed:
2878c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	mutex_unlock(&state->ca_mutex);
2888c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2898c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return ret;
2908c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
2918c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2928c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
2938c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
2948c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	u8 buf[1];
2958c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
2968c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
2978c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (slot)
2988c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return -EINVAL;
2998c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3008c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
3018c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret)
3028c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return ret;
3038c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3048c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (1 == buf[0]) {
3058c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return DVB_CA_EN50221_POLL_CAM_PRESENT |
3068c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero			DVB_CA_EN50221_POLL_CAM_READY;
3078c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	}
3088c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return 0;
3098c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
3108c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3118c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic void tt3650_ci_uninit(struct dvb_usb_device *d)
3128c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
3138c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct ttusb2_state *state;
3148c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3158c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("");
3168c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3178c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (NULL == d)
3188c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return;
3198c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3208c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state = d->priv;
3218c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (NULL == state)
3228c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return;
3238c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3248c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (NULL == state->ca.data)
3258c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return;
3268c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3278c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	dvb_ca_en50221_release(&state->ca);
3288c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3298c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	memset(&state->ca, 0, sizeof(state->ca));
3308c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
3318c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3328c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic int tt3650_ci_init(struct dvb_usb_adapter *a)
3338c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
3348c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct dvb_usb_device *d = a->dev;
3358c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct ttusb2_state *state = d->priv;
3368c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	int ret;
3378c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3388c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ci_dbg("");
3398c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3408c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	mutex_init(&state->ca_mutex);
3418c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3428c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.owner = THIS_MODULE;
3438c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
3448c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
3458c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.read_cam_control = tt3650_ci_read_cam_control;
3468c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.write_cam_control = tt3650_ci_write_cam_control;
3478c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.slot_reset = tt3650_ci_slot_reset;
3488c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
3498c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
3508c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
3518c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	state->ca.data = d;
3528c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3538c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	ret = dvb_ca_en50221_init(&a->dvb_adap,
3548c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero				  &state->ca,
3558c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero				  /* flags */ 0,
3568c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero				  /* n_slots */ 1);
3578c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	if (ret) {
3588c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		err("Cannot initialize CI: Error %d.", ret);
3598c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		memset(&state->ca, 0, sizeof(state->ca));
3608c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		return ret;
3618c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	}
3628c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3638c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	info("CI initialized.");
3648c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
3658c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	return 0;
3668c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
3678c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
368bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
369bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
370bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	struct dvb_usb_device *d = i2c_get_adapdata(adap);
371bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	static u8 obuf[60], ibuf[60];
372c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	int i, write_read, read;
373bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
374bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
375bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		return -EAGAIN;
376bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
377bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	if (num > 2)
378bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
379bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
380bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	for (i = 0; i < num; i++) {
381c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
382c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		read = msg[i].flags & I2C_M_RD;
383bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
384c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		obuf[0] = (msg[i].addr << 1) | (write_read | read);
385c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		if (read)
386c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			obuf[1] = 0;
387c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		else
388c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			obuf[1] = msg[i].len;
389bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
390bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		/* read request */
391c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		if (write_read)
392bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			obuf[2] = msg[i+1].len;
393c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		else if (read)
394c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			obuf[2] = msg[i].len;
395bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		else
396bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			obuf[2] = 0;
397bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
398c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		memcpy(&obuf[3], msg[i].buf, msg[i].len);
399bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
400a23d9d1227f05cf96d195401fe2af2c14ea44b92Jose Alberto Reguero		if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
401bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			err("i2c transfer failed.");
402bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			break;
403bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		}
404bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
405c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		if (write_read) {
406c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
407bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			i++;
408c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		} else if (read)
409c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			memcpy(msg[i].buf, &ibuf[3], msg[i].len);
410bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
411bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
412bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	mutex_unlock(&d->i2c_mutex);
413bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return i;
414bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
415bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
416bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
417bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
418bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return I2C_FUNC_I2C;
419bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
420bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
421bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct i2c_algorithm ttusb2_i2c_algo = {
422bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.master_xfer   = ttusb2_i2c_xfer,
423bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.functionality = ttusb2_i2c_func,
424bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
425bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
4269d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson/* command to poll IR receiver (copied from pctv452e.c) */
4279d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson#define CMD_GET_IR_CODE     0x1b
4289d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
4299d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson/* IR */
4309d1da730ee17e712c25c0b1e51653048f92d2385David Henningssonstatic int tt3650_rc_query(struct dvb_usb_device *d)
4319d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson{
4329d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	int ret;
4339d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
4349d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	struct ttusb2_state *st = d->priv;
4359d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
4369d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	if (ret != 0)
4379d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		return ret;
4389d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
4399d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	if (rx[8] & 0x01) {
4409d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		/* got a "press" event */
4419d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		st->last_rc_key = (rx[3] << 8) | rx[2];
4429d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
4439d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		rc_keydown(d->rc_dev, st->last_rc_key, 0);
4449d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	} else if (st->last_rc_key) {
4459d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		rc_keyup(d->rc_dev);
4469d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		st->last_rc_key = 0;
4479d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	}
4489d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
4499d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	return 0;
4509d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson}
4519d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
4529d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
453bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher/* Callbacks for DVB USB */
454bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int ttusb2_identify_state (struct usb_device *udev, struct
455bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
456bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		int *cold)
457bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
458bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
459bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return 0;
460bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
461bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
462bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
463bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
464bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	u8 b = onoff;
465bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
466bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
467bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
468bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
469bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
470bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct tda10086_config tda10086_config = {
471bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.demod_address = 0x0e,
472bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.invert = 0,
473ea75baf4b0f117564bd50827a49c4b14d61d24e9Hartmut Hackmann	.diseqc_tone = 1,
4749a1b04e461fc8127c902a988cd9a082ba0680b11Hartmut Hackmann	.xtal_freq = TDA10086_XTAL_16M,
475bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
476bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
47776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic struct tda10023_config tda10023_config = {
47876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.demod_address = 0x0c,
47976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.invert = 0,
48076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.xtal = 16000000,
48176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.pll_m = 11,
48276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.pll_p = 3,
48376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.pll_n = 1,
48476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.deltaf = 0xa511,
48576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin};
48676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
487c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguerostatic struct tda10048_config tda10048_config = {
488c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.demod_address    = 0x10 >> 1,
489c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.output_mode      = TDA10048_PARALLEL_OUTPUT,
490c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.inversion        = TDA10048_INVERSION_ON,
491c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.dtv6_if_freq_khz = TDA10048_IF_4000,
492c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.dtv7_if_freq_khz = TDA10048_IF_4500,
493c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.dtv8_if_freq_khz = TDA10048_IF_5000,
494c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.clk_freq_khz     = TDA10048_CLK_16000,
495c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.no_firmware      = 1,
496c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.set_pll          = true ,
497c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.pll_m            = 5,
498c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.pll_n            = 3,
499c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.pll_p            = 0,
500c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero};
501c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
502c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguerostatic struct tda827x_config tda827x_config = {
503c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	.config = 0,
504c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero};
505c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
50676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
507bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
508bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	if (usb_set_interface(adap->dev->udev,0,3) < 0)
509bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		err("set interface to alts=3 failed");
510bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
51177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
512bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		deb_info("TDA10086 attach failed\n");
513bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		return -ENODEV;
514bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
515bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
516bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return 0;
517bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
518bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
519c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguerostatic int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
520c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero{
521c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	struct dvb_usb_adapter *adap = fe->dvb->priv;
522c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
52377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
524c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero}
525c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
52676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
52776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin{
52876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
52976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		err("set interface to alts=3 failed");
530c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
53177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	if (adap->fe_adap[0].fe == NULL) {
532c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		/* FE 0 DVB-C */
53377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
534c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			&tda10023_config, &adap->dev->i2c_adap, 0x48);
535c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
53677eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		if (adap->fe_adap[0].fe == NULL) {
537c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			deb_info("TDA10023 attach failed\n");
538c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			return -ENODEV;
539c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		}
5408c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero		tt3650_ci_init(adap);
541c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	} else {
54277eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
543c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			&tda10048_config, &adap->dev->i2c_adap);
544c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
54577eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		if (adap->fe_adap[1].fe == NULL) {
546c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			deb_info("TDA10048 attach failed\n");
547c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero			return -ENODEV;
548c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		}
549c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
550c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero		/* tuner is behind TDA10023 I2C-gate */
55177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
552c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
55376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	}
554c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
55576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	return 0;
55676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin}
55776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
55876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
55976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin{
560c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	struct dvb_frontend *fe;
561c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
562c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	/* MFE: select correct FE to attach tuner since that's called twice */
56377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	if (adap->fe_adap[1].fe == NULL)
56477eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		fe = adap->fe_adap[0].fe;
565c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	else
56677eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		fe = adap->fe_adap[1].fe;
567c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero
568c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	/* attach tuner */
569c9f88aa976b79a26561fb7754a1e0e00ff7626feJose Alberto Reguero	if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
57076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		printk(KERN_ERR "%s: No tda827x found!\n", __func__);
57176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		return -ENODEV;
57276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	}
57376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	return 0;
57476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin}
57576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
57676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
577bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
57877eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
579bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		deb_info("TDA8263 attach failed\n");
580bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		return -ENODEV;
581bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
582bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
58377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky	if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
584bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		deb_info("LNBP21 attach failed\n");
585bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		return -ENODEV;
586bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
587bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	return 0;
588bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
589bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
590bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher/* DVB USB Driver stuff */
591bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct dvb_usb_device_properties ttusb2_properties;
5928c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemannstatic struct dvb_usb_device_properties ttusb2_properties_s2400;
59376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic struct dvb_usb_device_properties ttusb2_properties_ct3650;
594bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
5958c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguerostatic void ttusb2_usb_disconnect(struct usb_interface *intf)
5968c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero{
5978c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	struct dvb_usb_device *d = usb_get_intfdata(intf);
5988c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
5998c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	tt3650_ci_uninit(d);
6008c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	dvb_usb_device_exit(intf);
6018c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero}
6028c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero
603bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic int ttusb2_probe(struct usb_interface *intf,
604bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		const struct usb_device_id *id)
605bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher{
60678e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau	if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
60778e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau				     THIS_MODULE, NULL, adapter_nr) ||
60878e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau	    0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
60976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				     THIS_MODULE, NULL, adapter_nr) ||
61076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	    0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
61178e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau				     THIS_MODULE, NULL, adapter_nr))
6128c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		return 0;
6138c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	return -ENODEV;
614bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher}
615bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
616bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct usb_device_id ttusb2_table [] = {
6178c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
6188c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
6198c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	{ USB_DEVICE(USB_VID_TECHNOTREND,
6208c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		USB_PID_TECHNOTREND_CONNECT_S2400) },
62176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	{ USB_DEVICE(USB_VID_TECHNOTREND,
62276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		USB_PID_TECHNOTREND_CONNECT_CT3650) },
6238c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	{}		/* Terminating entry */
624bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
625bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_DEVICE_TABLE (usb, ttusb2_table);
626bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
627bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct dvb_usb_device_properties ttusb2_properties = {
628bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
629bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
630bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.usb_ctrl = CYPRESS_FX2,
631bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.firmware = "dvb-usb-pctv-400e-01.fw",
632bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
633bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.size_of_priv = sizeof(struct ttusb2_state),
634bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
635bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.num_adapters = 1,
636bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.adapter = {
637bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		{
63877eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.num_frontends = 1,
63977eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.fe = {{
640bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			.streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
641bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
64276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.frontend_attach  = ttusb2_frontend_tda10086_attach,
64376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.tuner_attach     = ttusb2_tuner_tda826x_attach,
644bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
645bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			/* parameter for the MPEG2-data transfer */
646bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			.stream = {
647bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher				.type = USB_ISOC,
648bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher				.count = 5,
649bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher				.endpoint = 0x02,
650bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher				.u = {
651bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher					.isoc = {
652bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher						.framesperurb = 4,
653bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher						.framesize = 940,
654bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher						.interval = 1,
655bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher					}
656bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher				}
657bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			}
65877eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		}},
659bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		}
660bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	},
661bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
662bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.power_ctrl       = ttusb2_power_ctrl,
663bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.identify_state   = ttusb2_identify_state,
664bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
665bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.i2c_algo         = &ttusb2_i2c_algo,
666bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
667bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.generic_bulk_ctrl_endpoint = 0x01,
668bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
669ddc9ece89dbeb374e34772232f5e26f64ce63390Christophe Cattelain	.num_device_descs = 2,
670bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.devices = {
671bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		{   "Pinnacle 400e DVB-S USB2.0",
672bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			{ &ttusb2_table[0], NULL },
673bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher			{ NULL },
674bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher		},
675ddc9ece89dbeb374e34772232f5e26f64ce63390Christophe Cattelain		{   "Pinnacle 450e DVB-S USB2.0",
676ddc9ece89dbeb374e34772232f5e26f64ce63390Christophe Cattelain			{ &ttusb2_table[1], NULL },
677ddc9ece89dbeb374e34772232f5e26f64ce63390Christophe Cattelain			{ NULL },
678ddc9ece89dbeb374e34772232f5e26f64ce63390Christophe Cattelain		},
679bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	}
680bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
681bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
6828c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemannstatic struct dvb_usb_device_properties ttusb2_properties_s2400 = {
6838c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
6848c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
6858c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.usb_ctrl = CYPRESS_FX2,
6868c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.firmware = "dvb-usb-tt-s2400-01.fw",
6878c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
6888c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.size_of_priv = sizeof(struct ttusb2_state),
6898c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
6908c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.num_adapters = 1,
6918c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.adapter = {
6928c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		{
69377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.num_frontends = 1,
69477eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.fe = {{
6958c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			.streaming_ctrl   = NULL,
6968c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
69776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.frontend_attach  = ttusb2_frontend_tda10086_attach,
69876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.tuner_attach     = ttusb2_tuner_tda826x_attach,
6998c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
7008c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			/* parameter for the MPEG2-data transfer */
7018c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			.stream = {
7028c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann				.type = USB_ISOC,
7038c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann				.count = 5,
7048c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann				.endpoint = 0x02,
7058c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann				.u = {
7068c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann					.isoc = {
7078c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann						.framesperurb = 4,
7088c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann						.framesize = 940,
7098c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann						.interval = 1,
7108c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann					}
7118c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann				}
7128c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			}
71377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		}},
7148c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		}
7158c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	},
7168c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
7178c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.power_ctrl       = ttusb2_power_ctrl,
7188c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.identify_state   = ttusb2_identify_state,
7198c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
7208c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.i2c_algo         = &ttusb2_i2c_algo,
7218c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
7228c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.generic_bulk_ctrl_endpoint = 0x01,
7238c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
7248c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.num_device_descs = 1,
7258c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	.devices = {
7268c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		{   "Technotrend TT-connect S-2400",
7278c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			{ &ttusb2_table[2], NULL },
7288c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann			{ NULL },
7298c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann		},
7308c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann	}
7318c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann};
7328c899bce2a5540b19e86dd3b355e5699657da144Andre Weidemann
73376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martinstatic struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
73476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
73576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
73676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.usb_ctrl = CYPRESS_FX2,
73776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
73876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.size_of_priv = sizeof(struct ttusb2_state),
73976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
7409d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	.rc.core = {
7419d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
7429d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		.rc_codes         = RC_MAP_TT_1500,
7439d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		.rc_query         = tt3650_rc_query,
7449d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson		.allowed_protos   = RC_TYPE_UNKNOWN,
7459d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson	},
7469d1da730ee17e712c25c0b1e51653048f92d2385David Henningsson
74776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.num_adapters = 1,
74876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.adapter = {
74976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		{
75077eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.num_frontends = 2,
75177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		.fe = {{
75276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.streaming_ctrl   = NULL,
75376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
75476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.frontend_attach  = ttusb2_frontend_tda10023_attach,
75576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.tuner_attach = ttusb2_tuner_tda827x_attach,
75676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
75776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			/* parameter for the MPEG2-data transfer */
75876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.stream = {
75976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				.type = USB_ISOC,
76076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				.count = 5,
76176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				.endpoint = 0x02,
76276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				.u = {
76376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin					.isoc = {
76476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin						.framesperurb = 4,
76576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin						.framesize = 940,
76676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin						.interval = 1,
76776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin					}
76876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin				}
76976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			}
7701645c879ff688f776371a2478e1948fdf5e0f7feMichael Krufky		}, {
77177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			.streaming_ctrl   = NULL,
77277eed219fed5a913f59329cc846420fdeab0150fMichael Krufky
77377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			.frontend_attach  = ttusb2_frontend_tda10023_attach,
77477eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			.tuner_attach = ttusb2_tuner_tda827x_attach,
77577eed219fed5a913f59329cc846420fdeab0150fMichael Krufky
77677eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			/* parameter for the MPEG2-data transfer */
77777eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			.stream = {
77877eed219fed5a913f59329cc846420fdeab0150fMichael Krufky				.type = USB_ISOC,
77977eed219fed5a913f59329cc846420fdeab0150fMichael Krufky				.count = 5,
78077eed219fed5a913f59329cc846420fdeab0150fMichael Krufky				.endpoint = 0x02,
78177eed219fed5a913f59329cc846420fdeab0150fMichael Krufky				.u = {
78277eed219fed5a913f59329cc846420fdeab0150fMichael Krufky					.isoc = {
78377eed219fed5a913f59329cc846420fdeab0150fMichael Krufky						.framesperurb = 4,
78477eed219fed5a913f59329cc846420fdeab0150fMichael Krufky						.framesize = 940,
78577eed219fed5a913f59329cc846420fdeab0150fMichael Krufky						.interval = 1,
78677eed219fed5a913f59329cc846420fdeab0150fMichael Krufky					}
78777eed219fed5a913f59329cc846420fdeab0150fMichael Krufky				}
78877eed219fed5a913f59329cc846420fdeab0150fMichael Krufky			}
78977eed219fed5a913f59329cc846420fdeab0150fMichael Krufky		}},
79076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		},
79176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	},
79276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
79376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.power_ctrl       = ttusb2_power_ctrl,
79476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.identify_state   = ttusb2_identify_state,
79576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
79676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.i2c_algo         = &ttusb2_i2c_algo,
79776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
79876952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.generic_bulk_ctrl_endpoint = 0x01,
79976952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
80076952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.num_device_descs = 1,
80176952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	.devices = {
80276952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		{   "Technotrend TT-connect CT-3650",
80376952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin			.warm_ids = { &ttusb2_table[3], NULL },
80476952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin		},
80576952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin	}
80676952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin};
80776952c7e598f68bf12adf307d6a9a0de3b33b985Guy Martin
808bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcherstatic struct usb_driver ttusb2_driver = {
809bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.name		= "dvb_usb_ttusb2",
810bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.probe		= ttusb2_probe,
8118c0bc03c80952e81db8cb11082c0c6375e9083abJose Alberto Reguero	.disconnect	= ttusb2_usb_disconnect,
812bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher	.id_table	= ttusb2_table,
813bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher};
814bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
815ecb3b2b35db49778b6d89e3ffd0c400776c20735Greg Kroah-Hartmanmodule_usb_driver(ttusb2_driver);
816bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick Boettcher
817bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
818bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
819bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_VERSION("1.0");
820bc2e3913c786d7387e21ee0818c1a3b66a571703Patrick BoettcherMODULE_LICENSE("GPL");
821