aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-11-19 19:57:10 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:02:32 -0500
commitaeb012bbf460171b75ba17dc064a543f7256521f (patch)
tree1e8a735d06bf9e541f4db37c0d808eb91074d2ee /drivers/media
parent45819c381fc4fb342dc091f30eef4b56193e34d5 (diff)
V4L/DVB (6649): Add support for the DViCO FusionHDTV Dual Digital 4
Add support for DViCO's Dual Digital 4 with xc3028 tuner, zl10353 DVB-T demodulator and a new-style I2C IR remote control receiver. This would not have been possible without the work of and advice from Mike Krufky, who originally got the Dual Digital 4 and second-gen DVB-T NANO devices working with the out-of-tree XC3028 driver. I converted it to use the in-tree XC3028 driver (after making it suitable for our use), and added the IR remote control support based on his advice. NB: a firmware package is required to use this device. 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')
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c200
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h1
3 files changed, 201 insertions, 2 deletions
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 74eeb168f241..ec8516ac8105 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -15,7 +15,7 @@
15 * 15 *
16 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) 16 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
17 * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) 17 * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
18 * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) 18 * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
19 * 19 *
20 * This program is free software; you can redistribute it and/or modify it 20 * This program is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License as published by the Free 21 * under the terms of the GNU General Public License as published by the Free
@@ -30,6 +30,8 @@
30#include "mt352.h" 30#include "mt352.h"
31#include "mt352_priv.h" 31#include "mt352_priv.h"
32#include "zl10353.h" 32#include "zl10353.h"
33#include "tuner-xc2028.h"
34#include "tuner-xc2028-types.h"
33 35
34/* debug */ 36/* debug */
35static int dvb_usb_cxusb_debug; 37static int dvb_usb_cxusb_debug;
@@ -73,6 +75,29 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
73 st->gpio_write_state[GPIO_TUNER] = onoff; 75 st->gpio_write_state[GPIO_TUNER] = onoff;
74} 76}
75 77
78static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
79 u8 newval)
80{
81 u8 o[2], gpio_state;
82 int rc;
83
84 o[0] = 0xff & ~changemask; /* mask of bits to keep */
85 o[1] = newval & changemask; /* new values for bits */
86
87 rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
88 if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
89 deb_info("bluebird_gpio_write failed.\n");
90
91 return rc < 0 ? rc : gpio_state;
92}
93
94static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
95{
96 cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
97 msleep(5);
98 cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
99}
100
76/* I2C */ 101/* I2C */
77static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], 102static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
78 int num) 103 int num)
@@ -210,6 +235,34 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
210 return 0; 235 return 0;
211} 236}
212 237
238static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
239 int *state)
240{
241 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
242 u8 ircode[4];
243 int i;
244 struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
245 .buf = ircode, .len = 4 };
246
247 *event = 0;
248 *state = REMOTE_NO_KEY_PRESSED;
249
250 if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
251 return 0;
252
253 for (i = 0; i < d->props.rc_key_map_size; i++) {
254 if (keymap[i].custom == ircode[1] &&
255 keymap[i].data == ircode[2]) {
256 *event = keymap[i].event;
257 *state = REMOTE_KEY_PRESSED;
258
259 return 0;
260 }
261 }
262
263 return 0;
264}
265
213static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { 266static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
214 { 0xfe, 0x02, KEY_TV }, 267 { 0xfe, 0x02, KEY_TV },
215 { 0xfe, 0x0e, KEY_MP3 }, 268 { 0xfe, 0x0e, KEY_MP3 },
@@ -364,6 +417,13 @@ static struct mt352_config cxusb_mt352_config = {
364 .demod_init = cxusb_mt352_demod_init, 417 .demod_init = cxusb_mt352_demod_init,
365}; 418};
366 419
420static struct zl10353_config cxusb_zl10353_xc3028_config = {
421 .demod_address = 0x0f,
422 .if2 = 4560,
423 .no_tuner = 1,
424 .parallel_ts = 1,
425};
426
367/* Callbacks for DVB USB */ 427/* Callbacks for DVB USB */
368static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) 428static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
369{ 429{
@@ -399,6 +459,52 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
399 return 0; 459 return 0;
400} 460}
401 461
462static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
463{
464 struct dvb_usb_device *d = ptr;
465
466 switch (command) {
467 case XC2028_TUNER_RESET:
468 deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
469 cxusb_bluebird_gpio_pulse(d, 0x01, 1);
470 break;
471 case XC2028_RESET_CLK:
472 deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
473 break;
474 default:
475 deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
476 command, arg);
477 return -EINVAL;
478 }
479
480 return 0;
481}
482
483static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
484{
485 struct dvb_frontend *fe;
486 struct xc2028_config cfg = {
487 .i2c_adap = &adap->dev->i2c_adap,
488 .i2c_addr = 0x61,
489 .video_dev = adap->dev,
490 .callback = dvico_bluebird_xc2028_callback,
491 };
492 static struct xc2028_ctrl ctl = {
493 .type = XC2028_FIRM_NORMAL,
494 .fname = "xc3028-dvico-au-01.fw",
495 .max_len = 64,
496 .scode_table = ZARLINK456,
497 };
498
499 fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
500 if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
501 return -EIO;
502
503 fe->ops.tuner_ops.set_config(fe, &ctl);
504
505 return 0;
506}
507
402static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) 508static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
403{ 509{
404 u8 b; 510 u8 b;
@@ -460,6 +566,46 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
460 return -EIO; 566 return -EIO;
461} 567}
462 568
569static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
570{
571 u8 ircode[4];
572 int i;
573 struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
574 .buf = ircode, .len = 4 };
575
576 if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
577 err("set interface failed");
578
579 cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
580
581 /* reset the tuner and demodulator */
582 cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
583 cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
584 cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
585
586 if ((adap->fe = dvb_attach(zl10353_attach,
587 &cxusb_zl10353_xc3028_config,
588 &adap->dev->i2c_adap)) == NULL)
589 return -EIO;
590
591 /* try to determine if there is no IR decoder on the I2C bus */
592 for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
593 msleep(20);
594 if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
595 goto no_IR;
596 if (ircode[0] == 0 && ircode[1] == 0)
597 continue;
598 if (ircode[2] + ircode[3] != 0xff) {
599no_IR:
600 adap->dev->props.rc_key_map = NULL;
601 info("No IR receiver detected on this device.");
602 break;
603 }
604 }
605
606 return 0;
607}
608
463/* 609/*
464 * DViCO bluebird firmware needs the "warm" product ID to be patched into the 610 * DViCO bluebird firmware needs the "warm" product ID to be patched into the
465 * firmware file before download. 611 * firmware file before download.
@@ -492,6 +638,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
492static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; 638static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
493static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; 639static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
494static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; 640static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
641static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
495 642
496static int cxusb_probe(struct usb_interface *intf, 643static int cxusb_probe(struct usb_interface *intf,
497 const struct usb_device_id *id) 644 const struct usb_device_id *id)
@@ -500,7 +647,8 @@ static int cxusb_probe(struct usb_interface *intf,
500 dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || 647 dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
501 dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 || 648 dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
502 dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 || 649 dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
503 dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) { 650 dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
651 dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0) {
504 return 0; 652 return 0;
505 } 653 }
506 654
@@ -521,6 +669,7 @@ static struct usb_device_id cxusb_table [] = {
521 { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, 669 { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
522 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, 670 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
523 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, 671 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
672 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
524 {} /* Terminating entry */ 673 {} /* Terminating entry */
525}; 674};
526MODULE_DEVICE_TABLE (usb, cxusb_table); 675MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -779,6 +928,53 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
779 } 928 }
780}; 929};
781 930
931static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
932 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
933
934 .usb_ctrl = CYPRESS_FX2,
935
936 .size_of_priv = sizeof(struct cxusb_state),
937
938 .num_adapters = 1,
939 .adapter = {
940 {
941 .streaming_ctrl = cxusb_streaming_ctrl,
942 .frontend_attach = cxusb_dualdig4_frontend_attach,
943 .tuner_attach = cxusb_dvico_xc3028_tuner_attach,
944 /* parameter for the MPEG2-data transfer */
945 .stream = {
946 .type = USB_BULK,
947 .count = 5,
948 .endpoint = 0x02,
949 .u = {
950 .bulk = {
951 .buffersize = 8192,
952 }
953 }
954 },
955 },
956 },
957
958 .power_ctrl = cxusb_power_ctrl,
959
960 .i2c_algo = &cxusb_i2c_algo,
961
962 .generic_bulk_ctrl_endpoint = 0x01,
963
964 .rc_interval = 100,
965 .rc_key_map = dvico_mce_rc_keys,
966 .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
967 .rc_query = cxusb_bluebird2_rc_query,
968
969 .num_device_descs = 1,
970 .devices = {
971 { "DViCO FusionHDTV DVB-T Dual Digital 4",
972 { NULL },
973 { &cxusb_table[13], NULL },
974 },
975 }
976};
977
782static struct usb_driver cxusb_driver = { 978static struct usb_driver cxusb_driver = {
783 .name = "dvb_usb_cxusb", 979 .name = "dvb_usb_cxusb",
784 .probe = cxusb_probe, 980 .probe = cxusb_probe,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 79ca7abb89a5..4768a2c35517 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -5,6 +5,8 @@
5#include "dvb-usb.h" 5#include "dvb-usb.h"
6 6
7/* usb commands - some of it are guesses, don't have a reference yet */ 7/* usb commands - some of it are guesses, don't have a reference yet */
8#define CMD_BLUEBIRD_GPIO_RW 0x05
9
8#define CMD_I2C_WRITE 0x08 10#define CMD_I2C_WRITE 0x08
9#define CMD_I2C_READ 0x09 11#define CMD_I2C_READ 0x09
10 12
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index d6d96308cbaa..6f14c853ffea 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -147,6 +147,7 @@
147#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 147#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
148#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 148#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
149#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 149#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
150#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
150#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 151#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
151#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 152#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
152#define USB_PID_MEDION_MD95700 0x0932 153#define USB_PID_MEDION_MD95700 0x0932