aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor M. Liplianin <liplianin@me.by>2009-06-14 19:51:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 18:07:48 -0400
commit1dac77c9d82f344b21c1d962d79875ec331f83cc (patch)
treeeb4c8c782935dd79e37d039cdeec13e90ce8ac99
parentb42e1d71f52995f0a25f2b593fdb166326db3fd4 (diff)
V4L/DVB (11983): Add support for DVBWorld DVB-C USB Cable card.
DVBWorld DVB-C USB Cable card contains TUA6034 tuner, TDA10023 demod and Cypress FX-2 controller. http://www.worlddvb.com/product/htm/usbc.htm Signed-off-by: Igor M. Liplianin <liplianin@me.by> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c176
1 files changed, 165 insertions, 11 deletions
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 06a0aa1ae2cb..75de49c0d943 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,7 +1,7 @@
1/* DVB USB framework compliant Linux driver for the 1/* DVB USB framework compliant Linux driver for the
2* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card 2* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
3* 3* TeVii S600, S650 Cards
4* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) 4* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
5* 5*
6* This program is free software; you can redistribute it and/or modify it 6* This program is free software; you can redistribute it and/or modify it
7* under the terms of the GNU General Public License as published by the 7* under the terms of the GNU General Public License as published by the
@@ -17,6 +17,7 @@
17#include "stb6000.h" 17#include "stb6000.h"
18#include "eds1547.h" 18#include "eds1547.h"
19#include "cx24116.h" 19#include "cx24116.h"
20#include "tda1002x.h"
20 21
21#ifndef USB_PID_DW2102 22#ifndef USB_PID_DW2102
22#define USB_PID_DW2102 0x2102 23#define USB_PID_DW2102 0x2102
@@ -26,10 +27,18 @@
26#define USB_PID_DW2104 0x2104 27#define USB_PID_DW2104 0x2104
27#endif 28#endif
28 29
30#ifndef USB_PID_DW3101
31#define USB_PID_DW3101 0x3101
32#endif
33
29#ifndef USB_PID_CINERGY_S 34#ifndef USB_PID_CINERGY_S
30#define USB_PID_CINERGY_S 0x0064 35#define USB_PID_CINERGY_S 0x0064
31#endif 36#endif
32 37
38#ifndef USB_PID_TEVII_S650
39#define USB_PID_TEVII_S650 0xd650
40#endif
41
33#define DW210X_READ_MSG 0 42#define DW210X_READ_MSG 0
34#define DW210X_WRITE_MSG 1 43#define DW210X_WRITE_MSG 1
35 44
@@ -82,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
82static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 91static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
83 int num) 92 int num)
84{ 93{
85struct dvb_usb_device *d = i2c_get_adapdata(adap); 94 struct dvb_usb_device *d = i2c_get_adapdata(adap);
86 int i = 0, ret = 0; 95 int i = 0, ret = 0;
87 u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; 96 u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
88 u16 value; 97 u16 value;
@@ -208,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
208 mutex_unlock(&d->i2c_mutex); 217 mutex_unlock(&d->i2c_mutex);
209 return num; 218 return num;
210} 219}
220
211static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) 221static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
212{ 222{
213 struct dvb_usb_device *d = i2c_get_adapdata(adap); 223 struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -222,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
222 case 2: { 232 case 2: {
223 /* read */ 233 /* read */
224 /* first write first register number */ 234 /* first write first register number */
225 u8 ibuf [msg[1].len + 2], obuf[3]; 235 u8 ibuf[msg[1].len + 2], obuf[3];
226 obuf[0] = 0xd0; 236 obuf[0] = 0xd0;
227 obuf[1] = msg[0].len; 237 obuf[1] = msg[0].len;
228 obuf[2] = msg[0].buf[0]; 238 obuf[2] = msg[0].buf[0];
@@ -296,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
296 case 2: { 306 case 2: {
297 /* read */ 307 /* read */
298 /* first write first register number */ 308 /* first write first register number */
299 u8 ibuf [msg[1].len + 2], obuf[3]; 309 u8 ibuf[msg[1].len + 2], obuf[3];
300 obuf[0] = 0xaa; 310 obuf[0] = 0xaa;
301 obuf[1] = msg[0].len; 311 obuf[1] = msg[0].len;
302 obuf[2] = msg[0].buf[0]; 312 obuf[2] = msg[0].buf[0];
@@ -363,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
363 return num; 373 return num;
364} 374}
365 375
376static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
377 int num)
378{
379 struct dvb_usb_device *d = i2c_get_adapdata(adap);
380 int ret = 0, i;
381
382 if (!d)
383 return -ENODEV;
384 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
385 return -EAGAIN;
386
387 switch (num) {
388 case 2: {
389 /* read */
390 /* first write first register number */
391 u8 ibuf[msg[1].len + 2], obuf[3];
392 obuf[0] = msg[0].addr << 1;
393 obuf[1] = msg[0].len;
394 obuf[2] = msg[0].buf[0];
395 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
396 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
397 /* second read registers */
398 ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
399 ibuf, msg[1].len + 2, DW210X_READ_MSG);
400 memcpy(msg[1].buf, ibuf + 2, msg[1].len);
401
402 break;
403 }
404 case 1:
405 switch (msg[0].addr) {
406 case 0x60:
407 case 0x0c: {
408 /* write to register */
409 u8 obuf[msg[0].len + 2];
410 obuf[0] = msg[0].addr << 1;
411 obuf[1] = msg[0].len;
412 memcpy(obuf + 2, msg[0].buf, msg[0].len);
413 ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
414 obuf, msg[0].len + 2, DW210X_WRITE_MSG);
415 break;
416 }
417 case(DW2102_RC_QUERY): {
418 u8 ibuf[2];
419 ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
420 ibuf, 2, DW210X_READ_MSG);
421 memcpy(msg[0].buf, ibuf , 2);
422 break;
423 }
424 }
425
426 break;
427 }
428
429 for (i = 0; i < num; i++) {
430 deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
431 msg[i].flags == 0 ? ">>>" : "<<<");
432 debug_dump(msg[i].buf, msg[i].len, deb_xfer);
433 }
434
435 mutex_unlock(&d->i2c_mutex);
436 return num;
437}
438
366static u32 dw210x_i2c_func(struct i2c_adapter *adapter) 439static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
367{ 440{
368 return I2C_FUNC_I2C; 441 return I2C_FUNC_I2C;
@@ -388,6 +461,11 @@ static struct i2c_algorithm dw2104_i2c_algo = {
388 .functionality = dw210x_i2c_func, 461 .functionality = dw210x_i2c_func,
389}; 462};
390 463
464static struct i2c_algorithm dw3101_i2c_algo = {
465 .master_xfer = dw3101_i2c_transfer,
466 .functionality = dw210x_i2c_func,
467};
468
391static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 469static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
392{ 470{
393 int i; 471 int i;
@@ -407,6 +485,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
407 debug_dump(eepromline, 16, deb_xfer); 485 debug_dump(eepromline, 16, deb_xfer);
408 } 486 }
409 } 487 }
488
410 memcpy(mac, eeprom + 8, 6); 489 memcpy(mac, eeprom + 8, 6);
411 return 0; 490 return 0;
412}; 491};
@@ -451,6 +530,11 @@ static struct si21xx_config serit_sp1511lhb_config = {
451 530
452}; 531};
453 532
533static struct tda10023_config dw3101_tda10023_config = {
534 .demod_address = 0x0c,
535 .invert = 1,
536};
537
454static int dw2104_frontend_attach(struct dvb_usb_adapter *d) 538static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
455{ 539{
456 if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, 540 if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
@@ -501,6 +585,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
501 return -EIO; 585 return -EIO;
502} 586}
503 587
588static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
589{
590 d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
591 &d->dev->i2c_adap, 0x48);
592 if (d->fe != NULL) {
593 info("Attached tda10023!\n");
594 return 0;
595 }
596 return -EIO;
597}
598
504static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) 599static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
505{ 600{
506 dvb_attach(dvb_pll_attach, adap->fe, 0x60, 601 dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -516,6 +611,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
516 return 0; 611 return 0;
517} 612}
518 613
614static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
615{
616 dvb_attach(dvb_pll_attach, adap->fe, 0x60,
617 &adap->dev->i2c_adap, DVB_PLL_TUA6034);
618
619 return 0;
620}
621
519static struct dvb_usb_rc_key dw210x_rc_keys[] = { 622static struct dvb_usb_rc_key dw210x_rc_keys[] = {
520 { 0xf8, 0x0a, KEY_Q }, /*power*/ 623 { 0xf8, 0x0a, KEY_Q }, /*power*/
521 { 0xf8, 0x0c, KEY_M }, /*mute*/ 624 { 0xf8, 0x0c, KEY_M }, /*mute*/
@@ -685,9 +788,10 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
685static struct usb_device_id dw2102_table[] = { 788static struct usb_device_id dw2102_table[] = {
686 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, 789 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
687 {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, 790 {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
688 {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, 791 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
689 {USB_DEVICE(0x9022, 0xd650)}, 792 {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
690 {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, 793 {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
794 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
691 { } 795 { }
692}; 796};
693 797
@@ -748,7 +852,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
748 } 852 }
749 /* init registers */ 853 /* init registers */
750 switch (dev->descriptor.idProduct) { 854 switch (dev->descriptor.idProduct) {
751 case 0xd650: 855 case USB_PID_TEVII_S650:
752 dw2104_properties.rc_key_map = tevii_rc_keys; 856 dw2104_properties.rc_key_map = tevii_rc_keys;
753 dw2104_properties.rc_key_map_size = 857 dw2104_properties.rc_key_map_size =
754 ARRAY_SIZE(tevii_rc_keys); 858 ARRAY_SIZE(tevii_rc_keys);
@@ -756,6 +860,8 @@ static int dw2102_load_firmware(struct usb_device *dev,
756 reset = 1; 860 reset = 1;
757 dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, 861 dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
758 DW210X_WRITE_MSG); 862 DW210X_WRITE_MSG);
863 /* break omitted intentionally */
864 case USB_PID_DW3101:
759 reset = 0; 865 reset = 0;
760 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, 866 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
761 DW210X_WRITE_MSG); 867 DW210X_WRITE_MSG);
@@ -799,6 +905,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
799 DW210X_READ_MSG); 905 DW210X_READ_MSG);
800 break; 906 break;
801 } 907 }
908
802 msleep(100); 909 msleep(100);
803 kfree(p); 910 kfree(p);
804 } 911 }
@@ -822,7 +929,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
822 .num_adapters = 1, 929 .num_adapters = 1,
823 .download_firmware = dw2102_load_firmware, 930 .download_firmware = dw2102_load_firmware,
824 .read_mac_address = dw210x_read_mac_address, 931 .read_mac_address = dw210x_read_mac_address,
825 .adapter = { 932 .adapter = {
826 { 933 {
827 .frontend_attach = dw2102_frontend_attach, 934 .frontend_attach = dw2102_frontend_attach,
828 .streaming_ctrl = NULL, 935 .streaming_ctrl = NULL,
@@ -903,12 +1010,57 @@ static struct dvb_usb_device_properties dw2104_properties = {
903 } 1010 }
904}; 1011};
905 1012
1013static struct dvb_usb_device_properties dw3101_properties = {
1014 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1015 .usb_ctrl = DEVICE_SPECIFIC,
1016 .firmware = "dvb-usb-dw3101.fw",
1017 .no_reconnect = 1,
1018
1019 .i2c_algo = &dw3101_i2c_algo,
1020 .rc_key_map = dw210x_rc_keys,
1021 .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
1022 .rc_interval = 150,
1023 .rc_query = dw2102_rc_query,
1024
1025 .generic_bulk_ctrl_endpoint = 0x81,
1026 /* parameter for the MPEG2-data transfer */
1027 .num_adapters = 1,
1028 .download_firmware = dw2102_load_firmware,
1029 .read_mac_address = dw210x_read_mac_address,
1030 .adapter = {
1031 {
1032 .frontend_attach = dw3101_frontend_attach,
1033 .streaming_ctrl = NULL,
1034 .tuner_attach = dw3101_tuner_attach,
1035 .stream = {
1036 .type = USB_BULK,
1037 .count = 8,
1038 .endpoint = 0x82,
1039 .u = {
1040 .bulk = {
1041 .buffersize = 4096,
1042 }
1043 }
1044 },
1045 }
1046 },
1047 .num_device_descs = 1,
1048 .devices = {
1049 { "DVBWorld DVB-C 3101 USB2.0",
1050 {&dw2102_table[5], NULL},
1051 {NULL},
1052 },
1053 }
1054};
1055
906static int dw2102_probe(struct usb_interface *intf, 1056static int dw2102_probe(struct usb_interface *intf,
907 const struct usb_device_id *id) 1057 const struct usb_device_id *id)
908{ 1058{
909 if (0 == dvb_usb_device_init(intf, &dw2102_properties, 1059 if (0 == dvb_usb_device_init(intf, &dw2102_properties,
910 THIS_MODULE, NULL, adapter_nr) || 1060 THIS_MODULE, NULL, adapter_nr) ||
911 0 == dvb_usb_device_init(intf, &dw2104_properties, 1061 0 == dvb_usb_device_init(intf, &dw2104_properties,
1062 THIS_MODULE, NULL, adapter_nr) ||
1063 0 == dvb_usb_device_init(intf, &dw3101_properties,
912 THIS_MODULE, NULL, adapter_nr)) { 1064 THIS_MODULE, NULL, adapter_nr)) {
913 return 0; 1065 return 0;
914 } 1066 }
@@ -940,6 +1092,8 @@ module_init(dw2102_module_init);
940module_exit(dw2102_module_exit); 1092module_exit(dw2102_module_exit);
941 1093
942MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); 1094MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
943MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); 1095MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
1096 " DVB-C 3101 USB2.0,"
1097 " TeVii S600, S650 USB2.0 devices");
944MODULE_VERSION("0.1"); 1098MODULE_VERSION("0.1");
945MODULE_LICENSE("GPL"); 1099MODULE_LICENSE("GPL");