aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-usb/cxusb.c
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-20 01:34:11 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:37 -0500
commit702a67624e4bc9c7056418b576af928940b7dbb9 (patch)
tree2253278899e39f160d80ab386a03b77a474a749c /drivers/media/dvb/dvb-usb/cxusb.c
parentc6e62a3a398d62e8ae366ac1465911db0ac7fc0b (diff)
V4L/DVB (6655): Add support for MT352-based DViCO FusionHDTV DVB-T NANO devices
There are at least three variants of the DViCO FusionHDTV DVB-T NANO that share the same USB device ID. The first (ZL10353 w/ firmware in ROM) is already supported; the latter two both require firmware and have either an MT352 or ZL10353 demodulator, and have a different IR receiver from the first. This introduces a new identify_state that can tell the difference between a "warm" device which is running the embedded firmware, and a "cold" device that needs us to upload firmware to it before it will work. We patch the uploaded device ID (like we do for other bluebird devices) to make it easy to identify the particular device variant when it reattaches. NB: These devices use a different firmware file from previous bluebird devices. You need a new firmware file to make this work. Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/cxusb.c')
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c116
1 files changed, 105 insertions, 11 deletions
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index f6fa2c22b0bf..c44b9799efaa 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -440,6 +440,13 @@ static struct zl10353_config cxusb_zl10353_xc3028_config = {
440 .parallel_ts = 1, 440 .parallel_ts = 1,
441}; 441};
442 442
443static struct mt352_config cxusb_mt352_xc3028_config = {
444 .demod_address = 0x0f,
445 .if2 = 4560,
446 .no_tuner = 1,
447 .demod_init = cxusb_mt352_demod_init,
448};
449
443/* Callbacks for DVB USB */ 450/* Callbacks for DVB USB */
444static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) 451static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
445{ 452{
@@ -639,30 +646,63 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
639 &adap->dev->i2c_adap)) != NULL) 646 &adap->dev->i2c_adap)) != NULL)
640 return 0; 647 return 0;
641 648
649 if ((adap->fe = dvb_attach(mt352_attach,
650 &cxusb_mt352_xc3028_config,
651 &adap->dev->i2c_adap)) != NULL)
652 return 0;
653
642 return -EIO; 654 return -EIO;
643} 655}
644 656
645/* 657/*
658 * DViCO has shipped two devices with the same USB ID, but only one of them
659 * needs a firmware download. Check the device class details to see if they
660 * have non-default values to decide whether the device is actually cold or
661 * not, and forget a match if it turns out we selected the wrong device.
662 */
663static int bluebird_fx2_identify_state(struct usb_device *udev,
664 struct dvb_usb_device_properties *props,
665 struct dvb_usb_device_description **desc,
666 int *cold)
667{
668 int wascold = *cold;
669
670 *cold = udev->descriptor.bDeviceClass == 0xff &&
671 udev->descriptor.bDeviceSubClass == 0xff &&
672 udev->descriptor.bDeviceProtocol == 0xff;
673
674 if (*cold && !wascold)
675 *desc = NULL;
676
677 return 0;
678}
679
680/*
646 * DViCO bluebird firmware needs the "warm" product ID to be patched into the 681 * DViCO bluebird firmware needs the "warm" product ID to be patched into the
647 * firmware file before download. 682 * firmware file before download.
648 */ 683 */
649 684
650#define BLUEBIRD_01_ID_OFFSET 6638 685static const int dvico_firmware_id_offsets[] = { 6638, 3204 };
651static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, 686static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
652 const struct firmware *fw) 687 const struct firmware *fw)
653{ 688{
654 if (fw->size < BLUEBIRD_01_ID_OFFSET + 4) 689 int pos;
655 return -EINVAL; 690
691 for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
692 int idoff = dvico_firmware_id_offsets[pos];
656 693
657 if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && 694 if (fw->size < idoff + 4)
658 fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { 695 continue;
659 696
660 fw->data[BLUEBIRD_01_ID_OFFSET + 2] = 697 if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
661 le16_to_cpu(udev->descriptor.idProduct) + 1; 698 fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
662 fw->data[BLUEBIRD_01_ID_OFFSET + 3] = 699 fw->data[idoff + 2] =
663 le16_to_cpu(udev->descriptor.idProduct) >> 8; 700 le16_to_cpu(udev->descriptor.idProduct) + 1;
701 fw->data[idoff + 3] =
702 le16_to_cpu(udev->descriptor.idProduct) >> 8;
664 703
665 return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); 704 return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
705 }
666 } 706 }
667 707
668 return -EINVAL; 708 return -EINVAL;
@@ -676,6 +716,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
676static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; 716static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
677static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; 717static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
678static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; 718static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
719static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
679 720
680static int cxusb_probe(struct usb_interface *intf, 721static int cxusb_probe(struct usb_interface *intf,
681 const struct usb_device_id *id) 722 const struct usb_device_id *id)
@@ -686,7 +727,8 @@ static int cxusb_probe(struct usb_interface *intf,
686 dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 || 727 dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
687 dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 || 728 dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
688 dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 || 729 dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
689 dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0) { 730 dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
731 dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
690 return 0; 732 return 0;
691 } 733 }
692 734
@@ -709,6 +751,7 @@ static struct usb_device_id cxusb_table [] = {
709 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, 751 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
710 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, 752 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
711 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, 753 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
754 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
712 {} /* Terminating entry */ 755 {} /* Terminating entry */
713}; 756};
714MODULE_DEVICE_TABLE (usb, cxusb_table); 757MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1018,6 +1061,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
1018 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 1061 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1019 1062
1020 .usb_ctrl = CYPRESS_FX2, 1063 .usb_ctrl = CYPRESS_FX2,
1064 .identify_state = bluebird_fx2_identify_state,
1021 1065
1022 .size_of_priv = sizeof(struct cxusb_state), 1066 .size_of_priv = sizeof(struct cxusb_state),
1023 1067
@@ -1061,6 +1105,56 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
1061 } 1105 }
1062}; 1106};
1063 1107
1108static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = {
1109 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1110
1111 .usb_ctrl = DEVICE_SPECIFIC,
1112 .firmware = "dvb-usb-bluebird-02.fw",
1113 .download_firmware = bluebird_patch_dvico_firmware_download,
1114 .identify_state = bluebird_fx2_identify_state,
1115
1116 .size_of_priv = sizeof(struct cxusb_state),
1117
1118 .num_adapters = 1,
1119 .adapter = {
1120 {
1121 .streaming_ctrl = cxusb_streaming_ctrl,
1122 .frontend_attach = cxusb_nano2_frontend_attach,
1123 .tuner_attach = cxusb_dvico_xc3028_tuner_attach,
1124 /* parameter for the MPEG2-data transfer */
1125 .stream = {
1126 .type = USB_BULK,
1127 .count = 5,
1128 .endpoint = 0x02,
1129 .u = {
1130 .bulk = {
1131 .buffersize = 8192,
1132 }
1133 }
1134 },
1135 },
1136 },
1137
1138 .power_ctrl = cxusb_nano2_power_ctrl,
1139
1140 .i2c_algo = &cxusb_i2c_algo,
1141
1142 .generic_bulk_ctrl_endpoint = 0x01,
1143
1144 .rc_interval = 100,
1145 .rc_key_map = dvico_portable_rc_keys,
1146 .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
1147 .rc_query = cxusb_rc_query,
1148
1149 .num_device_descs = 1,
1150 .devices = {
1151 { "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
1152 { &cxusb_table[14], NULL },
1153 { &cxusb_table[15], NULL },
1154 },
1155 }
1156};
1157
1064static struct usb_driver cxusb_driver = { 1158static struct usb_driver cxusb_driver = {
1065 .name = "dvb_usb_cxusb", 1159 .name = "dvb_usb_cxusb",
1066 .probe = cxusb_probe, 1160 .probe = cxusb_probe,