blob: 0c3f69ae946a5411d3d5d877387b875d7d196cce [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 Krufky77eed212011-09-06 09:31:57 -0300382 struct mxl111sf_adap_state *adap_state = adap->fe_adap[0].priv;
Michael Krufky4c66c922011-08-29 00:05:35 -0300383 int ret;
384
385 deb_adv("%s()\n", __func__);
386
387 /* save a pointer to the dvb_usb_device in device state */
388 state->d = d;
389 adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
390 state->alt_mode = adap_state->alt_mode;
391
392 if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
393 err("set interface failed");
394
395 state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
396 adap_state->gpio_mode = state->gpio_mode;
397 adap_state->device_mode = MXL_TUNER_MODE;
398 adap_state->ep6_clockphase = 1;
399
400 ret = mxl1x1sf_soft_reset(state);
401 if (mxl_fail(ret))
402 goto fail;
403 ret = mxl111sf_init_tuner_demod(state);
404 if (mxl_fail(ret))
405 goto fail;
406
407 ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
408 if (mxl_fail(ret))
409 goto fail;
410
411 ret = mxl111sf_enable_usb_output(state);
412 if (mxl_fail(ret))
413 goto fail;
414 ret = mxl1x1sf_top_master_ctrl(state, 1);
415 if (mxl_fail(ret))
416 goto fail;
417
418 ret = mxl111sf_init_port_expander(state);
419 if (mxl_fail(ret))
420 goto fail;
421 ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
422 if (mxl_fail(ret))
423 goto fail;
424
Michael Krufky77eed212011-09-06 09:31:57 -0300425 adap->fe_adap[0].fe = dvb_attach(lgdt3305_attach,
Michael Krufky4c66c922011-08-29 00:05:35 -0300426 &hauppauge_lgdt3305_config,
427 &adap->dev->i2c_adap);
Michael Krufky77eed212011-09-06 09:31:57 -0300428 if (adap->fe_adap[0].fe) {
429 adap_state->fe_init = adap->fe_adap[0].fe->ops.init;
430 adap->fe_adap[0].fe->ops.init = mxl111sf_adap_fe_init;
431 adap_state->fe_sleep = adap->fe_adap[0].fe->ops.sleep;
432 adap->fe_adap[0].fe->ops.sleep = mxl111sf_adap_fe_sleep;
Michael Krufky4c66c922011-08-29 00:05:35 -0300433 return 0;
434 }
435 ret = -EIO;
436fail:
437 return ret;
438}
439
440static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
441 int antpath)
442{
443 return mxl111sf_idac_config(state, 1, 1,
444 (antpath == ANT_PATH_INTERNAL) ?
445 0x3f : 0x00, 0);
446}
447
448#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
449 err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
450 __func__, __LINE__, \
451 (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
452 pwr0, pwr1, pwr2, pwr3)
453
454#define ANT_HUNT_SLEEP 90
455#define ANT_EXT_TWEAK 0
456
457static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
458{
459 struct dvb_usb_adapter *adap = fe->dvb->priv;
460 struct dvb_usb_device *d = adap->dev;
461 struct mxl111sf_state *state = d->priv;
462
463 int antctrl = dvb_usb_mxl111sf_rfswitch;
464
465 u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
466
467 /* FIXME: must force EXTERNAL for QAM - done elsewhere */
468 mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
469 ANT_PATH_EXTERNAL : antctrl);
470
471 if (antctrl == ANT_PATH_AUTO) {
472#if 0
473 msleep(ANT_HUNT_SLEEP);
474#endif
475 fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
476
477 mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
478 msleep(ANT_HUNT_SLEEP);
479 fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
480
481 mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
482 msleep(ANT_HUNT_SLEEP);
483 fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
484
485 mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
486 msleep(ANT_HUNT_SLEEP);
487 fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
488
489 if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
490 /* return with EXTERNAL enabled */
491 mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
492 DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
493 rxPwr0, rxPwr1, rxPwr2);
494 } else {
495 /* return with INTERNAL enabled */
496 DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
497 rxPwr0, rxPwr1, rxPwr2);
498 }
499 }
500 return 0;
501}
502
503static struct mxl111sf_tuner_config mxl_tuner_config = {
504 .if_freq = MXL_IF_6_0, /* applies to external IF output, only */
505 .invert_spectrum = 0,
506 .read_reg = mxl111sf_read_reg,
507 .write_reg = mxl111sf_write_reg,
508 .program_regs = mxl111sf_ctrl_program_regs,
509 .top_master_ctrl = mxl1x1sf_top_master_ctrl,
510 .ant_hunt = mxl111sf_ant_hunt,
511};
512
513static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
514{
515 struct dvb_usb_device *d = adap->dev;
516 struct mxl111sf_state *state = d->priv;
517
518 deb_adv("%s()\n", __func__);
519
Michael Krufky77eed212011-09-06 09:31:57 -0300520 if (NULL != dvb_attach(mxl111sf_tuner_attach, adap->fe_adap[0].fe, state,
Michael Krufky4c66c922011-08-29 00:05:35 -0300521 &mxl_tuner_config))
522 return 0;
523
524 return -EIO;
525}
526
527static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
528 unsigned int cmd, void *parg,
529 unsigned int stage)
530{
531 int err = 0;
532
533 switch (stage) {
534 case DVB_FE_IOCTL_PRE:
535
536 switch (cmd) {
537 case FE_READ_SIGNAL_STRENGTH:
538 err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
539 /* If no error occurs, prevent dvb-core from handling
540 * this IOCTL, otherwise return the error */
541 if (0 == err)
542 err = 1;
543 break;
544 }
545 break;
546
547 case DVB_FE_IOCTL_POST:
548 /* no post-ioctl handling required */
549 break;
550 }
551 return err;
552};
553
554static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
555{
556 return I2C_FUNC_I2C;
557}
558
559struct i2c_algorithm mxl111sf_i2c_algo = {
560 .master_xfer = mxl111sf_i2c_xfer,
561 .functionality = mxl111sf_i2c_func,
562#ifdef NEED_ALGO_CONTROL
563 .algo_control = dummy_algo_control,
564#endif
565};
566
567/* DVB USB Driver stuff */
568static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
569static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
570
571static int mxl111sf_probe(struct usb_interface *intf,
572 const struct usb_device_id *id)
573{
574 struct dvb_usb_device *d = NULL;
575
576 deb_adv("%s()\n", __func__);
577
578 if (((dvb_usb_mxl111sf_isoc) &&
579 (0 == dvb_usb_device_init(intf,
580 &mxl111sf_atsc_isoc_properties,
581 THIS_MODULE, &d, adapter_nr))) ||
582 0 == dvb_usb_device_init(intf,
583 &mxl111sf_atsc_bulk_properties,
584 THIS_MODULE, &d, adapter_nr) || 0) {
585
586 struct mxl111sf_state *state = d->priv;
587 static u8 eeprom[256];
588 struct i2c_client c;
589 int ret;
590
591 ret = get_chip_info(state);
592 if (mxl_fail(ret))
593 err("failed to get chip info during probe");
594
595 mutex_init(&state->fe_lock);
596
597 if (state->chip_rev > MXL111SF_V6)
598 mxl111sf_config_pin_mux_modes(state,
599 PIN_MUX_TS_SPI_IN_MODE_1);
600
601 c.adapter = &d->i2c_adap;
602 c.addr = 0xa0 >> 1;
603
604 ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
605 if (mxl_fail(ret))
606 return 0;
607 tveeprom_hauppauge_analog(&c, &state->tv,
608 (0x84 == eeprom[0xa0]) ?
609 eeprom + 0xa0 : eeprom + 0x80);
610#if 0
611 switch (state->tv.model) {
612 case 117001:
613 case 126001:
614 case 138001:
615 break;
616 default:
617 printk(KERN_WARNING "%s: warning: "
618 "unknown hauppauge model #%d\n",
619 __func__, state->tv.model);
620 }
621#endif
622 return 0;
623 }
624 err("Your device is not yet supported by this driver. "
625 "See kernellabs.com for more info");
626 return -EINVAL;
627}
628
629static struct usb_device_id mxl111sf_table[] = {
630/* 0 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR */
631 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC */
632 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /* + */
633 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+ */
634 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT */
635/* 5 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC IR */
636 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /* + IR */
637 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR */
638 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT IR */
639 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+ */
640/*10 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR */
641 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw */
642 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC sw */
643 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /* + sw */
644 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw */
645/*15 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT sw */
646 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw */
647 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no */
648 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT no */
649 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw */
650/*20 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT sw */
651 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no */
652 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT no */
653 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw */
654 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT sw */
655/*25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no */
656 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT no */
657 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+ */
658 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /* + */
659 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+ */
660/*30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /* + IR */
661 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR */
662 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
663 { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
664 {} /* Terminating entry */
665};
666MODULE_DEVICE_TABLE(usb, mxl111sf_table);
667
668
669#define MXL111SF_EP6_BULK_STREAMING_CONFIG \
670 .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
671 .stream = { \
672 .type = USB_BULK, \
673 .count = 5, \
674 .endpoint = 0x06, \
675 .u = { \
676 .bulk = { \
677 .buffersize = 8192, \
678 } \
679 } \
680 }
681
682/* FIXME */
683#define MXL111SF_EP6_ISOC_STREAMING_CONFIG \
684 .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
685 .stream = { \
686 .type = USB_ISOC, \
687 .count = 5, \
688 .endpoint = 0x06, \
689 .u = { \
690 .isoc = { \
691 .framesperurb = 24, \
692 .framesize = 3072, \
693 .interval = 1, \
694 } \
695 } \
696 }
697
698#define MXL111SF_DEFAULT_DEVICE_PROPERTIES \
699 .caps = DVB_USB_IS_AN_I2C_ADAPTER, \
700 .usb_ctrl = DEVICE_SPECIFIC, \
701 /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), \
702 EP6 BULK transfer (atsc/qam), \
703 use usb alt setting 2 for EP4 BULK transfer (dvb-t), \
704 EP6 ISOC transfer (atsc/qam), \
705 */ \
706 .power_ctrl = mxl111sf_power_ctrl, \
707 .i2c_algo = &mxl111sf_i2c_algo, \
708 .generic_bulk_ctrl_endpoint = MXL_EP2_REG_WRITE, \
709 .generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
710 .size_of_priv = sizeof(struct mxl111sf_state)
711
712static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
713 MXL111SF_DEFAULT_DEVICE_PROPERTIES,
714
715 .num_adapters = 1,
716 .adapter = {
717 {
Michael Krufky77eed212011-09-06 09:31:57 -0300718 .fe_ioctl_override = mxl111sf_fe_ioctl_override,
719 .num_frontends = 1,
720 .fe = {{
Michael Krufky4c66c922011-08-29 00:05:35 -0300721 .size_of_priv = sizeof(struct mxl111sf_adap_state),
Michael Krufky4c66c922011-08-29 00:05:35 -0300722
723 .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
724 .tuner_attach = mxl111sf_attach_tuner,
725
726 MXL111SF_EP6_BULK_STREAMING_CONFIG,
Michael Krufky77eed212011-09-06 09:31:57 -0300727 }},
Michael Krufky4c66c922011-08-29 00:05:35 -0300728 },
729 },
730 .num_device_descs = 6,
731 .devices = {
732 { "Hauppauge 126xxx ATSC (bulk)",
733 { NULL },
734 { &mxl111sf_table[1], &mxl111sf_table[5],
735 NULL },
736 },
737 { "Hauppauge 117xxx ATSC (bulk)",
738 { NULL },
739 { &mxl111sf_table[12],
740 NULL },
741 },
742 { "Hauppauge 126xxx ATSC+ (bulk)",
743 { NULL },
744 { &mxl111sf_table[0], &mxl111sf_table[3],
745 &mxl111sf_table[7], &mxl111sf_table[9],
746 &mxl111sf_table[10], NULL },
747 },
748 { "Hauppauge 117xxx ATSC+ (bulk)",
749 { NULL },
750 { &mxl111sf_table[11], &mxl111sf_table[14],
751 &mxl111sf_table[16], &mxl111sf_table[17],
752 &mxl111sf_table[32], &mxl111sf_table[33],
753 NULL },
754 },
755 { "Hauppauge Mercury (tp-bulk)",
756 { NULL },
757 { &mxl111sf_table[19], &mxl111sf_table[21],
758 &mxl111sf_table[23], &mxl111sf_table[25],
759 &mxl111sf_table[27], NULL },
760 },
761 { "Hauppauge WinTV-Aero-M",
762 { NULL },
763 { &mxl111sf_table[29], &mxl111sf_table[31],
764 NULL },
765 },
766 }
767};
768
769static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
770 MXL111SF_DEFAULT_DEVICE_PROPERTIES,
771
772 .num_adapters = 1,
773 .adapter = {
774 {
Michael Krufky77eed212011-09-06 09:31:57 -0300775 .fe_ioctl_override = mxl111sf_fe_ioctl_override,
776 .num_frontends = 1,
777 .fe = {{
Michael Krufky4c66c922011-08-29 00:05:35 -0300778 .size_of_priv = sizeof(struct mxl111sf_adap_state),
Michael Krufky4c66c922011-08-29 00:05:35 -0300779
780 .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
781 .tuner_attach = mxl111sf_attach_tuner,
782
783 MXL111SF_EP6_ISOC_STREAMING_CONFIG,
Michael Krufky77eed212011-09-06 09:31:57 -0300784 }},
Michael Krufky4c66c922011-08-29 00:05:35 -0300785 },
786 },
787 .num_device_descs = 6,
788 .devices = {
789 { "Hauppauge 126xxx ATSC (isoc)",
790 { NULL },
791 { &mxl111sf_table[1], &mxl111sf_table[5],
792 NULL },
793 },
794 { "Hauppauge 117xxx ATSC (isoc)",
795 { NULL },
796 { &mxl111sf_table[12],
797 NULL },
798 },
799 { "Hauppauge 126xxx ATSC+ (isoc)",
800 { NULL },
801 { &mxl111sf_table[0], &mxl111sf_table[3],
802 &mxl111sf_table[7], &mxl111sf_table[9],
803 &mxl111sf_table[10], NULL },
804 },
805 { "Hauppauge 117xxx ATSC+ (isoc)",
806 { NULL },
807 { &mxl111sf_table[11], &mxl111sf_table[14],
808 &mxl111sf_table[16], &mxl111sf_table[17],
809 &mxl111sf_table[32], &mxl111sf_table[33],
810 NULL },
811 },
812 { "Hauppauge Mercury (tp-isoc)",
813 { NULL },
814 { &mxl111sf_table[19], &mxl111sf_table[21],
815 &mxl111sf_table[23], &mxl111sf_table[25],
816 &mxl111sf_table[27], NULL },
817 },
818 { "Hauppauge WinTV-Aero-M (tp-isoc)",
819 { NULL },
820 { &mxl111sf_table[29], &mxl111sf_table[31],
821 NULL },
822 },
823 }
824};
825
826static struct usb_driver mxl111sf_driver = {
827 .name = "dvb_usb_mxl111sf",
828 .probe = mxl111sf_probe,
829 .disconnect = dvb_usb_device_exit,
830 .id_table = mxl111sf_table,
831};
832
833static int __init mxl111sf_module_init(void)
834{
835 int result = usb_register(&mxl111sf_driver);
836 if (result) {
837 err("usb_register failed. Error number %d", result);
838 return result;
839 }
840
841 return 0;
842}
843
844static void __exit mxl111sf_module_exit(void)
845{
846 usb_deregister(&mxl111sf_driver);
847}
848
849module_init(mxl111sf_module_init);
850module_exit(mxl111sf_module_exit);
851
852MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
853MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
854MODULE_VERSION("1.0");
855MODULE_LICENSE("GPL");
856
857/*
858 * Local variables:
859 * c-basic-offset: 8
860 * End:
861 */