diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb/m920x.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/m920x.c | 235 |
1 files changed, 157 insertions, 78 deletions
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index d48b24d9abf4..45d7bc214c18 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include "mt352.h" | 14 | #include "mt352.h" |
15 | #include "mt352_priv.h" | 15 | #include "mt352_priv.h" |
16 | #include "qt1010.h" | 16 | #include "qt1010.h" |
17 | #include "tda1004x.h" | ||
18 | #include "tda827x.h" | ||
17 | 19 | ||
18 | /* debug */ | 20 | /* debug */ |
19 | static int dvb_usb_m920x_debug; | 21 | static int dvb_usb_m920x_debug; |
@@ -47,11 +49,15 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ | |||
47 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 49 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
48 | request, USB_TYPE_VENDOR | USB_DIR_IN, | 50 | request, USB_TYPE_VENDOR | USB_DIR_IN, |
49 | value, index, data, size, 2000); | 51 | value, index, data, size, 2000); |
50 | if (ret < 0) | 52 | if (ret < 0) { |
53 | printk(KERN_INFO "m920x_read = error: %d\n", ret); | ||
51 | return ret; | 54 | return ret; |
55 | } | ||
52 | 56 | ||
53 | if (ret != size) | 57 | if (ret != size) { |
58 | deb_rc("m920x_read = no data\n"); | ||
54 | return -EIO; | 59 | return -EIO; |
60 | } | ||
55 | 61 | ||
56 | return 0; | 62 | return 0; |
57 | } | 63 | } |
@@ -64,19 +70,22 @@ static inline int m9206_write(struct usb_device *udev, u8 request, | |||
64 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 70 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
65 | request, USB_TYPE_VENDOR | USB_DIR_OUT, | 71 | request, USB_TYPE_VENDOR | USB_DIR_OUT, |
66 | value, index, NULL, 0, 2000); | 72 | value, index, NULL, 0, 2000); |
73 | |||
67 | return ret; | 74 | return ret; |
68 | } | 75 | } |
69 | 76 | ||
70 | static int m9206_rc_init(struct usb_device *udev) | 77 | static int m9206_init(struct dvb_usb_device *d) |
71 | { | 78 | { |
72 | int ret = 0; | 79 | int ret = 0; |
73 | 80 | ||
74 | /* Remote controller init. */ | 81 | /* Remote controller init. */ |
75 | if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) | 82 | if (d->props.rc_query) { |
76 | return ret; | 83 | if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) |
84 | return ret; | ||
77 | 85 | ||
78 | if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) | 86 | if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) |
79 | return ret; | 87 | return ret; |
88 | } | ||
80 | 89 | ||
81 | return ret; | 90 | return ret; |
82 | } | 91 | } |
@@ -87,16 +96,15 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
87 | int i, ret = 0; | 96 | int i, ret = 0; |
88 | u8 rc_state[2]; | 97 | u8 rc_state[2]; |
89 | 98 | ||
90 | |||
91 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) | 99 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) |
92 | goto unlock; | 100 | goto unlock; |
93 | 101 | ||
94 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) | 102 | if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) |
95 | goto unlock; | 103 | goto unlock; |
96 | 104 | ||
97 | for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) | 105 | for (i = 0; i < d->props.rc_key_map_size; i++) |
98 | if (megasky_rc_keys[i].data == rc_state[1]) { | 106 | if (d->props.rc_key_map[i].data == rc_state[1]) { |
99 | *event = megasky_rc_keys[i].event; | 107 | *event = d->props.rc_key_map[i].event; |
100 | 108 | ||
101 | switch(rc_state[0]) { | 109 | switch(rc_state[0]) { |
102 | case 0x80: | 110 | case 0x80: |
@@ -137,53 +145,51 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
137 | int num) | 145 | int num) |
138 | { | 146 | { |
139 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 147 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
140 | struct m9206_state *m = d->priv; | 148 | int i, j; |
141 | int i; | ||
142 | int ret = 0; | 149 | int ret = 0; |
143 | 150 | ||
151 | if (!num) | ||
152 | return -EINVAL; | ||
153 | |||
144 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 154 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
145 | return -EAGAIN; | 155 | return -EAGAIN; |
146 | 156 | ||
147 | if (num > 2) | ||
148 | return -EINVAL; | ||
149 | |||
150 | for (i = 0; i < num; i++) { | 157 | for (i = 0; i < num; i++) { |
151 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0) | 158 | if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) || |
152 | goto unlock; | 159 | msg[i].len == 0) { |
153 | 160 | /* For a 0 byte message, I think sending the address to index 0x80|0x40 | |
154 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0) | 161 | * would be the correct thing to do. However, zero byte messages are |
162 | * only used for probing, and since we don't know how to get the slave's | ||
163 | * ack, we can't probe. */ | ||
164 | ret = -ENOTSUPP; | ||
155 | goto unlock; | 165 | goto unlock; |
156 | 166 | } | |
157 | if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { | 167 | /* Send START & address/RW bit */ |
158 | int i2c_i; | 168 | if (!(msg[i].flags & I2C_M_NOSTART)) { |
159 | 169 | if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0) | |
160 | for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++) | ||
161 | if (msg[i].addr == m->i2c_r[i2c_i].addr) | ||
162 | break; | ||
163 | |||
164 | if (i2c_i >= M9206_I2C_MAX) { | ||
165 | deb_rc("No magic for i2c addr!\n"); | ||
166 | ret = -EINVAL; | ||
167 | goto unlock; | 170 | goto unlock; |
171 | /* Should check for ack here, if we knew how. */ | ||
172 | } | ||
173 | if (msg[i].flags & I2C_M_RD) { | ||
174 | for (j = 0; j < msg[i].len; j++) { | ||
175 | /* Last byte of transaction? Send STOP, otherwise send ACK. */ | ||
176 | int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01; | ||
177 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0) | ||
178 | goto unlock; | ||
168 | } | 179 | } |
169 | |||
170 | if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0) | ||
171 | goto unlock; | ||
172 | |||
173 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) | ||
174 | goto unlock; | ||
175 | |||
176 | i++; | ||
177 | } else { | 180 | } else { |
178 | if (msg[i].len != 2) | 181 | for (j = 0; j < msg[i].len; j++) { |
179 | return -EINVAL; | 182 | /* Last byte of transaction? Then send STOP. */ |
180 | 183 | int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00; | |
181 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0) | 184 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) |
182 | goto unlock; | 185 | goto unlock; |
186 | /* Should check for ack here too. */ | ||
187 | } | ||
183 | } | 188 | } |
184 | } | 189 | } |
185 | ret = i; | 190 | ret = num; |
186 | unlock: | 191 | |
192 | unlock: | ||
187 | mutex_unlock(&d->i2c_mutex); | 193 | mutex_unlock(&d->i2c_mutex); |
188 | 194 | ||
189 | return ret; | 195 | return ret; |
@@ -324,6 +330,7 @@ static int m9206_firmware_download(struct usb_device *udev, | |||
324 | i += size; | 330 | i += size; |
325 | } | 331 | } |
326 | if (i != fw->size) { | 332 | if (i != fw->size) { |
333 | deb_rc("bad firmware file!\n"); | ||
327 | ret = -EINVAL; | 334 | ret = -EINVAL; |
328 | goto done; | 335 | goto done; |
329 | } | 336 | } |
@@ -342,10 +349,10 @@ static int m9206_firmware_download(struct usb_device *udev, | |||
342 | } | 349 | } |
343 | 350 | ||
344 | /* Callbacks for DVB USB */ | 351 | /* Callbacks for DVB USB */ |
345 | static int megasky_identify_state(struct usb_device *udev, | 352 | static int m920x_identify_state(struct usb_device *udev, |
346 | struct dvb_usb_device_properties *props, | 353 | struct dvb_usb_device_properties *props, |
347 | struct dvb_usb_device_description **desc, | 354 | struct dvb_usb_device_description **desc, |
348 | int *cold) | 355 | int *cold) |
349 | { | 356 | { |
350 | struct usb_host_interface *alt; | 357 | struct usb_host_interface *alt; |
351 | 358 | ||
@@ -381,20 +388,15 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) | |||
381 | } | 388 | } |
382 | 389 | ||
383 | static struct mt352_config megasky_mt352_config = { | 390 | static struct mt352_config megasky_mt352_config = { |
384 | .demod_address = 0x1e, | 391 | .demod_address = 0x0f, |
385 | .no_tuner = 1, | 392 | .no_tuner = 1, |
386 | .demod_init = megasky_mt352_demod_init, | 393 | .demod_init = megasky_mt352_demod_init, |
387 | }; | 394 | }; |
388 | 395 | ||
389 | static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) | 396 | static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) |
390 | { | 397 | { |
391 | struct m9206_state *m = adap->dev->priv; | ||
392 | |||
393 | deb_rc("megasky_frontend_attach!\n"); | 398 | deb_rc("megasky_frontend_attach!\n"); |
394 | 399 | ||
395 | m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; | ||
396 | m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; | ||
397 | |||
398 | if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) | 400 | if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) |
399 | return -EIO; | 401 | return -EIO; |
400 | 402 | ||
@@ -402,16 +404,11 @@ static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) | |||
402 | } | 404 | } |
403 | 405 | ||
404 | static struct qt1010_config megasky_qt1010_config = { | 406 | static struct qt1010_config megasky_qt1010_config = { |
405 | .i2c_address = 0xc4 | 407 | .i2c_address = 0x62 |
406 | }; | 408 | }; |
407 | 409 | ||
408 | static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | 410 | static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) |
409 | { | 411 | { |
410 | struct m9206_state *m = adap->dev->priv; | ||
411 | |||
412 | m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address; | ||
413 | m->i2c_r[M9206_I2C_TUNER].magic = 0xc5; | ||
414 | |||
415 | if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, | 412 | if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, |
416 | &megasky_qt1010_config) == NULL) | 413 | &megasky_qt1010_config) == NULL) |
417 | return -ENODEV; | 414 | return -ENODEV; |
@@ -419,8 +416,40 @@ static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | |||
419 | return 0; | 416 | return 0; |
420 | } | 417 | } |
421 | 418 | ||
419 | static struct tda1004x_config digivox_tda10046_config = { | ||
420 | .demod_address = 0x08, | ||
421 | .invert = 0, | ||
422 | .invert_oclk = 0, | ||
423 | .ts_mode = TDA10046_TS_SERIAL, | ||
424 | .xtal_freq = TDA10046_XTAL_16M, | ||
425 | .if_freq = TDA10046_FREQ_045, | ||
426 | .agc_config = TDA10046_AGC_TDA827X, | ||
427 | .gpio_config = TDA10046_GPTRI, | ||
428 | .request_firmware = NULL, | ||
429 | }; | ||
430 | |||
431 | static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap) | ||
432 | { | ||
433 | deb_rc("digivox_tda10046_frontend_attach!\n"); | ||
434 | |||
435 | if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config, | ||
436 | &adap->dev->i2c_adap)) == NULL) | ||
437 | return -EIO; | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap) | ||
443 | { | ||
444 | if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, | ||
445 | NULL) == NULL) | ||
446 | return -ENODEV; | ||
447 | return 0; | ||
448 | } | ||
449 | |||
422 | /* DVB USB Driver stuff */ | 450 | /* DVB USB Driver stuff */ |
423 | static struct dvb_usb_device_properties megasky_properties; | 451 | static struct dvb_usb_device_properties megasky_properties; |
452 | static struct dvb_usb_device_properties digivox_mini_ii_properties; | ||
424 | 453 | ||
425 | static int m920x_probe(struct usb_interface *intf, | 454 | static int m920x_probe(struct usb_interface *intf, |
426 | const struct usb_device_id *id) | 455 | const struct usb_device_id *id) |
@@ -429,30 +458,36 @@ static int m920x_probe(struct usb_interface *intf, | |||
429 | struct usb_host_interface *alt; | 458 | struct usb_host_interface *alt; |
430 | int ret; | 459 | int ret; |
431 | 460 | ||
432 | if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { | 461 | deb_rc("Probed!\n"); |
433 | deb_rc("probed!\n"); | ||
434 | 462 | ||
435 | alt = usb_altnum_to_altsetting(intf, 1); | 463 | if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) || |
436 | if (alt == NULL) { | 464 | ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0)) |
437 | deb_rc("not alt found!\n"); | 465 | goto found; |
438 | return -ENODEV; | ||
439 | } | ||
440 | 466 | ||
441 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | 467 | return ret; |
442 | alt->desc.bAlternateSetting); | ||
443 | if (ret < 0) | ||
444 | return ret; | ||
445 | |||
446 | deb_rc("Changed to alternate setting!\n"); | ||
447 | 468 | ||
448 | if ((ret = m9206_rc_init(d->udev)) != 0) | 469 | found: |
449 | return ret; | 470 | alt = usb_altnum_to_altsetting(intf, 1); |
471 | if (alt == NULL) { | ||
472 | deb_rc("No alt found!\n"); | ||
473 | return -ENODEV; | ||
450 | } | 474 | } |
475 | |||
476 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
477 | alt->desc.bAlternateSetting); | ||
478 | if (ret < 0) | ||
479 | return ret; | ||
480 | |||
481 | if ((ret = m9206_init(d)) != 0) | ||
482 | return ret; | ||
483 | |||
451 | return ret; | 484 | return ret; |
452 | } | 485 | } |
453 | 486 | ||
454 | static struct usb_device_id m920x_table [] = { | 487 | static struct usb_device_id m920x_table [] = { |
455 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, | 488 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, |
489 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
490 | USB_PID_MSI_DIGI_VOX_MINI_II) }, | ||
456 | { } /* Terminating entry */ | 491 | { } /* Terminating entry */ |
457 | }; | 492 | }; |
458 | MODULE_DEVICE_TABLE (usb, m920x_table); | 493 | MODULE_DEVICE_TABLE (usb, m920x_table); |
@@ -471,7 +506,7 @@ static struct dvb_usb_device_properties megasky_properties = { | |||
471 | 506 | ||
472 | .size_of_priv = sizeof(struct m9206_state), | 507 | .size_of_priv = sizeof(struct m9206_state), |
473 | 508 | ||
474 | .identify_state = megasky_identify_state, | 509 | .identify_state = m920x_identify_state, |
475 | .num_adapters = 1, | 510 | .num_adapters = 1, |
476 | .adapter = {{ | 511 | .adapter = {{ |
477 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | 512 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | |
@@ -502,6 +537,50 @@ static struct dvb_usb_device_properties megasky_properties = { | |||
502 | { "MSI Mega Sky 580 DVB-T USB2.0", | 537 | { "MSI Mega Sky 580 DVB-T USB2.0", |
503 | { &m920x_table[0], NULL }, | 538 | { &m920x_table[0], NULL }, |
504 | { NULL }, | 539 | { NULL }, |
540 | } | ||
541 | } | ||
542 | }; | ||
543 | |||
544 | static struct dvb_usb_device_properties digivox_mini_ii_properties = { | ||
545 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
546 | |||
547 | .usb_ctrl = DEVICE_SPECIFIC, | ||
548 | .firmware = "dvb-usb-digivox-02.fw", | ||
549 | .download_firmware = m9206_firmware_download, | ||
550 | |||
551 | .size_of_priv = sizeof(struct m9206_state), | ||
552 | |||
553 | .identify_state = m920x_identify_state, | ||
554 | .num_adapters = 1, | ||
555 | .adapter = {{ | ||
556 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
557 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
558 | |||
559 | .pid_filter_count = 8, | ||
560 | .pid_filter = m9206_pid_filter, | ||
561 | .pid_filter_ctrl = m9206_pid_filter_ctrl, | ||
562 | |||
563 | .frontend_attach = digivox_tda10046_frontend_attach, | ||
564 | .tuner_attach = digivox_tda8275_tuner_attach, | ||
565 | |||
566 | .stream = { | ||
567 | .type = USB_BULK, | ||
568 | .count = 8, | ||
569 | .endpoint = 0x81, | ||
570 | .u = { | ||
571 | .bulk = { | ||
572 | .buffersize = 0x4000, | ||
573 | } | ||
574 | } | ||
575 | }, | ||
576 | }}, | ||
577 | .i2c_algo = &m9206_i2c_algo, | ||
578 | |||
579 | .num_device_descs = 1, | ||
580 | .devices = { | ||
581 | { "MSI DIGI VOX mini II DVB-T USB2.0", | ||
582 | { &m920x_table[1], NULL }, | ||
583 | { NULL }, | ||
505 | }, | 584 | }, |
506 | } | 585 | } |
507 | }; | 586 | }; |