diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb/dw2102.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dw2102.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 64132c0cf80d..accc65509b07 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -1,6 +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, DVB-C 3101, | 2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, |
3 | * TeVii S600, S630, S650 Cards | 3 | * TeVii S600, S630, S650, |
4 | * Prof 1100, 7500 Cards | ||
4 | * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) | 5 | * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
@@ -469,11 +470,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
469 | int num) | 470 | int num) |
470 | { | 471 | { |
471 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 472 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
473 | struct usb_device *udev; | ||
472 | int ret = 0; | 474 | int ret = 0; |
473 | int len, i, j; | 475 | int len, i, j; |
474 | 476 | ||
475 | if (!d) | 477 | if (!d) |
476 | return -ENODEV; | 478 | return -ENODEV; |
479 | udev = d->udev; | ||
477 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 480 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
478 | return -EAGAIN; | 481 | return -EAGAIN; |
479 | 482 | ||
@@ -488,8 +491,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
488 | } | 491 | } |
489 | case (DW2102_VOLTAGE_CTRL): { | 492 | case (DW2102_VOLTAGE_CTRL): { |
490 | u8 obuf[2]; | 493 | u8 obuf[2]; |
494 | |||
495 | obuf[0] = 1; | ||
496 | obuf[1] = msg[j].buf[1];/* off-on */ | ||
497 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | ||
498 | obuf, 2, DW210X_WRITE_MSG); | ||
491 | obuf[0] = 3; | 499 | obuf[0] = 3; |
492 | obuf[1] = msg[j].buf[0]; | 500 | obuf[1] = msg[j].buf[0];/* 13v-18v */ |
493 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | 501 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, |
494 | obuf, 2, DW210X_WRITE_MSG); | 502 | obuf, 2, DW210X_WRITE_MSG); |
495 | break; | 503 | break; |
@@ -527,6 +535,17 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
527 | i += 16; | 535 | i += 16; |
528 | len -= 16; | 536 | len -= 16; |
529 | } while (len > 0); | 537 | } while (len > 0); |
538 | } else if ((udev->descriptor.idProduct == 0x7500) | ||
539 | && (j < (num - 1))) { | ||
540 | /* write register addr before read */ | ||
541 | u8 obuf[msg[j].len + 2]; | ||
542 | obuf[0] = msg[j + 1].len; | ||
543 | obuf[1] = (msg[j].addr << 1); | ||
544 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
545 | ret = dw210x_op_rw(d->udev, 0x92, 0, 0, | ||
546 | obuf, msg[j].len + 2, | ||
547 | DW210X_WRITE_MSG); | ||
548 | break; | ||
530 | } else { | 549 | } else { |
531 | /* write registers */ | 550 | /* write registers */ |
532 | u8 obuf[msg[j].len + 2]; | 551 | u8 obuf[msg[j].len + 2]; |
@@ -651,18 +670,25 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | |||
651 | 670 | ||
652 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 671 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
653 | { | 672 | { |
654 | static u8 command_13v[1] = {0x00}; | 673 | static u8 command_13v[] = {0x00, 0x01}; |
655 | static u8 command_18v[1] = {0x01}; | 674 | static u8 command_18v[] = {0x01, 0x01}; |
656 | struct i2c_msg msg[] = { | 675 | static u8 command_off[] = {0x00, 0x00}; |
657 | {.addr = DW2102_VOLTAGE_CTRL, .flags = 0, | 676 | struct i2c_msg msg = { |
658 | .buf = command_13v, .len = 1}, | 677 | .addr = DW2102_VOLTAGE_CTRL, |
678 | .flags = 0, | ||
679 | .buf = command_off, | ||
680 | .len = 2, | ||
659 | }; | 681 | }; |
660 | 682 | ||
661 | struct dvb_usb_adapter *udev_adap = | 683 | struct dvb_usb_adapter *udev_adap = |
662 | (struct dvb_usb_adapter *)(fe->dvb->priv); | 684 | (struct dvb_usb_adapter *)(fe->dvb->priv); |
663 | if (voltage == SEC_VOLTAGE_18) | 685 | if (voltage == SEC_VOLTAGE_18) |
664 | msg[0].buf = command_18v; | 686 | msg.buf = command_18v; |
665 | i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); | 687 | else if (voltage == SEC_VOLTAGE_13) |
688 | msg.buf = command_13v; | ||
689 | |||
690 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | ||
691 | |||
666 | return 0; | 692 | return 0; |
667 | } | 693 | } |
668 | 694 | ||
@@ -735,6 +761,18 @@ static struct stv6110_config dw2104_stv6110_config = { | |||
735 | .clk_div = 1, | 761 | .clk_div = 1, |
736 | }; | 762 | }; |
737 | 763 | ||
764 | static struct stv0900_config prof_7500_stv0900_config = { | ||
765 | .demod_address = 0x6a, | ||
766 | .demod_mode = 0, | ||
767 | .xtal = 27000000, | ||
768 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
769 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
770 | .tun1_maddress = 0,/* 0x60 */ | ||
771 | .tun1_adc = 0,/* 2 Vpp */ | ||
772 | .path1_mode = 3, | ||
773 | .tun1_type = 3, | ||
774 | }; | ||
775 | |||
738 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | 776 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) |
739 | { | 777 | { |
740 | struct dvb_tuner_ops *tuner_ops = NULL; | 778 | struct dvb_tuner_ops *tuner_ops = NULL; |
@@ -882,6 +920,19 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d) | |||
882 | return -EIO; | 920 | return -EIO; |
883 | } | 921 | } |
884 | 922 | ||
923 | static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) | ||
924 | { | ||
925 | d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, | ||
926 | &d->dev->i2c_adap, 0); | ||
927 | if (d->fe == NULL) | ||
928 | return -EIO; | ||
929 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
930 | |||
931 | info("Attached STV0900+STB6100A!\n"); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
885 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | 936 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) |
886 | { | 937 | { |
887 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | 938 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
@@ -1073,6 +1124,7 @@ static struct usb_device_id dw2102_table[] = { | |||
1073 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, | 1124 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, |
1074 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, | 1125 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, |
1075 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, | 1126 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, |
1127 | {USB_DEVICE(0x3034, 0x7500)}, | ||
1076 | { } | 1128 | { } |
1077 | }; | 1129 | }; |
1078 | 1130 | ||
@@ -1387,9 +1439,30 @@ static struct dvb_usb_device_properties s6x0_properties = { | |||
1387 | } | 1439 | } |
1388 | }; | 1440 | }; |
1389 | 1441 | ||
1442 | struct dvb_usb_device_properties *p7500; | ||
1443 | static struct dvb_usb_device_description d7500 = { | ||
1444 | "Prof 7500 USB DVB-S2", | ||
1445 | {&dw2102_table[9], NULL}, | ||
1446 | {NULL}, | ||
1447 | }; | ||
1448 | |||
1390 | static int dw2102_probe(struct usb_interface *intf, | 1449 | static int dw2102_probe(struct usb_interface *intf, |
1391 | const struct usb_device_id *id) | 1450 | const struct usb_device_id *id) |
1392 | { | 1451 | { |
1452 | |||
1453 | p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | ||
1454 | if (!p7500) | ||
1455 | return -ENOMEM; | ||
1456 | /* copy default structure */ | ||
1457 | memcpy(p7500, &s6x0_properties, | ||
1458 | sizeof(struct dvb_usb_device_properties)); | ||
1459 | /* fill only different fields */ | ||
1460 | p7500->firmware = "dvb-usb-p7500.fw"; | ||
1461 | p7500->devices[0] = d7500; | ||
1462 | p7500->rc_key_map = tbs_rc_keys; | ||
1463 | p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys); | ||
1464 | p7500->adapter->frontend_attach = prof_7500_frontend_attach; | ||
1465 | |||
1393 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, | 1466 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
1394 | THIS_MODULE, NULL, adapter_nr) || | 1467 | THIS_MODULE, NULL, adapter_nr) || |
1395 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | 1468 | 0 == dvb_usb_device_init(intf, &dw2104_properties, |
@@ -1397,6 +1470,8 @@ static int dw2102_probe(struct usb_interface *intf, | |||
1397 | 0 == dvb_usb_device_init(intf, &dw3101_properties, | 1470 | 0 == dvb_usb_device_init(intf, &dw3101_properties, |
1398 | THIS_MODULE, NULL, adapter_nr) || | 1471 | THIS_MODULE, NULL, adapter_nr) || |
1399 | 0 == dvb_usb_device_init(intf, &s6x0_properties, | 1472 | 0 == dvb_usb_device_init(intf, &s6x0_properties, |
1473 | THIS_MODULE, NULL, adapter_nr) || | ||
1474 | 0 == dvb_usb_device_init(intf, p7500, | ||
1400 | THIS_MODULE, NULL, adapter_nr)) | 1475 | THIS_MODULE, NULL, adapter_nr)) |
1401 | return 0; | 1476 | return 0; |
1402 | 1477 | ||
@@ -1431,6 +1506,6 @@ MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | |||
1431 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," | 1506 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," |
1432 | " DVB-C 3101 USB2.0," | 1507 | " DVB-C 3101 USB2.0," |
1433 | " TeVii S600, S630, S650, S660 USB2.0," | 1508 | " TeVii S600, S630, S650, S660 USB2.0," |
1434 | " Prof 1100 USB2.0 devices"); | 1509 | " Prof 1100, 7500 USB2.0 devices"); |
1435 | MODULE_VERSION("0.1"); | 1510 | MODULE_VERSION("0.1"); |
1436 | MODULE_LICENSE("GPL"); | 1511 | MODULE_LICENSE("GPL"); |