Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Igor M. Liplianin and committed by
Mauro Carvalho Chehab
d2ffc447 195288da

+325 -3
+284 -3
drivers/media/dvb/dvb-usb/dw2102.c
··· 1 1 /* DVB USB framework compliant Linux driver for the 2 2 * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, 3 3 * TeVii S600, S630, S650, 4 - * Prof 1100, 7500 Cards 4 + * Prof 1100, 7500, 5 + * Geniatech SU3000 Cards 5 6 * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) 6 7 * 7 8 * This program is free software; you can redistribute it and/or modify it ··· 68 67 #define REG_21_SYMBOLRATE_BYTE2 0x21 69 68 /* on my own*/ 70 69 #define DW2102_VOLTAGE_CTRL (0x1800) 70 + #define SU3000_STREAM_CTRL (0x1900) 71 71 #define DW2102_RC_QUERY (0x1a00) 72 72 73 73 #define err_str "did not find the firmware file. (%s) " \ ··· 78 76 struct rc_map_dvb_usb_table_table { 79 77 struct rc_map_table *rc_keys; 80 78 int rc_keys_size; 79 + }; 80 + 81 + struct su3000_state { 82 + u8 initialized; 81 83 }; 82 84 83 85 /* debug */ ··· 576 570 return num; 577 571 } 578 572 573 + static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], 574 + int num) 575 + { 576 + struct dvb_usb_device *d = i2c_get_adapdata(adap); 577 + u8 obuf[0x40], ibuf[0x40]; 578 + 579 + if (!d) 580 + return -ENODEV; 581 + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 582 + return -EAGAIN; 583 + 584 + switch (num) { 585 + case 1: 586 + switch (msg[0].addr) { 587 + case SU3000_STREAM_CTRL: 588 + obuf[0] = msg[0].buf[0] + 0x36; 589 + obuf[1] = 3; 590 + obuf[2] = 0; 591 + if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0) 592 + err("i2c transfer failed."); 593 + break; 594 + case DW2102_RC_QUERY: 595 + obuf[0] = 0x10; 596 + if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0) 597 + err("i2c transfer failed."); 598 + msg[0].buf[1] = ibuf[0]; 599 + msg[0].buf[0] = ibuf[1]; 600 + break; 601 + default: 602 + /* always i2c write*/ 603 + obuf[0] = 0x08; 604 + obuf[1] = msg[0].addr; 605 + obuf[2] = msg[0].len; 606 + 607 + memcpy(&obuf[3], msg[0].buf, msg[0].len); 608 + 609 + if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3, 610 + ibuf, 1, 0) < 0) 611 + err("i2c transfer failed."); 612 + 613 + } 614 + break; 615 + case 2: 616 + /* always i2c read */ 617 + obuf[0] = 0x09; 618 + obuf[1] = msg[0].len; 619 + obuf[2] = msg[1].len; 620 + obuf[3] = msg[0].addr; 621 + memcpy(&obuf[4], msg[0].buf, msg[0].len); 622 + 623 + if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4, 624 + ibuf, msg[1].len + 1, 0) < 0) 625 + err("i2c transfer failed."); 626 + 627 + memcpy(msg[1].buf, &ibuf[1], msg[1].len); 628 + break; 629 + default: 630 + warn("more than 2 i2c messages at a time is not handled yet."); 631 + break; 632 + } 633 + mutex_unlock(&d->i2c_mutex); 634 + return num; 635 + } 636 + 579 637 static u32 dw210x_i2c_func(struct i2c_adapter *adapter) 580 638 { 581 639 return I2C_FUNC_I2C; ··· 672 602 673 603 static struct i2c_algorithm s6x0_i2c_algo = { 674 604 .master_xfer = s6x0_i2c_transfer, 605 + .functionality = dw210x_i2c_func, 606 + }; 607 + 608 + static struct i2c_algorithm su3000_i2c_algo = { 609 + .master_xfer = su3000_i2c_transfer, 675 610 .functionality = dw210x_i2c_func, 676 611 }; 677 612 ··· 743 668 memcpy(mac, eeprom + 16, 6); 744 669 return 0; 745 670 }; 671 + 672 + static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 673 + { 674 + static u8 command_start[] = {0x00}; 675 + static u8 command_stop[] = {0x01}; 676 + struct i2c_msg msg = { 677 + .addr = SU3000_STREAM_CTRL, 678 + .flags = 0, 679 + .buf = onoff ? command_start : command_stop, 680 + .len = 1 681 + }; 682 + 683 + i2c_transfer(&adap->dev->i2c_adap, &msg, 1); 684 + 685 + return 0; 686 + } 687 + 688 + static int su3000_power_ctrl(struct dvb_usb_device *d, int i) 689 + { 690 + struct su3000_state *state = (struct su3000_state *)d->priv; 691 + u8 obuf[] = {0xde, 0}; 692 + 693 + info("%s: %d, initialized %d\n", __func__, i, state->initialized); 694 + 695 + if (i && !state->initialized) { 696 + state->initialized = 1; 697 + /* reset board */ 698 + dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); 699 + } 700 + 701 + return 0; 702 + } 703 + 704 + static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) 705 + { 706 + int i; 707 + u8 obuf[] = { 0x1f, 0xf0 }; 708 + u8 ibuf[] = { 0 }; 709 + struct i2c_msg msg[] = { 710 + { 711 + .addr = 0x51, 712 + .flags = 0, 713 + .buf = obuf, 714 + .len = 2, 715 + }, { 716 + .addr = 0x51, 717 + .flags = I2C_M_RD, 718 + .buf = ibuf, 719 + .len = 1, 720 + 721 + } 722 + }; 723 + 724 + for (i = 0; i < 6; i++) { 725 + obuf[1] = 0xf0 + i; 726 + if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) 727 + break; 728 + else 729 + mac[i] = ibuf[0]; 730 + 731 + debug_dump(mac, 6, printk); 732 + } 733 + 734 + return 0; 735 + } 736 + 737 + static int su3000_identify_state(struct usb_device *udev, 738 + struct dvb_usb_device_properties *props, 739 + struct dvb_usb_device_description **desc, 740 + int *cold) 741 + { 742 + info("%s\n", __func__); 743 + 744 + *cold = 0; 745 + return 0; 746 + } 746 747 747 748 static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 748 749 { ··· 923 772 .tun1_adc = 0,/* 2 Vpp */ 924 773 .path1_mode = 3, 925 774 .tun1_type = 3, 775 + }; 776 + 777 + static struct ds3000_config su3000_ds3000_config = { 778 + .demod_address = 0x68, 779 + .ci_mode = 1, 926 780 }; 927 781 928 782 static int dw2104_frontend_attach(struct dvb_usb_adapter *d) ··· 1100 944 return 0; 1101 945 } 1102 946 947 + static int su3000_frontend_attach(struct dvb_usb_adapter *d) 948 + { 949 + u8 obuf[3] = { 0xe, 0x80, 0 }; 950 + u8 ibuf[] = { 0 }; 951 + 952 + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) 953 + err("command 0x0e transfer failed."); 954 + 955 + obuf[0] = 0xe; 956 + obuf[1] = 0x83; 957 + obuf[2] = 0; 958 + 959 + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) 960 + err("command 0x0e transfer failed."); 961 + 962 + obuf[0] = 0xe; 963 + obuf[1] = 0x83; 964 + obuf[2] = 1; 965 + 966 + if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) 967 + err("command 0x0e transfer failed."); 968 + 969 + obuf[0] = 0x51; 970 + 971 + if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0) 972 + err("command 0x51 transfer failed."); 973 + 974 + d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config, 975 + &d->dev->i2c_adap); 976 + if (d->fe == NULL) 977 + return -EIO; 978 + 979 + info("Attached DS3000!\n"); 980 + 981 + return 0; 982 + } 983 + 1103 984 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) 1104 985 { 1105 986 dvb_attach(dvb_pll_attach, adap->fe, 0x60, ··· 1271 1078 { 0xf89b, KEY_MODE } 1272 1079 }; 1273 1080 1081 + static struct rc_map_table rc_map_su3000_table[] = { 1082 + { 0x25, KEY_POWER }, /* right-bottom Red */ 1083 + { 0x0a, KEY_MUTE }, /* -/-- */ 1084 + { 0x01, KEY_1 }, 1085 + { 0x02, KEY_2 }, 1086 + { 0x03, KEY_3 }, 1087 + { 0x04, KEY_4 }, 1088 + { 0x05, KEY_5 }, 1089 + { 0x06, KEY_6 }, 1090 + { 0x07, KEY_7 }, 1091 + { 0x08, KEY_8 }, 1092 + { 0x09, KEY_9 }, 1093 + { 0x00, KEY_0 }, 1094 + { 0x20, KEY_UP }, /* CH+ */ 1095 + { 0x21, KEY_DOWN }, /* CH+ */ 1096 + { 0x12, KEY_VOLUMEUP }, /* Brightness Up */ 1097 + { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */ 1098 + { 0x1f, KEY_RECORD }, 1099 + { 0x17, KEY_PLAY }, 1100 + { 0x16, KEY_PAUSE }, 1101 + { 0x0b, KEY_STOP }, 1102 + { 0x27, KEY_FASTFORWARD },/* >> */ 1103 + { 0x26, KEY_REWIND }, /* << */ 1104 + { 0x0d, KEY_OK }, /* Mute */ 1105 + { 0x11, KEY_LEFT }, /* VOL- */ 1106 + { 0x10, KEY_RIGHT }, /* VOL+ */ 1107 + { 0x29, KEY_BACK }, /* button under 9 */ 1108 + { 0x2c, KEY_MENU }, /* TTX */ 1109 + { 0x2b, KEY_EPG }, /* EPG */ 1110 + { 0x1e, KEY_RED }, /* OSD */ 1111 + { 0x0e, KEY_GREEN }, /* Window */ 1112 + { 0x2d, KEY_YELLOW }, /* button under << */ 1113 + { 0x0f, KEY_BLUE }, /* bottom yellow button */ 1114 + { 0x14, KEY_AUDIO }, /* Snapshot */ 1115 + { 0x38, KEY_TV }, /* TV/Radio */ 1116 + { 0x0c, KEY_ESC } /* upper Red buttton */ 1117 + }; 1118 + 1274 1119 static struct rc_map_dvb_usb_table_table keys_tables[] = { 1275 1120 { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) }, 1276 1121 { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) }, 1277 1122 { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) }, 1123 + { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) }, 1278 1124 }; 1279 1125 1280 1126 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ··· 1369 1137 {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, 1370 1138 {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, 1371 1139 {USB_DEVICE(0x3034, 0x7500)}, 1140 + {USB_DEVICE(0x1f4d, 0x3000)}, 1372 1141 { } 1373 1142 }; 1374 1143 ··· 1706 1473 {NULL}, 1707 1474 }; 1708 1475 1476 + static struct dvb_usb_device_properties su3000_properties = { 1477 + .caps = DVB_USB_IS_AN_I2C_ADAPTER, 1478 + .usb_ctrl = DEVICE_SPECIFIC, 1479 + .size_of_priv = sizeof(struct su3000_state), 1480 + .power_ctrl = su3000_power_ctrl, 1481 + .num_adapters = 1, 1482 + .identify_state = su3000_identify_state, 1483 + .i2c_algo = &su3000_i2c_algo, 1484 + 1485 + .rc.legacy = { 1486 + .rc_map_table = rc_map_su3000_table, 1487 + .rc_map_size = ARRAY_SIZE(rc_map_su3000_table), 1488 + .rc_interval = 150, 1489 + .rc_query = dw2102_rc_query, 1490 + }, 1491 + 1492 + .read_mac_address = su3000_read_mac_address, 1493 + 1494 + .generic_bulk_ctrl_endpoint = 0x01, 1495 + 1496 + .adapter = { 1497 + { 1498 + .streaming_ctrl = su3000_streaming_ctrl, 1499 + .frontend_attach = su3000_frontend_attach, 1500 + .stream = { 1501 + .type = USB_BULK, 1502 + .count = 8, 1503 + .endpoint = 0x82, 1504 + .u = { 1505 + .bulk = { 1506 + .buffersize = 4096, 1507 + } 1508 + } 1509 + } 1510 + } 1511 + }, 1512 + .num_device_descs = 1, 1513 + .devices = { 1514 + { "SU3000HD DVB-S USB2.0", 1515 + { &dw2102_table[10], NULL }, 1516 + { NULL }, 1517 + }, 1518 + } 1519 + }; 1520 + 1709 1521 static int dw2102_probe(struct usb_interface *intf, 1710 1522 const struct usb_device_id *id) 1711 1523 { ··· 1805 1527 0 == dvb_usb_device_init(intf, s660, 1806 1528 THIS_MODULE, NULL, adapter_nr) || 1807 1529 0 == dvb_usb_device_init(intf, p7500, 1808 - THIS_MODULE, NULL, adapter_nr)) 1530 + THIS_MODULE, NULL, adapter_nr) || 1531 + 0 == dvb_usb_device_init(intf, &su3000_properties, 1532 + THIS_MODULE, NULL, adapter_nr)) 1809 1533 return 0; 1810 1534 1811 1535 return -ENODEV; ··· 1841 1561 MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," 1842 1562 " DVB-C 3101 USB2.0," 1843 1563 " TeVii S600, S630, S650, S660 USB2.0," 1844 - " Prof 1100, 7500 USB2.0 devices"); 1564 + " Prof 1100, 7500 USB2.0," 1565 + " Geniatech SU3000 devices"); 1845 1566 MODULE_VERSION("0.1"); 1846 1567 MODULE_LICENSE("GPL");
+40
drivers/media/dvb/frontends/ds3000.c
··· 509 509 return 0; 510 510 } 511 511 512 + static 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 + 512 539 static void ds3000_dump_registers(struct dvb_frontend *fe) 513 540 { 514 541 struct ds3000_state *state = fe->demodulator_priv; ··· 1282 1255 ds3000_writereg(state, 0xfd, 0x42); 1283 1256 ds3000_writereg(state, 0x08, 0x07);*/ 1284 1257 1258 + if (state->config->ci_mode) { 1259 + switch (c->delivery_system) { 1260 + case SYS_DVBS: 1261 + default: 1262 + ds3000_writereg(state, 0xfd, 0x80); 1263 + break; 1264 + case SYS_DVBS2: 1265 + ds3000_writereg(state, 0xfd, 0x01); 1266 + break; 1267 + } 1268 + } 1269 + 1285 1270 /* ds3000 out of software reset */ 1286 1271 ds3000_writereg(state, 0x00, 0x00); 1287 1272 /* start ds3000 build-in uC */ ··· 1390 1351 .read_signal_strength = ds3000_read_signal_strength, 1391 1352 .read_snr = ds3000_read_snr, 1392 1353 .read_ucblocks = ds3000_read_ucblocks, 1354 + .set_voltage = ds3000_set_voltage, 1393 1355 .set_tone = ds3000_set_tone, 1394 1356 .diseqc_send_master_cmd = ds3000_send_diseqc_msg, 1395 1357 .diseqc_send_burst = ds3000_diseqc_send_burst,
+1
drivers/media/dvb/frontends/ds3000.h
··· 27 27 struct ds3000_config { 28 28 /* the demodulator's i2c address */ 29 29 u8 demod_address; 30 + u8 ci_mode; 30 31 }; 31 32 32 33 #if defined(CONFIG_DVB_DS3000) || \