aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorNick Andrew <nick@nick-andrew.net>2007-03-22 16:09:35 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-05-09 09:12:57 -0400
commitaa50ec2b4998f3937d7050826db190c82bed64e7 (patch)
tree09c342e058ddb4ea516b3f6f3db994a32c51fb2f /drivers/media
parent36a63ee34b568de8d0762f9b07f34ae5caae7724 (diff)
V4L/DVB (5605): M920x: Add support for LifeView TV Walker Twin
Add support for "LifeView TV Walker Twin" (USB IDs 10fd:0513, 10fd:0514) Signed-off-by: Nick Andrew <nick@nick-andrew.net> Signed-off-by: Aapo Tahkola <aet@rasterburn.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h2
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c280
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.h9
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
44static 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
44static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ 64static 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
77static int m9206_init(struct dvb_usb_device *d) 97static 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
455static struct m9206_inits megasky_rc_init [] = {
456 { M9206_RC_INIT2, 0xa8 },
457 { M9206_RC_INIT1, 0x51 },
458 { } /* terminating entry */
459};
460
419static struct tda1004x_config digivox_tda10046_config = { 461static 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
499static 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
511static 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
523static 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
535static 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
547static 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
562static 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
577static 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 */
451static struct dvb_usb_device_properties megasky_properties; 587static struct dvb_usb_device_properties megasky_properties;
452static struct dvb_usb_device_properties digivox_mini_ii_properties; 588static struct dvb_usb_device_properties digivox_mini_ii_properties;
589static struct dvb_usb_device_properties tvwalkertwin_properties;
590static struct m9206_inits megasky_rc_init [];
591static struct m9206_inits tvwalkertwin_rc_init [];
453 592
454static int m920x_probe(struct usb_interface *intf, 593static 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
469found: 640found:
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};
493MODULE_DEVICE_TABLE (usb, m920x_table); 668MODULE_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
765static 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
588static struct usb_driver m920x_driver = { 838static 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);
615module_exit (m920x_module_exit); 865module_exit (m920x_module_exit);
616 866
617MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); 867MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
618MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); 868MODULE_DESCRIPTION("DVB Driver for ULI M920x");
619MODULE_VERSION("0.1"); 869MODULE_VERSION("0.1");
620MODULE_LICENSE("GPL"); 870MODULE_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
71struct m9206_inits {
72 u16 address;
73 u8 data;
74};
75
67#endif 76#endif