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