aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig4
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c63
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h75
-rw-r--r--drivers/media/dvb/dvb-usb/ce6230.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h4
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig7
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c12
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx.c816
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx.h90
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx_priv.h70
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c2
14 files changed, 1121 insertions, 35 deletions
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 5b20cf5a29f..971a8b18f6d 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -662,7 +662,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
662 if (ret < 0) 662 if (ret < 0)
663 goto err_kfree; 663 goto err_kfree;
664 664
665 ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 665 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
666 if (ret < 0) 666 if (ret < 0)
667 goto err_pci_disable_device; 667 goto err_pci_disable_device;
668 668
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 6103caad164..60955a70d88 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -294,7 +294,7 @@ config DVB_USB_DTV5100
294 294
295config DVB_USB_AF9015 295config DVB_USB_AF9015
296 tristate "Afatech AF9015 DVB-T USB2.0 support" 296 tristate "Afatech AF9015 DVB-T USB2.0 support"
297 depends on DVB_USB && EXPERIMENTAL 297 depends on DVB_USB
298 select DVB_AF9013 298 select DVB_AF9013
299 select DVB_PLL if !DVB_FE_CUSTOMISE 299 select DVB_PLL if !DVB_FE_CUSTOMISE
300 select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE 300 select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
@@ -309,6 +309,6 @@ config DVB_USB_CE6230
309 tristate "Intel CE6230 DVB-T USB2.0 support" 309 tristate "Intel CE6230 DVB-T USB2.0 support"
310 depends on DVB_USB && EXPERIMENTAL 310 depends on DVB_USB && EXPERIMENTAL
311 select DVB_ZL10353 311 select DVB_ZL10353
312 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE 312 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
313 help 313 help
314 Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver 314 Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index f0ba8b07b84..53bfc8e42fb 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -782,17 +782,14 @@ static int af9015_read_config(struct usb_device *udev)
782 ARRAY_SIZE(af9015_ir_table_leadtek); 782 ARRAY_SIZE(af9015_ir_table_leadtek);
783 break; 783 break;
784 case USB_VID_VISIONPLUS: 784 case USB_VID_VISIONPLUS:
785 if (udev->descriptor.idProduct == 785 af9015_properties[i].rc_key_map =
786 cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) { 786 af9015_rc_keys_twinhan;
787 af9015_properties[i].rc_key_map = 787 af9015_properties[i].rc_key_map_size =
788 af9015_rc_keys_twinhan; 788 ARRAY_SIZE(af9015_rc_keys_twinhan);
789 af9015_properties[i].rc_key_map_size = 789 af9015_config.ir_table =
790 ARRAY_SIZE(af9015_rc_keys_twinhan); 790 af9015_ir_table_twinhan;
791 af9015_config.ir_table = 791 af9015_config.ir_table_size =
792 af9015_ir_table_twinhan; 792 ARRAY_SIZE(af9015_ir_table_twinhan);
793 af9015_config.ir_table_size =
794 ARRAY_SIZE(af9015_ir_table_twinhan);
795 }
796 break; 793 break;
797 case USB_VID_KWORLD_2: 794 case USB_VID_KWORLD_2:
798 /* TODO: use correct rc keys */ 795 /* TODO: use correct rc keys */
@@ -833,6 +830,16 @@ static int af9015_read_config(struct usb_device *udev)
833 af9015_ir_table_msi; 830 af9015_ir_table_msi;
834 af9015_config.ir_table_size = 831 af9015_config.ir_table_size =
835 ARRAY_SIZE(af9015_ir_table_msi); 832 ARRAY_SIZE(af9015_ir_table_msi);
833 } else if (udev->descriptor.idProduct ==
834 cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
835 af9015_properties[i].rc_key_map =
836 af9015_rc_keys_trekstor;
837 af9015_properties[i].rc_key_map_size =
838 ARRAY_SIZE(af9015_rc_keys_trekstor);
839 af9015_config.ir_table =
840 af9015_ir_table_trekstor;
841 af9015_config.ir_table_size =
842 ARRAY_SIZE(af9015_ir_table_trekstor);
836 } 843 }
837 break; 844 break;
838 case USB_VID_AVERMEDIA: 845 case USB_VID_AVERMEDIA:
@@ -981,6 +988,21 @@ error:
981 if (ret) 988 if (ret)
982 err("eeprom read failed:%d", ret); 989 err("eeprom read failed:%d", ret);
983 990
991 /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
992 content :-( Override some wrong values here. */
993 if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
994 le16_to_cpu(udev->descriptor.idProduct) == USB_PID_AVERMEDIA_A850) {
995 deb_info("%s: AverMedia A850: overriding config\n", __func__);
996 /* disable dual mode */
997 af9015_config.dual_mode = 0;
998 /* disable 2nd adapter */
999 for (i = 0; i < af9015_properties_count; i++)
1000 af9015_properties[i].num_adapters = 1;
1001
1002 /* set correct IF */
1003 af9015_af9013_config[0].tuner_if = 4570;
1004 }
1005
984 return ret; 1006 return ret;
985} 1007}
986 1008
@@ -1237,6 +1259,9 @@ static struct usb_device_id af9015_usb_table[] = {
1237/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, 1259/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
1238 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, 1260 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
1239 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, 1261 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
1262 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
1263 {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
1264 {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
1240 {0}, 1265 {0},
1241}; 1266};
1242MODULE_DEVICE_TABLE(usb, af9015_usb_table); 1267MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1401,7 +1426,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1401 1426
1402 .i2c_algo = &af9015_i2c_algo, 1427 .i2c_algo = &af9015_i2c_algo,
1403 1428
1404 .num_device_descs = 7, 1429 .num_device_descs = 9,
1405 .devices = { 1430 .devices = {
1406 { 1431 {
1407 .name = "Xtensions XD-380", 1432 .name = "Xtensions XD-380",
@@ -1437,7 +1462,19 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1437 .name = "KWorld USB DVB-T TV Stick II " \ 1462 .name = "KWorld USB DVB-T TV Stick II " \
1438 "(VS-DVB-T 395U)", 1463 "(VS-DVB-T 395U)",
1439 .cold_ids = {&af9015_usb_table[16], 1464 .cold_ids = {&af9015_usb_table[16],
1440 &af9015_usb_table[17], NULL}, 1465 &af9015_usb_table[17],
1466 &af9015_usb_table[18], NULL},
1467 .warm_ids = {NULL},
1468 },
1469 {
1470 .name = "TrekStor DVB-T USB Stick",
1471 .cold_ids = {&af9015_usb_table[19], NULL},
1472 .warm_ids = {NULL},
1473 },
1474 {
1475 .name = "AverMedia AVerTV Volar Black HD " \
1476 "(A850)",
1477 .cold_ids = {&af9015_usb_table[20], NULL},
1441 .warm_ids = {NULL}, 1478 .warm_ids = {NULL},
1442 }, 1479 },
1443 } 1480 }
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index 00e25714662..8d81a17c116 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -64,14 +64,6 @@
64 64
65#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) 65#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1)
66 66
67#define AF9015_GPIO_ON (1 << 0)
68#define AF9015_GPIO_EN (1 << 1)
69#define AF9015_GPIO_O (1 << 2)
70#define AF9015_GPIO_I (1 << 3)
71
72#define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN)
73#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O)
74
75struct req_t { 67struct req_t {
76 u8 cmd; /* [0] */ 68 u8 cmd; /* [0] */
77 /* seq */ /* [1] */ 69 /* seq */ /* [1] */
@@ -120,11 +112,11 @@ struct af9015_config {
120 112
121enum af9015_remote { 113enum af9015_remote {
122 AF9015_REMOTE_NONE = 0, 114 AF9015_REMOTE_NONE = 0,
123 AF9015_REMOTE_A_LINK_DTU_M, 115/* 1 */ AF9015_REMOTE_A_LINK_DTU_M,
124 AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, 116 AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
125 AF9015_REMOTE_MYGICTV_U718, 117 AF9015_REMOTE_MYGICTV_U718,
126 AF9015_REMOTE_DIGITTRADE_DVB_T, 118 AF9015_REMOTE_DIGITTRADE_DVB_T,
127 AF9015_REMOTE_AVERMEDIA_KS, 119/* 5 */ AF9015_REMOTE_AVERMEDIA_KS,
128}; 120};
129 121
130/* Leadtek WinFast DTV Dongle Gold */ 122/* Leadtek WinFast DTV Dongle Gold */
@@ -691,4 +683,67 @@ static u8 af9015_ir_table_digittrade[] = {
691 0x00, 0xff, 0x1d, 0xe2, 0x40, 0x00, 0x00, 683 0x00, 0xff, 0x1d, 0xe2, 0x40, 0x00, 0x00,
692}; 684};
693 685
686/* TREKSTOR DVB-T USB Stick */
687static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = {
688 { 0x07, 0x04, KEY_AGAIN }, /* Home */
689 { 0x07, 0x05, KEY_MUTE }, /* Mute */
690 { 0x07, 0x06, KEY_UP }, /* Up */
691 { 0x07, 0x07, KEY_DOWN }, /* Down */
692 { 0x07, 0x09, KEY_RIGHT }, /* Right */
693 { 0x07, 0x0a, KEY_ENTER }, /* OK */
694 { 0x07, 0x0b, KEY_FASTFORWARD }, /* Fast forward */
695 { 0x07, 0x0c, KEY_REWIND }, /* Rewind */
696 { 0x07, 0x0d, KEY_PLAY }, /* Play/Pause */
697 { 0x07, 0x0e, KEY_VOLUMEUP }, /* Volume + */
698 { 0x07, 0x0f, KEY_VOLUMEDOWN }, /* Volume - */
699 { 0x07, 0x10, KEY_RECORD }, /* Record */
700 { 0x07, 0x11, KEY_STOP }, /* Stop */
701 { 0x07, 0x12, KEY_ZOOM }, /* TV */
702 { 0x07, 0x13, KEY_EPG }, /* Info/EPG */
703 { 0x07, 0x14, KEY_CHANNELDOWN }, /* Channel - */
704 { 0x07, 0x15, KEY_CHANNELUP }, /* Channel + */
705 { 0x07, 0x1e, KEY_1 },
706 { 0x07, 0x1f, KEY_2 },
707 { 0x07, 0x20, KEY_3 },
708 { 0x07, 0x21, KEY_4 },
709 { 0x07, 0x22, KEY_5 },
710 { 0x07, 0x23, KEY_6 },
711 { 0x07, 0x24, KEY_7 },
712 { 0x07, 0x25, KEY_8 },
713 { 0x07, 0x26, KEY_9 },
714 { 0x07, 0x08, KEY_LEFT }, /* LEFT */
715 { 0x07, 0x27, KEY_0 },
716};
717
718static u8 af9015_ir_table_trekstor[] = {
719 0x00, 0xff, 0x86, 0x79, 0x04, 0x07, 0x00,
720 0x00, 0xff, 0x85, 0x7a, 0x05, 0x07, 0x00,
721 0x00, 0xff, 0x87, 0x78, 0x06, 0x07, 0x00,
722 0x00, 0xff, 0x8c, 0x73, 0x07, 0x07, 0x00,
723 0x00, 0xff, 0x89, 0x76, 0x09, 0x07, 0x00,
724 0x00, 0xff, 0x88, 0x77, 0x0a, 0x07, 0x00,
725 0x00, 0xff, 0x8a, 0x75, 0x0b, 0x07, 0x00,
726 0x00, 0xff, 0x9e, 0x61, 0x0c, 0x07, 0x00,
727 0x00, 0xff, 0x8d, 0x72, 0x0d, 0x07, 0x00,
728 0x00, 0xff, 0x8b, 0x74, 0x0e, 0x07, 0x00,
729 0x00, 0xff, 0x9b, 0x64, 0x0f, 0x07, 0x00,
730 0x00, 0xff, 0x9d, 0x62, 0x10, 0x07, 0x00,
731 0x00, 0xff, 0x8e, 0x71, 0x11, 0x07, 0x00,
732 0x00, 0xff, 0x9c, 0x63, 0x12, 0x07, 0x00,
733 0x00, 0xff, 0x8f, 0x70, 0x13, 0x07, 0x00,
734 0x00, 0xff, 0x93, 0x6c, 0x14, 0x07, 0x00,
735 0x00, 0xff, 0x97, 0x68, 0x15, 0x07, 0x00,
736 0x00, 0xff, 0x92, 0x6d, 0x1e, 0x07, 0x00,
737 0x00, 0xff, 0x96, 0x69, 0x1f, 0x07, 0x00,
738 0x00, 0xff, 0x9a, 0x65, 0x20, 0x07, 0x00,
739 0x00, 0xff, 0x91, 0x6e, 0x21, 0x07, 0x00,
740 0x00, 0xff, 0x95, 0x6a, 0x22, 0x07, 0x00,
741 0x00, 0xff, 0x99, 0x66, 0x23, 0x07, 0x00,
742 0x00, 0xff, 0x90, 0x6f, 0x24, 0x07, 0x00,
743 0x00, 0xff, 0x94, 0x6b, 0x25, 0x07, 0x00,
744 0x00, 0xff, 0x98, 0x67, 0x26, 0x07, 0x00,
745 0x00, 0xff, 0x9f, 0x60, 0x08, 0x07, 0x00,
746 0x00, 0xff, 0x84, 0x7b, 0x27, 0x07, 0x00,
747};
748
694#endif 749#endif
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c
index 5862820f109..52badc00e67 100644
--- a/drivers/media/dvb/dvb-usb/ce6230.c
+++ b/drivers/media/dvb/dvb-usb/ce6230.c
@@ -250,6 +250,7 @@ static int ce6230_probe(struct usb_interface *intf,
250 250
251static struct usb_device_id ce6230_table[] = { 251static struct usb_device_id ce6230_table[] = {
252 { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, 252 { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) },
253 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) },
253 { } /* Terminating entry */ 254 { } /* Terminating entry */
254}; 255};
255MODULE_DEVICE_TABLE(usb, ce6230_table); 256MODULE_DEVICE_TABLE(usb, ce6230_table);
@@ -284,13 +285,18 @@ static struct dvb_usb_device_properties ce6230_properties = {
284 285
285 .i2c_algo = &ce6230_i2c_algo, 286 .i2c_algo = &ce6230_i2c_algo,
286 287
287 .num_device_descs = 1, 288 .num_device_descs = 2,
288 .devices = { 289 .devices = {
289 { 290 {
290 .name = "Intel CE9500 reference design", 291 .name = "Intel CE9500 reference design",
291 .cold_ids = {NULL}, 292 .cold_ids = {NULL},
292 .warm_ids = {&ce6230_table[0], NULL}, 293 .warm_ids = {&ce6230_table[0], NULL},
293 }, 294 },
295 {
296 .name = "AVerMedia A310 USB 2.0 DVB-T tuner",
297 .cold_ids = {NULL},
298 .warm_ids = {&ce6230_table[1], NULL},
299 },
294 } 300 }
295}; 301};
296 302
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index dc7ea21cd13..f506c74119f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -65,6 +65,7 @@
65#define USB_PID_AFATECH_AF9005 0x9020 65#define USB_PID_AFATECH_AF9005 0x9020
66#define USB_PID_AFATECH_AF9015_9015 0x9015 66#define USB_PID_AFATECH_AF9015_9015 0x9015
67#define USB_PID_AFATECH_AF9015_9016 0x9016 67#define USB_PID_AFATECH_AF9015_9016 0x9016
68#define USB_PID_TREKSTOR_DVBT 0x901b
68#define USB_VID_ALINK_DTU 0xf170 69#define USB_VID_ALINK_DTU 0xf170
69#define USB_PID_ANSONIC_DVBT_USB 0x6000 70#define USB_PID_ANSONIC_DVBT_USB 0x6000
70#define USB_PID_ANYSEE 0x861f 71#define USB_PID_ANYSEE 0x861f
@@ -102,6 +103,7 @@
102#define USB_PID_KWORLD_399U 0xe399 103#define USB_PID_KWORLD_399U 0xe399
103#define USB_PID_KWORLD_395U 0xe396 104#define USB_PID_KWORLD_395U 0xe396
104#define USB_PID_KWORLD_395U_2 0xe39b 105#define USB_PID_KWORLD_395U_2 0xe39b
106#define USB_PID_KWORLD_395U_3 0xe395
105#define USB_PID_KWORLD_PC160_2T 0xc160 107#define USB_PID_KWORLD_PC160_2T 0xc160
106#define USB_PID_KWORLD_VSTREAM_COLD 0x17de 108#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
107#define USB_PID_KWORLD_VSTREAM_WARM 0x17df 109#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
@@ -167,6 +169,8 @@
167#define USB_PID_AVERMEDIA_VOLAR_X 0xa815 169#define USB_PID_AVERMEDIA_VOLAR_X 0xa815
168#define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 170#define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150
169#define USB_PID_AVERMEDIA_A309 0xa309 171#define USB_PID_AVERMEDIA_A309 0xa309
172#define USB_PID_AVERMEDIA_A310 0xa310
173#define USB_PID_AVERMEDIA_A850 0x850a
170#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 174#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
171#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a 175#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
172#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 176#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 12f7730184a..32526f103b5 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -151,7 +151,7 @@ static void debug_fcp(const u8 *data, int length)
151 subunit_type = data[1] >> 3; 151 subunit_type = data[1] >> 3;
152 subunit_id = data[1] & 7; 152 subunit_id = data[1] & 7;
153 op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; 153 op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
154 printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n", 154 printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
155 prefix, subunit_type, subunit_id, length, 155 prefix, subunit_type, subunit_id, length,
156 debug_fcp_ctype(data[0]), 156 debug_fcp_ctype(data[0]),
157 debug_fcp_opcode(op, data, length)); 157 debug_fcp_opcode(op, data, length));
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index a486a7f81fa..23e4cffeba3 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -513,6 +513,13 @@ config DVB_LGS8GL5
513 help 513 help
514 A DMB-TH tuner module. Say Y when you want to support this frontend. 514 A DMB-TH tuner module. Say Y when you want to support this frontend.
515 515
516config DVB_LGS8GXX
517 tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
518 depends on DVB_CORE && I2C
519 default m if DVB_FE_CUSTOMISE
520 help
521 A DMB-TH tuner module. Say Y when you want to support this frontend.
522
516comment "Tools to develop new frontends" 523comment "Tools to develop new frontends"
517 524
518config DVB_DUMMY_FE 525config DVB_DUMMY_FE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 65a336aa1db..bc2b00abd10 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o
61obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o 61obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
62obj-$(CONFIG_DVB_S5H1411) += s5h1411.o 62obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
63obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o 63obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
64obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
64obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o 65obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
65obj-$(CONFIG_DVB_AF9013) += af9013.o 66obj-$(CONFIG_DVB_AF9013) += af9013.o
66obj-$(CONFIG_DVB_CX24116) += cx24116.o 67obj-$(CONFIG_DVB_CX24116) += cx24116.o
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index d63e1527dc8..9e9a75576a1 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -652,7 +652,7 @@ static int au8522_reset(struct v4l2_subdev *sd, u32 val)
652} 652}
653 653
654static int au8522_s_video_routing(struct v4l2_subdev *sd, 654static int au8522_s_video_routing(struct v4l2_subdev *sd,
655 const struct v4l2_routing *route) 655 u32 input, u32 output, u32 config)
656{ 656{
657 struct au8522_state *state = to_state(sd); 657 struct au8522_state *state = to_state(sd);
658 658
@@ -663,11 +663,11 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd,
663 closed), and then came back to analog mode */ 663 closed), and then came back to analog mode */
664 au8522_writereg(state, 0x106, 1); 664 au8522_writereg(state, 0x106, 1);
665 665
666 if (route->input == AU8522_COMPOSITE_CH1) { 666 if (input == AU8522_COMPOSITE_CH1) {
667 au8522_setup_cvbs_mode(state); 667 au8522_setup_cvbs_mode(state);
668 } else if (route->input == AU8522_SVIDEO_CH13) { 668 } else if (input == AU8522_SVIDEO_CH13) {
669 au8522_setup_svideo_mode(state); 669 au8522_setup_svideo_mode(state);
670 } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { 670 } else if (input == AU8522_COMPOSITE_CH4_SIF) {
671 au8522_setup_cvbs_tuner_mode(state); 671 au8522_setup_cvbs_tuner_mode(state);
672 } else { 672 } else {
673 printk(KERN_ERR "au8522 mode not currently supported\n"); 673 printk(KERN_ERR "au8522 mode not currently supported\n");
@@ -677,10 +677,10 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd,
677} 677}
678 678
679static int au8522_s_audio_routing(struct v4l2_subdev *sd, 679static int au8522_s_audio_routing(struct v4l2_subdev *sd,
680 const struct v4l2_routing *route) 680 u32 input, u32 output, u32 config)
681{ 681{
682 struct au8522_state *state = to_state(sd); 682 struct au8522_state *state = to_state(sd);
683 set_audio_input(state, route->input); 683 set_audio_input(state, input);
684 return 0; 684 return 0;
685} 685}
686 686
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
new file mode 100644
index 00000000000..f9785dfe735
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -0,0 +1,816 @@
1/*
2 * Support for Legend Silicon DMB-TH demodulator
3 * LGS8913, LGS8GL5
4 * experimental support LGS8G42, LGS8G52
5 *
6 * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com>
7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited
8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26#include <asm/div64.h>
27
28#include "dvb_frontend.h"
29
30#include "lgs8gxx.h"
31#include "lgs8gxx_priv.h"
32
33#define dprintk(args...) \
34 do { \
35 if (debug) \
36 printk(KERN_DEBUG "lgs8gxx: " args); \
37 } while (0)
38
39static int debug;
40static int fake_signal_str;
41
42module_param(debug, int, 0644);
43MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
44
45module_param(fake_signal_str, int, 0644);
46MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
47"Signal strength calculation is slow.(default:off).");
48
49/* LGS8GXX internal helper functions */
50
51static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
52{
53 int ret;
54 u8 buf[] = { reg, data };
55 struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
56
57 msg.addr = priv->config->demod_address;
58 if (reg >= 0xC0)
59 msg.addr += 0x02;
60
61 if (debug >= 2)
62 printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
63 __func__, reg, data);
64
65 ret = i2c_transfer(priv->i2c, &msg, 1);
66
67 if (ret != 1)
68 dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
69 __func__, reg, data, ret);
70
71 return (ret != 1) ? -1 : 0;
72}
73
74static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
75{
76 int ret;
77 u8 dev_addr;
78
79 u8 b0[] = { reg };
80 u8 b1[] = { 0 };
81 struct i2c_msg msg[] = {
82 { .flags = 0, .buf = b0, .len = 1 },
83 { .flags = I2C_M_RD, .buf = b1, .len = 1 },
84 };
85
86 dev_addr = priv->config->demod_address;
87 if (reg >= 0xC0)
88 dev_addr += 0x02;
89 msg[1].addr = msg[0].addr = dev_addr;
90
91 ret = i2c_transfer(priv->i2c, msg, 2);
92 if (ret != 2) {
93 dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
94 __func__, reg, ret);
95 return -1;
96 }
97
98 *p_data = b1[0];
99 if (debug >= 2)
100 printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
101 __func__, reg, b1[0]);
102 return 0;
103}
104
105static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
106{
107 lgs8gxx_write_reg(priv, 0x02, 0x00);
108 msleep(1);
109 lgs8gxx_write_reg(priv, 0x02, 0x01);
110 msleep(100);
111
112 return 0;
113}
114
115static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
116{
117 const struct lgs8gxx_config *config = priv->config;
118 u8 if_conf;
119
120 if_conf = 0x10; /* AGC output on; */
121
122 if_conf |=
123 ((config->ext_adc) ? 0x80 : 0x00) |
124 ((config->if_neg_center) ? 0x04 : 0x00) |
125 ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
126 ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) |
127 ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00);
128
129 if (config->ext_adc &&
130 (config->prod == LGS8GXX_PROD_LGS8G52)) {
131 lgs8gxx_write_reg(priv, 0xBA, 0x40);
132 }
133
134 lgs8gxx_write_reg(priv, 0x07, if_conf);
135
136 return 0;
137}
138
139static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
140{
141 u64 val;
142 u32 v32;
143 u32 if_clk;
144
145 if_clk = priv->config->if_clk_freq;
146
147 val = freq;
148 if (freq != 0) {
149 val *= (u64)1 << 32;
150 if (if_clk != 0)
151 do_div(val, if_clk);
152 v32 = val & 0xFFFFFFFF;
153 dprintk("Set IF Freq to %dkHz\n", freq);
154 } else {
155 v32 = 0;
156 dprintk("Set IF Freq to baseband\n");
157 }
158 dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
159
160 lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
161 lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
162 lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
163 lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
164
165 return 0;
166}
167
168static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
169{
170 u8 t;
171
172 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
173 lgs8gxx_write_reg(priv, 0xC6, 0x01);
174
175 lgs8gxx_read_reg(priv, 0x7E, &t);
176 lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
177
178 /* clear FEC self reset */
179 lgs8gxx_read_reg(priv, 0xC5, &t);
180 lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
181
182 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
183 /* FEC auto detect */
184 lgs8gxx_write_reg(priv, 0xC1, 0x03);
185
186 lgs8gxx_read_reg(priv, 0x7C, &t);
187 t = (t & 0x8C) | 0x03;
188 lgs8gxx_write_reg(priv, 0x7C, t);
189 }
190
191
192 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
193 /* BER test mode */
194 lgs8gxx_read_reg(priv, 0xC3, &t);
195 t = (t & 0xEF) | 0x10;
196 lgs8gxx_write_reg(priv, 0xC3, t);
197 }
198
199 if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
200 lgs8gxx_write_reg(priv, 0xD9, 0x40);
201
202 return 0;
203}
204
205static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
206{
207 int ret = 0;
208 u8 t;
209
210 /* turn off auto-detect; manual settings */
211 lgs8gxx_write_reg(priv, 0x7E, 0);
212 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
213 lgs8gxx_write_reg(priv, 0xC1, 0);
214
215 ret = lgs8gxx_read_reg(priv, 0xC5, &t);
216 t = (t & 0xE0) | 0x06;
217 lgs8gxx_write_reg(priv, 0xC5, t);
218
219 lgs8gxx_soft_reset(priv);
220
221 return 0;
222}
223
224static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
225{
226 int ret = 0;
227 u8 t;
228
229 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
230 if (ret != 0)
231 return ret;
232
233 *locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
234 return 0;
235}
236
237static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
238 u8 *finished)
239{
240 int ret = 0;
241 u8 t;
242
243 ret = lgs8gxx_read_reg(priv, 0xA4, &t);
244 if (ret != 0)
245 return ret;
246
247 *finished = ((t & 0x3) == 0x1) ? 1 : 0;
248
249 return 0;
250}
251
252static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked)
253{
254 int err;
255 u8 ad_fini = 0;
256
257 if (gi == GI_945)
258 dprintk("try GI 945\n");
259 else if (gi == GI_595)
260 dprintk("try GI 595\n");
261 else if (gi == GI_420)
262 dprintk("try GI 420\n");
263 lgs8gxx_write_reg(priv, 0x04, gi);
264 lgs8gxx_soft_reset(priv);
265 msleep(50);
266 err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
267 if (err != 0)
268 return err;
269 if (ad_fini) {
270 err = lgs8gxx_is_locked(priv, locked);
271 if (err != 0)
272 return err;
273 }
274
275 return 0;
276}
277
278static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
279 u8 *detected_param, u8 *gi)
280{
281 int i, j;
282 int err = 0;
283 u8 locked = 0, tmp_gi;
284
285 dprintk("%s\n", __func__);
286
287 lgs8gxx_set_mode_auto(priv);
288 /* Guard Interval */
289 lgs8gxx_write_reg(priv, 0x03, 00);
290
291 for (i = 0; i < 2; i++) {
292 for (j = 0; j < 2; j++) {
293 tmp_gi = GI_945;
294 err = lgs8gxx_autolock_gi(priv, GI_945, &locked);
295 if (err)
296 goto out;
297 if (locked)
298 goto locked;
299 }
300 for (j = 0; j < 2; j++) {
301 tmp_gi = GI_420;
302 err = lgs8gxx_autolock_gi(priv, GI_420, &locked);
303 if (err)
304 goto out;
305 if (locked)
306 goto locked;
307 }
308 tmp_gi = GI_595;
309 err = lgs8gxx_autolock_gi(priv, GI_595, &locked);
310 if (err)
311 goto out;
312 if (locked)
313 goto locked;
314 }
315
316locked:
317 if ((err == 0) && (locked == 1)) {
318 u8 t;
319
320 lgs8gxx_read_reg(priv, 0xA2, &t);
321 *detected_param = t;
322
323 if (tmp_gi == GI_945)
324 dprintk("GI 945 locked\n");
325 else if (tmp_gi == GI_595)
326 dprintk("GI 595 locked\n");
327 else if (tmp_gi == GI_420)
328 dprintk("GI 420 locked\n");
329 *gi = tmp_gi;
330 }
331 if (!locked)
332 err = -1;
333
334out:
335 return err;
336}
337
338static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
339{
340 s8 err;
341 u8 gi = 0x2;
342 u8 detected_param = 0;
343
344 err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
345
346 if (err != 0) {
347 dprintk("lgs8gxx_auto_detect failed\n");
348 }
349
350 /* Apply detected parameters */
351 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
352 u8 inter_leave_len = detected_param & TIM_MASK ;
353 inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40;
354 detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK;
355 detected_param |= inter_leave_len;
356 }
357 lgs8gxx_write_reg(priv, 0x7D, detected_param);
358 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
359 lgs8gxx_write_reg(priv, 0xC0, detected_param);
360 /* lgs8gxx_soft_reset(priv); */
361
362 /* Enter manual mode */
363 lgs8gxx_set_mode_manual(priv);
364
365 switch (gi) {
366 case GI_945:
367 priv->curr_gi = 945; break;
368 case GI_595:
369 priv->curr_gi = 595; break;
370 case GI_420:
371 priv->curr_gi = 420; break;
372 default:
373 priv->curr_gi = 945; break;
374 }
375}
376
377static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
378 u8 serial, u8 clk_pol, u8 clk_gated)
379{
380 int ret = 0;
381 u8 t;
382
383 ret = lgs8gxx_read_reg(priv, 0xC2, &t);
384 if (ret != 0)
385 return ret;
386
387 t &= 0xF8;
388 t |= serial ? TS_SERIAL : TS_PARALLEL;
389 t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
390 t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
391
392 ret = lgs8gxx_write_reg(priv, 0xC2, t);
393 if (ret != 0)
394 return ret;
395
396 return 0;
397}
398
399
400/* LGS8913 demod frontend functions */
401
402static int lgs8913_init(struct lgs8gxx_state *priv)
403{
404 u8 t;
405
406 /* LGS8913 specific */
407 lgs8gxx_write_reg(priv, 0xc1, 0x3);
408
409 lgs8gxx_read_reg(priv, 0x7c, &t);
410 lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
411
412 /* LGS8913 specific */
413 lgs8gxx_read_reg(priv, 0xc3, &t);
414 lgs8gxx_write_reg(priv, 0xc3, t&0x10);
415
416
417 return 0;
418}
419
420static int lgs8gxx_init(struct dvb_frontend *fe)
421{
422 struct lgs8gxx_state *priv =
423 (struct lgs8gxx_state *)fe->demodulator_priv;
424 const struct lgs8gxx_config *config = priv->config;
425 u8 data = 0;
426 s8 err;
427 dprintk("%s\n", __func__);
428
429 lgs8gxx_read_reg(priv, 0, &data);
430 dprintk("reg 0 = 0x%02X\n", data);
431
432 /* Setup MPEG output format */
433 err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
434 config->ts_clk_pol,
435 config->ts_clk_gated);
436 if (err != 0)
437 return -EIO;
438
439 if (config->prod == LGS8GXX_PROD_LGS8913)
440 lgs8913_init(priv);
441 lgs8gxx_set_if_freq(priv, priv->config->if_freq);
442 if (config->prod != LGS8GXX_PROD_LGS8913)
443 lgs8gxx_set_ad_mode(priv);
444
445 return 0;
446}
447
448static void lgs8gxx_release(struct dvb_frontend *fe)
449{
450 struct lgs8gxx_state *state = fe->demodulator_priv;
451 dprintk("%s\n", __func__);
452
453 kfree(state);
454}
455
456
457static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len)
458{
459 struct lgs8gxx_state *priv = fe->demodulator_priv;
460
461 if (len != 2)
462 return -EINVAL;
463
464 return lgs8gxx_write_reg(priv, buf[0], buf[1]);
465}
466
467static int lgs8gxx_set_fe(struct dvb_frontend *fe,
468 struct dvb_frontend_parameters *fe_params)
469{
470 struct lgs8gxx_state *priv = fe->demodulator_priv;
471
472 dprintk("%s\n", __func__);
473
474 /* set frequency */
475 if (fe->ops.tuner_ops.set_params) {
476 fe->ops.tuner_ops.set_params(fe, fe_params);
477 if (fe->ops.i2c_gate_ctrl)
478 fe->ops.i2c_gate_ctrl(fe, 0);
479 }
480
481 /* start auto lock */
482 lgs8gxx_auto_lock(priv);
483
484 msleep(10);
485
486 return 0;
487}
488
489static int lgs8gxx_get_fe(struct dvb_frontend *fe,
490 struct dvb_frontend_parameters *fe_params)
491{
492 struct lgs8gxx_state *priv = fe->demodulator_priv;
493 u8 t;
494
495 dprintk("%s\n", __func__);
496
497 /* TODO: get real readings from device */
498 /* inversion status */
499 fe_params->inversion = INVERSION_OFF;
500
501 /* bandwidth */
502 fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
503
504
505 lgs8gxx_read_reg(priv, 0x7D, &t);
506 fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
507 fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
508
509 /* constellation */
510 switch (t & SC_MASK) {
511 case SC_QAM64:
512 fe_params->u.ofdm.constellation = QAM_64;
513 break;
514 case SC_QAM32:
515 fe_params->u.ofdm.constellation = QAM_32;
516 break;
517 case SC_QAM16:
518 fe_params->u.ofdm.constellation = QAM_16;
519 break;
520 case SC_QAM4:
521 case SC_QAM4NR:
522 fe_params->u.ofdm.constellation = QPSK;
523 break;
524 default:
525 fe_params->u.ofdm.constellation = QAM_64;
526 }
527
528 /* transmission mode */
529 fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
530
531 /* guard interval */
532 fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
533
534 /* hierarchy */
535 fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
536
537 return 0;
538}
539
540static
541int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
542 struct dvb_frontend_tune_settings *fesettings)
543{
544 /* FIXME: copy from tda1004x.c */
545 fesettings->min_delay_ms = 800;
546 fesettings->step_size = 0;
547 fesettings->max_drift = 0;
548 return 0;
549}
550
551static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
552{
553 struct lgs8gxx_state *priv = fe->demodulator_priv;
554 s8 ret;
555 u8 t;
556
557 dprintk("%s\n", __func__);
558
559 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
560 if (ret != 0)
561 return -EIO;
562
563 dprintk("Reg 0x4B: 0x%02X\n", t);
564
565 *fe_status = 0;
566 if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
567 if ((t & 0x40) == 0x40)
568 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
569 if ((t & 0x80) == 0x80)
570 *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
571 FE_HAS_LOCK;
572 } else {
573 if ((t & 0x80) == 0x80)
574 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
575 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
576 }
577
578 /* success */
579 dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
580 return 0;
581}
582
583static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
584{
585 u16 v;
586 u8 agc_lvl[2], cat;
587
588 dprintk("%s()\n", __func__);
589 lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
590 lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
591
592 v = agc_lvl[0];
593 v <<= 8;
594 v |= agc_lvl[1];
595
596 dprintk("agc_lvl: 0x%04X\n", v);
597
598 if (v < 0x100)
599 cat = 0;
600 else if (v < 0x190)
601 cat = 5;
602 else if (v < 0x2A8)
603 cat = 4;
604 else if (v < 0x381)
605 cat = 3;
606 else if (v < 0x400)
607 cat = 2;
608 else if (v == 0x400)
609 cat = 1;
610 else
611 cat = 0;
612
613 *signal = cat;
614
615 return 0;
616}
617
618static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
619{
620 u8 t; s8 ret;
621 s16 max_strength = 0;
622 u8 str;
623 u16 i, gi = priv->curr_gi;
624
625 dprintk("%s\n", __func__);
626
627 ret = lgs8gxx_read_reg(priv, 0x4B, &t);
628 if (ret != 0)
629 return -EIO;
630
631 if (fake_signal_str) {
632 if ((t & 0xC0) == 0xC0) {
633 dprintk("Fake signal strength as 50\n");
634 *signal = 0x32;
635 } else
636 *signal = 0;
637 return 0;
638 }
639
640 dprintk("gi = %d\n", gi);
641 for (i = 0; i < gi; i++) {
642
643 if ((i & 0xFF) == 0)
644 lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
645 lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
646
647 lgs8gxx_read_reg(priv, 0x94, &str);
648 if (max_strength < str)
649 max_strength = str;
650 }
651
652 *signal = max_strength;
653 dprintk("%s: signal=0x%02X\n", __func__, *signal);
654
655 lgs8gxx_read_reg(priv, 0x95, &t);
656 dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
657
658 return 0;
659}
660
661static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
662{
663 struct lgs8gxx_state *priv = fe->demodulator_priv;
664
665 if (priv->config->prod == LGS8GXX_PROD_LGS8913)
666 return lgs8913_read_signal_strength(priv, signal);
667 else
668 return lgs8gxx_read_signal_agc(priv, signal);
669}
670
671static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
672{
673 struct lgs8gxx_state *priv = fe->demodulator_priv;
674 u8 t;
675 *snr = 0;
676
677 lgs8gxx_read_reg(priv, 0x95, &t);
678 dprintk("AVG Noise=0x%02X\n", t);
679 *snr = 256 - t;
680 *snr <<= 8;
681 dprintk("snr=0x%x\n", *snr);
682
683 return 0;
684}
685
686static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
687{
688 *ucblocks = 0;
689 dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
690 return 0;
691}
692
693static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
694{
695 struct lgs8gxx_state *priv = fe->demodulator_priv;
696 u8 r0, r1, r2, r3;
697 u32 total_cnt, err_cnt;
698
699 dprintk("%s\n", __func__);
700
701 lgs8gxx_write_reg(priv, 0xc6, 0x01);
702 lgs8gxx_write_reg(priv, 0xc6, 0x41);
703 lgs8gxx_write_reg(priv, 0xc6, 0x01);
704
705 msleep(200);
706
707 lgs8gxx_write_reg(priv, 0xc6, 0x81);
708 lgs8gxx_read_reg(priv, 0xd0, &r0);
709 lgs8gxx_read_reg(priv, 0xd1, &r1);
710 lgs8gxx_read_reg(priv, 0xd2, &r2);
711 lgs8gxx_read_reg(priv, 0xd3, &r3);
712 total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0);
713 lgs8gxx_read_reg(priv, 0xd4, &r0);
714 lgs8gxx_read_reg(priv, 0xd5, &r1);
715 lgs8gxx_read_reg(priv, 0xd6, &r2);
716 lgs8gxx_read_reg(priv, 0xd7, &r3);
717 err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0);
718 dprintk("error=%d total=%d\n", err_cnt, total_cnt);
719
720 if (total_cnt == 0)
721 *ber = 0;
722 else
723 *ber = err_cnt * 100 / total_cnt;
724
725 dprintk("%s: ber=0x%x\n", __func__, *ber);
726 return 0;
727}
728
729static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
730{
731 struct lgs8gxx_state *priv = fe->demodulator_priv;
732
733 if (priv->config->tuner_address == 0)
734 return 0;
735 if (enable) {
736 u8 v = 0x80 | priv->config->tuner_address;
737 return lgs8gxx_write_reg(priv, 0x01, v);
738 }
739 return lgs8gxx_write_reg(priv, 0x01, 0);
740}
741
742static struct dvb_frontend_ops lgs8gxx_ops = {
743 .info = {
744 .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
745 .type = FE_OFDM,
746 .frequency_min = 474000000,
747 .frequency_max = 858000000,
748 .frequency_stepsize = 10000,
749 .caps =
750 FE_CAN_FEC_AUTO |
751 FE_CAN_QAM_AUTO |
752 FE_CAN_TRANSMISSION_MODE_AUTO |
753 FE_CAN_GUARD_INTERVAL_AUTO
754 },
755
756 .release = lgs8gxx_release,
757
758 .init = lgs8gxx_init,
759 .write = lgs8gxx_write,
760 .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
761
762 .set_frontend = lgs8gxx_set_fe,
763 .get_frontend = lgs8gxx_get_fe,
764 .get_tune_settings = lgs8gxx_get_tune_settings,
765
766 .read_status = lgs8gxx_read_status,
767 .read_ber = lgs8gxx_read_ber,
768 .read_signal_strength = lgs8gxx_read_signal_strength,
769 .read_snr = lgs8gxx_read_snr,
770 .read_ucblocks = lgs8gxx_read_ucblocks,
771};
772
773struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
774 struct i2c_adapter *i2c)
775{
776 struct lgs8gxx_state *priv = NULL;
777 u8 data = 0;
778
779 dprintk("%s()\n", __func__);
780
781 if (config == NULL || i2c == NULL)
782 return NULL;
783
784 priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
785 if (priv == NULL)
786 goto error_out;
787
788 priv->config = config;
789 priv->i2c = i2c;
790
791 /* check if the demod is there */
792 if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
793 dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
794 __func__, priv->config->demod_address);
795 goto error_out;
796 }
797
798 lgs8gxx_read_reg(priv, 1, &data);
799
800 memcpy(&priv->frontend.ops, &lgs8gxx_ops,
801 sizeof(struct dvb_frontend_ops));
802 priv->frontend.demodulator_priv = priv;
803
804 return &priv->frontend;
805
806error_out:
807 dprintk("%s() error_out\n", __func__);
808 kfree(priv);
809 return NULL;
810
811}
812EXPORT_SYMBOL(lgs8gxx_attach);
813
814MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
815MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
816MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb/frontends/lgs8gxx.h
new file mode 100644
index 00000000000..321d366a830
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgs8gxx.h
@@ -0,0 +1,90 @@
1/*
2 * Support for Legend Silicon DMB-TH demodulator
3 * LGS8913, LGS8GL5
4 * experimental support LGS8G42, LGS8G52
5 *
6 * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com>
7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited
8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26#ifndef __LGS8GXX_H__
27#define __LGS8GXX_H__
28
29#include <linux/dvb/frontend.h>
30#include <linux/i2c.h>
31
32#define LGS8GXX_PROD_LGS8913 0
33#define LGS8GXX_PROD_LGS8GL5 1
34#define LGS8GXX_PROD_LGS8G42 3
35#define LGS8GXX_PROD_LGS8G52 4
36#define LGS8GXX_PROD_LGS8G54 5
37
38struct lgs8gxx_config {
39
40 /* product type */
41 u8 prod;
42
43 /* the demodulator's i2c address */
44 u8 demod_address;
45
46 /* parallel or serial transport stream */
47 u8 serial_ts;
48
49 /* transport stream polarity*/
50 u8 ts_clk_pol;
51
52 /* transport stream clock gated by ts_valid */
53 u8 ts_clk_gated;
54
55 /* A/D Clock frequency */
56 u32 if_clk_freq; /* in kHz */
57
58 /* IF frequency */
59 u32 if_freq; /* in kHz */
60
61 /*Use External ADC*/
62 u8 ext_adc;
63
64 /*External ADC output two's complement*/
65 u8 adc_signed;
66
67 /*Sample IF data at falling edge of IF_CLK*/
68 u8 if_neg_edge;
69
70 /*IF use Negative center frequency*/
71 u8 if_neg_center;
72
73 /* slave address and configuration of the tuner */
74 u8 tuner_address;
75};
76
77#if defined(CONFIG_DVB_LGS8GXX) || \
78 (defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE))
79extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
80 struct i2c_adapter *i2c);
81#else
82static inline
83struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
84 struct i2c_adapter *i2c) {
85 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
86 return NULL;
87}
88#endif /* CONFIG_DVB_LGS8GXX */
89
90#endif /* __LGS8GXX_H__ */
diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb/frontends/lgs8gxx_priv.h
new file mode 100644
index 00000000000..9776d30686d
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgs8gxx_priv.h
@@ -0,0 +1,70 @@
1/*
2 * Support for Legend Silicon DMB-TH demodulator
3 * LGS8913, LGS8GL5
4 * experimental support LGS8G42, LGS8G52
5 *
6 * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com>
7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited
8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26#ifndef LGS8913_PRIV_H
27#define LGS8913_PRIV_H
28
29struct lgs8gxx_state {
30 struct i2c_adapter *i2c;
31 /* configuration settings */
32 const struct lgs8gxx_config *config;
33 struct dvb_frontend frontend;
34 u16 curr_gi; /* current guard interval */
35};
36
37#define SC_MASK 0x1C /* Sub-Carrier Modulation Mask */
38#define SC_QAM64 0x10 /* 64QAM modulation */
39#define SC_QAM32 0x0C /* 32QAM modulation */
40#define SC_QAM16 0x08 /* 16QAM modulation */
41#define SC_QAM4NR 0x04 /* 4QAM modulation */
42#define SC_QAM4 0x00 /* 4QAM modulation */
43
44#define LGS_FEC_MASK 0x03 /* FEC Rate Mask */
45#define LGS_FEC_0_4 0x00 /* FEC Rate 0.4 */
46#define LGS_FEC_0_6 0x01 /* FEC Rate 0.6 */
47#define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */
48
49#define TIM_MASK 0x20 /* Time Interleave Length Mask */
50#define TIM_LONG 0x00 /* Time Interleave Length = 720 */
51#define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */
52
53#define CF_MASK 0x80 /* Control Frame Mask */
54#define CF_EN 0x80 /* Control Frame On */
55
56#define GI_MASK 0x03 /* Guard Interval Mask */
57#define GI_420 0x00 /* 1/9 Guard Interval */
58#define GI_595 0x01 /* */
59#define GI_945 0x02 /* 1/4 Guard Interval */
60
61
62#define TS_PARALLEL 0x00 /* Parallel TS Output a.k.a. SPI */
63#define TS_SERIAL 0x01 /* Serial TS Output a.k.a. SSI */
64#define TS_CLK_NORMAL 0x00 /* MPEG Clock Normal */
65#define TS_CLK_INVERTED 0x02 /* MPEG Clock Inverted */
66#define TS_CLK_GATED 0x00 /* MPEG clock gated */
67#define TS_CLK_FREERUN 0x04 /* MPEG clock free running*/
68
69
70#endif
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index ee89623be85..598eaf8acc6 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -616,7 +616,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
616 /* enable interrupts */ 616 /* enable interrupts */
617 pci_write_config_dword(pdev, 0x6c, 0x8000); 617 pci_write_config_dword(pdev, 0x6c, 0x8000);
618 618
619 ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 619 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
620 if (ret < 0) 620 if (ret < 0)
621 goto err_pci_disable_device; 621 goto err_pci_disable_device;
622 622