aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor M. Liplianin <liplianin@me.by>2011-02-25 16:41:22 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:32:25 -0400
commitd2ffc447cabb3a497d7f413403abd8793b348329 (patch)
tree7999af844cecb0ff688ff9b180eb1c9ff5907f93
parent195288da53e03c35f97df8fa08f48f5b625bfb4e (diff)
[media] dw2102: add support for Geniatech SU3000 USB DVB-S2 card
The card uses ds3000 demod from Montage. 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.c287
-rw-r--r--drivers/media/dvb/frontends/ds3000.c40
-rw-r--r--drivers/media/dvb/frontends/ds3000.h1
3 files changed, 325 insertions, 3 deletions
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index f9affdd12d91..461c96a816d7 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,7 +1,8 @@
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, DVB-C 3101, 2* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
3* TeVii S600, S630, S650, 3* TeVii S600, S630, S650,
4* Prof 1100, 7500 Cards 4* Prof 1100, 7500,
5 * Geniatech SU3000 Cards
5* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) 6* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
6* 7*
7* This program is free software; you can redistribute it and/or modify it 8* This program is free software; you can redistribute it and/or modify it
@@ -67,6 +68,7 @@
67#define REG_21_SYMBOLRATE_BYTE2 0x21 68#define REG_21_SYMBOLRATE_BYTE2 0x21
68/* on my own*/ 69/* on my own*/
69#define DW2102_VOLTAGE_CTRL (0x1800) 70#define DW2102_VOLTAGE_CTRL (0x1800)
71#define SU3000_STREAM_CTRL (0x1900)
70#define DW2102_RC_QUERY (0x1a00) 72#define DW2102_RC_QUERY (0x1a00)
71 73
72#define err_str "did not find the firmware file. (%s) " \ 74#define err_str "did not find the firmware file. (%s) " \
@@ -78,6 +80,10 @@ struct rc_map_dvb_usb_table_table {
78 int rc_keys_size; 80 int rc_keys_size;
79}; 81};
80 82
83struct su3000_state {
84 u8 initialized;
85};
86
81/* debug */ 87/* debug */
82static int dvb_usb_dw2102_debug; 88static int dvb_usb_dw2102_debug;
83module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); 89module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
@@ -570,6 +576,70 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
570 return num; 576 return num;
571} 577}
572 578
579static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
580 int num)
581{
582 struct dvb_usb_device *d = i2c_get_adapdata(adap);
583 u8 obuf[0x40], ibuf[0x40];
584
585 if (!d)
586 return -ENODEV;
587 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
588 return -EAGAIN;
589
590 switch (num) {
591 case 1:
592 switch (msg[0].addr) {
593 case SU3000_STREAM_CTRL:
594 obuf[0] = msg[0].buf[0] + 0x36;
595 obuf[1] = 3;
596 obuf[2] = 0;
597 if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
598 err("i2c transfer failed.");
599 break;
600 case DW2102_RC_QUERY:
601 obuf[0] = 0x10;
602 if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
603 err("i2c transfer failed.");
604 msg[0].buf[1] = ibuf[0];
605 msg[0].buf[0] = ibuf[1];
606 break;
607 default:
608 /* always i2c write*/
609 obuf[0] = 0x08;
610 obuf[1] = msg[0].addr;
611 obuf[2] = msg[0].len;
612
613 memcpy(&obuf[3], msg[0].buf, msg[0].len);
614
615 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
616 ibuf, 1, 0) < 0)
617 err("i2c transfer failed.");
618
619 }
620 break;
621 case 2:
622 /* always i2c read */
623 obuf[0] = 0x09;
624 obuf[1] = msg[0].len;
625 obuf[2] = msg[1].len;
626 obuf[3] = msg[0].addr;
627 memcpy(&obuf[4], msg[0].buf, msg[0].len);
628
629 if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
630 ibuf, msg[1].len + 1, 0) < 0)
631 err("i2c transfer failed.");
632
633 memcpy(msg[1].buf, &ibuf[1], msg[1].len);
634 break;
635 default:
636 warn("more than 2 i2c messages at a time is not handled yet.");
637 break;
638 }
639 mutex_unlock(&d->i2c_mutex);
640 return num;
641}
642
573static u32 dw210x_i2c_func(struct i2c_adapter *adapter) 643static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
574{ 644{
575 return I2C_FUNC_I2C; 645 return I2C_FUNC_I2C;
@@ -605,6 +675,11 @@ static struct i2c_algorithm s6x0_i2c_algo = {
605 .functionality = dw210x_i2c_func, 675 .functionality = dw210x_i2c_func,
606}; 676};
607 677
678static struct i2c_algorithm su3000_i2c_algo = {
679 .master_xfer = su3000_i2c_transfer,
680 .functionality = dw210x_i2c_func,
681};
682
608static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 683static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
609{ 684{
610 int i; 685 int i;
@@ -669,6 +744,82 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
669 return 0; 744 return 0;
670}; 745};
671 746
747static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
748{
749 static u8 command_start[] = {0x00};
750 static u8 command_stop[] = {0x01};
751 struct i2c_msg msg = {
752 .addr = SU3000_STREAM_CTRL,
753 .flags = 0,
754 .buf = onoff ? command_start : command_stop,
755 .len = 1
756 };
757
758 i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
759
760 return 0;
761}
762
763static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
764{
765 struct su3000_state *state = (struct su3000_state *)d->priv;
766 u8 obuf[] = {0xde, 0};
767
768 info("%s: %d, initialized %d\n", __func__, i, state->initialized);
769
770 if (i && !state->initialized) {
771 state->initialized = 1;
772 /* reset board */
773 dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
774 }
775
776 return 0;
777}
778
779static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
780{
781 int i;
782 u8 obuf[] = { 0x1f, 0xf0 };
783 u8 ibuf[] = { 0 };
784 struct i2c_msg msg[] = {
785 {
786 .addr = 0x51,
787 .flags = 0,
788 .buf = obuf,
789 .len = 2,
790 }, {
791 .addr = 0x51,
792 .flags = I2C_M_RD,
793 .buf = ibuf,
794 .len = 1,
795
796 }
797 };
798
799 for (i = 0; i < 6; i++) {
800 obuf[1] = 0xf0 + i;
801 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
802 break;
803 else
804 mac[i] = ibuf[0];
805
806 debug_dump(mac, 6, printk);
807 }
808
809 return 0;
810}
811
812static int su3000_identify_state(struct usb_device *udev,
813 struct dvb_usb_device_properties *props,
814 struct dvb_usb_device_description **desc,
815 int *cold)
816{
817 info("%s\n", __func__);
818
819 *cold = 0;
820 return 0;
821}
822
672static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 823static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
673{ 824{
674 static u8 command_13v[] = {0x00, 0x01}; 825 static u8 command_13v[] = {0x00, 0x01};
@@ -774,6 +925,11 @@ static struct stv0900_config prof_7500_stv0900_config = {
774 .tun1_type = 3, 925 .tun1_type = 3,
775}; 926};
776 927
928static struct ds3000_config su3000_ds3000_config = {
929 .demod_address = 0x68,
930 .ci_mode = 1,
931};
932
777static int dw2104_frontend_attach(struct dvb_usb_adapter *d) 933static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
778{ 934{
779 struct dvb_tuner_ops *tuner_ops = NULL; 935 struct dvb_tuner_ops *tuner_ops = NULL;
@@ -944,6 +1100,43 @@ static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
944 return 0; 1100 return 0;
945} 1101}
946 1102
1103static int su3000_frontend_attach(struct dvb_usb_adapter *d)
1104{
1105 u8 obuf[3] = { 0xe, 0x80, 0 };
1106 u8 ibuf[] = { 0 };
1107
1108 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1109 err("command 0x0e transfer failed.");
1110
1111 obuf[0] = 0xe;
1112 obuf[1] = 0x83;
1113 obuf[2] = 0;
1114
1115 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1116 err("command 0x0e transfer failed.");
1117
1118 obuf[0] = 0xe;
1119 obuf[1] = 0x83;
1120 obuf[2] = 1;
1121
1122 if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
1123 err("command 0x0e transfer failed.");
1124
1125 obuf[0] = 0x51;
1126
1127 if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
1128 err("command 0x51 transfer failed.");
1129
1130 d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
1131 &d->dev->i2c_adap);
1132 if (d->fe == NULL)
1133 return -EIO;
1134
1135 info("Attached DS3000!\n");
1136
1137 return 0;
1138}
1139
947static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) 1140static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
948{ 1141{
949 dvb_attach(dvb_pll_attach, adap->fe, 0x60, 1142 dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -1078,10 +1271,49 @@ static struct rc_map_table rc_map_tbs_table[] = {
1078 { 0xf89b, KEY_MODE } 1271 { 0xf89b, KEY_MODE }
1079}; 1272};
1080 1273
1274static struct rc_map_table rc_map_su3000_table[] = {
1275 { 0x25, KEY_POWER }, /* right-bottom Red */
1276 { 0x0a, KEY_MUTE }, /* -/-- */
1277 { 0x01, KEY_1 },
1278 { 0x02, KEY_2 },
1279 { 0x03, KEY_3 },
1280 { 0x04, KEY_4 },
1281 { 0x05, KEY_5 },
1282 { 0x06, KEY_6 },
1283 { 0x07, KEY_7 },
1284 { 0x08, KEY_8 },
1285 { 0x09, KEY_9 },
1286 { 0x00, KEY_0 },
1287 { 0x20, KEY_UP }, /* CH+ */
1288 { 0x21, KEY_DOWN }, /* CH+ */
1289 { 0x12, KEY_VOLUMEUP }, /* Brightness Up */
1290 { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
1291 { 0x1f, KEY_RECORD },
1292 { 0x17, KEY_PLAY },
1293 { 0x16, KEY_PAUSE },
1294 { 0x0b, KEY_STOP },
1295 { 0x27, KEY_FASTFORWARD },/* >> */
1296 { 0x26, KEY_REWIND }, /* << */
1297 { 0x0d, KEY_OK }, /* Mute */
1298 { 0x11, KEY_LEFT }, /* VOL- */
1299 { 0x10, KEY_RIGHT }, /* VOL+ */
1300 { 0x29, KEY_BACK }, /* button under 9 */
1301 { 0x2c, KEY_MENU }, /* TTX */
1302 { 0x2b, KEY_EPG }, /* EPG */
1303 { 0x1e, KEY_RED }, /* OSD */
1304 { 0x0e, KEY_GREEN }, /* Window */
1305 { 0x2d, KEY_YELLOW }, /* button under << */
1306 { 0x0f, KEY_BLUE }, /* bottom yellow button */
1307 { 0x14, KEY_AUDIO }, /* Snapshot */
1308 { 0x38, KEY_TV }, /* TV/Radio */
1309 { 0x0c, KEY_ESC } /* upper Red buttton */
1310};
1311
1081static struct rc_map_dvb_usb_table_table keys_tables[] = { 1312static struct rc_map_dvb_usb_table_table keys_tables[] = {
1082 { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) }, 1313 { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
1083 { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) }, 1314 { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
1084 { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) }, 1315 { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
1316 { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
1085}; 1317};
1086 1318
1087static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 1319static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@@ -1137,6 +1369,7 @@ static struct usb_device_id dw2102_table[] = {
1137 {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, 1369 {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
1138 {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, 1370 {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
1139 {USB_DEVICE(0x3034, 0x7500)}, 1371 {USB_DEVICE(0x3034, 0x7500)},
1372 {USB_DEVICE(0x1f4d, 0x3000)},
1140 { } 1373 { }
1141}; 1374};
1142 1375
@@ -1473,6 +1706,51 @@ static struct dvb_usb_device_description d7500 = {
1473 {NULL}, 1706 {NULL},
1474}; 1707};
1475 1708
1709static struct dvb_usb_device_properties su3000_properties = {
1710 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1711 .usb_ctrl = DEVICE_SPECIFIC,
1712 .size_of_priv = sizeof(struct su3000_state),
1713 .power_ctrl = su3000_power_ctrl,
1714 .num_adapters = 1,
1715 .identify_state = su3000_identify_state,
1716 .i2c_algo = &su3000_i2c_algo,
1717
1718 .rc.legacy = {
1719 .rc_map_table = rc_map_su3000_table,
1720 .rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
1721 .rc_interval = 150,
1722 .rc_query = dw2102_rc_query,
1723 },
1724
1725 .read_mac_address = su3000_read_mac_address,
1726
1727 .generic_bulk_ctrl_endpoint = 0x01,
1728
1729 .adapter = {
1730 {
1731 .streaming_ctrl = su3000_streaming_ctrl,
1732 .frontend_attach = su3000_frontend_attach,
1733 .stream = {
1734 .type = USB_BULK,
1735 .count = 8,
1736 .endpoint = 0x82,
1737 .u = {
1738 .bulk = {
1739 .buffersize = 4096,
1740 }
1741 }
1742 }
1743 }
1744 },
1745 .num_device_descs = 1,
1746 .devices = {
1747 { "SU3000HD DVB-S USB2.0",
1748 { &dw2102_table[10], NULL },
1749 { NULL },
1750 },
1751 }
1752};
1753
1476static int dw2102_probe(struct usb_interface *intf, 1754static int dw2102_probe(struct usb_interface *intf,
1477 const struct usb_device_id *id) 1755 const struct usb_device_id *id)
1478{ 1756{
@@ -1527,7 +1805,9 @@ static int dw2102_probe(struct usb_interface *intf,
1527 0 == dvb_usb_device_init(intf, s660, 1805 0 == dvb_usb_device_init(intf, s660,
1528 THIS_MODULE, NULL, adapter_nr) || 1806 THIS_MODULE, NULL, adapter_nr) ||
1529 0 == dvb_usb_device_init(intf, p7500, 1807 0 == dvb_usb_device_init(intf, p7500,
1530 THIS_MODULE, NULL, adapter_nr)) 1808 THIS_MODULE, NULL, adapter_nr) ||
1809 0 == dvb_usb_device_init(intf, &su3000_properties,
1810 THIS_MODULE, NULL, adapter_nr))
1531 return 0; 1811 return 0;
1532 1812
1533 return -ENODEV; 1813 return -ENODEV;
@@ -1561,6 +1841,7 @@ MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
1561MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," 1841MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
1562 " DVB-C 3101 USB2.0," 1842 " DVB-C 3101 USB2.0,"
1563 " TeVii S600, S630, S650, S660 USB2.0," 1843 " TeVii S600, S630, S650, S660 USB2.0,"
1564 " Prof 1100, 7500 USB2.0 devices"); 1844 " Prof 1100, 7500 USB2.0,"
1845 " Geniatech SU3000 devices");
1565MODULE_VERSION("0.1"); 1846MODULE_VERSION("0.1");
1566MODULE_LICENSE("GPL"); 1847MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 993357383fd4..3373890c092e 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -509,6 +509,33 @@ static int ds3000_load_firmware(struct dvb_frontend *fe,
509 return 0; 509 return 0;
510} 510}
511 511
512static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
513{
514 struct ds3000_state *state = fe->demodulator_priv;
515 u8 data;
516
517 dprintk("%s(%d)\n", __func__, voltage);
518
519 data = ds3000_readreg(state, 0xa2);
520 data |= 0x03; /* bit0 V/H, bit1 off/on */
521
522 switch (voltage) {
523 case SEC_VOLTAGE_18:
524 data &= ~0x03;
525 break;
526 case SEC_VOLTAGE_13:
527 data &= ~0x03;
528 data |= 0x01;
529 break;
530 case SEC_VOLTAGE_OFF:
531 break;
532 }
533
534 ds3000_writereg(state, 0xa2, data);
535
536 return 0;
537}
538
512static void ds3000_dump_registers(struct dvb_frontend *fe) 539static void ds3000_dump_registers(struct dvb_frontend *fe)
513{ 540{
514 struct ds3000_state *state = fe->demodulator_priv; 541 struct ds3000_state *state = fe->demodulator_priv;
@@ -1255,6 +1282,18 @@ static int ds3000_tune(struct dvb_frontend *fe,
1255 ds3000_writereg(state, 0xfd, 0x42); 1282 ds3000_writereg(state, 0xfd, 0x42);
1256 ds3000_writereg(state, 0x08, 0x07);*/ 1283 ds3000_writereg(state, 0x08, 0x07);*/
1257 1284
1285 if (state->config->ci_mode) {
1286 switch (c->delivery_system) {
1287 case SYS_DVBS:
1288 default:
1289 ds3000_writereg(state, 0xfd, 0x80);
1290 break;
1291 case SYS_DVBS2:
1292 ds3000_writereg(state, 0xfd, 0x01);
1293 break;
1294 }
1295 }
1296
1258 /* ds3000 out of software reset */ 1297 /* ds3000 out of software reset */
1259 ds3000_writereg(state, 0x00, 0x00); 1298 ds3000_writereg(state, 0x00, 0x00);
1260 /* start ds3000 build-in uC */ 1299 /* start ds3000 build-in uC */
@@ -1351,6 +1390,7 @@ static struct dvb_frontend_ops ds3000_ops = {
1351 .read_signal_strength = ds3000_read_signal_strength, 1390 .read_signal_strength = ds3000_read_signal_strength,
1352 .read_snr = ds3000_read_snr, 1391 .read_snr = ds3000_read_snr,
1353 .read_ucblocks = ds3000_read_ucblocks, 1392 .read_ucblocks = ds3000_read_ucblocks,
1393 .set_voltage = ds3000_set_voltage,
1354 .set_tone = ds3000_set_tone, 1394 .set_tone = ds3000_set_tone,
1355 .diseqc_send_master_cmd = ds3000_send_diseqc_msg, 1395 .diseqc_send_master_cmd = ds3000_send_diseqc_msg,
1356 .diseqc_send_burst = ds3000_diseqc_send_burst, 1396 .diseqc_send_burst = ds3000_diseqc_send_burst,
diff --git a/drivers/media/dvb/frontends/ds3000.h b/drivers/media/dvb/frontends/ds3000.h
index 67f67038740a..00e4e95590e9 100644
--- a/drivers/media/dvb/frontends/ds3000.h
+++ b/drivers/media/dvb/frontends/ds3000.h
@@ -27,6 +27,7 @@
27struct ds3000_config { 27struct ds3000_config {
28 /* the demodulator's i2c address */ 28 /* the demodulator's i2c address */
29 u8 demod_address; 29 u8 demod_address;
30 u8 ci_mode;
30}; 31};
31 32
32#if defined(CONFIG_DVB_DS3000) || \ 33#if defined(CONFIG_DVB_DS3000) || \