xref: /linux/drivers/media/usb/dvb-usb-v2/dvbsky.c (revision b43a590d)
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"
25*b43a590dSNibble Max #include "si2168.h"
26*b43a590dSNibble 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;
42*b43a590dSNibble 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 
523*b43a590dSNibble Max static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
524*b43a590dSNibble Max {
525*b43a590dSNibble Max 	struct dvbsky_state *state = adap_to_priv(adap);
526*b43a590dSNibble Max 	struct dvb_usb_device *d = adap_to_d(adap);
527*b43a590dSNibble Max 	int ret = 0;
528*b43a590dSNibble Max 	struct i2c_adapter *i2c_adapter;
529*b43a590dSNibble Max 	struct i2c_client *client_demod, *client_tuner, *client_ci;
530*b43a590dSNibble Max 	struct i2c_board_info info;
531*b43a590dSNibble Max 	struct si2168_config si2168_config;
532*b43a590dSNibble Max 	struct si2157_config si2157_config;
533*b43a590dSNibble Max 	struct sp2_config sp2_config;
534*b43a590dSNibble Max 
535*b43a590dSNibble Max 	/* attach demod */
536*b43a590dSNibble Max 	memset(&si2168_config, 0, sizeof(si2168_config));
537*b43a590dSNibble Max 	si2168_config.i2c_adapter = &i2c_adapter;
538*b43a590dSNibble Max 	si2168_config.fe = &adap->fe[0];
539*b43a590dSNibble Max 	si2168_config.ts_mode = SI2168_TS_PARALLEL;
540*b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
541*b43a590dSNibble Max 	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
542*b43a590dSNibble Max 	info.addr = 0x64;
543*b43a590dSNibble Max 	info.platform_data = &si2168_config;
544*b43a590dSNibble Max 
545*b43a590dSNibble Max 	request_module(info.type);
546*b43a590dSNibble Max 	client_demod = i2c_new_device(&d->i2c_adap, &info);
547*b43a590dSNibble Max 	if (client_demod == NULL ||
548*b43a590dSNibble Max 			client_demod->dev.driver == NULL)
549*b43a590dSNibble Max 		goto fail_demod_device;
550*b43a590dSNibble Max 	if (!try_module_get(client_demod->dev.driver->owner))
551*b43a590dSNibble Max 		goto fail_demod_module;
552*b43a590dSNibble Max 
553*b43a590dSNibble Max 	/* attach tuner */
554*b43a590dSNibble Max 	memset(&si2157_config, 0, sizeof(si2157_config));
555*b43a590dSNibble Max 	si2157_config.fe = adap->fe[0];
556*b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
557*b43a590dSNibble Max 	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
558*b43a590dSNibble Max 	info.addr = 0x60;
559*b43a590dSNibble Max 	info.platform_data = &si2157_config;
560*b43a590dSNibble Max 
561*b43a590dSNibble Max 	request_module(info.type);
562*b43a590dSNibble Max 	client_tuner = i2c_new_device(i2c_adapter, &info);
563*b43a590dSNibble Max 	if (client_tuner == NULL ||
564*b43a590dSNibble Max 			client_tuner->dev.driver == NULL)
565*b43a590dSNibble Max 		goto fail_tuner_device;
566*b43a590dSNibble Max 	if (!try_module_get(client_tuner->dev.driver->owner))
567*b43a590dSNibble Max 		goto fail_tuner_module;
568*b43a590dSNibble Max 
569*b43a590dSNibble Max 	/* attach ci controller */
570*b43a590dSNibble Max 	memset(&sp2_config, 0, sizeof(sp2_config));
571*b43a590dSNibble Max 	sp2_config.dvb_adap = &adap->dvb_adap;
572*b43a590dSNibble Max 	sp2_config.priv = d;
573*b43a590dSNibble Max 	sp2_config.ci_control = dvbsky_ci_ctrl;
574*b43a590dSNibble Max 	memset(&info, 0, sizeof(struct i2c_board_info));
575*b43a590dSNibble Max 	strlcpy(info.type, "sp2", I2C_NAME_SIZE);
576*b43a590dSNibble Max 	info.addr = 0x40;
577*b43a590dSNibble Max 	info.platform_data = &sp2_config;
578*b43a590dSNibble Max 
579*b43a590dSNibble Max 	request_module(info.type);
580*b43a590dSNibble Max 	client_ci = i2c_new_device(&d->i2c_adap, &info);
581*b43a590dSNibble Max 
582*b43a590dSNibble Max 	if (client_ci == NULL || client_ci->dev.driver == NULL)
583*b43a590dSNibble Max 		goto fail_ci_device;
584*b43a590dSNibble Max 
585*b43a590dSNibble Max 	if (!try_module_get(client_ci->dev.driver->owner))
586*b43a590dSNibble Max 		goto fail_ci_module;
587*b43a590dSNibble Max 
588*b43a590dSNibble Max 	state->i2c_client_demod = client_demod;
589*b43a590dSNibble Max 	state->i2c_client_tuner = client_tuner;
590*b43a590dSNibble Max 	state->i2c_client_ci = client_ci;
591*b43a590dSNibble Max 	return ret;
592*b43a590dSNibble Max fail_ci_module:
593*b43a590dSNibble Max 	i2c_unregister_device(client_ci);
594*b43a590dSNibble Max fail_ci_device:
595*b43a590dSNibble Max 	module_put(client_tuner->dev.driver->owner);
596*b43a590dSNibble Max fail_tuner_module:
597*b43a590dSNibble Max 	i2c_unregister_device(client_tuner);
598*b43a590dSNibble Max fail_tuner_device:
599*b43a590dSNibble Max 	module_put(client_demod->dev.driver->owner);
600*b43a590dSNibble Max fail_demod_module:
601*b43a590dSNibble Max 	i2c_unregister_device(client_demod);
602*b43a590dSNibble Max fail_demod_device:
603*b43a590dSNibble Max 	ret = -ENODEV;
604*b43a590dSNibble Max 	return ret;
605*b43a590dSNibble Max }
606*b43a590dSNibble Max 
607af64fb3fSnibble.max static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
608af64fb3fSnibble.max {
609af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x04, 1);
610af64fb3fSnibble.max 	msleep(20);
611af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x83, 0);
612af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0xc0, 1);
613af64fb3fSnibble.max 	msleep(100);
614af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0x83, 1);
615af64fb3fSnibble.max 	dvbsky_gpio_ctrl(d, 0xc0, 0);
616af64fb3fSnibble.max 	msleep(50);
617af64fb3fSnibble.max 
618af64fb3fSnibble.max 	return WARM;
619af64fb3fSnibble.max }
620af64fb3fSnibble.max 
621af64fb3fSnibble.max static int dvbsky_init(struct dvb_usb_device *d)
622af64fb3fSnibble.max {
623af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
624af64fb3fSnibble.max 
625af64fb3fSnibble.max 	/* use default interface */
626af64fb3fSnibble.max 	/*
627af64fb3fSnibble.max 	ret = usb_set_interface(d->udev, 0, 0);
628af64fb3fSnibble.max 	if (ret)
629af64fb3fSnibble.max 		return ret;
630af64fb3fSnibble.max 	*/
631af64fb3fSnibble.max 	mutex_init(&state->stream_mutex);
632af64fb3fSnibble.max 
633af64fb3fSnibble.max 	state->last_lock = 0;
634af64fb3fSnibble.max 
635af64fb3fSnibble.max 	return 0;
636af64fb3fSnibble.max }
637af64fb3fSnibble.max 
638af64fb3fSnibble.max static void dvbsky_exit(struct dvb_usb_device *d)
639af64fb3fSnibble.max {
640af64fb3fSnibble.max 	struct dvbsky_state *state = d_to_priv(d);
641af64fb3fSnibble.max 	struct i2c_client *client;
642af64fb3fSnibble.max 
643af64fb3fSnibble.max 	client = state->i2c_client_tuner;
644af64fb3fSnibble.max 	/* remove I2C tuner */
645af64fb3fSnibble.max 	if (client) {
646af64fb3fSnibble.max 		module_put(client->dev.driver->owner);
647af64fb3fSnibble.max 		i2c_unregister_device(client);
648af64fb3fSnibble.max 	}
649*b43a590dSNibble Max 	client = state->i2c_client_demod;
650*b43a590dSNibble Max 	/* remove I2C demod */
651*b43a590dSNibble Max 	if (client) {
652*b43a590dSNibble Max 		module_put(client->dev.driver->owner);
653*b43a590dSNibble Max 		i2c_unregister_device(client);
654*b43a590dSNibble Max 	}
65524d333f3Snibble.max 	client = state->i2c_client_ci;
65624d333f3Snibble.max 	/* remove I2C ci */
65724d333f3Snibble.max 	if (client) {
65824d333f3Snibble.max 		module_put(client->dev.driver->owner);
65924d333f3Snibble.max 		i2c_unregister_device(client);
66024d333f3Snibble.max 	}
661af64fb3fSnibble.max }
662af64fb3fSnibble.max 
663af64fb3fSnibble.max /* DVB USB Driver stuff */
664af64fb3fSnibble.max static struct dvb_usb_device_properties dvbsky_s960_props = {
665af64fb3fSnibble.max 	.driver_name = KBUILD_MODNAME,
666af64fb3fSnibble.max 	.owner = THIS_MODULE,
667af64fb3fSnibble.max 	.adapter_nr = adapter_nr,
668af64fb3fSnibble.max 	.size_of_priv = sizeof(struct dvbsky_state),
669af64fb3fSnibble.max 
670af64fb3fSnibble.max 	.generic_bulk_ctrl_endpoint = 0x01,
671af64fb3fSnibble.max 	.generic_bulk_ctrl_endpoint_response = 0x81,
672af64fb3fSnibble.max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
673af64fb3fSnibble.max 
674af64fb3fSnibble.max 	.i2c_algo         = &dvbsky_i2c_algo,
675af64fb3fSnibble.max 	.frontend_attach  = dvbsky_s960_attach,
676af64fb3fSnibble.max 	.init             = dvbsky_init,
677af64fb3fSnibble.max 	.get_rc_config    = dvbsky_get_rc_config,
678af64fb3fSnibble.max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
679af64fb3fSnibble.max 	.identify_state	  = dvbsky_identify_state,
680af64fb3fSnibble.max 	.exit             = dvbsky_exit,
681af64fb3fSnibble.max 	.read_mac_address = dvbsky_read_mac_addr,
682af64fb3fSnibble.max 
683af64fb3fSnibble.max 	.num_adapters = 1,
684af64fb3fSnibble.max 	.adapter = {
685af64fb3fSnibble.max 		{
686af64fb3fSnibble.max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
687af64fb3fSnibble.max 		}
688af64fb3fSnibble.max 	}
689af64fb3fSnibble.max };
690af64fb3fSnibble.max 
69124d333f3Snibble.max static struct dvb_usb_device_properties dvbsky_s960c_props = {
69224d333f3Snibble.max 	.driver_name = KBUILD_MODNAME,
69324d333f3Snibble.max 	.owner = THIS_MODULE,
69424d333f3Snibble.max 	.adapter_nr = adapter_nr,
69524d333f3Snibble.max 	.size_of_priv = sizeof(struct dvbsky_state),
69624d333f3Snibble.max 
69724d333f3Snibble.max 	.generic_bulk_ctrl_endpoint = 0x01,
69824d333f3Snibble.max 	.generic_bulk_ctrl_endpoint_response = 0x81,
69924d333f3Snibble.max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
70024d333f3Snibble.max 
70124d333f3Snibble.max 	.i2c_algo         = &dvbsky_i2c_algo,
70224d333f3Snibble.max 	.frontend_attach  = dvbsky_s960c_attach,
70324d333f3Snibble.max 	.init             = dvbsky_init,
70424d333f3Snibble.max 	.get_rc_config    = dvbsky_get_rc_config,
70524d333f3Snibble.max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
70624d333f3Snibble.max 	.identify_state	  = dvbsky_identify_state,
70724d333f3Snibble.max 	.exit             = dvbsky_exit,
70824d333f3Snibble.max 	.read_mac_address = dvbsky_read_mac_addr,
70924d333f3Snibble.max 
71024d333f3Snibble.max 	.num_adapters = 1,
71124d333f3Snibble.max 	.adapter = {
71224d333f3Snibble.max 		{
71324d333f3Snibble.max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
71424d333f3Snibble.max 		}
71524d333f3Snibble.max 	}
71624d333f3Snibble.max };
71724d333f3Snibble.max 
718*b43a590dSNibble Max static struct dvb_usb_device_properties dvbsky_t680c_props = {
719*b43a590dSNibble Max 	.driver_name = KBUILD_MODNAME,
720*b43a590dSNibble Max 	.owner = THIS_MODULE,
721*b43a590dSNibble Max 	.adapter_nr = adapter_nr,
722*b43a590dSNibble Max 	.size_of_priv = sizeof(struct dvbsky_state),
723*b43a590dSNibble Max 
724*b43a590dSNibble Max 	.generic_bulk_ctrl_endpoint = 0x01,
725*b43a590dSNibble Max 	.generic_bulk_ctrl_endpoint_response = 0x81,
726*b43a590dSNibble Max 	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
727*b43a590dSNibble Max 
728*b43a590dSNibble Max 	.i2c_algo         = &dvbsky_i2c_algo,
729*b43a590dSNibble Max 	.frontend_attach  = dvbsky_t680c_attach,
730*b43a590dSNibble Max 	.init             = dvbsky_init,
731*b43a590dSNibble Max 	.get_rc_config    = dvbsky_get_rc_config,
732*b43a590dSNibble Max 	.streaming_ctrl   = dvbsky_streaming_ctrl,
733*b43a590dSNibble Max 	.identify_state	  = dvbsky_identify_state,
734*b43a590dSNibble Max 	.exit             = dvbsky_exit,
735*b43a590dSNibble Max 	.read_mac_address = dvbsky_read_mac_addr,
736*b43a590dSNibble Max 
737*b43a590dSNibble Max 	.num_adapters = 1,
738*b43a590dSNibble Max 	.adapter = {
739*b43a590dSNibble Max 		{
740*b43a590dSNibble Max 			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
741*b43a590dSNibble Max 		}
742*b43a590dSNibble Max 	}
743*b43a590dSNibble Max };
744*b43a590dSNibble Max 
745af64fb3fSnibble.max static const struct usb_device_id dvbsky_id_table[] = {
746af64fb3fSnibble.max 	{ DVB_USB_DEVICE(0x0572, 0x6831,
747af64fb3fSnibble.max 		&dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
74824d333f3Snibble.max 	{ DVB_USB_DEVICE(0x0572, 0x960c,
74924d333f3Snibble.max 		&dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
750*b43a590dSNibble Max 	{ DVB_USB_DEVICE(0x0572, 0x680c,
751*b43a590dSNibble Max 		&dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
752af64fb3fSnibble.max 	{ }
753af64fb3fSnibble.max };
754af64fb3fSnibble.max MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
755af64fb3fSnibble.max 
756af64fb3fSnibble.max static struct usb_driver dvbsky_usb_driver = {
757af64fb3fSnibble.max 	.name = KBUILD_MODNAME,
758af64fb3fSnibble.max 	.id_table = dvbsky_id_table,
759af64fb3fSnibble.max 	.probe = dvb_usbv2_probe,
760af64fb3fSnibble.max 	.disconnect = dvb_usbv2_disconnect,
761af64fb3fSnibble.max 	.suspend = dvb_usbv2_suspend,
762af64fb3fSnibble.max 	.resume = dvb_usbv2_resume,
763af64fb3fSnibble.max 	.reset_resume = dvb_usbv2_reset_resume,
764af64fb3fSnibble.max 	.no_dynamic_id = 1,
765af64fb3fSnibble.max 	.soft_unbind = 1,
766af64fb3fSnibble.max };
767af64fb3fSnibble.max 
768af64fb3fSnibble.max module_usb_driver(dvbsky_usb_driver);
769af64fb3fSnibble.max 
770af64fb3fSnibble.max MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
771af64fb3fSnibble.max MODULE_DESCRIPTION("Driver for DVBSky USB");
772af64fb3fSnibble.max MODULE_LICENSE("GPL");
773