xref: /linux/drivers/media/usb/dvb-usb-v2/dvbsky.c (revision 0a5a4f32)
1af64fb3fSnibble.max /*
2af64fb3fSnibble.max  * Driver for DVBSky USB2.0 receiver
3af64fb3fSnibble.max  *
4af64fb3fSnibble.max  * Copyright (C) 2013 Max nibble <nibble.max@gmail.com>
5af64fb3fSnibble.max  *
6af64fb3fSnibble.max  *    This program is free software; you can redistribute it and/or modify
7af64fb3fSnibble.max  *    it under the terms of the GNU General Public License as published by
8af64fb3fSnibble.max  *    the Free Software Foundation; either version 2 of the License, or
9af64fb3fSnibble.max  *    (at your option) any later version.
10af64fb3fSnibble.max  *
11af64fb3fSnibble.max  *    This program is distributed in the hope that it will be useful,
12af64fb3fSnibble.max  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13af64fb3fSnibble.max  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14af64fb3fSnibble.max  *    GNU General Public License for more details.
15af64fb3fSnibble.max  *
16af64fb3fSnibble.max  *    You should have received a copy of the GNU General Public License
17af64fb3fSnibble.max  *    along with this program; if not, write to the Free Software
18af64fb3fSnibble.max  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19af64fb3fSnibble.max  */
20af64fb3fSnibble.max 
21af64fb3fSnibble.max #include "dvb_usb.h"
22af64fb3fSnibble.max #include "m88ds3103.h"
23af64fb3fSnibble.max #include "m88ts2022.h"
2424d333f3Snibble.max #include "sp2.h"
25b43a590dSNibble Max #include "si2168.h"
26b43a590dSNibble Max #include "si2157.h"
27af64fb3fSnibble.max 
28af64fb3fSnibble.max #define DVBSKY_MSG_DELAY	0/*2000*/
29af64fb3fSnibble.max #define DVBSKY_BUF_LEN	64
30af64fb3fSnibble.max 
3169e7b650SOlli Salonen static int dvb_usb_dvbsky_disable_rc;
3269e7b650SOlli Salonen module_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644);
3369e7b650SOlli Salonen MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver.");
3469e7b650SOlli Salonen 
35af64fb3fSnibble.max DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
36af64fb3fSnibble.max 
37af64fb3fSnibble.max struct dvbsky_state {
38af64fb3fSnibble.max 	struct mutex stream_mutex;
39af64fb3fSnibble.max 	u8 ibuf[DVBSKY_BUF_LEN];
40af64fb3fSnibble.max 	u8 obuf[DVBSKY_BUF_LEN];
41af64fb3fSnibble.max 	u8 last_lock;
42b43a590dSNibble Max 	struct i2c_client *i2c_client_demod;
43af64fb3fSnibble.max 	struct i2c_client *i2c_client_tuner;
4424d333f3Snibble.max 	struct i2c_client *i2c_client_ci;
45af64fb3fSnibble.max 
46af64fb3fSnibble.max 	/* fe hook functions*/
47af64fb3fSnibble.max 	int (*fe_set_voltage)(struct dvb_frontend *fe,
48af64fb3fSnibble.max 		fe_sec_voltage_t voltage);
49af64fb3fSnibble.max 	int (*fe_read_status)(struct dvb_frontend *fe,
50af64fb3fSnibble.max 		fe_status_t *status);
51af64fb3fSnibble.max };
52af64fb3fSnibble.max 
53af64fb3fSnibble.max static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
54af64fb3fSnibble.max 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
55af64fb3fSnibble.max {
56af64fb3fSnibble.max 	int ret;
57af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
58af64fb3fSnibble.max 
59af64fb3fSnibble.max 	mutex_lock(&d->usb_mutex);
60af64fb3fSnibble.max 	if (wlen != 0)
61af64fb3fSnibble.max 		memcpy(state->obuf, wbuf, wlen);
62af64fb3fSnibble.max 
63af64fb3fSnibble.max 	ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen,
64af64fb3fSnibble.max 			state->ibuf, rlen);
65af64fb3fSnibble.max 
66af64fb3fSnibble.max 	if (!ret && (rlen != 0))
67af64fb3fSnibble.max 		memcpy(rbuf, state->ibuf, rlen);
68af64fb3fSnibble.max 
69af64fb3fSnibble.max 	mutex_unlock(&d->usb_mutex);
70af64fb3fSnibble.max 	return ret;
71af64fb3fSnibble.max }
72af64fb3fSnibble.max 
73af64fb3fSnibble.max static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
74af64fb3fSnibble.max {
75af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
76af64fb3fSnibble.max 	int ret;
77af64fb3fSnibble.max 	u8 obuf_pre[3] = { 0x37, 0, 0 };
78af64fb3fSnibble.max 	u8 obuf_post[3] = { 0x36, 3, 0 };
79af64fb3fSnibble.max 
80af64fb3fSnibble.max 	mutex_lock(&state->stream_mutex);
81af64fb3fSnibble.max 	ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0);
82af64fb3fSnibble.max 	if (!ret && onoff) {
83af64fb3fSnibble.max 		msleep(20);
84af64fb3fSnibble.max 		ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0);
85af64fb3fSnibble.max 	}
86af64fb3fSnibble.max 	mutex_unlock(&state->stream_mutex);
87af64fb3fSnibble.max 	return ret;
88af64fb3fSnibble.max }
89af64fb3fSnibble.max 
90af64fb3fSnibble.max static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff)
91af64fb3fSnibble.max {
92af64fb3fSnibble.max 	struct dvb_usb_device *d = fe_to_d(fe);
93af64fb3fSnibble.max 
94af64fb3fSnibble.max 	return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1);
95af64fb3fSnibble.max }
96af64fb3fSnibble.max 
97af64fb3fSnibble.max /* GPIO */
98af64fb3fSnibble.max static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
99af64fb3fSnibble.max {
100af64fb3fSnibble.max 	int ret;
101af64fb3fSnibble.max 	u8 obuf[3], ibuf[2];
102af64fb3fSnibble.max 
103af64fb3fSnibble.max 	obuf[0] = 0x0e;
104af64fb3fSnibble.max 	obuf[1] = gport;
105af64fb3fSnibble.max 	obuf[2] = value;
106af64fb3fSnibble.max 	ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
107af64fb3fSnibble.max 	if (ret)
10840bba097SOlli Salonen 		dev_err(&d->udev->dev, "failed=%d\n", ret);
109af64fb3fSnibble.max 	return ret;
110af64fb3fSnibble.max }
111af64fb3fSnibble.max 
112af64fb3fSnibble.max /* I2C */
113af64fb3fSnibble.max static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
114af64fb3fSnibble.max 	int num)
115af64fb3fSnibble.max {
116af64fb3fSnibble.max 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
117af64fb3fSnibble.max 	int ret = 0;
118af64fb3fSnibble.max 	u8 ibuf[64], obuf[64];
119af64fb3fSnibble.max 
120af64fb3fSnibble.max 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
121af64fb3fSnibble.max 		return -EAGAIN;
122af64fb3fSnibble.max 
123af64fb3fSnibble.max 	if (num > 2) {
124af64fb3fSnibble.max 		dev_err(&d->udev->dev,
12540bba097SOlli Salonen 		"too many i2c messages[%d], max 2.", num);
126af64fb3fSnibble.max 		ret = -EOPNOTSUPP;
127af64fb3fSnibble.max 		goto i2c_error;
128af64fb3fSnibble.max 	}
129af64fb3fSnibble.max 
130af64fb3fSnibble.max 	if (num == 1) {
131af64fb3fSnibble.max 		if (msg[0].len > 60) {
132af64fb3fSnibble.max 			dev_err(&d->udev->dev,
13340bba097SOlli Salonen 			"too many i2c bytes[%d], max 60.",
134af64fb3fSnibble.max 			msg[0].len);
135af64fb3fSnibble.max 			ret = -EOPNOTSUPP;
136af64fb3fSnibble.max 			goto i2c_error;
137af64fb3fSnibble.max 		}
138af64fb3fSnibble.max 		if (msg[0].flags & I2C_M_RD) {
139af64fb3fSnibble.max 			/* single read */
140af64fb3fSnibble.max 			obuf[0] = 0x09;
141af64fb3fSnibble.max 			obuf[1] = 0;
142af64fb3fSnibble.max 			obuf[2] = msg[0].len;
143af64fb3fSnibble.max 			obuf[3] = msg[0].addr;
144af64fb3fSnibble.max 			ret = dvbsky_usb_generic_rw(d, obuf, 4,
145af64fb3fSnibble.max 					ibuf, msg[0].len + 1);
146af64fb3fSnibble.max 			if (ret)
14740bba097SOlli Salonen 				dev_err(&d->udev->dev, "failed=%d\n", ret);
148af64fb3fSnibble.max 			if (!ret)
149af64fb3fSnibble.max 				memcpy(msg[0].buf, &ibuf[1], msg[0].len);
150af64fb3fSnibble.max 		} else {
151af64fb3fSnibble.max 			/* write */
152af64fb3fSnibble.max 			obuf[0] = 0x08;
153af64fb3fSnibble.max 			obuf[1] = msg[0].addr;
154af64fb3fSnibble.max 			obuf[2] = msg[0].len;
155af64fb3fSnibble.max 			memcpy(&obuf[3], msg[0].buf, msg[0].len);
156af64fb3fSnibble.max 			ret = dvbsky_usb_generic_rw(d, obuf,
157af64fb3fSnibble.max 					msg[0].len + 3, ibuf, 1);
158af64fb3fSnibble.max 			if (ret)
15940bba097SOlli Salonen 				dev_err(&d->udev->dev, "failed=%d\n", ret);
160af64fb3fSnibble.max 		}
161af64fb3fSnibble.max 	} else {
162af64fb3fSnibble.max 		if ((msg[0].len > 60) || (msg[1].len > 60)) {
163af64fb3fSnibble.max 			dev_err(&d->udev->dev,
16440bba097SOlli Salonen 			"too many i2c bytes[w-%d][r-%d], max 60.",
165af64fb3fSnibble.max 			msg[0].len, msg[1].len);
166af64fb3fSnibble.max 			ret = -EOPNOTSUPP;
167af64fb3fSnibble.max 			goto i2c_error;
168af64fb3fSnibble.max 		}
169af64fb3fSnibble.max 		/* write then read */
170af64fb3fSnibble.max 		obuf[0] = 0x09;
171af64fb3fSnibble.max 		obuf[1] = msg[0].len;
172af64fb3fSnibble.max 		obuf[2] = msg[1].len;
173af64fb3fSnibble.max 		obuf[3] = msg[0].addr;
174af64fb3fSnibble.max 		memcpy(&obuf[4], msg[0].buf, msg[0].len);
175af64fb3fSnibble.max 		ret = dvbsky_usb_generic_rw(d, obuf,
176af64fb3fSnibble.max 			msg[0].len + 4, ibuf, msg[1].len + 1);
177af64fb3fSnibble.max 		if (ret)
17840bba097SOlli Salonen 			dev_err(&d->udev->dev, "failed=%d\n", ret);
179af64fb3fSnibble.max 
180af64fb3fSnibble.max 		if (!ret)
181af64fb3fSnibble.max 			memcpy(msg[1].buf, &ibuf[1], msg[1].len);
182af64fb3fSnibble.max 	}
183af64fb3fSnibble.max i2c_error:
184af64fb3fSnibble.max 	mutex_unlock(&d->i2c_mutex);
185af64fb3fSnibble.max 	return (ret) ? ret : num;
186af64fb3fSnibble.max }
187af64fb3fSnibble.max 
188af64fb3fSnibble.max static u32 dvbsky_i2c_func(struct i2c_adapter *adapter)
189af64fb3fSnibble.max {
190af64fb3fSnibble.max 	return I2C_FUNC_I2C;
191af64fb3fSnibble.max }
192af64fb3fSnibble.max 
193af64fb3fSnibble.max static struct i2c_algorithm dvbsky_i2c_algo = {
194af64fb3fSnibble.max 	.master_xfer   = dvbsky_i2c_xfer,
195af64fb3fSnibble.max 	.functionality = dvbsky_i2c_func,
196af64fb3fSnibble.max };
197af64fb3fSnibble.max 
198af64fb3fSnibble.max #if IS_ENABLED(CONFIG_RC_CORE)
199af64fb3fSnibble.max static int dvbsky_rc_query(struct dvb_usb_device *d)
200af64fb3fSnibble.max {
201af64fb3fSnibble.max 	u32 code = 0xffff, scancode;
202af64fb3fSnibble.max 	u8 rc5_command, rc5_system;
203af64fb3fSnibble.max 	u8 obuf[2], ibuf[2], toggle;
204af64fb3fSnibble.max 	int ret;
205af64fb3fSnibble.max 
206af64fb3fSnibble.max 	obuf[0] = 0x10;
207af64fb3fSnibble.max 	ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
208af64fb3fSnibble.max 	if (ret)
20940bba097SOlli Salonen 		dev_err(&d->udev->dev, "failed=%d\n", ret);
210af64fb3fSnibble.max 	if (ret == 0)
211af64fb3fSnibble.max 		code = (ibuf[0] << 8) | ibuf[1];
212af64fb3fSnibble.max 	if (code != 0xffff) {
213af64fb3fSnibble.max 		dev_dbg(&d->udev->dev, "rc code: %x\n", code);
214af64fb3fSnibble.max 		rc5_command = code & 0x3F;
215af64fb3fSnibble.max 		rc5_system = (code & 0x7C0) >> 6;
216af64fb3fSnibble.max 		toggle = (code & 0x800) ? 1 : 0;
217af64fb3fSnibble.max 		scancode = rc5_system << 8 | rc5_command;
218af64fb3fSnibble.max 		rc_keydown(d->rc_dev, RC_TYPE_RC5, scancode, toggle);
219af64fb3fSnibble.max 	}
220af64fb3fSnibble.max 	return 0;
221af64fb3fSnibble.max }
222af64fb3fSnibble.max 
223af64fb3fSnibble.max static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
224af64fb3fSnibble.max {
22569e7b650SOlli Salonen 	if (dvb_usb_dvbsky_disable_rc) {
22669e7b650SOlli Salonen 		rc->map_name = NULL;
22769e7b650SOlli Salonen 		return 0;
22869e7b650SOlli Salonen 	}
22969e7b650SOlli Salonen 
230af64fb3fSnibble.max 	rc->allowed_protos = RC_BIT_RC5;
231af64fb3fSnibble.max 	rc->query          = dvbsky_rc_query;
232af64fb3fSnibble.max 	rc->interval       = 300;
233af64fb3fSnibble.max 	return 0;
234af64fb3fSnibble.max }
235af64fb3fSnibble.max #else
236af64fb3fSnibble.max 	#define dvbsky_get_rc_config NULL
237af64fb3fSnibble.max #endif
238af64fb3fSnibble.max 
239af64fb3fSnibble.max static int dvbsky_usb_set_voltage(struct dvb_frontend *fe,
240af64fb3fSnibble.max 	fe_sec_voltage_t voltage)
241af64fb3fSnibble.max {
242af64fb3fSnibble.max 	struct dvb_usb_device *d = fe_to_d(fe);
243af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
244af64fb3fSnibble.max 	u8 value;
245af64fb3fSnibble.max 
246af64fb3fSnibble.max 	if (voltage == SEC_VOLTAGE_OFF)
247af64fb3fSnibble.max 		value = 0;
248af64fb3fSnibble.max 	else
249af64fb3fSnibble.max 		value = 1;
250af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x80, value);
251af64fb3fSnibble.max 
252af64fb3fSnibble.max 	return state->fe_set_voltage(fe, voltage);
253af64fb3fSnibble.max }
254af64fb3fSnibble.max 
255af64fb3fSnibble.max static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
256af64fb3fSnibble.max {
257af64fb3fSnibble.max 	struct dvb_usb_device *d = adap_to_d(adap);
258af64fb3fSnibble.max 	u8 obuf[] = { 0x1e, 0x00 };
259af64fb3fSnibble.max 	u8 ibuf[6] = { 0 };
260af64fb3fSnibble.max 	struct i2c_msg msg[] = {
261af64fb3fSnibble.max 		{
262af64fb3fSnibble.max 			.addr = 0x51,
263af64fb3fSnibble.max 			.flags = 0,
264af64fb3fSnibble.max 			.buf = obuf,
265af64fb3fSnibble.max 			.len = 2,
266af64fb3fSnibble.max 		}, {
267af64fb3fSnibble.max 			.addr = 0x51,
268af64fb3fSnibble.max 			.flags = I2C_M_RD,
269af64fb3fSnibble.max 			.buf = ibuf,
270af64fb3fSnibble.max 			.len = 6,
271af64fb3fSnibble.max 		}
272af64fb3fSnibble.max 	};
273af64fb3fSnibble.max 
274af64fb3fSnibble.max 	if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
275af64fb3fSnibble.max 		memcpy(mac, ibuf, 6);
276af64fb3fSnibble.max 
277af64fb3fSnibble.max 	return 0;
278af64fb3fSnibble.max }
279af64fb3fSnibble.max 
280af64fb3fSnibble.max static int dvbsky_usb_read_status(struct dvb_frontend *fe, fe_status_t *status)
281af64fb3fSnibble.max {
282af64fb3fSnibble.max 	struct dvb_usb_device *d = fe_to_d(fe);
283af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
284af64fb3fSnibble.max 	int ret;
285af64fb3fSnibble.max 
286af64fb3fSnibble.max 	ret = state->fe_read_status(fe, status);
287af64fb3fSnibble.max 
288af64fb3fSnibble.max 	/* it need resync slave fifo when signal change from unlock to lock.*/
289af64fb3fSnibble.max 	if ((*status & FE_HAS_LOCK) && (!state->last_lock))
290af64fb3fSnibble.max 		dvbsky_stream_ctrl(d, 1);
291af64fb3fSnibble.max 
292af64fb3fSnibble.max 	state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0;
293af64fb3fSnibble.max 	return ret;
294af64fb3fSnibble.max }
295af64fb3fSnibble.max 
296af64fb3fSnibble.max static const struct m88ds3103_config dvbsky_s960_m88ds3103_config = {
297af64fb3fSnibble.max 	.i2c_addr = 0x68,
298af64fb3fSnibble.max 	.clock = 27000000,
299af64fb3fSnibble.max 	.i2c_wr_max = 33,
300af64fb3fSnibble.max 	.clock_out = 0,
301af64fb3fSnibble.max 	.ts_mode = M88DS3103_TS_CI,
302af64fb3fSnibble.max 	.ts_clk = 16000,
303af64fb3fSnibble.max 	.ts_clk_pol = 0,
304af64fb3fSnibble.max 	.agc = 0x99,
305af64fb3fSnibble.max 	.lnb_hv_pol = 1,
306af64fb3fSnibble.max 	.lnb_en_pol = 1,
307af64fb3fSnibble.max };
308af64fb3fSnibble.max 
309af64fb3fSnibble.max static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
310af64fb3fSnibble.max {
311af64fb3fSnibble.max 	struct dvbsky_state *state = adap_to_priv(adap);
312af64fb3fSnibble.max 	struct dvb_usb_device *d = adap_to_d(adap);
313af64fb3fSnibble.max 	int ret = 0;
314af64fb3fSnibble.max 	/* demod I2C adapter */
315af64fb3fSnibble.max 	struct i2c_adapter *i2c_adapter;
316af64fb3fSnibble.max 	struct i2c_client *client;
317af64fb3fSnibble.max 	struct i2c_board_info info;
318af64fb3fSnibble.max 	struct m88ts2022_config m88ts2022_config = {
319af64fb3fSnibble.max 			.clock = 27000000,
320af64fb3fSnibble.max 		};
321af64fb3fSnibble.max 	memset(&info, 0, sizeof(struct i2c_board_info));
322af64fb3fSnibble.max 
323af64fb3fSnibble.max 	/* attach demod */
324af64fb3fSnibble.max 	adap->fe[0] = dvb_attach(m88ds3103_attach,
325af64fb3fSnibble.max 			&dvbsky_s960_m88ds3103_config,
326af64fb3fSnibble.max 			&d->i2c_adap,
327af64fb3fSnibble.max 			&i2c_adapter);
328af64fb3fSnibble.max 	if (!adap->fe[0]) {
329af64fb3fSnibble.max 		dev_err(&d->udev->dev, "dvbsky_s960_attach fail.\n");
330af64fb3fSnibble.max 		ret = -ENODEV;
331af64fb3fSnibble.max 		goto fail_attach;
332af64fb3fSnibble.max 	}
333af64fb3fSnibble.max 
334af64fb3fSnibble.max 	/* attach tuner */
335af64fb3fSnibble.max 	m88ts2022_config.fe = adap->fe[0];
336af64fb3fSnibble.max 	strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
337af64fb3fSnibble.max 	info.addr = 0x60;
338af64fb3fSnibble.max 	info.platform_data = &m88ts2022_config;
339af64fb3fSnibble.max 	request_module("m88ts2022");
340af64fb3fSnibble.max 	client = i2c_new_device(i2c_adapter, &info);
341af64fb3fSnibble.max 	if (client == NULL || client->dev.driver == NULL) {
342af64fb3fSnibble.max 		dvb_frontend_detach(adap->fe[0]);
343af64fb3fSnibble.max 		ret = -ENODEV;
344af64fb3fSnibble.max 		goto fail_attach;
345af64fb3fSnibble.max 	}
346af64fb3fSnibble.max 
347af64fb3fSnibble.max 	if (!try_module_get(client->dev.driver->owner)) {
348af64fb3fSnibble.max 		i2c_unregister_device(client);
349af64fb3fSnibble.max 		dvb_frontend_detach(adap->fe[0]);
350af64fb3fSnibble.max 		ret = -ENODEV;
351af64fb3fSnibble.max 		goto fail_attach;
352af64fb3fSnibble.max 	}
353af64fb3fSnibble.max 
354af64fb3fSnibble.max 	/* delegate signal strength measurement to tuner */
355af64fb3fSnibble.max 	adap->fe[0]->ops.read_signal_strength =
356af64fb3fSnibble.max 			adap->fe[0]->ops.tuner_ops.get_rf_strength;
357af64fb3fSnibble.max 
358af64fb3fSnibble.max 	/* hook fe: need to resync the slave fifo when signal locks. */
359af64fb3fSnibble.max 	state->fe_read_status = adap->fe[0]->ops.read_status;
360af64fb3fSnibble.max 	adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
361af64fb3fSnibble.max 
362af64fb3fSnibble.max 	/* hook fe: LNB off/on is control by Cypress usb chip. */
363af64fb3fSnibble.max 	state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
364af64fb3fSnibble.max 	adap->fe[0]->ops.set_voltage = dvbsky_usb_set_voltage;
365af64fb3fSnibble.max 
366af64fb3fSnibble.max 	state->i2c_client_tuner = client;
367af64fb3fSnibble.max 
368af64fb3fSnibble.max fail_attach:
369af64fb3fSnibble.max 	return ret;
370af64fb3fSnibble.max }
371af64fb3fSnibble.max 
37224d333f3Snibble.max static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe,
37324d333f3Snibble.max 	fe_sec_voltage_t voltage)
37424d333f3Snibble.max {
37524d333f3Snibble.max 	struct dvb_usb_device *d = fe_to_d(fe);
37624d333f3Snibble.max 	struct dvbsky_state *state = d_to_priv(d);
37724d333f3Snibble.max 	u8 value;
37824d333f3Snibble.max 
37924d333f3Snibble.max 	if (voltage == SEC_VOLTAGE_OFF)
38024d333f3Snibble.max 		value = 0;
38124d333f3Snibble.max 	else
38224d333f3Snibble.max 		value = 1;
38324d333f3Snibble.max 	dvbsky_gpio_ctrl(d, 0x00, value);
38424d333f3Snibble.max 
38524d333f3Snibble.max 	return state->fe_set_voltage(fe, voltage);
38624d333f3Snibble.max }
38724d333f3Snibble.max 
38824d333f3Snibble.max static int dvbsky_ci_ctrl(void *priv, u8 read, int addr,
38924d333f3Snibble.max 					u8 data, int *mem)
39024d333f3Snibble.max {
39124d333f3Snibble.max 	struct dvb_usb_device *d = priv;
39224d333f3Snibble.max 	int ret = 0;
39324d333f3Snibble.max 	u8 command[4], respond[2], command_size, respond_size;
39424d333f3Snibble.max 
39524d333f3Snibble.max 	command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
39624d333f3Snibble.max 	command[2] = (u8)(addr & 0xff); /*low part of address*/
39724d333f3Snibble.max 	if (read) {
39824d333f3Snibble.max 		command[0] = 0x71;
39924d333f3Snibble.max 		command_size = 3;
40024d333f3Snibble.max 		respond_size = 2;
40124d333f3Snibble.max 	} else {
40224d333f3Snibble.max 		command[0] = 0x70;
40324d333f3Snibble.max 		command[3] = data;
40424d333f3Snibble.max 		command_size = 4;
40524d333f3Snibble.max 		respond_size = 1;
40624d333f3Snibble.max 	}
40724d333f3Snibble.max 	ret = dvbsky_usb_generic_rw(d, command, command_size,
40824d333f3Snibble.max 			respond, respond_size);
40924d333f3Snibble.max 	if (ret)
41024d333f3Snibble.max 		goto err;
41124d333f3Snibble.max 	if (read)
41224d333f3Snibble.max 		*mem = respond[1];
41324d333f3Snibble.max 	return ret;
41424d333f3Snibble.max err:
41524d333f3Snibble.max 	dev_err(&d->udev->dev, "ci control failed=%d\n", ret);
41624d333f3Snibble.max 	return ret;
41724d333f3Snibble.max }
41824d333f3Snibble.max 
41924d333f3Snibble.max static const struct m88ds3103_config dvbsky_s960c_m88ds3103_config = {
42024d333f3Snibble.max 	.i2c_addr = 0x68,
42124d333f3Snibble.max 	.clock = 27000000,
42224d333f3Snibble.max 	.i2c_wr_max = 33,
42324d333f3Snibble.max 	.clock_out = 0,
42424d333f3Snibble.max 	.ts_mode = M88DS3103_TS_CI,
42524d333f3Snibble.max 	.ts_clk = 10000,
42624d333f3Snibble.max 	.ts_clk_pol = 1,
42724d333f3Snibble.max 	.agc = 0x99,
42824d333f3Snibble.max 	.lnb_hv_pol = 0,
42924d333f3Snibble.max 	.lnb_en_pol = 1,
43024d333f3Snibble.max };
43124d333f3Snibble.max 
43224d333f3Snibble.max static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
43324d333f3Snibble.max {
43424d333f3Snibble.max 	struct dvbsky_state *state = adap_to_priv(adap);
43524d333f3Snibble.max 	struct dvb_usb_device *d = adap_to_d(adap);
43624d333f3Snibble.max 	int ret = 0;
43724d333f3Snibble.max 	/* demod I2C adapter */
43824d333f3Snibble.max 	struct i2c_adapter *i2c_adapter;
43924d333f3Snibble.max 	struct i2c_client *client_tuner, *client_ci;
44024d333f3Snibble.max 	struct i2c_board_info info;
44124d333f3Snibble.max 	struct sp2_config sp2_config;
44224d333f3Snibble.max 	struct m88ts2022_config m88ts2022_config = {
44324d333f3Snibble.max 			.clock = 27000000,
44424d333f3Snibble.max 		};
44524d333f3Snibble.max 	memset(&info, 0, sizeof(struct i2c_board_info));
44624d333f3Snibble.max 
44724d333f3Snibble.max 	/* attach demod */
44824d333f3Snibble.max 	adap->fe[0] = dvb_attach(m88ds3103_attach,
44924d333f3Snibble.max 			&dvbsky_s960c_m88ds3103_config,
45024d333f3Snibble.max 			&d->i2c_adap,
45124d333f3Snibble.max 			&i2c_adapter);
45224d333f3Snibble.max 	if (!adap->fe[0]) {
45324d333f3Snibble.max 		dev_err(&d->udev->dev, "dvbsky_s960ci_attach fail.\n");
45424d333f3Snibble.max 		ret = -ENODEV;
45524d333f3Snibble.max 		goto fail_attach;
45624d333f3Snibble.max 	}
45724d333f3Snibble.max 
45824d333f3Snibble.max 	/* attach tuner */
45924d333f3Snibble.max 	m88ts2022_config.fe = adap->fe[0];
46024d333f3Snibble.max 	strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
46124d333f3Snibble.max 	info.addr = 0x60;
46224d333f3Snibble.max 	info.platform_data = &m88ts2022_config;
46324d333f3Snibble.max 	request_module("m88ts2022");
46424d333f3Snibble.max 	client_tuner = i2c_new_device(i2c_adapter, &info);
46524d333f3Snibble.max 	if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
46624d333f3Snibble.max 		ret = -ENODEV;
46724d333f3Snibble.max 		goto fail_tuner_device;
46824d333f3Snibble.max 	}
46924d333f3Snibble.max 
47024d333f3Snibble.max 	if (!try_module_get(client_tuner->dev.driver->owner)) {
47124d333f3Snibble.max 		ret = -ENODEV;
47224d333f3Snibble.max 		goto fail_tuner_module;
47324d333f3Snibble.max 	}
47424d333f3Snibble.max 
47524d333f3Snibble.max 	/* attach ci controller */
47624d333f3Snibble.max 	memset(&sp2_config, 0, sizeof(sp2_config));
47724d333f3Snibble.max 	sp2_config.dvb_adap = &adap->dvb_adap;
47824d333f3Snibble.max 	sp2_config.priv = d;
47924d333f3Snibble.max 	sp2_config.ci_control = dvbsky_ci_ctrl;
48024d333f3Snibble.max 	memset(&info, 0, sizeof(struct i2c_board_info));
48124d333f3Snibble.max 	strlcpy(info.type, "sp2", I2C_NAME_SIZE);
48224d333f3Snibble.max 	info.addr = 0x40;
48324d333f3Snibble.max 	info.platform_data = &sp2_config;
48424d333f3Snibble.max 	request_module("sp2");
485dd0a6fe2Snibble.max 	client_ci = i2c_new_device(&d->i2c_adap, &info);
48624d333f3Snibble.max 	if (client_ci == NULL || client_ci->dev.driver == NULL) {
48724d333f3Snibble.max 		ret = -ENODEV;
48824d333f3Snibble.max 		goto fail_ci_device;
48924d333f3Snibble.max 	}
49024d333f3Snibble.max 
49124d333f3Snibble.max 	if (!try_module_get(client_ci->dev.driver->owner)) {
49224d333f3Snibble.max 		ret = -ENODEV;
49324d333f3Snibble.max 		goto fail_ci_module;
49424d333f3Snibble.max 	}
49524d333f3Snibble.max 
49624d333f3Snibble.max 	/* delegate signal strength measurement to tuner */
49724d333f3Snibble.max 	adap->fe[0]->ops.read_signal_strength =
49824d333f3Snibble.max 			adap->fe[0]->ops.tuner_ops.get_rf_strength;
49924d333f3Snibble.max 
50024d333f3Snibble.max 	/* hook fe: need to resync the slave fifo when signal locks. */
50124d333f3Snibble.max 	state->fe_read_status = adap->fe[0]->ops.read_status;
50224d333f3Snibble.max 	adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
50324d333f3Snibble.max 
50424d333f3Snibble.max 	/* hook fe: LNB off/on is control by Cypress usb chip. */
50524d333f3Snibble.max 	state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
50624d333f3Snibble.max 	adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage;
50724d333f3Snibble.max 
50824d333f3Snibble.max 	state->i2c_client_tuner = client_tuner;
50924d333f3Snibble.max 	state->i2c_client_ci = client_ci;
51024d333f3Snibble.max 	return ret;
51124d333f3Snibble.max fail_ci_module:
51224d333f3Snibble.max 	i2c_unregister_device(client_ci);
51324d333f3Snibble.max fail_ci_device:
51424d333f3Snibble.max 	module_put(client_tuner->dev.driver->owner);
51524d333f3Snibble.max fail_tuner_module:
51624d333f3Snibble.max 	i2c_unregister_device(client_tuner);
51724d333f3Snibble.max fail_tuner_device:
51824d333f3Snibble.max 	dvb_frontend_detach(adap->fe[0]);
51924d333f3Snibble.max fail_attach:
52024d333f3Snibble.max 	return ret;
52124d333f3Snibble.max }
52224d333f3Snibble.max 
523b43a590dSNibble Max static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
524b43a590dSNibble Max {
525b43a590dSNibble Max 	struct dvbsky_state *state = adap_to_priv(adap);
526b43a590dSNibble Max 	struct dvb_usb_device *d = adap_to_d(adap);
527b43a590dSNibble Max 	int ret = 0;
528b43a590dSNibble Max 	struct i2c_adapter *i2c_adapter;
529b43a590dSNibble Max 	struct i2c_client *client_demod, *client_tuner, *client_ci;
530b43a590dSNibble Max 	struct i2c_board_info info;
531b43a590dSNibble Max 	struct si2168_config si2168_config;
532b43a590dSNibble Max 	struct si2157_config si2157_config;
533b43a590dSNibble Max 	struct sp2_config sp2_config;
534b43a590dSNibble Max 
535b43a590dSNibble Max 	/* attach demod */
536b43a590dSNibble Max 	memset(&si2168_config, 0, sizeof(si2168_config));
537b43a590dSNibble Max 	si2168_config.i2c_adapter = &i2c_adapter;
538b43a590dSNibble Max 	si2168_config.fe = &adap->fe[0];
539b43a590dSNibble Max 	si2168_config.ts_mode = SI2168_TS_PARALLEL;
540b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
541b43a590dSNibble Max 	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
542b43a590dSNibble Max 	info.addr = 0x64;
543b43a590dSNibble Max 	info.platform_data = &si2168_config;
544b43a590dSNibble Max 
545b43a590dSNibble Max 	request_module(info.type);
546b43a590dSNibble Max 	client_demod = i2c_new_device(&d->i2c_adap, &info);
547b43a590dSNibble Max 	if (client_demod == NULL ||
548b43a590dSNibble Max 			client_demod->dev.driver == NULL)
549b43a590dSNibble Max 		goto fail_demod_device;
550b43a590dSNibble Max 	if (!try_module_get(client_demod->dev.driver->owner))
551b43a590dSNibble Max 		goto fail_demod_module;
552b43a590dSNibble Max 
553b43a590dSNibble Max 	/* attach tuner */
554b43a590dSNibble Max 	memset(&si2157_config, 0, sizeof(si2157_config));
555b43a590dSNibble Max 	si2157_config.fe = adap->fe[0];
556b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
557b43a590dSNibble Max 	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
558b43a590dSNibble Max 	info.addr = 0x60;
559b43a590dSNibble Max 	info.platform_data = &si2157_config;
560b43a590dSNibble Max 
561b43a590dSNibble Max 	request_module(info.type);
562b43a590dSNibble Max 	client_tuner = i2c_new_device(i2c_adapter, &info);
563b43a590dSNibble Max 	if (client_tuner == NULL ||
564b43a590dSNibble Max 			client_tuner->dev.driver == NULL)
565b43a590dSNibble Max 		goto fail_tuner_device;
566b43a590dSNibble Max 	if (!try_module_get(client_tuner->dev.driver->owner))
567b43a590dSNibble Max 		goto fail_tuner_module;
568b43a590dSNibble Max 
569b43a590dSNibble Max 	/* attach ci controller */
570b43a590dSNibble Max 	memset(&sp2_config, 0, sizeof(sp2_config));
571b43a590dSNibble Max 	sp2_config.dvb_adap = &adap->dvb_adap;
572b43a590dSNibble Max 	sp2_config.priv = d;
573b43a590dSNibble Max 	sp2_config.ci_control = dvbsky_ci_ctrl;
574b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
575b43a590dSNibble Max 	strlcpy(info.type, "sp2", I2C_NAME_SIZE);
576b43a590dSNibble Max 	info.addr = 0x40;
577b43a590dSNibble Max 	info.platform_data = &sp2_config;
578b43a590dSNibble Max 
579b43a590dSNibble Max 	request_module(info.type);
580b43a590dSNibble Max 	client_ci = i2c_new_device(&d->i2c_adap, &info);
581b43a590dSNibble Max 
582b43a590dSNibble Max 	if (client_ci == NULL || client_ci->dev.driver == NULL)
583b43a590dSNibble Max 		goto fail_ci_device;
584b43a590dSNibble Max 
585b43a590dSNibble Max 	if (!try_module_get(client_ci->dev.driver->owner))
586b43a590dSNibble Max 		goto fail_ci_module;
587b43a590dSNibble Max 
588b43a590dSNibble Max 	state->i2c_client_demod = client_demod;
589b43a590dSNibble Max 	state->i2c_client_tuner = client_tuner;
590b43a590dSNibble Max 	state->i2c_client_ci = client_ci;
591b43a590dSNibble Max 	return ret;
592b43a590dSNibble Max fail_ci_module:
593b43a590dSNibble Max 	i2c_unregister_device(client_ci);
594b43a590dSNibble Max fail_ci_device:
595b43a590dSNibble Max 	module_put(client_tuner->dev.driver->owner);
596b43a590dSNibble Max fail_tuner_module:
597b43a590dSNibble Max 	i2c_unregister_device(client_tuner);
598b43a590dSNibble Max fail_tuner_device:
599b43a590dSNibble Max 	module_put(client_demod->dev.driver->owner);
600b43a590dSNibble Max fail_demod_module:
601b43a590dSNibble Max 	i2c_unregister_device(client_demod);
602b43a590dSNibble Max fail_demod_device:
603b43a590dSNibble Max 	ret = -ENODEV;
604b43a590dSNibble Max 	return ret;
605b43a590dSNibble Max }
606b43a590dSNibble Max 
607*0a5a4f32SNibble Max static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
608*0a5a4f32SNibble Max {
609*0a5a4f32SNibble Max 	struct dvbsky_state *state = adap_to_priv(adap);
610*0a5a4f32SNibble Max 	struct dvb_usb_device *d = adap_to_d(adap);
611*0a5a4f32SNibble Max 	int ret = 0;
612*0a5a4f32SNibble Max 	struct i2c_adapter *i2c_adapter;
613*0a5a4f32SNibble Max 	struct i2c_client *client_demod, *client_tuner;
614*0a5a4f32SNibble Max 	struct i2c_board_info info;
615*0a5a4f32SNibble Max 	struct si2168_config si2168_config;
616*0a5a4f32SNibble Max 	struct si2157_config si2157_config;
617*0a5a4f32SNibble Max 
618*0a5a4f32SNibble Max 	/* attach demod */
619*0a5a4f32SNibble Max 	memset(&si2168_config, 0, sizeof(si2168_config));
620*0a5a4f32SNibble Max 	si2168_config.i2c_adapter = &i2c_adapter;
621*0a5a4f32SNibble Max 	si2168_config.fe = &adap->fe[0];
622*0a5a4f32SNibble Max 	si2168_config.ts_mode = SI2168_TS_PARALLEL | 0x40;
623*0a5a4f32SNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
624*0a5a4f32SNibble Max 	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
625*0a5a4f32SNibble Max 	info.addr = 0x64;
626*0a5a4f32SNibble Max 	info.platform_data = &si2168_config;
627*0a5a4f32SNibble Max 
628*0a5a4f32SNibble Max 	request_module(info.type);
629*0a5a4f32SNibble Max 	client_demod = i2c_new_device(&d->i2c_adap, &info);
630*0a5a4f32SNibble Max 	if (client_demod == NULL ||
631*0a5a4f32SNibble Max 			client_demod->dev.driver == NULL)
632*0a5a4f32SNibble Max 		goto fail_demod_device;
633*0a5a4f32SNibble Max 	if (!try_module_get(client_demod->dev.driver->owner))
634*0a5a4f32SNibble Max 		goto fail_demod_module;
635*0a5a4f32SNibble Max 
636*0a5a4f32SNibble Max 	/* attach tuner */
637*0a5a4f32SNibble Max 	memset(&si2157_config, 0, sizeof(si2157_config));
638*0a5a4f32SNibble Max 	si2157_config.fe = adap->fe[0];
639*0a5a4f32SNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
640*0a5a4f32SNibble Max 	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
641*0a5a4f32SNibble Max 	info.addr = 0x60;
642*0a5a4f32SNibble Max 	info.platform_data = &si2157_config;
643*0a5a4f32SNibble Max 
644*0a5a4f32SNibble Max 	request_module(info.type);
645*0a5a4f32SNibble Max 	client_tuner = i2c_new_device(i2c_adapter, &info);
646*0a5a4f32SNibble Max 	if (client_tuner == NULL ||
647*0a5a4f32SNibble Max 			client_tuner->dev.driver == NULL)
648*0a5a4f32SNibble Max 		goto fail_tuner_device;
649*0a5a4f32SNibble Max 	if (!try_module_get(client_tuner->dev.driver->owner))
650*0a5a4f32SNibble Max 		goto fail_tuner_module;
651*0a5a4f32SNibble Max 
652*0a5a4f32SNibble Max 	state->i2c_client_demod = client_demod;
653*0a5a4f32SNibble Max 	state->i2c_client_tuner = client_tuner;
654*0a5a4f32SNibble Max 	return ret;
655*0a5a4f32SNibble Max fail_tuner_module:
656*0a5a4f32SNibble Max 	i2c_unregister_device(client_tuner);
657*0a5a4f32SNibble Max fail_tuner_device:
658*0a5a4f32SNibble Max 	module_put(client_demod->dev.driver->owner);
659*0a5a4f32SNibble Max fail_demod_module:
660*0a5a4f32SNibble Max 	i2c_unregister_device(client_demod);
661*0a5a4f32SNibble Max fail_demod_device:
662*0a5a4f32SNibble Max 	ret = -ENODEV;
663*0a5a4f32SNibble Max 	return ret;
664*0a5a4f32SNibble Max }
665*0a5a4f32SNibble Max 
666af64fb3fSnibble.max static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
667af64fb3fSnibble.max {
668af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x04, 1);
669af64fb3fSnibble.max 	msleep(20);
670af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x83, 0);
671af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0xc0, 1);
672af64fb3fSnibble.max 	msleep(100);
673af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x83, 1);
674af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0xc0, 0);
675af64fb3fSnibble.max 	msleep(50);
676af64fb3fSnibble.max 
677af64fb3fSnibble.max 	return WARM;
678af64fb3fSnibble.max }
679af64fb3fSnibble.max 
680af64fb3fSnibble.max static int dvbsky_init(struct dvb_usb_device *d)
681af64fb3fSnibble.max {
682af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
683af64fb3fSnibble.max 
684af64fb3fSnibble.max 	/* use default interface */
685af64fb3fSnibble.max 	/*
686af64fb3fSnibble.max 	ret = usb_set_interface(d->udev, 0, 0);
687af64fb3fSnibble.max 	if (ret)
688af64fb3fSnibble.max 		return ret;
689af64fb3fSnibble.max 	*/
690af64fb3fSnibble.max 	mutex_init(&state->stream_mutex);
691af64fb3fSnibble.max 
692af64fb3fSnibble.max 	state->last_lock = 0;
693af64fb3fSnibble.max 
694af64fb3fSnibble.max 	return 0;
695af64fb3fSnibble.max }
696af64fb3fSnibble.max 
697af64fb3fSnibble.max static void dvbsky_exit(struct dvb_usb_device *d)
698af64fb3fSnibble.max {
699af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
700af64fb3fSnibble.max 	struct i2c_client *client;
701af64fb3fSnibble.max 
702af64fb3fSnibble.max 	client = state->i2c_client_tuner;
703af64fb3fSnibble.max 	/* remove I2C tuner */
704af64fb3fSnibble.max 	if (client) {
705af64fb3fSnibble.max 		module_put(client->dev.driver->owner);
706af64fb3fSnibble.max 		i2c_unregister_device(client);
707af64fb3fSnibble.max 	}
708b43a590dSNibble Max 	client = state->i2c_client_demod;
709b43a590dSNibble Max 	/* remove I2C demod */
710b43a590dSNibble Max 	if (client) {
711b43a590dSNibble Max 		module_put(client->dev.driver->owner);
712b43a590dSNibble Max 		i2c_unregister_device(client);
713b43a590dSNibble Max 	}
71424d333f3Snibble.max 	client = state->i2c_client_ci;
71524d333f3Snibble.max 	/* remove I2C ci */
71624d333f3Snibble.max 	if (client) {
71724d333f3Snibble.max 		module_put(client->dev.driver->owner);
71824d333f3Snibble.max 		i2c_unregister_device(client);
71924d333f3Snibble.max 	}
720af64fb3fSnibble.max }
721af64fb3fSnibble.max 
722af64fb3fSnibble.max /* DVB USB Driver stuff */
723af64fb3fSnibble.max static struct dvb_usb_device_properties dvbsky_s960_props = {
724af64fb3fSnibble.max 	.driver_name = KBUILD_MODNAME,
725af64fb3fSnibble.max 	.owner = THIS_MODULE,
726af64fb3fSnibble.max 	.adapter_nr = adapter_nr,
727af64fb3fSnibble.max 	.size_of_priv = sizeof(struct dvbsky_state),
728af64fb3fSnibble.max 
729af64fb3fSnibble.max 	.generic_bulk_ctrl_endpoint = 0x01,
730af64fb3fSnibble.max 	.generic_bulk_ctrl_endpoint_response = 0x81,
731af64fb3fSnibble.max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
732af64fb3fSnibble.max 
733af64fb3fSnibble.max 	.i2c_algo         = &dvbsky_i2c_algo,
734af64fb3fSnibble.max 	.frontend_attach  = dvbsky_s960_attach,
735af64fb3fSnibble.max 	.init             = dvbsky_init,
736af64fb3fSnibble.max 	.get_rc_config    = dvbsky_get_rc_config,
737af64fb3fSnibble.max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
738af64fb3fSnibble.max 	.identify_state	  = dvbsky_identify_state,
739af64fb3fSnibble.max 	.exit             = dvbsky_exit,
740af64fb3fSnibble.max 	.read_mac_address = dvbsky_read_mac_addr,
741af64fb3fSnibble.max 
742af64fb3fSnibble.max 	.num_adapters = 1,
743af64fb3fSnibble.max 	.adapter = {
744af64fb3fSnibble.max 		{
745af64fb3fSnibble.max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
746af64fb3fSnibble.max 		}
747af64fb3fSnibble.max 	}
748af64fb3fSnibble.max };
749af64fb3fSnibble.max 
75024d333f3Snibble.max static struct dvb_usb_device_properties dvbsky_s960c_props = {
75124d333f3Snibble.max 	.driver_name = KBUILD_MODNAME,
75224d333f3Snibble.max 	.owner = THIS_MODULE,
75324d333f3Snibble.max 	.adapter_nr = adapter_nr,
75424d333f3Snibble.max 	.size_of_priv = sizeof(struct dvbsky_state),
75524d333f3Snibble.max 
75624d333f3Snibble.max 	.generic_bulk_ctrl_endpoint = 0x01,
75724d333f3Snibble.max 	.generic_bulk_ctrl_endpoint_response = 0x81,
75824d333f3Snibble.max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
75924d333f3Snibble.max 
76024d333f3Snibble.max 	.i2c_algo         = &dvbsky_i2c_algo,
76124d333f3Snibble.max 	.frontend_attach  = dvbsky_s960c_attach,
76224d333f3Snibble.max 	.init             = dvbsky_init,
76324d333f3Snibble.max 	.get_rc_config    = dvbsky_get_rc_config,
76424d333f3Snibble.max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
76524d333f3Snibble.max 	.identify_state	  = dvbsky_identify_state,
76624d333f3Snibble.max 	.exit             = dvbsky_exit,
76724d333f3Snibble.max 	.read_mac_address = dvbsky_read_mac_addr,
76824d333f3Snibble.max 
76924d333f3Snibble.max 	.num_adapters = 1,
77024d333f3Snibble.max 	.adapter = {
77124d333f3Snibble.max 		{
77224d333f3Snibble.max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
77324d333f3Snibble.max 		}
77424d333f3Snibble.max 	}
77524d333f3Snibble.max };
77624d333f3Snibble.max 
777b43a590dSNibble Max static struct dvb_usb_device_properties dvbsky_t680c_props = {
778b43a590dSNibble Max 	.driver_name = KBUILD_MODNAME,
779b43a590dSNibble Max 	.owner = THIS_MODULE,
780b43a590dSNibble Max 	.adapter_nr = adapter_nr,
781b43a590dSNibble Max 	.size_of_priv = sizeof(struct dvbsky_state),
782b43a590dSNibble Max 
783b43a590dSNibble Max 	.generic_bulk_ctrl_endpoint = 0x01,
784b43a590dSNibble Max 	.generic_bulk_ctrl_endpoint_response = 0x81,
785b43a590dSNibble Max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
786b43a590dSNibble Max 
787b43a590dSNibble Max 	.i2c_algo         = &dvbsky_i2c_algo,
788b43a590dSNibble Max 	.frontend_attach  = dvbsky_t680c_attach,
789b43a590dSNibble Max 	.init             = dvbsky_init,
790b43a590dSNibble Max 	.get_rc_config    = dvbsky_get_rc_config,
791b43a590dSNibble Max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
792b43a590dSNibble Max 	.identify_state	  = dvbsky_identify_state,
793b43a590dSNibble Max 	.exit             = dvbsky_exit,
794b43a590dSNibble Max 	.read_mac_address = dvbsky_read_mac_addr,
795b43a590dSNibble Max 
796b43a590dSNibble Max 	.num_adapters = 1,
797b43a590dSNibble Max 	.adapter = {
798b43a590dSNibble Max 		{
799b43a590dSNibble Max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
800b43a590dSNibble Max 		}
801b43a590dSNibble Max 	}
802b43a590dSNibble Max };
803b43a590dSNibble Max 
804*0a5a4f32SNibble Max static struct dvb_usb_device_properties dvbsky_t330_props = {
805*0a5a4f32SNibble Max 	.driver_name = KBUILD_MODNAME,
806*0a5a4f32SNibble Max 	.owner = THIS_MODULE,
807*0a5a4f32SNibble Max 	.adapter_nr = adapter_nr,
808*0a5a4f32SNibble Max 	.size_of_priv = sizeof(struct dvbsky_state),
809*0a5a4f32SNibble Max 
810*0a5a4f32SNibble Max 	.generic_bulk_ctrl_endpoint = 0x01,
811*0a5a4f32SNibble Max 	.generic_bulk_ctrl_endpoint_response = 0x81,
812*0a5a4f32SNibble Max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
813*0a5a4f32SNibble Max 
814*0a5a4f32SNibble Max 	.i2c_algo         = &dvbsky_i2c_algo,
815*0a5a4f32SNibble Max 	.frontend_attach  = dvbsky_t330_attach,
816*0a5a4f32SNibble Max 	.init             = dvbsky_init,
817*0a5a4f32SNibble Max 	.get_rc_config    = dvbsky_get_rc_config,
818*0a5a4f32SNibble Max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
819*0a5a4f32SNibble Max 	.identify_state	  = dvbsky_identify_state,
820*0a5a4f32SNibble Max 	.exit             = dvbsky_exit,
821*0a5a4f32SNibble Max 	.read_mac_address = dvbsky_read_mac_addr,
822*0a5a4f32SNibble Max 
823*0a5a4f32SNibble Max 	.num_adapters = 1,
824*0a5a4f32SNibble Max 	.adapter = {
825*0a5a4f32SNibble Max 		{
826*0a5a4f32SNibble Max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
827*0a5a4f32SNibble Max 		}
828*0a5a4f32SNibble Max 	}
829*0a5a4f32SNibble Max };
830*0a5a4f32SNibble Max 
831af64fb3fSnibble.max static const struct usb_device_id dvbsky_id_table[] = {
832af64fb3fSnibble.max 	{ DVB_USB_DEVICE(0x0572, 0x6831,
833af64fb3fSnibble.max 		&dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
83424d333f3Snibble.max 	{ DVB_USB_DEVICE(0x0572, 0x960c,
83524d333f3Snibble.max 		&dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
836b43a590dSNibble Max 	{ DVB_USB_DEVICE(0x0572, 0x680c,
837b43a590dSNibble Max 		&dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
838*0a5a4f32SNibble Max 	{ DVB_USB_DEVICE(0x0572, 0x0320,
839*0a5a4f32SNibble Max 		&dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) },
840af64fb3fSnibble.max 	{ }
841af64fb3fSnibble.max };
842af64fb3fSnibble.max MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
843af64fb3fSnibble.max 
844af64fb3fSnibble.max static struct usb_driver dvbsky_usb_driver = {
845af64fb3fSnibble.max 	.name = KBUILD_MODNAME,
846af64fb3fSnibble.max 	.id_table = dvbsky_id_table,
847af64fb3fSnibble.max 	.probe = dvb_usbv2_probe,
848af64fb3fSnibble.max 	.disconnect = dvb_usbv2_disconnect,
849af64fb3fSnibble.max 	.suspend = dvb_usbv2_suspend,
850af64fb3fSnibble.max 	.resume = dvb_usbv2_resume,
851af64fb3fSnibble.max 	.reset_resume = dvb_usbv2_reset_resume,
852af64fb3fSnibble.max 	.no_dynamic_id = 1,
853af64fb3fSnibble.max 	.soft_unbind = 1,
854af64fb3fSnibble.max };
855af64fb3fSnibble.max 
856af64fb3fSnibble.max module_usb_driver(dvbsky_usb_driver);
857af64fb3fSnibble.max 
858af64fb3fSnibble.max MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
859af64fb3fSnibble.max MODULE_DESCRIPTION("Driver for DVBSky USB");
860af64fb3fSnibble.max MODULE_LICENSE("GPL");
861