diff options
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/m920x.c | 280 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/m920x.h | 9 |
3 files changed, 276 insertions, 15 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 97715f7514d6..dffce1d4ecd3 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -145,6 +145,8 @@ | |||
145 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | 145 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 |
146 | #define USB_PID_OPERA1_COLD 0x2830 | 146 | #define USB_PID_OPERA1_COLD 0x2830 |
147 | #define USB_PID_OPERA1_WARM 0x3829 | 147 | #define USB_PID_OPERA1_WARM 0x3829 |
148 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | ||
149 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | ||
148 | 150 | ||
149 | 151 | ||
150 | #endif | 152 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 45d7bc214c18..fe5deeefbf5e 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -41,6 +41,26 @@ static struct dvb_usb_rc_key megasky_rc_keys [] = { | |||
41 | { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ | 41 | { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { | ||
45 | { 0x0, 0x01, KEY_ZOOM }, /* Full Screen */ | ||
46 | { 0x0, 0x02, KEY_CAMERA }, /* snapshot */ | ||
47 | { 0x0, 0x03, KEY_MUTE }, | ||
48 | { 0x0, 0x04, KEY_REWIND }, | ||
49 | { 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */ | ||
50 | { 0x0, 0x06, KEY_FASTFORWARD }, | ||
51 | { 0x0, 0x07, KEY_RECORD }, | ||
52 | { 0x0, 0x08, KEY_STOP }, | ||
53 | { 0x0, 0x09, KEY_TIME }, /* Timeshift */ | ||
54 | { 0x0, 0x0c, KEY_COFFEE }, /* Recall */ | ||
55 | { 0x0, 0x0e, KEY_CHANNELUP }, | ||
56 | { 0x0, 0x12, KEY_POWER }, | ||
57 | { 0x0, 0x15, KEY_MENU }, /* source */ | ||
58 | { 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */ | ||
59 | { 0x0, 0x1a, KEY_CHANNELDOWN }, | ||
60 | { 0x0, 0x1b, KEY_VOLUMEDOWN }, | ||
61 | { 0x0, 0x1e, KEY_VOLUMEUP }, | ||
62 | }; | ||
63 | |||
44 | static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ | 64 | static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ |
45 | u16 index, void *data, int size) | 65 | u16 index, void *data, int size) |
46 | { | 66 | { |
@@ -74,17 +94,23 @@ static inline int m9206_write(struct usb_device *udev, u8 request, | |||
74 | return ret; | 94 | return ret; |
75 | } | 95 | } |
76 | 96 | ||
77 | static int m9206_init(struct dvb_usb_device *d) | 97 | static int m9206_init(struct dvb_usb_device *d, struct m9206_inits *rc_seq) |
78 | { | 98 | { |
79 | int ret = 0; | 99 | int ret = 0; |
80 | 100 | ||
81 | /* Remote controller init. */ | 101 | /* Remote controller init. */ |
82 | if (d->props.rc_query) { | 102 | if (d->props.rc_query) { |
83 | if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) | 103 | deb_rc("Initialising remote control\n"); |
84 | return ret; | 104 | while (rc_seq->address) { |
105 | if ((ret = m9206_write(d->udev, M9206_CORE, rc_seq->data, rc_seq->address)) != 0) { | ||
106 | deb_rc("Initialising remote control failed\n"); | ||
107 | return ret; | ||
108 | } | ||
85 | 109 | ||
86 | if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) | 110 | rc_seq++; |
87 | return ret; | 111 | } |
112 | |||
113 | deb_rc("Initialising remote control success\n"); | ||
88 | } | 114 | } |
89 | 115 | ||
90 | return ret; | 116 | return ret; |
@@ -111,6 +137,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
111 | *state = REMOTE_NO_KEY_PRESSED; | 137 | *state = REMOTE_NO_KEY_PRESSED; |
112 | goto unlock; | 138 | goto unlock; |
113 | 139 | ||
140 | case 0x88: /* framing error or "invalid code" */ | ||
141 | case 0x99: | ||
142 | case 0xc0: | ||
143 | case 0xd8: | ||
144 | *state = REMOTE_NO_KEY_PRESSED; | ||
145 | m->rep_count = 0; | ||
146 | goto unlock; | ||
147 | |||
114 | case 0x93: | 148 | case 0x93: |
115 | case 0x92: | 149 | case 0x92: |
116 | m->rep_count = 0; | 150 | m->rep_count = 0; |
@@ -118,20 +152,22 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
118 | goto unlock; | 152 | goto unlock; |
119 | 153 | ||
120 | case 0x91: | 154 | case 0x91: |
121 | /* For comfort. */ | 155 | /* prevent immediate auto-repeat */ |
122 | if (++m->rep_count > 2) | 156 | if (++m->rep_count > 2) |
123 | *state = REMOTE_KEY_REPEAT; | 157 | *state = REMOTE_KEY_REPEAT; |
158 | else | ||
159 | *state = REMOTE_NO_KEY_PRESSED; | ||
124 | goto unlock; | 160 | goto unlock; |
125 | 161 | ||
126 | default: | 162 | default: |
127 | deb_rc("Unexpected rc response %x\n", rc_state[0]); | 163 | deb_rc("Unexpected rc state %02x\n", rc_state[0]); |
128 | *state = REMOTE_NO_KEY_PRESSED; | 164 | *state = REMOTE_NO_KEY_PRESSED; |
129 | goto unlock; | 165 | goto unlock; |
130 | } | 166 | } |
131 | } | 167 | } |
132 | 168 | ||
133 | if (rc_state[1] != 0) | 169 | if (rc_state[1] != 0) |
134 | deb_rc("Unknown rc key %x\n", rc_state[1]); | 170 | deb_rc("Unknown rc key %02x\n", rc_state[1]); |
135 | 171 | ||
136 | *state = REMOTE_NO_KEY_PRESSED; | 172 | *state = REMOTE_NO_KEY_PRESSED; |
137 | 173 | ||
@@ -416,6 +452,12 @@ static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | |||
416 | return 0; | 452 | return 0; |
417 | } | 453 | } |
418 | 454 | ||
455 | static struct m9206_inits megasky_rc_init [] = { | ||
456 | { M9206_RC_INIT2, 0xa8 }, | ||
457 | { M9206_RC_INIT1, 0x51 }, | ||
458 | { } /* terminating entry */ | ||
459 | }; | ||
460 | |||
419 | static struct tda1004x_config digivox_tda10046_config = { | 461 | static struct tda1004x_config digivox_tda10046_config = { |
420 | .demod_address = 0x08, | 462 | .demod_address = 0x08, |
421 | .invert = 0, | 463 | .invert = 0, |
@@ -447,9 +489,106 @@ static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap) | |||
447 | return 0; | 489 | return 0; |
448 | } | 490 | } |
449 | 491 | ||
492 | /* LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A | ||
493 | * TDA10046 #0 is located at i2c address 0x08 | ||
494 | * TDA10046 #1 is located at i2c address 0x0b | ||
495 | * TDA8275A #0 is located at i2c address 0x60 | ||
496 | * TDA8275A #1 is located at i2c address 0x61 | ||
497 | */ | ||
498 | |||
499 | static struct tda1004x_config tvwalkertwin_0_tda10046_config = { | ||
500 | .demod_address = 0x08, | ||
501 | .invert = 0, | ||
502 | .invert_oclk = 0, | ||
503 | .ts_mode = TDA10046_TS_SERIAL, | ||
504 | .xtal_freq = TDA10046_XTAL_16M, | ||
505 | .if_freq = TDA10046_FREQ_045, | ||
506 | .agc_config = TDA10046_AGC_TDA827X, | ||
507 | .gpio_config = TDA10046_GPTRI, | ||
508 | .request_firmware = NULL, /* uses firmware EEPROM */ | ||
509 | }; | ||
510 | |||
511 | static struct tda1004x_config tvwalkertwin_1_tda10046_config = { | ||
512 | .demod_address = 0x0b, | ||
513 | .invert = 0, | ||
514 | .invert_oclk = 0, | ||
515 | .ts_mode = TDA10046_TS_SERIAL, | ||
516 | .xtal_freq = TDA10046_XTAL_16M, | ||
517 | .if_freq = TDA10046_FREQ_045, | ||
518 | .agc_config = TDA10046_AGC_TDA827X, | ||
519 | .gpio_config = TDA10046_GPTRI, | ||
520 | .request_firmware = NULL, /* uses firmware EEPROM */ | ||
521 | }; | ||
522 | |||
523 | static int tvwalkertwin_0_tda10046_frontend_attach(struct dvb_usb_adapter *adap) | ||
524 | { | ||
525 | deb_rc("tvwalkertwin_0_tda10046_frontend_attach!\n"); | ||
526 | |||
527 | if ((adap->fe = dvb_attach(tda10046_attach, &tvwalkertwin_0_tda10046_config, &adap->dev->i2c_adap)) == NULL) | ||
528 | return -EIO; | ||
529 | |||
530 | deb_rc("Attached demod 0 at address %02x\n", tvwalkertwin_0_tda10046_config.demod_address); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static int tvwalkertwin_1_tda10046_frontend_attach(struct dvb_usb_adapter *adap) | ||
536 | { | ||
537 | deb_rc("tvwalkertwin_1_tda10046_frontend_attach!\n"); | ||
538 | |||
539 | if ((adap->fe = dvb_attach(tda10046_attach, &tvwalkertwin_1_tda10046_config, &adap->dev->i2c_adap)) == NULL) | ||
540 | return -EIO; | ||
541 | |||
542 | deb_rc("Attached demod 1 at address %02x\n", tvwalkertwin_1_tda10046_config.demod_address); | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int tvwalkertwin_0_tda8275_tuner_attach(struct dvb_usb_adapter *adap) | ||
548 | { | ||
549 | int address = 0x60; | ||
550 | |||
551 | deb_rc("tvwalkertwin_0_tda8275_tuner_attach!\n"); | ||
552 | |||
553 | if (dvb_attach(tda827x_attach, adap->fe, address, &adap->dev->i2c_adap, | ||
554 | NULL) == NULL) | ||
555 | return -ENODEV; | ||
556 | |||
557 | deb_rc("Attached tuner 0 at address %02x\n", address); | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int tvwalkertwin_1_tda8275_tuner_attach(struct dvb_usb_adapter *adap) | ||
563 | { | ||
564 | int address = 0x61; | ||
565 | |||
566 | deb_rc("tvwalkertwin_1_tda8275_tuner_attach!\n"); | ||
567 | |||
568 | if (dvb_attach(tda827x_attach, adap->fe, address, &adap->dev->i2c_adap, | ||
569 | NULL) == NULL) | ||
570 | return -ENODEV; | ||
571 | |||
572 | deb_rc("Attached tuner 1 at address %02x\n", address); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static struct m9206_inits tvwalkertwin_rc_init [] = { | ||
578 | { M9206_RC_INIT2, 0x00 }, | ||
579 | { M9206_RC_INIT1, 0xef }, | ||
580 | { 0xff28, 0x00 }, | ||
581 | { 0xff23, 0x00 }, | ||
582 | { 0xff21, 0x30 }, | ||
583 | { } /* terminating entry */ | ||
584 | }; | ||
585 | |||
450 | /* DVB USB Driver stuff */ | 586 | /* DVB USB Driver stuff */ |
451 | static struct dvb_usb_device_properties megasky_properties; | 587 | static struct dvb_usb_device_properties megasky_properties; |
452 | static struct dvb_usb_device_properties digivox_mini_ii_properties; | 588 | static struct dvb_usb_device_properties digivox_mini_ii_properties; |
589 | static struct dvb_usb_device_properties tvwalkertwin_properties; | ||
590 | static struct m9206_inits megasky_rc_init []; | ||
591 | static struct m9206_inits tvwalkertwin_rc_init []; | ||
453 | 592 | ||
454 | static int m920x_probe(struct usb_interface *intf, | 593 | static int m920x_probe(struct usb_interface *intf, |
455 | const struct usb_device_id *id) | 594 | const struct usb_device_id *id) |
@@ -457,14 +596,46 @@ static int m920x_probe(struct usb_interface *intf, | |||
457 | struct dvb_usb_device *d; | 596 | struct dvb_usb_device *d; |
458 | struct usb_host_interface *alt; | 597 | struct usb_host_interface *alt; |
459 | int ret; | 598 | int ret; |
599 | struct m9206_inits *rc_init_seq = NULL; | ||
600 | int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; | ||
460 | 601 | ||
461 | deb_rc("Probed!\n"); | 602 | deb_rc("Probing for m920x device at interface %d\n", bInterfaceNumber); |
462 | 603 | ||
463 | if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) || | 604 | if (bInterfaceNumber == 0) { |
464 | ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0)) | 605 | /* Single-tuner device, or first interface on |
465 | goto found; | 606 | * multi-tuner device |
607 | */ | ||
466 | 608 | ||
467 | return ret; | 609 | if ((ret = dvb_usb_device_init(intf, &megasky_properties, |
610 | THIS_MODULE, &d)) == 0) { | ||
611 | rc_init_seq = megasky_rc_init; | ||
612 | goto found; | ||
613 | } | ||
614 | |||
615 | if ((ret = dvb_usb_device_init(intf, | ||
616 | &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0) { | ||
617 | /* No remote control, so no rc_init_seq */ | ||
618 | goto found; | ||
619 | } | ||
620 | |||
621 | /* This configures both tuners on the TV Walker Twin */ | ||
622 | if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, | ||
623 | THIS_MODULE, &d)) == 0) { | ||
624 | rc_init_seq = tvwalkertwin_rc_init; | ||
625 | goto found; | ||
626 | } | ||
627 | |||
628 | return ret; | ||
629 | } else { | ||
630 | /* Another interface on a multi-tuner device */ | ||
631 | |||
632 | /* The LifeView TV Walker Twin gets here, but struct | ||
633 | * tvwalkertwin_properties already configured both | ||
634 | * tuners, so there is nothing for us to do here | ||
635 | */ | ||
636 | |||
637 | return -ENODEV; | ||
638 | } | ||
468 | 639 | ||
469 | found: | 640 | found: |
470 | alt = usb_altnum_to_altsetting(intf, 1); | 641 | alt = usb_altnum_to_altsetting(intf, 1); |
@@ -478,7 +649,7 @@ found: | |||
478 | if (ret < 0) | 649 | if (ret < 0) |
479 | return ret; | 650 | return ret; |
480 | 651 | ||
481 | if ((ret = m9206_init(d)) != 0) | 652 | if ((ret = m9206_init(d, rc_init_seq)) != 0) |
482 | return ret; | 653 | return ret; |
483 | 654 | ||
484 | return ret; | 655 | return ret; |
@@ -488,6 +659,10 @@ static struct usb_device_id m920x_table [] = { | |||
488 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, | 659 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, |
489 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | 660 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, |
490 | USB_PID_MSI_DIGI_VOX_MINI_II) }, | 661 | USB_PID_MSI_DIGI_VOX_MINI_II) }, |
662 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
663 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) }, | ||
664 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
665 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, | ||
491 | { } /* Terminating entry */ | 666 | { } /* Terminating entry */ |
492 | }; | 667 | }; |
493 | MODULE_DEVICE_TABLE (usb, m920x_table); | 668 | MODULE_DEVICE_TABLE (usb, m920x_table); |
@@ -585,6 +760,81 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { | |||
585 | } | 760 | } |
586 | }; | 761 | }; |
587 | 762 | ||
763 | /* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net> */ | ||
764 | |||
765 | static struct dvb_usb_device_properties tvwalkertwin_properties = { | ||
766 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
767 | |||
768 | .usb_ctrl = DEVICE_SPECIFIC, | ||
769 | .firmware = "dvb-usb-tvwalkert.fw", | ||
770 | .download_firmware = m9206_firmware_download, | ||
771 | |||
772 | .rc_interval = 100, | ||
773 | .rc_key_map = tvwalkertwin_rc_keys, | ||
774 | .rc_key_map_size = ARRAY_SIZE(tvwalkertwin_rc_keys), | ||
775 | .rc_query = m9206_rc_query, | ||
776 | |||
777 | .size_of_priv = sizeof(struct m9206_state), | ||
778 | |||
779 | .identify_state = m920x_identify_state, | ||
780 | .num_adapters = 2, | ||
781 | .adapter = { | ||
782 | { | ||
783 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
784 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
785 | |||
786 | .pid_filter_count = 8, | ||
787 | .pid_filter = m9206_pid_filter, | ||
788 | .pid_filter_ctrl = m9206_pid_filter_ctrl, | ||
789 | |||
790 | .frontend_attach = tvwalkertwin_0_tda10046_frontend_attach, | ||
791 | .tuner_attach = tvwalkertwin_0_tda8275_tuner_attach, | ||
792 | |||
793 | .stream = { | ||
794 | .type = USB_BULK, | ||
795 | .count = 8, | ||
796 | .endpoint = 0x81, | ||
797 | .u = { | ||
798 | .bulk = { | ||
799 | .buffersize = 512, | ||
800 | } | ||
801 | } | ||
802 | }, | ||
803 | }, | ||
804 | { | ||
805 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
806 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
807 | |||
808 | .pid_filter_count = 8, | ||
809 | .pid_filter = m9206_pid_filter, | ||
810 | .pid_filter_ctrl = m9206_pid_filter_ctrl, | ||
811 | |||
812 | .frontend_attach = tvwalkertwin_1_tda10046_frontend_attach, | ||
813 | .tuner_attach = tvwalkertwin_1_tda8275_tuner_attach, | ||
814 | |||
815 | .stream = { | ||
816 | .type = USB_BULK, | ||
817 | .count = 8, | ||
818 | .endpoint = 0x82, | ||
819 | .u = { | ||
820 | .bulk = { | ||
821 | .buffersize = 512, | ||
822 | } | ||
823 | } | ||
824 | }, | ||
825 | } | ||
826 | }, | ||
827 | .i2c_algo = &m9206_i2c_algo, | ||
828 | |||
829 | .num_device_descs = 1, | ||
830 | .devices = { | ||
831 | { .name = "LifeView TV Walker Twin DVB-T USB2.0", | ||
832 | .cold_ids = { &m920x_table[2], NULL }, | ||
833 | .warm_ids = { &m920x_table[3], NULL }, | ||
834 | }, | ||
835 | } | ||
836 | }; | ||
837 | |||
588 | static struct usb_driver m920x_driver = { | 838 | static struct usb_driver m920x_driver = { |
589 | .name = "dvb_usb_m920x", | 839 | .name = "dvb_usb_m920x", |
590 | .probe = m920x_probe, | 840 | .probe = m920x_probe, |
@@ -615,6 +865,6 @@ module_init (m920x_module_init); | |||
615 | module_exit (m920x_module_exit); | 865 | module_exit (m920x_module_exit); |
616 | 866 | ||
617 | MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); | 867 | MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); |
618 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); | 868 | MODULE_DESCRIPTION("DVB Driver for ULI M920x"); |
619 | MODULE_VERSION("0.1"); | 869 | MODULE_VERSION("0.1"); |
620 | MODULE_LICENSE("GPL"); | 870 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index 7dd3db65c80e..a2a975588967 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h | |||
@@ -64,4 +64,13 @@ struct m9206_state { | |||
64 | int filtering_enabled; | 64 | int filtering_enabled; |
65 | int rep_count; | 65 | int rep_count; |
66 | }; | 66 | }; |
67 | |||
68 | /* Initialisation data for the m920x | ||
69 | */ | ||
70 | |||
71 | struct m9206_inits { | ||
72 | u16 address; | ||
73 | u8 data; | ||
74 | }; | ||
75 | |||
67 | #endif | 76 | #endif |