1/*
2 * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
3 *
4 *   This program is free software; you can redistribute it and/or modify it
5 *   under the terms of the GNU General Public License as published by the Free
6 *   Software Foundation, version 2.
7 *
8 * see Documentation/dvb/README.dvb-usb for more information
9 */
10
11#include <linux/vmalloc.h>
12#include <linux/i2c.h>
13
14#include "mxl111sf.h"
15#include "mxl111sf-reg.h"
16#include "mxl111sf-phy.h"
17#include "mxl111sf-i2c.h"
18#include "mxl111sf-gpio.h"
19
20#include "mxl111sf-demod.h"
21#include "mxl111sf-tuner.h"
22
23#include "lgdt3305.h"
24
25int dvb_usb_mxl111sf_debug;
26module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
27MODULE_PARM_DESC(debug, "set debugging level "
28		 "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
29
30int dvb_usb_mxl111sf_isoc;
31module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
32MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
33
34#define ANT_PATH_AUTO 0
35#define ANT_PATH_EXTERNAL 1
36#define ANT_PATH_INTERNAL 2
37
38int dvb_usb_mxl111sf_rfswitch =
39#if 0
40		ANT_PATH_AUTO;
41#else
42		ANT_PATH_EXTERNAL;
43#endif
44
45module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
46MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
47
48DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
49
50#define deb_info(args...)   dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
51#define deb_reg(args...)    dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
52#define deb_adv(args...)    dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
53
54int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
55		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
56{
57	int wo = (rbuf == NULL || rlen == 0); /* write-only */
58	int ret;
59	u8 sndbuf[1+wlen];
60
61	deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
62
63	memset(sndbuf, 0, 1+wlen);
64
65	sndbuf[0] = cmd;
66	memcpy(&sndbuf[1], wbuf, wlen);
67
68	ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
69		dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
70	mxl_fail(ret);
71
72	return ret;
73}
74
75/* ------------------------------------------------------------------------ */
76
77#define MXL_CMD_REG_READ	0xaa
78#define MXL_CMD_REG_WRITE	0x55
79
80int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
81{
82	u8 buf[2];
83	int ret;
84
85	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
86	if (mxl_fail(ret)) {
87		mxl_debug("error reading reg: 0x%02x", addr);
88		goto fail;
89	}
90
91	if (buf[0] == addr)
92		*data = buf[1];
93	else {
94		err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
95		    addr, buf[0], buf[1]);
96		ret = -EINVAL;
97	}
98
99	deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
100fail:
101	return ret;
102}
103
104int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
105{
106	u8 buf[] = { addr, data };
107	int ret;
108
109	deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
110
111	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
112	if (mxl_fail(ret))
113		err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
114	return ret;
115}
116
117/* ------------------------------------------------------------------------ */
118
119int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
120				   u8 addr, u8 mask, u8 data)
121{
122	int ret;
123	u8 val;
124
125	if (mask != 0xff) {
126		ret = mxl111sf_read_reg(state, addr, &val);
127#if 1
128		/* dont know why this usually errors out on the first try */
129		if (mxl_fail(ret))
130			err("error writing addr: 0x%02x, mask: 0x%02x, "
131			    "data: 0x%02x, retrying...", addr, mask, data);
132
133		ret = mxl111sf_read_reg(state, addr, &val);
134#endif
135		if (mxl_fail(ret))
136			goto fail;
137	}
138	val &= ~mask;
139	val |= data;
140
141	ret = mxl111sf_write_reg(state, addr, val);
142	mxl_fail(ret);
143fail:
144	return ret;
145}
146
147/* ------------------------------------------------------------------------ */
148
149int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
150			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
151{
152	int i, ret = 0;
153
154	for (i = 0;  ctrl_reg_info[i].addr |
155		     ctrl_reg_info[i].mask |
156		     ctrl_reg_info[i].data;  i++) {
157
158		ret = mxl111sf_write_reg_mask(state,
159					      ctrl_reg_info[i].addr,
160					      ctrl_reg_info[i].mask,
161					      ctrl_reg_info[i].data);
162		if (mxl_fail(ret)) {
163			err("failed on reg #%d (0x%02x)", i,
164			    ctrl_reg_info[i].addr);
165			break;
166		}
167	}
168	return ret;
169}
170
171/* ------------------------------------------------------------------------ */
172
173static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
174{
175	int ret;
176	u8 id, ver;
177	char *mxl_chip, *mxl_rev;
178
179	if ((state->chip_id) && (state->chip_ver))
180		return 0;
181
182	ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
183	if (mxl_fail(ret))
184		goto fail;
185	state->chip_id = id;
186
187	ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
188	if (mxl_fail(ret))
189		goto fail;
190	state->chip_ver = ver;
191
192	switch (id) {
193	case 0x61:
194		mxl_chip = "MxL101SF";
195		break;
196	case 0x63:
197		mxl_chip = "MxL111SF";
198		break;
199	default:
200		mxl_chip = "UNKNOWN MxL1X1";
201		break;
202	}
203	switch (ver) {
204	case 0x36:
205		state->chip_rev = MXL111SF_V6;
206		mxl_rev = "v6";
207		break;
208	case 0x08:
209		state->chip_rev = MXL111SF_V8_100;
210		mxl_rev = "v8_100";
211		break;
212	case 0x18:
213		state->chip_rev = MXL111SF_V8_200;
214		mxl_rev = "v8_200";
215		break;
216	default:
217		state->chip_rev = 0;
218		mxl_rev = "UNKNOWN REVISION";
219		break;
220	}
221	info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
222fail:
223	return ret;
224}
225
226#define get_chip_info(state)						\
227({									\
228	int ___ret;							\
229	___ret = mxl1x1sf_get_chip_info(state);				\
230	if (mxl_fail(___ret)) {						\
231		mxl_debug("failed to get chip info"			\
232			  " on first probe attempt");			\
233		___ret = mxl1x1sf_get_chip_info(state);			\
234		if (mxl_fail(___ret))					\
235			err("failed to get chip info during probe");	\
236		else							\
237			mxl_debug("probe needed a retry "		\
238				  "in order to succeed.");		\
239	}								\
240	___ret;								\
241})
242
243/* ------------------------------------------------------------------------ */
244
245static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
246{
247	/* power control depends on which adapter is being woken:
248	 * save this for init, instead, via mxl111sf_adap_fe_init */
249	return 0;
250}
251
252static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
253{
254	struct dvb_usb_adapter *adap = fe->dvb->priv;
255	struct dvb_usb_device *d = adap->dev;
256	struct mxl111sf_state *state = d->priv;
257	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
258
259	int err;
260
261	/* exit if we didnt initialize the driver yet */
262	if (!state->chip_id) {
263		mxl_debug("driver not yet initialized, exit.");
264		goto fail;
265	}
266
267	deb_info("%s()\n", __func__);
268
269	mutex_lock(&state->fe_lock);
270
271	state->alt_mode = adap_state->alt_mode;
272
273	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
274		err("set interface failed");
275
276	err = mxl1x1sf_soft_reset(state);
277	mxl_fail(err);
278	err = mxl111sf_init_tuner_demod(state);
279	mxl_fail(err);
280	err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
281
282	mxl_fail(err);
283	mxl111sf_enable_usb_output(state);
284	mxl_fail(err);
285	mxl1x1sf_top_master_ctrl(state, 1);
286	mxl_fail(err);
287
288	if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
289	    (state->chip_rev > MXL111SF_V6)) {
290		mxl111sf_config_pin_mux_modes(state,
291					      PIN_MUX_TS_SPI_IN_MODE_1);
292		mxl_fail(err);
293	}
294	err = mxl111sf_init_port_expander(state);
295	if (!mxl_fail(err)) {
296		state->gpio_mode = adap_state->gpio_mode;
297		err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
298		mxl_fail(err);
299#if 0
300		err = fe->ops.init(fe);
301#endif
302		msleep(100); /* add short delay after enabling
303			      * the demod before touching it */
304	}
305
306	return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
307fail:
308	return -ENODEV;
309}
310
311static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
312{
313	struct dvb_usb_adapter *adap = fe->dvb->priv;
314	struct dvb_usb_device *d = adap->dev;
315	struct mxl111sf_state *state = d->priv;
316	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
317	int err;
318
319	/* exit if we didnt initialize the driver yet */
320	if (!state->chip_id) {
321		mxl_debug("driver not yet initialized, exit.");
322		goto fail;
323	}
324
325	deb_info("%s()\n", __func__);
326
327	err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
328
329	mutex_unlock(&state->fe_lock);
330
331	return err;
332fail:
333	return -ENODEV;
334}
335
336
337static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
338{
339	struct dvb_usb_device *d = adap->dev;
340	struct mxl111sf_state *state = d->priv;
341	struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
342	int ret = 0;
343	u8 tmp;
344
345	deb_info("%s(%d)\n", __func__, onoff);
346
347	if (onoff) {
348		ret = mxl111sf_enable_usb_output(state);
349		mxl_fail(ret);
350		ret = mxl111sf_config_mpeg_in(state, 1, 1,
351					      adap_state->ep6_clockphase,
352					      0, 0);
353		mxl_fail(ret);
354#if 0
355	} else {
356		ret = mxl111sf_disable_656_port(state);
357		mxl_fail(ret);
358#endif
359	}
360
361	return ret;
362}
363
364static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
365{
366	struct dvb_usb_device *d = adap->dev;
367	struct mxl111sf_state *state = d->priv;
368	int ret = 0;
369
370	deb_info("%s(%d)\n", __func__, onoff);
371
372	if (onoff) {
373		ret = mxl111sf_enable_usb_output(state);
374		mxl_fail(ret);
375	}
376
377	return ret;
378}
379
380/* ------------------------------------------------------------------------ */
381
382static struct lgdt3305_config hauppauge_lgdt3305_config = {
383	.i2c_addr           = 0xb2 >> 1,
384	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
385	.tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
386	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
387	.deny_i2c_rptr      = 1,
388	.spectral_inversion = 0,
389	.qam_if_khz         = 6000,
390	.vsb_if_khz         = 6000,
391};
392
393static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
394{
395	struct dvb_usb_device *d = adap->dev;
396	struct mxl111sf_state *state = d->priv;
397	int fe_id = adap->num_frontends_initialized;
398	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
399	int ret;
400
401	deb_adv("%s()\n", __func__);
402
403	/* save a pointer to the dvb_usb_device in device state */
404	state->d = d;
405	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
406	state->alt_mode = adap_state->alt_mode;
407
408	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
409		err("set interface failed");
410
411	state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
412	adap_state->gpio_mode = state->gpio_mode;
413	adap_state->device_mode = MXL_TUNER_MODE;
414	adap_state->ep6_clockphase = 1;
415
416	ret = mxl1x1sf_soft_reset(state);
417	if (mxl_fail(ret))
418		goto fail;
419	ret = mxl111sf_init_tuner_demod(state);
420	if (mxl_fail(ret))
421		goto fail;
422
423	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
424	if (mxl_fail(ret))
425		goto fail;
426
427	ret = mxl111sf_enable_usb_output(state);
428	if (mxl_fail(ret))
429		goto fail;
430	ret = mxl1x1sf_top_master_ctrl(state, 1);
431	if (mxl_fail(ret))
432		goto fail;
433
434	ret = mxl111sf_init_port_expander(state);
435	if (mxl_fail(ret))
436		goto fail;
437	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
438	if (mxl_fail(ret))
439		goto fail;
440
441	adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
442				 &hauppauge_lgdt3305_config,
443				 &adap->dev->i2c_adap);
444	if (adap->fe_adap[fe_id].fe) {
445		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
446		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
447		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
448		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
449		return 0;
450	}
451	ret = -EIO;
452fail:
453	return ret;
454}
455
456static struct mxl111sf_demod_config mxl_demod_config = {
457	.read_reg        = mxl111sf_read_reg,
458	.write_reg       = mxl111sf_write_reg,
459	.program_regs    = mxl111sf_ctrl_program_regs,
460};
461
462static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
463{
464	struct dvb_usb_device *d = adap->dev;
465	struct mxl111sf_state *state = d->priv;
466	int fe_id = adap->num_frontends_initialized;
467	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
468	int ret;
469
470	deb_adv("%s()\n", __func__);
471
472	/* save a pointer to the dvb_usb_device in device state */
473	state->d = d;
474	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
475	state->alt_mode = adap_state->alt_mode;
476
477	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
478		err("set interface failed");
479
480	state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
481	adap_state->gpio_mode = state->gpio_mode;
482	adap_state->device_mode = MXL_SOC_MODE;
483	adap_state->ep6_clockphase = 1;
484
485	ret = mxl1x1sf_soft_reset(state);
486	if (mxl_fail(ret))
487		goto fail;
488	ret = mxl111sf_init_tuner_demod(state);
489	if (mxl_fail(ret))
490		goto fail;
491
492	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
493	if (mxl_fail(ret))
494		goto fail;
495
496	ret = mxl111sf_enable_usb_output(state);
497	if (mxl_fail(ret))
498		goto fail;
499	ret = mxl1x1sf_top_master_ctrl(state, 1);
500	if (mxl_fail(ret))
501		goto fail;
502
503	/* dont care if this fails */
504	mxl111sf_init_port_expander(state);
505
506	adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
507			      &mxl_demod_config);
508	if (adap->fe_adap[fe_id].fe) {
509		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
510		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
511		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
512		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
513		return 0;
514	}
515	ret = -EIO;
516fail:
517	return ret;
518}
519
520static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
521					int antpath)
522{
523	return mxl111sf_idac_config(state, 1, 1,
524				    (antpath == ANT_PATH_INTERNAL) ?
525				    0x3f : 0x00, 0);
526}
527
528#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
529	err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
530	    __func__, __LINE__, \
531	    (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
532	    pwr0, pwr1, pwr2, pwr3)
533
534#define ANT_HUNT_SLEEP 90
535#define ANT_EXT_TWEAK 0
536
537static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
538{
539	struct dvb_usb_adapter *adap = fe->dvb->priv;
540	struct dvb_usb_device *d = adap->dev;
541	struct mxl111sf_state *state = d->priv;
542
543	int antctrl = dvb_usb_mxl111sf_rfswitch;
544
545	u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
546
547	/* FIXME: must force EXTERNAL for QAM - done elsewhere */
548	mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
549			      ANT_PATH_EXTERNAL : antctrl);
550
551	if (antctrl == ANT_PATH_AUTO) {
552#if 0
553		msleep(ANT_HUNT_SLEEP);
554#endif
555		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
556
557		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
558		msleep(ANT_HUNT_SLEEP);
559		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
560
561		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
562		msleep(ANT_HUNT_SLEEP);
563		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
564
565		mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
566		msleep(ANT_HUNT_SLEEP);
567		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
568
569		if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
570			/* return with EXTERNAL enabled */
571			mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
572			DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
573				   rxPwr0, rxPwr1, rxPwr2);
574		} else {
575			/* return with INTERNAL enabled */
576			DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
577				   rxPwr0, rxPwr1, rxPwr2);
578		}
579	}
580	return 0;
581}
582
583static struct mxl111sf_tuner_config mxl_tuner_config = {
584	.if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
585	.invert_spectrum = 0,
586	.read_reg        = mxl111sf_read_reg,
587	.write_reg       = mxl111sf_write_reg,
588	.program_regs    = mxl111sf_ctrl_program_regs,
589	.top_master_ctrl = mxl1x1sf_top_master_ctrl,
590	.ant_hunt        = mxl111sf_ant_hunt,
591};
592
593static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
594{
595	struct dvb_usb_device *d = adap->dev;
596	struct mxl111sf_state *state = d->priv;
597	int fe_id = adap->num_frontends_initialized;
598
599	deb_adv("%s()\n", __func__);
600
601	if (NULL != dvb_attach(mxl111sf_tuner_attach,
602			       adap->fe_adap[fe_id].fe, state,
603			       &mxl_tuner_config))
604		return 0;
605
606	return -EIO;
607}
608
609static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
610				      unsigned int cmd, void *parg,
611				      unsigned int stage)
612{
613	int err = 0;
614
615	switch (stage) {
616	case DVB_FE_IOCTL_PRE:
617
618		switch (cmd) {
619		case FE_READ_SIGNAL_STRENGTH:
620			err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
621			/* If no error occurs, prevent dvb-core from handling
622			 * this IOCTL, otherwise return the error */
623			if (0 == err)
624				err = 1;
625			break;
626		}
627		break;
628
629	case DVB_FE_IOCTL_POST:
630		/* no post-ioctl handling required */
631		break;
632	}
633	return err;
634};
635
636static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
637{
638	return I2C_FUNC_I2C;
639}
640
641struct i2c_algorithm mxl111sf_i2c_algo = {
642	.master_xfer   = mxl111sf_i2c_xfer,
643	.functionality = mxl111sf_i2c_func,
644#ifdef NEED_ALGO_CONTROL
645	.algo_control = dummy_algo_control,
646#endif
647};
648
649static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
650static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
651static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
652static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
653
654static int mxl111sf_probe(struct usb_interface *intf,
655			  const struct usb_device_id *id)
656{
657	struct dvb_usb_device *d = NULL;
658
659	deb_adv("%s()\n", __func__);
660
661	if (((dvb_usb_mxl111sf_isoc) &&
662	     (0 == dvb_usb_device_init(intf,
663				       &mxl111sf_dvbt_isoc_properties,
664				       THIS_MODULE, &d, adapter_nr) ||
665	      0 == dvb_usb_device_init(intf,
666				       &mxl111sf_atsc_isoc_properties,
667				       THIS_MODULE, &d, adapter_nr))) ||
668	    0 == dvb_usb_device_init(intf,
669				     &mxl111sf_dvbt_bulk_properties,
670				     THIS_MODULE, &d, adapter_nr) ||
671	    0 == dvb_usb_device_init(intf,
672				     &mxl111sf_atsc_bulk_properties,
673				     THIS_MODULE, &d, adapter_nr) || 0) {
674
675		struct mxl111sf_state *state = d->priv;
676		static u8 eeprom[256];
677		struct i2c_client c;
678		int ret;
679
680		ret = get_chip_info(state);
681		if (mxl_fail(ret))
682			err("failed to get chip info during probe");
683
684		mutex_init(&state->fe_lock);
685
686		if (state->chip_rev > MXL111SF_V6)
687			mxl111sf_config_pin_mux_modes(state,
688						      PIN_MUX_TS_SPI_IN_MODE_1);
689
690		c.adapter = &d->i2c_adap;
691		c.addr = 0xa0 >> 1;
692
693		ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
694		if (mxl_fail(ret))
695			return 0;
696		tveeprom_hauppauge_analog(&c, &state->tv,
697					  (0x84 == eeprom[0xa0]) ?
698					  eeprom + 0xa0 : eeprom + 0x80);
699#if 0
700		switch (state->tv.model) {
701		case 117001:
702		case 126001:
703		case 138001:
704			break;
705		default:
706			printk(KERN_WARNING "%s: warning: "
707			       "unknown hauppauge model #%d\n",
708			       __func__, state->tv.model);
709		}
710#endif
711		return 0;
712	}
713	err("Your device is not yet supported by this driver. "
714	    "See kernellabs.com for more info");
715	return -EINVAL;
716}
717
718static struct usb_device_id mxl111sf_table[] = {
719/* 0 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR     */
720	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC         */
721	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /*     +        */
722	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+        */
723	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT         */
724/* 5 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC  IR     */
725	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /*     + IR     */
726	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR     */
727	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT  IR     */
728	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+        */
729/*10 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR     */
730	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw     */
731	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC  sw     */
732	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /*     + sw     */
733	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw     */
734/*15 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT  sw     */
735	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw     */
736	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no     */
737	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT  no     */
738	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw     */
739/*20 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT  sw     */
740	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no     */
741	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT  no     */
742	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw     */
743	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT  sw     */
744/*25 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no     */
745	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT  no     */
746	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+        */
747	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /*     +        */
748	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+        */
749/*30 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /*     + IR     */
750	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR     */
751	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
752	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
753	{}		/* Terminating entry */
754};
755MODULE_DEVICE_TABLE(usb, mxl111sf_table);
756
757
758#define MXL111SF_EP4_BULK_STREAMING_CONFIG		\
759	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
760	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
761	.stream = {					\
762		.type = USB_BULK,			\
763		.count = 5,				\
764		.endpoint = 0x04,			\
765		.u = {					\
766			.bulk = {			\
767				.buffersize = 8192,	\
768			}				\
769		}					\
770	}
771
772/* FIXME: works for v6 but not v8 silicon */
773#define MXL111SF_EP4_ISOC_STREAMING_CONFIG		\
774	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
775	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
776	.stream = {					\
777		.type = USB_ISOC,			\
778		.count = 5,				\
779		.endpoint = 0x04,			\
780		.u = {					\
781			.isoc = {			\
782				.framesperurb = 96,	\
783				/* FIXME: v6 SILICON: */	\
784				.framesize = 564,	\
785				.interval = 1,		\
786			}				\
787		}					\
788	}
789
790#define MXL111SF_EP6_BULK_STREAMING_CONFIG		\
791	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
792	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
793	.stream = {					\
794		.type = USB_BULK,			\
795		.count = 5,				\
796		.endpoint = 0x06,			\
797		.u = {					\
798			.bulk = {			\
799				.buffersize = 8192,	\
800			}				\
801		}					\
802	}
803
804/* FIXME */
805#define MXL111SF_EP6_ISOC_STREAMING_CONFIG		\
806	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
807	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
808	.stream = {					\
809		.type = USB_ISOC,			\
810		.count = 5,				\
811		.endpoint = 0x06,			\
812		.u = {					\
813			.isoc = {			\
814				.framesperurb = 24,	\
815				.framesize = 3072,	\
816				.interval = 1,		\
817			}				\
818		}					\
819	}
820
821#define MXL111SF_DEFAULT_DEVICE_PROPERTIES			\
822	.caps = DVB_USB_IS_AN_I2C_ADAPTER,			\
823	.usb_ctrl = DEVICE_SPECIFIC,				\
824	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),	\
825				     EP6 BULK transfer (atsc/qam), \
826	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),	\
827				     EP6 ISOC transfer (atsc/qam), \
828	*/							\
829	.power_ctrl       = mxl111sf_power_ctrl,		\
830	.i2c_algo         = &mxl111sf_i2c_algo,			\
831	.generic_bulk_ctrl_endpoint          = MXL_EP2_REG_WRITE, \
832	.generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
833	.size_of_priv     = sizeof(struct mxl111sf_state)
834
835static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
836	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
837
838	.num_adapters = 1,
839	.adapter = {
840		{
841		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
842		.num_frontends = 1,
843		.fe = {{
844			.frontend_attach  = mxl111sf_attach_demod,
845			.tuner_attach     = mxl111sf_attach_tuner,
846
847			MXL111SF_EP4_BULK_STREAMING_CONFIG,
848		} },
849		},
850	},
851	.num_device_descs = 4,
852	.devices = {
853		{   "Hauppauge 126xxx DVBT (bulk)",
854			{ NULL },
855			{ &mxl111sf_table[4], &mxl111sf_table[8],
856			  NULL },
857		},
858		{   "Hauppauge 117xxx DVBT (bulk)",
859			{ NULL },
860			{ &mxl111sf_table[15], &mxl111sf_table[18],
861			  NULL },
862		},
863		{   "Hauppauge 138xxx DVBT (bulk)",
864			{ NULL },
865			{ &mxl111sf_table[20], &mxl111sf_table[22],
866			  &mxl111sf_table[24], &mxl111sf_table[26],
867			  NULL },
868		},
869		{   "Hauppauge 126xxx (tp-bulk)",
870			{ NULL },
871			{ &mxl111sf_table[28], &mxl111sf_table[30],
872			  NULL },
873		},
874	}
875};
876
877static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
878	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
879
880	.num_adapters = 1,
881	.adapter = {
882		{
883		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
884		.num_frontends = 1,
885		.fe = {{
886			.frontend_attach  = mxl111sf_attach_demod,
887			.tuner_attach     = mxl111sf_attach_tuner,
888
889			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
890		} },
891		},
892	},
893	.num_device_descs = 4,
894	.devices = {
895		{   "Hauppauge 126xxx DVBT (isoc)",
896			{ NULL },
897			{ &mxl111sf_table[4], &mxl111sf_table[8],
898			  NULL },
899		},
900		{   "Hauppauge 117xxx DVBT (isoc)",
901			{ NULL },
902			{ &mxl111sf_table[15], &mxl111sf_table[18],
903			  NULL },
904		},
905		{   "Hauppauge 138xxx DVBT (isoc)",
906			{ NULL },
907			{ &mxl111sf_table[20], &mxl111sf_table[22],
908			  &mxl111sf_table[24], &mxl111sf_table[26],
909			  NULL },
910		},
911		{   "Hauppauge 126xxx (tp-isoc)",
912			{ NULL },
913			{ &mxl111sf_table[28], &mxl111sf_table[30],
914			  NULL },
915		},
916	}
917};
918
919static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
920	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
921
922	.num_adapters = 1,
923	.adapter = {
924		{
925		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
926		.num_frontends = 2,
927		.fe = {{
928			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
929			.tuner_attach     = mxl111sf_attach_tuner,
930
931			MXL111SF_EP6_BULK_STREAMING_CONFIG,
932		},
933		{
934			.frontend_attach  = mxl111sf_attach_demod,
935			.tuner_attach     = mxl111sf_attach_tuner,
936
937			MXL111SF_EP4_BULK_STREAMING_CONFIG,
938		}},
939		},
940	},
941	.num_device_descs = 6,
942	.devices = {
943		{   "Hauppauge 126xxx ATSC (bulk)",
944			{ NULL },
945			{ &mxl111sf_table[1], &mxl111sf_table[5],
946			  NULL },
947		},
948		{   "Hauppauge 117xxx ATSC (bulk)",
949			{ NULL },
950			{ &mxl111sf_table[12],
951			  NULL },
952		},
953		{   "Hauppauge 126xxx ATSC+ (bulk)",
954			{ NULL },
955			{ &mxl111sf_table[0], &mxl111sf_table[3],
956			  &mxl111sf_table[7], &mxl111sf_table[9],
957			  &mxl111sf_table[10], NULL },
958		},
959		{   "Hauppauge 117xxx ATSC+ (bulk)",
960			{ NULL },
961			{ &mxl111sf_table[11], &mxl111sf_table[14],
962			  &mxl111sf_table[16], &mxl111sf_table[17],
963			  &mxl111sf_table[32], &mxl111sf_table[33],
964			  NULL },
965		},
966		{   "Hauppauge Mercury (tp-bulk)",
967			{ NULL },
968			{ &mxl111sf_table[19], &mxl111sf_table[21],
969			  &mxl111sf_table[23], &mxl111sf_table[25],
970			  &mxl111sf_table[27], NULL },
971		},
972		{   "Hauppauge WinTV-Aero-M",
973			{ NULL },
974			{ &mxl111sf_table[29], &mxl111sf_table[31],
975			  NULL },
976		},
977	}
978};
979
980static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
981	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
982
983	.num_adapters = 1,
984	.adapter = {
985		{
986		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
987		.num_frontends = 2,
988		.fe = {{
989			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
990			.tuner_attach     = mxl111sf_attach_tuner,
991
992			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
993		},
994		{
995			.frontend_attach  = mxl111sf_attach_demod,
996			.tuner_attach     = mxl111sf_attach_tuner,
997
998			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
999		}},
1000		},
1001	},
1002	.num_device_descs = 6,
1003	.devices = {
1004		{   "Hauppauge 126xxx ATSC (isoc)",
1005			{ NULL },
1006			{ &mxl111sf_table[1], &mxl111sf_table[5],
1007			  NULL },
1008		},
1009		{   "Hauppauge 117xxx ATSC (isoc)",
1010			{ NULL },
1011			{ &mxl111sf_table[12],
1012			  NULL },
1013		},
1014		{   "Hauppauge 126xxx ATSC+ (isoc)",
1015			{ NULL },
1016			{ &mxl111sf_table[0], &mxl111sf_table[3],
1017			  &mxl111sf_table[7], &mxl111sf_table[9],
1018			  &mxl111sf_table[10], NULL },
1019		},
1020		{   "Hauppauge 117xxx ATSC+ (isoc)",
1021			{ NULL },
1022			{ &mxl111sf_table[11], &mxl111sf_table[14],
1023			  &mxl111sf_table[16], &mxl111sf_table[17],
1024			  &mxl111sf_table[32], &mxl111sf_table[33],
1025			  NULL },
1026		},
1027		{   "Hauppauge Mercury (tp-isoc)",
1028			{ NULL },
1029			{ &mxl111sf_table[19], &mxl111sf_table[21],
1030			  &mxl111sf_table[23], &mxl111sf_table[25],
1031			  &mxl111sf_table[27], NULL },
1032		},
1033		{   "Hauppauge WinTV-Aero-M (tp-isoc)",
1034			{ NULL },
1035			{ &mxl111sf_table[29], &mxl111sf_table[31],
1036			  NULL },
1037		},
1038	}
1039};
1040
1041static struct usb_driver mxl111sf_driver = {
1042	.name		= "dvb_usb_mxl111sf",
1043	.probe		= mxl111sf_probe,
1044	.disconnect     = dvb_usb_device_exit,
1045	.id_table	= mxl111sf_table,
1046};
1047
1048module_usb_driver(mxl111sf_driver);
1049
1050MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
1051MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
1052MODULE_VERSION("1.0");
1053MODULE_LICENSE("GPL");
1054
1055/*
1056 * Local variables:
1057 * c-basic-offset: 8
1058 * End:
1059 */
1060