mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	Compare commits
	
		
			82 Commits
		
	
	
		
			0.9.38pre1
			...
			0.9.38pre3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ccc13aed48 | ||
|  | 442b1c3bf6 | ||
|  | c23435e275 | ||
|  | 0fe2c2feb3 | ||
|  | 8f5af7742d | ||
|  | 4a93d1056a | ||
|  | 309713674c | ||
|  | bfddf62f64 | ||
|  | 2b0e5eb9d2 | ||
|  | 1d96274993 | ||
|  | 3ff4d900a5 | ||
|  | e1e569975f | ||
|  | b9998ee9e2 | ||
|  | dfe6b385a9 | ||
|  | 6e926c1452 | ||
|  | 8039097426 | ||
|  | f3d5adc777 | ||
|  | e974925430 | ||
|  | 23bdd90595 | ||
|  | 7bafb76461 | ||
|  | 9cde52a6d8 | ||
|  | 50e354c49a | ||
|  | 03d84ba75a | ||
|  | c4f82de8b0 | ||
|  | a5ad0b0584 | ||
|  | 3cb3df51cf | ||
|  | 2311b94970 | ||
|  | f12fe91b51 | ||
|  | 35c283bf2f | ||
|  | 41a9626be4 | ||
|  | 0d66d5bab0 | ||
|  | 91af1be97e | ||
|  | a6c3b82f83 | ||
|  | e863a2037a | ||
|  | 92cd675f5d | ||
|  | dda8698514 | ||
|  | fc9a89c870 | ||
|  | 4b0a0c4ff2 | ||
|  | 2ac970ef83 | ||
|  | c3c734b0e8 | ||
|  | 8380cb185f | ||
|  | f9eb03a065 | ||
|  | f8c97ad3d6 | ||
|  | 60646a6b26 | ||
|  | de0e970999 | ||
|  | cf35c3038b | ||
|  | 4c96f54ddf | ||
|  | eb427a8df2 | ||
|  | b200ce3596 | ||
|  | 31f36de0d7 | ||
|  | 9269270c79 | ||
|  | 04fa5041d3 | ||
|  | 8f4cd19539 | ||
|  | f3cbbf3ba7 | ||
|  | a2d39f90d5 | ||
|  | 7af71dfdcb | ||
|  | acb5931ed0 | ||
|  | 476a105de7 | ||
|  | b025599e9f | ||
|  | 9028e75f63 | ||
|  | 177e6b0fd6 | ||
|  | de82a50b4e | ||
|  | 5714b85238 | ||
|  | 01ca1b8805 | ||
|  | 28e09191af | ||
|  | abb2c56ddc | ||
|  | c6ada48892 | ||
|  | baf6a090b8 | ||
|  | d259d69808 | ||
|  | f72c7b2256 | ||
|  | c82c9d3218 | ||
|  | 1598ab98bc | ||
|  | 7efa935a30 | ||
|  | fc728ab51e | ||
|  | ea41e57ba3 | ||
|  | cd3868afff | ||
|  | b72f0365ea | ||
|  | b3f2580e84 | ||
|  | f1976b5f74 | ||
|  | ee6787d2d0 | ||
|  | 37eb11fb4b | ||
|  | a276a370cb | 
| @@ -6,6 +6,9 @@ We can only accept patches which don't break compilation for older kernels (as f | |||||||
| Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain | Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain | ||||||
| incompatiblities to this driver package. | incompatiblities to this driver package. | ||||||
|  |  | ||||||
|  | For installation instructions see: | ||||||
|  |  | ||||||
|  | http://support.digital-devices.eu/index.php?article=152 | ||||||
| ### Prepare for Building | ### Prepare for Building | ||||||
|  |  | ||||||
|    TBD |    TBD | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 | all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo | ||||||
|  |  | ||||||
| cit: cit.c | cit: cit.c | ||||||
| 	$(CC) -o cit cit.c -lpthread | 	$(CC) -o cit cit.c -lpthread | ||||||
| @@ -15,6 +15,12 @@ setmod2: setmod2.c | |||||||
| setmod3: setmod3.c | setmod3: setmod3.c | ||||||
| 	$(CC) -o setmod3 setmod3.c -I../include/ | 	$(CC) -o setmod3 setmod3.c -I../include/ | ||||||
|  |  | ||||||
| %.o: %.c | modconfig: modconfig.c | ||||||
| 	$(CC) $(CFLAGS) -o $@ $< | 	$(CC) -o modconfig modconfig.c -I../include/ | ||||||
|  |  | ||||||
|  | %: %.c | ||||||
|  | 	$(CC) $(CFLAGS) -I../ddbridge  -I../include/ $< -o $@ | ||||||
|  |  | ||||||
|  | %.o: %.c | ||||||
|  | 	$(CC) $(CFLAGS) -I../ddbridge -o $@ $< | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ | |||||||
| #include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||||
| #include <linux/dvb/dmx.h> | #include <linux/dvb/dmx.h> | ||||||
| #include <linux/dvb/frontend.h> | #include <linux/dvb/frontend.h> | ||||||
| #include <linux/dvb/video.h> |  | ||||||
|  |  | ||||||
| void proc_ts(int i, uint8_t *buf) | void proc_ts(int i, uint8_t *buf) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										499
									
								
								apps/ddinfo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										499
									
								
								apps/ddinfo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,499 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <getopt.h> | ||||||
|  |  | ||||||
|  | typedef uint8_t u8; | ||||||
|  | typedef uint16_t u16; | ||||||
|  | typedef int16_t s16; | ||||||
|  | typedef uint32_t u32; | ||||||
|  | typedef uint64_t u64; | ||||||
|  |  | ||||||
|  | #include "../ddbridge/ddbridge-mci.h" | ||||||
|  | #include "../ddbridge/ddbridge-ioctl.h" | ||||||
|  |  | ||||||
|  | char *Rolloff[8] = { | ||||||
|  | 	"0.35", | ||||||
|  | 	"0.25", | ||||||
|  | 	"0.20", | ||||||
|  | 	"0.10", | ||||||
|  | 	"0.05", | ||||||
|  | 	"0.15", | ||||||
|  | 	"rsvd", | ||||||
|  | 	"rsvd", | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void print_temp(struct mci_result *res) | ||||||
|  | { | ||||||
|  | 	printf("Die temperature = %u\n", res->sx8_bist.temperature); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int temp_info(int dev, uint32_t link) | ||||||
|  | { | ||||||
|  | 	struct ddb_mci_msg msg = { | ||||||
|  | 		.link = link, | ||||||
|  | 		.cmd.command = SX8_CMD_GETBIST, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 	int i; | ||||||
|  | 	 | ||||||
|  | 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		printf("Error: %d %d\n", ret, errno); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	if (msg.res.status & 0x80) { | ||||||
|  | 		printf("MCI errror %02x\n", msg.res.status); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 		 | ||||||
|  | 	print_temp(&msg.res); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0])) | ||||||
|  |  | ||||||
|  | char *DemodStatus[] = { | ||||||
|  |     "Idle", | ||||||
|  |     "IQ Mode", | ||||||
|  |     "Wait for Signal", | ||||||
|  |     "DVB-S2 Wait for MATYPE", | ||||||
|  |     "DVB-S2 Wait for FEC", | ||||||
|  |     "DVB-S1 Wait for FEC", | ||||||
|  |     "Wait for TS", | ||||||
|  |     "Unknown 7", | ||||||
|  |     "Unknown 8", | ||||||
|  |     "Unknown 9", | ||||||
|  |     "Unknown 10", | ||||||
|  |     "Unknown 11", | ||||||
|  |     "Unknown 12", | ||||||
|  |     "Unknown 13", | ||||||
|  |     "Timeout", | ||||||
|  |     "Locked", | ||||||
|  |     "C2 Scan", | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | char* S2ModCods[32] = { | ||||||
|  | /* 0x00 */    "DummyPL"     ,  | ||||||
|  |  | ||||||
|  | // Legacy S2:   index is S2_Modcod * 2 + short | ||||||
|  |  | ||||||
|  | /* 0x01 */    "QPSK 1/4"    , | ||||||
|  | /* 0x02 */    "QPSK 1/3"    , | ||||||
|  | /* 0x03 */    "QPSK 2/5"    , | ||||||
|  | /* 0x04 */    "QPSK 1/2"    , | ||||||
|  | /* 0x05 */    "QPSK 3/5"    , | ||||||
|  | /* 0x06 */    "QPSK 2/3"    , | ||||||
|  | /* 0x07 */    "QPSK 3/4"    , | ||||||
|  | /* 0x08 */    "QPSK 4/5"    , | ||||||
|  | /* 0x09 */    "QPSK 5/6"    , | ||||||
|  | /* 0x0A */    "QPSK 8/9"    , | ||||||
|  | /* 0x0B */    "QPSK 9/10"   , | ||||||
|  |                               | ||||||
|  | /* 0x0C */    "8PSK 3/5"    , | ||||||
|  | /* 0x0D */    "8PSK 2/3"    , | ||||||
|  | /* 0x0E */    "8PSK 3/4"    , | ||||||
|  | /* 0x0F */    "8PSK 5/6"    , | ||||||
|  | /* 0x10 */    "8PSK 8/9"    , | ||||||
|  | /* 0x11 */    "8PSK 9/10"   , | ||||||
|  |                               | ||||||
|  | /* 0x12 */    "16APSK 2/3"  , | ||||||
|  | /* 0x13 */    "16APSK 3/4"  , | ||||||
|  | /* 0x14 */    "16APSK 4/5"  , | ||||||
|  | /* 0x15 */    "16APSK 5/6"  , | ||||||
|  | /* 0x16 */    "16APSK 8/9"  , | ||||||
|  | /* 0x17 */    "16APSK 9/10" , | ||||||
|  |                               | ||||||
|  | /* 0x18 */    "32APSK 3/4"  , | ||||||
|  | /* 0x19 */    "32APSK 4/5"  , | ||||||
|  | /* 0x1A */    "32APSK 5/6"  , | ||||||
|  | /* 0x1B */    "32APSK 8/9"  , | ||||||
|  | /* 0x1C */    "32APSK 9/10" , | ||||||
|  |                               | ||||||
|  | /* 0x1D */    "rsvd 0x1D"   , | ||||||
|  | /* 0x1E */    "rsvd 0x1E"   , | ||||||
|  | /* 0x1F */    "rsvd 0x1F"   , | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ///* 129 */    "VLSNR1"          ,   | ||||||
|  | ///* 131 */    "VLSNR2"          ,   | ||||||
|  |  | ||||||
|  | char* S2XModCods[59] = { | ||||||
|  | /* 0x42 */    "QPSK 13/45"      ,  | ||||||
|  | /* 0x43 */    "QPSK 9/20"       ,  | ||||||
|  | /* 0x44 */    "QPSK 11/20"      ,  | ||||||
|  |                                    | ||||||
|  | /* 0x45 */    "8APSK 5/9-L"     ,  | ||||||
|  | /* 0x46 */    "8APSK 26/45-L"   ,  | ||||||
|  | /* 0x47 */    "8PSK 23/36"      ,  | ||||||
|  | /* 0x48 */    "8PSK 25/36"      ,  | ||||||
|  | /* 0x49 */    "8PSK 13/18"      ,  | ||||||
|  |                                    | ||||||
|  | /* 0x4A */    "16APSK 1/2-L"    ,  | ||||||
|  | /* 0x4B */    "16APSK 8/15-L"   ,  | ||||||
|  | /* 0x4C */    "16APSK 5/9-L"    ,  | ||||||
|  | /* 0x4D */    "16APSK 26/45"    ,  | ||||||
|  | /* 0x4E */    "16APSK 3/5"      ,  | ||||||
|  | /* 0x4F */    "16APSK 3/5-L"    ,  | ||||||
|  | /* 0x50 */    "16APSK 28/45"    ,  | ||||||
|  | /* 0x51 */    "16APSK 23/36"    ,  | ||||||
|  | /* 0x52 */    "16APSK 2/3-L"    ,  | ||||||
|  | /* 0x53 */    "16APSK 25/36"    ,  | ||||||
|  | /* 0x54 */    "16APSK 13/18"    ,  | ||||||
|  |                                    | ||||||
|  | /* 0x55 */    "16APSK 7/9"      ,  | ||||||
|  | /* 0x56 */    "16APSK 77/90"    ,  | ||||||
|  |                                    | ||||||
|  | /* 0x57 */    "32APSK 2/3-L"    ,  | ||||||
|  | /* 0x58 */    "rsvd 32APSK"     ,  | ||||||
|  | /* 0x59 */    "32APSK 32/45"    ,  | ||||||
|  | /* 0x5A */    "32APSK 11/15"    ,  | ||||||
|  | /* 0x5B */    "32APSK 7/9"      ,  | ||||||
|  |                                    | ||||||
|  | /* 0x5C */    "64APSK 32/45-L"  ,  | ||||||
|  | /* 0x5D */    "64APSK 11/15"    ,  | ||||||
|  | /* 0x5E */    "rsvd 64APSK"     ,  | ||||||
|  | /* 0x5F */    "64APSK 7/9"      ,  | ||||||
|  |                                    | ||||||
|  | /* 0x60 */    "rsvd 64APSK"     ,  | ||||||
|  | /* 0x61 */    "64APSK 4/5"      ,  | ||||||
|  | /* 0x62 */    "rsvd 64APSK"     ,  | ||||||
|  | /* 0x63 */    "64APSK 5/6"      ,  | ||||||
|  |                                    | ||||||
|  | /* 0x64 */    "128APSK 3/4"     ,  | ||||||
|  | /* 0x65 */    "128APSK 7/9"     ,  | ||||||
|  |  | ||||||
|  | /* 0x66 */    "256APSK 29/45-L" ,  | ||||||
|  | /* 0x67 */    "256APSK 2/3-L"   ,  | ||||||
|  | /* 0x68 */    "256APSK 31/45-L" ,  | ||||||
|  | /* 0x69 */    "256APSK 32/45"   ,  | ||||||
|  | /* 0x6A */    "256APSK 11/15-L" ,  | ||||||
|  | /* 0x6B */    "256APSK 3/4"     ,  | ||||||
|  |  | ||||||
|  | /* 0x6C */    "QPSK 11/45-S"    , | ||||||
|  | /* 0x6D */    "QPSK 4/15-S"     , | ||||||
|  | /* 0x6E */    "QPSK 14/45-S"    , | ||||||
|  | /* 0x6F */    "QPSK 7/15-S"     , | ||||||
|  | /* 0x70 */    "QPSK 8/15-S"     , | ||||||
|  | /* 0x71 */    "QPSK 32/45-S"    , | ||||||
|  |                                   | ||||||
|  | /* 0x72 */    "8PSK 7/15-S"     , | ||||||
|  | /* 0x73 */    "8PSK 8/15-S"     , | ||||||
|  | /* 0x74 */    "8PSK 26/45-S"    , | ||||||
|  | /* 0x75 */    "8PSK 32/45-S"    , | ||||||
|  |                                   | ||||||
|  | /* 0x76 */    "16APSK 7/15-S"   , | ||||||
|  | /* 0x77 */    "16APSK 8/15-S"   , | ||||||
|  | /* 0x78 */    "16APSK 26/45-S"  , | ||||||
|  | /* 0x79 */    "16APSK 3/5-S"    , | ||||||
|  | /* 0x7A */    "16APSK 32/45-S"  , | ||||||
|  |                                   | ||||||
|  | /* 0x7B */    "32APSK 2/3-S"    , | ||||||
|  | /* 0x7C */    "32APSK 32/45-S"  , | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | char* S2Xrsvd[] = { | ||||||
|  | /* 250 */    "rsvd 8PSK"       , | ||||||
|  | /* 251 */    "rsvd 16APSK"     , | ||||||
|  | /* 252 */    "rsvd 32APSK"     , | ||||||
|  | /* 253 */    "rsvd 64APSK"     , | ||||||
|  | /* 254 */    "rsvd 256APSK"    , | ||||||
|  | /* 255 */    "rsvd 1024APSK"   , | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | char* PunctureRates[32] = { | ||||||
|  | /* 0x00 */    "QPSK 1/2",   // DVB-S1  | ||||||
|  | /* 0x01 */    "QPSK 2/3",   // DVB-S1  | ||||||
|  | /* 0x02 */    "QPSK 3/4",   // DVB-S1  | ||||||
|  | /* 0x03 */    "QPSK 5/6",   // DVB-S1  | ||||||
|  | /* 0x04 */    "QPSK 6/7",   // DSS | ||||||
|  | /* 0x05 */    "QPSK 7/8",   // DVB-S1  | ||||||
|  | /* 0x06 */    "rsvd 6.0", | ||||||
|  | /* 0x07 */    "rsvd 7.0", | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void print_info(struct mci_result *res, uint8_t demod) | ||||||
|  | { | ||||||
|  | 	if (res->status == MCI_DEMOD_STOPPED) { | ||||||
|  | 		printf("\nDemod %u: stopped\n", demod); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	printf("\nDemod %u:\n", demod); | ||||||
|  | 	if (res->status == MCI_DEMOD_LOCKED) { | ||||||
|  | 		switch (res->mode) { | ||||||
|  | 		case M4_MODE_DVBSX: | ||||||
|  | 			if (res->dvbs2_signal_info.standard == 2) { | ||||||
|  | 				int short_frame = 0, pilots = 0; | ||||||
|  | 				char *modcod = "unknown"; | ||||||
|  | 				uint8_t pls = res->dvbs2_signal_info.pls_code; | ||||||
|  | 				 | ||||||
|  | 				if ((pls >= 128) || ((res->dvbs2_signal_info.roll_off & 0x7f) > 2)) | ||||||
|  | 					printf("Demod Locked:  DVB-S2X\n"); | ||||||
|  | 				else | ||||||
|  | 					printf("Demod Locked:  DVB-S2\n"); | ||||||
|  | 				printf("PLS-Code:      %u\n", res->dvbs2_signal_info.pls_code); | ||||||
|  | 				if (pls >= 250)  { | ||||||
|  | 					pilots = 1; | ||||||
|  | 					modcod = S2Xrsvd[pls - 250]; | ||||||
|  | 				} else if (pls >= 132) { | ||||||
|  | 					pilots = pls & 1; | ||||||
|  | 					short_frame = pls > 216; | ||||||
|  | 					modcod = S2XModCods[(pls - 132)/2]; | ||||||
|  | 				} else if (pls < 128) { | ||||||
|  | 					pilots = pls & 1; | ||||||
|  | 					short_frame = pls & 2; | ||||||
|  | 					modcod = S2ModCods[pls / 4]; | ||||||
|  | 				} | ||||||
|  | 				printf("Roll-Off:      %s\n", Rolloff[res->dvbs2_signal_info.roll_off & 7]); | ||||||
|  | 				printf("Pilots:        %s\n", pilots ? "On" : "Off"); | ||||||
|  | 				printf("Frame:         %s\n", short_frame ? "Short" : "Long"); | ||||||
|  | 			} else { | ||||||
|  | 				printf("Demod Locked:  DVB-S\n"); | ||||||
|  | 				printf("PR:            %s\n", | ||||||
|  | 				       PunctureRates[res->dvbs2_signal_info.pls_code & 0x07]); | ||||||
|  | 			} | ||||||
|  | 			printf("Inversion:     %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off"); | ||||||
|  | 		case M4_MODE_DVBT: | ||||||
|  | 			printf("Locked DVB-T\n"); | ||||||
|  | 			break; | ||||||
|  | 		case M4_MODE_DVBT2: | ||||||
|  | 			printf("Locked DVB-T2\n"); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		printf("SNR:           %.2f dB\n", (float) res->dvbs2_signal_info.signal_to_noise / 100); | ||||||
|  | 		printf("Packet Errors: %u\n", res->dvbs2_signal_info.packet_errors); | ||||||
|  | 		printf("BER Numerator: %u\n", res->dvbs2_signal_info.ber_numerator); | ||||||
|  | 		printf("BER Denom.:    %u\n", res->dvbs2_signal_info.ber_denominator); | ||||||
|  | 	} else { | ||||||
|  | 		printf("Demod State:   %s\n", | ||||||
|  | 		       res->status < SIZE_OF_ARRAY(DemodStatus) ? DemodStatus[res->status] : "?"); | ||||||
|  | 		 | ||||||
|  | 	} | ||||||
|  | 	printf("Frequency:     %u Hz\n", res->dvbs2_signal_info.frequency); | ||||||
|  | 	printf("Symbol Rate:   %u Symbols/s\n", res->dvbs2_signal_info.symbol_rate); | ||||||
|  | 	printf("Channel Power: %.2f dBm\n", (float) res->dvbs2_signal_info.channel_power / 100); | ||||||
|  | 	if (res->dvbs2_signal_info.band_power > -10000) | ||||||
|  | 		printf("Band Power:    %.2f dBm\n", (float) res->dvbs2_signal_info.band_power / 100); | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int readreg(int dev, uint32_t reg, uint32_t link, uint32_t *val) | ||||||
|  | { | ||||||
|  | 	struct ddb_reg ddbreg; | ||||||
|  |  | ||||||
|  |         ddbreg.reg =  reg + (link << 28); | ||||||
|  | 	if (ioctl(dev, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 	*val = ddbreg.val; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void mci_firmware(int dev, uint32_t link) | ||||||
|  | { | ||||||
|  | 	union { | ||||||
|  | 		uint32_t u[4]; | ||||||
|  | 		char  s[16]; | ||||||
|  | 	} version; | ||||||
|  | 	 | ||||||
|  | 	readreg(dev, MIC_INTERFACE_VER     , link, &version.u[0]); | ||||||
|  | 	readreg(dev, MIC_INTERFACE_VER +  4, link, &version.u[1]); | ||||||
|  | 	readreg(dev, MIC_INTERFACE_VER +  8, link, &version.u[2]); | ||||||
|  | 	readreg(dev, MIC_INTERFACE_VER + 12, link, &version.u[3]); | ||||||
|  |      | ||||||
|  | 	printf("MCI firmware: %s.%d\n", &version.s, version.s[15]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int mci_info(int dev, uint32_t link, uint8_t demod) | ||||||
|  | { | ||||||
|  | 	struct ddb_mci_msg msg = { | ||||||
|  | 		.link = link, | ||||||
|  | 		.cmd.command = MCI_CMD_GETSIGNALINFO, | ||||||
|  | 		.cmd.demod = demod | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 	int i; | ||||||
|  | 	 | ||||||
|  | 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		printf("Error: %d %d\n", ret, errno); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	print_info(&msg.res, demod); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int get_id(int fd, int link, struct ddb_id *id) | ||||||
|  | { | ||||||
|  | 	struct ddb_reg ddbreg; | ||||||
|  |  | ||||||
|  | 	if (link == 0) { | ||||||
|  | 		if (ioctl(fd, IOCTL_DDB_ID, id) < 0) | ||||||
|  | 			return -1; | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |         ddbreg.reg = 8 + (link << 28); | ||||||
|  | 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 	id->vendor = ddbreg.val; | ||||||
|  | 	id->device = ddbreg.val >> 16; | ||||||
|  |  | ||||||
|  |         ddbreg.reg = 12 + (link << 28); | ||||||
|  | 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 	id->subvendor = ddbreg.val; | ||||||
|  | 	id->subdevice = ddbreg.val >> 16; | ||||||
|  |  | ||||||
|  |         ddbreg.reg = 0 + (link << 28); | ||||||
|  | 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 	id->hw = ddbreg.val; | ||||||
|  |  | ||||||
|  | 	ddbreg.reg = 4 + (link << 28); | ||||||
|  | 	if (ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 	id->regmap = ddbreg.val; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *id2name(uint16_t id) | ||||||
|  | { | ||||||
|  | 	switch (id) { | ||||||
|  | 	case 0x222: | ||||||
|  | 		return "MOD"; | ||||||
|  | 	case 0x0009: | ||||||
|  | 		return "MAX SX8"; | ||||||
|  | 	case 0x000b: | ||||||
|  | 		return "MAX SX8 Basic"; | ||||||
|  | 	case 0x000a: | ||||||
|  | 		return "MAX M4"; | ||||||
|  | 	default: | ||||||
|  | 		return " "; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int card_info(int ddbnum, int demod) | ||||||
|  | { | ||||||
|  | 	char ddbname[80]; | ||||||
|  | 	struct ddb_id ddbid; | ||||||
|  | 	int ddb, ret, link, links = 1, i; | ||||||
|  | 	struct ddb_id id; | ||||||
|  | 	 | ||||||
|  | 	sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum); | ||||||
|  | 	ddb = open(ddbname, O_RDWR); | ||||||
|  | 	if (ddb < 0) | ||||||
|  | 		return -3; | ||||||
|  |  | ||||||
|  | 	for (link = 0; link < links; link++) { | ||||||
|  | 		ret = get_id(ddb, link, &id); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			goto out; | ||||||
|  | 		if (!link) { | ||||||
|  | 			switch (id.device) { | ||||||
|  | 			case 0x20: | ||||||
|  | 				links = 4; | ||||||
|  | 				break; | ||||||
|  | 			case 0x300: | ||||||
|  | 			case 0x301: | ||||||
|  | 			case 0x307: | ||||||
|  | 				links = 2; | ||||||
|  | 				break; | ||||||
|  | 			 | ||||||
|  | 			default: | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		printf("\n\nCard %s link %u id %04x (%s):\n", | ||||||
|  | 		       ddbname, link, id.device, id2name(id.device)); | ||||||
|  | 		printf("HW %08x REGMAP %08x FW %u.%u\n", | ||||||
|  | 		       id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff)); | ||||||
|  | 		switch (id.device) { | ||||||
|  | 		case 0x0009: | ||||||
|  | 			mci_firmware(ddb, link); | ||||||
|  | 			if (demod >= 0) | ||||||
|  | 				mci_info(ddb, link, demod); | ||||||
|  | 			else { | ||||||
|  | 				for (i = 0; i < 8; i++) | ||||||
|  | 					mci_info(ddb, link, i); | ||||||
|  | 			} | ||||||
|  | 			temp_info(ddb, link); | ||||||
|  | 			break; | ||||||
|  | 		case 0x000a: | ||||||
|  | 			mci_firmware(ddb, link); | ||||||
|  | 			if (demod >= 0) | ||||||
|  | 				mci_info(ddb, link, demod); | ||||||
|  | 			else { | ||||||
|  | 				for (i = 0; i < 4; i++) | ||||||
|  | 					mci_info(ddb, link, i); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | out: | ||||||
|  | 	close(ddb); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char*argv[]) | ||||||
|  | { | ||||||
|  | 	int fd = -1, all = 1, i, ret = 0; | ||||||
|  | 	char fn[128]; | ||||||
|  | 	int32_t device = -1, demod = -1; | ||||||
|  | 	 | ||||||
|  | 	while (1) { | ||||||
|  | 		int cur_optind = optind ? optind : 1; | ||||||
|  | 		int option_index = 0; | ||||||
|  | 		int c; | ||||||
|  | 		static struct option long_options[] = { | ||||||
|  | 			{"device", required_argument, 0, 'd'}, | ||||||
|  | 			{"demod", required_argument, 0, 'n'}, | ||||||
|  | 			{0, 0, 0, 0} | ||||||
|  | 		}; | ||||||
|  |                 c = getopt_long(argc, argv, "ad:n:", | ||||||
|  | 				long_options, &option_index); | ||||||
|  | 		if (c == -1) | ||||||
|  | 			break; | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'd': | ||||||
|  | 			device = strtoul(optarg, NULL, 0); | ||||||
|  | 			break; | ||||||
|  | 		case 'n': | ||||||
|  | 			demod = strtoul(optarg, NULL, 0); | ||||||
|  | 			break; | ||||||
|  | 		case 'a': | ||||||
|  | 			all = 1; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (optind < argc) { | ||||||
|  | 		printf("too many arguments\n"); | ||||||
|  | 		exit(1); | ||||||
|  | 	} | ||||||
|  | 	if (device >=0) | ||||||
|  | 		ret = card_info(device, demod); | ||||||
|  | 	else | ||||||
|  | 		for (i = 0; i < 100; i++) { | ||||||
|  | 			ret = card_info(i, -1); | ||||||
|  | 			 | ||||||
|  | 			if (ret == -3)     /* could not open, no more cards! */ | ||||||
|  | 				break;  | ||||||
|  | 			if (ret < 0) | ||||||
|  | 				return i; /* fatal error */  | ||||||
|  | 		} | ||||||
|  | } | ||||||
							
								
								
									
										392
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,392 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <getopt.h> | ||||||
|  | #include <ctype.h> | ||||||
|  |  | ||||||
|  | typedef uint8_t u8; | ||||||
|  | typedef uint16_t u16; | ||||||
|  | typedef int16_t s16; | ||||||
|  | typedef uint32_t u32; | ||||||
|  | typedef uint64_t u64; | ||||||
|  |  | ||||||
|  | #include "../ddbridge/ddbridge-mci.h" | ||||||
|  | #include "../ddbridge/ddbridge-ioctl.h" | ||||||
|  |  | ||||||
|  | struct mconf { | ||||||
|  | 	int set_output; | ||||||
|  | 	int set_channels; | ||||||
|  | 	int fd; | ||||||
|  |  | ||||||
|  | 	struct mci_command channels; | ||||||
|  | 	struct mci_command stream; | ||||||
|  | 	struct mci_command output; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void strim(char *s) | ||||||
|  | { | ||||||
|  | 	int l = strlen(s); | ||||||
|  |  | ||||||
|  | 	while (l && isspace(s[l-1])) | ||||||
|  | 		l--; | ||||||
|  | 	s[l] = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *)) | ||||||
|  | { | ||||||
|  | 	char line[256], csec[80], par[80], val[80], *p; | ||||||
|  | 	FILE *f; | ||||||
|  |  | ||||||
|  | 	if ((f = fopen(fname, "r")) == NULL) | ||||||
|  | 		return; | ||||||
|  | 	while ((p = fgets(line, sizeof(line), f))) { | ||||||
|  | 		if (*p == '\r' || *p == '\n' || *p == '#') | ||||||
|  | 			continue; | ||||||
|  | 		if (*p == '[') { | ||||||
|  | 			if ((p = strtok(line + 1, "]")) == NULL) | ||||||
|  | 				continue; | ||||||
|  | 			strncpy(csec, p, sizeof(csec)); | ||||||
|  | 			if (!strcmp(sec, csec) && cb) | ||||||
|  | 				cb(priv, NULL, NULL); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (!(p = strtok(line, "="))) | ||||||
|  | 			continue; | ||||||
|  | 		while (isspace(*p)) | ||||||
|  | 			p++; | ||||||
|  | 		strncpy(par, p, sizeof(par)); | ||||||
|  | 		strim(par); | ||||||
|  | 		if (!(p = strtok(NULL, "="))) | ||||||
|  | 			continue; | ||||||
|  | 		while (isspace(*p)) | ||||||
|  | 			p++; | ||||||
|  | 		strncpy (val, p, sizeof(val)); | ||||||
|  | 		strim(val); | ||||||
|  | 		if (!strcmp(sec, csec) && cb) | ||||||
|  | 			cb(priv, par, val); | ||||||
|  | 	} | ||||||
|  | 	if (!strcmp(sec, csec) && cb) | ||||||
|  | 		cb(priv, NULL, NULL); | ||||||
|  | 	fclose(f); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct param_table_entry { | ||||||
|  | 	int value; | ||||||
|  | 	char* name; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct param_table_entry mod_standard_table[] = { | ||||||
|  | 	{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC }, | ||||||
|  | 	{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 }, | ||||||
|  | 	{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 }, | ||||||
|  | 	{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 }, | ||||||
|  | 	{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 }, | ||||||
|  | 	{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 }, | ||||||
|  | 	{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 }, | ||||||
|  | 	{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 }, | ||||||
|  | 	{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 }, | ||||||
|  | 	{ .name = "0", .value = MOD_STANDARD_GENERIC }, | ||||||
|  | 	{ .name = "1", .value = MOD_STANDARD_DVBT_8 }, | ||||||
|  | 	{ .name = "2", .value = MOD_STANDARD_DVBT_7 }, | ||||||
|  | 	{ .name = "3", .value = MOD_STANDARD_DVBT_6 }, | ||||||
|  | 	{ .name = "4", .value = MOD_STANDARD_DVBT_5 }, | ||||||
|  | 	{ .name = NULL, .value = 0 } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct param_table_entry stream_format_table[] = { | ||||||
|  | 	{ .name = "default", .value = MOD_FORMAT_DEFAULT }, | ||||||
|  | 	{ .name = "IQ16", .value = MOD_FORMAT_IQ16 }, | ||||||
|  | 	{ .name = "IQ8", .value = MOD_FORMAT_IQ8 }, | ||||||
|  | 	{ .name = "IDX8", .value = MOD_FORMAT_IDX8 }, | ||||||
|  | 	{ .name = "TS", .value = MOD_FORMAT_TS }, | ||||||
|  | 	{ .name = "0", .value = MOD_FORMAT_DEFAULT }, | ||||||
|  | 	{ .name = "1", .value = MOD_FORMAT_IQ16 }, | ||||||
|  | 	{ .name = "2", .value = MOD_FORMAT_IQ8 }, | ||||||
|  | 	{ .name = "3", .value = MOD_FORMAT_IDX8 }, | ||||||
|  | 	{ .name = "4", .value = MOD_FORMAT_TS }, | ||||||
|  | 	{ .name = NULL, .value = 0 } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct param_table_entry guard_interval_table[] = { | ||||||
|  | 	{ .name = "1/32", .value = MOD_DVBT_GI_1_32 }, | ||||||
|  | 	{ .name = "1/16", .value = MOD_DVBT_GI_1_16 }, | ||||||
|  | 	{ .name = "1/8", .value = MOD_DVBT_GI_1_8	 }, | ||||||
|  | 	{ .name = "1/4", .value = MOD_DVBT_GI_1_4	 }, | ||||||
|  | 	{ .name = "0", .value = MOD_DVBT_GI_1_32 }, | ||||||
|  | 	{ .name = "1", .value = MOD_DVBT_GI_1_16 }, | ||||||
|  | 	{ .name = "2", .value = MOD_DVBT_GI_1_8	 }, | ||||||
|  | 	{ .name = "3", .value = MOD_DVBT_GI_1_4	 }, | ||||||
|  | 	{ .name = NULL, .value = 0 } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct param_table_entry puncture_rate_table[] = { | ||||||
|  | 	{ .name = "1/2", .value = MOD_DVBT_PR_1_2 }, | ||||||
|  | 	{ .name = "2/3", .value = MOD_DVBT_PR_2_3 }, | ||||||
|  | 	{ .name = "3/4", .value = MOD_DVBT_PR_3_4 }, | ||||||
|  | 	{ .name = "5/6", .value = MOD_DVBT_PR_5_6 }, | ||||||
|  | 	{ .name = "7/8", .value = MOD_DVBT_PR_7_8 }, | ||||||
|  | 	{ .name = "1", .value = MOD_DVBT_PR_1_2 }, | ||||||
|  | 	{ .name = "2", .value = MOD_DVBT_PR_2_3 }, | ||||||
|  | 	{ .name = "3", .value = MOD_DVBT_PR_3_4 }, | ||||||
|  | 	{ .name = "5", .value = MOD_DVBT_PR_5_6 }, | ||||||
|  | 	{ .name = "7", .value = MOD_DVBT_PR_7_8 }, | ||||||
|  | 	{ .name = NULL, .value = 0 } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct param_table_entry dvbt_constellation_table[] = { | ||||||
|  | 	{ .name = "0", .value = MOD_DVBT_QPSK }, | ||||||
|  | 	{ .name = "qpsk", .value = MOD_DVBT_QPSK }, | ||||||
|  | 	{ .name = "1", .value = MOD_DVBT_16QAM }, | ||||||
|  | 	{ .name = "16qam", .value = MOD_DVBT_16QAM }, | ||||||
|  | 	{ .name = "qam16", .value = MOD_DVBT_16QAM }, | ||||||
|  | 	{ .name = "2", .value = MOD_DVBT_64QAM }, | ||||||
|  | 	{ .name = "64qam", .value = MOD_DVBT_64QAM }, | ||||||
|  | 	{ .name = "qam64", .value = MOD_DVBT_64QAM }, | ||||||
|  | 	{ .name = NULL, .value = 0 } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int parse_param(char *val,struct param_table_entry *table, int *value) { | ||||||
|  | 	if (value) { | ||||||
|  | 		*value = 0; | ||||||
|  | 		if (table) { | ||||||
|  | 			while (table->name) { | ||||||
|  | 				if( !strcasecmp(val,table->name)) { | ||||||
|  | 					*value = table->value; | ||||||
|  | 					return 0; | ||||||
|  | 				} | ||||||
|  | 				table++; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int mci_cmd(int dev, struct mci_command *cmd) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	struct ddb_mci_msg msg; | ||||||
|  | 	uint8_t status; | ||||||
|  |  | ||||||
|  | 	msg.link = 0; | ||||||
|  | 	memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); | ||||||
|  | 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		dprintf(2, "mci_cmd error %d\n", errno); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	status = msg.res.status; | ||||||
|  | 	if (status == MCI_STATUS_OK) | ||||||
|  | 		return ret; | ||||||
|  | 	if (status == MCI_STATUS_UNSUPPORTED) { | ||||||
|  | 		dprintf(2, "Unsupported MCI command\n"); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	if (status == MCI_STATUS_INVALID_PARAMETER) { | ||||||
|  | 		dprintf(2, "Invalid MCI parameters\n"); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct mci_command msg_channels = { | ||||||
|  | 	.mod_command = MOD_SETUP_CHANNELS, | ||||||
|  | 	.mod_channel = 0, | ||||||
|  | 	.mod_stream = 0, | ||||||
|  | 	.mod_setup_channels[0] = { | ||||||
|  | 		.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID, | ||||||
|  | 		.standard = MOD_STANDARD_DVBT_8, | ||||||
|  | 		.num_channels = 25, | ||||||
|  | 		.frequency = 474000000, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mci_command msg_stream = { | ||||||
|  | 	.mod_command = MOD_SETUP_STREAM, | ||||||
|  | 	.mod_channel = 1, | ||||||
|  | 	.mod_stream = 0, | ||||||
|  | 	.mod_setup_stream = { | ||||||
|  | 		.standard = MOD_STANDARD_DVBT_8, | ||||||
|  | 		.fft_size = 1, | ||||||
|  | 		.guard_interval = 0, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mci_command msg_output = { | ||||||
|  | 	.mod_command = MOD_SETUP_OUTPUT, | ||||||
|  | 	.mod_channel = 0, | ||||||
|  | 	.mod_stream = 0, | ||||||
|  | 	.mod_setup_output = { | ||||||
|  | 		.connector = MOD_CONNECTOR_F, | ||||||
|  | 		.num_channels = 16, | ||||||
|  | 		.unit = MOD_UNIT_DBUV, | ||||||
|  | 		.channel_power = 5000, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void output_cb(void *priv, char *par, char *val) | ||||||
|  | { | ||||||
|  | 	struct mconf *mc = (struct mconf *) priv; | ||||||
|  |  | ||||||
|  | 	if (!par && !val) { | ||||||
|  | 		mc->set_output = 1; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (!strcasecmp(par, "connector")) { | ||||||
|  | 		if (!strcasecmp(val, "F")) { | ||||||
|  | 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_F; | ||||||
|  | 		} else if (!strcasecmp(val, "SMA")) { | ||||||
|  | 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_SMA; | ||||||
|  | 		} else if (!strcasecmp(val, "OFF")) { | ||||||
|  | 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_OFF; | ||||||
|  | 		} else | ||||||
|  | 			printf("invalid connector\n"); | ||||||
|  | 	} else if (!strcasecmp(par, "power")) { | ||||||
|  | 		mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0); | ||||||
|  | 	} else if (!strcasecmp(par, "channels")) { | ||||||
|  | 		mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10); | ||||||
|  | 	}else if (!strcasecmp(par, "unit")) { | ||||||
|  | 		if (!strcasecmp(val, "DBUV")) { | ||||||
|  | 			mc->output.mod_setup_output.unit = MOD_UNIT_DBUV; | ||||||
|  | 		} else if (!strcasecmp(val, "DBM")) { | ||||||
|  | 			mc->output.mod_setup_output.unit = MOD_UNIT_DBM; | ||||||
|  | 		} else | ||||||
|  | 			printf("invalid unit\n"); | ||||||
|  | 	} else | ||||||
|  | 		printf("invalid output parameter: %s\n", par); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void channels_cb(void *priv, char *par, char *val) | ||||||
|  | { | ||||||
|  | 	struct mconf *mc = (struct mconf *) priv; | ||||||
|  | 	int value; | ||||||
|  |  | ||||||
|  | 	if (!par && !val) { | ||||||
|  | 		mc->set_channels = 1; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (!strcasecmp(par, "frequency")) { | ||||||
|  | 		mc->channels.mod_setup_channels[0].frequency =	(uint32_t) (strtod(val, NULL) * 1000000.0); | ||||||
|  | 		printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency); | ||||||
|  | 	} else if (!strcasecmp(par, "channels")) { | ||||||
|  | 		mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10); | ||||||
|  | 	} else if (!strcasecmp(par, "standard")) { | ||||||
|  | 		if (!parse_param(val,mod_standard_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_channels[0].standard = value; | ||||||
|  | 	} else if (!strcasecmp(par, "offset")) { | ||||||
|  | 		mc->channels.mod_setup_channels[0].offset =	 (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||||
|  | 	} else if (!strcasecmp(par, "bandwidth")) { | ||||||
|  | 		mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||||
|  | 		mc->channels.mod_setup_channels[0].offset = | ||||||
|  | 			mc->channels.mod_setup_channels[0].bandwidth / 2; | ||||||
|  | 	} else | ||||||
|  | 		printf("invalid channels parameter: %s\n", par); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void streams_cb(void *priv, char *par, char *val) | ||||||
|  | { | ||||||
|  | 	struct mconf *mc = (struct mconf *) priv; | ||||||
|  | 	int value; | ||||||
|  |  | ||||||
|  | 	if (!par && !val) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (!strcasecmp(par, "fft_size")) { | ||||||
|  | 		mc->stream.mod_setup_stream.fft_size = strtol(val, NULL, 10); | ||||||
|  | 	} else if (!strcasecmp(par, "guard_interval")) { | ||||||
|  | 		if (!parse_param(val,guard_interval_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_stream.guard_interval = value; | ||||||
|  | 	} else if (!strcasecmp(par, "puncture_rate")) { | ||||||
|  | 		if (!parse_param(val,puncture_rate_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_stream.puncture_rate = value; | ||||||
|  | 	} else if (!strcasecmp(par, "constellation")) { | ||||||
|  | 		if (!parse_param(val,dvbt_constellation_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_stream.constellation = value; | ||||||
|  | 	} else if (!strcasecmp(par, "cell_identifier")) { | ||||||
|  | 		mc->stream.mod_setup_stream.cell_identifier = strtol(val, NULL, 0); | ||||||
|  | 	} else if (!strcasecmp(par, "standard")) { | ||||||
|  | 		if (!parse_param(val,mod_standard_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_stream.standard = value; | ||||||
|  | 	} else if (!strcasecmp(par, "stream_format")) { | ||||||
|  | 		if (!parse_param(val,stream_format_table,&value)) | ||||||
|  | 			mc->stream.mod_setup_stream.stream_format = value; | ||||||
|  | 	} else if (!strcasecmp(par, "symbol_rate")) { | ||||||
|  | 		mc->stream.mod_setup_stream.symbol_rate = (uint32_t) (strtod(val, NULL) * 1000000.0); | ||||||
|  | 	} else if (!strcasecmp(par, "channel")) { | ||||||
|  | 		mc->stream.mod_channel = strtol(val, NULL, 10); | ||||||
|  | 	} else if (!strcasecmp(par, "stream")) { | ||||||
|  | 		mc->stream.mod_stream = strtol(val, NULL, 10); | ||||||
|  | 		printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel); | ||||||
|  | 		mci_cmd(mc->fd, &mc->stream); | ||||||
|  | 	} else | ||||||
|  | 		printf("invalid streams parameter: %s = %s\n", par, val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char*argv[]) | ||||||
|  | { | ||||||
|  | 	int fd = -1; | ||||||
|  | 	char fn[128]; | ||||||
|  | 	uint32_t device = 0; | ||||||
|  | 	uint32_t frequency = 0; | ||||||
|  | 	char *configname = "modulator.conf"; | ||||||
|  | 	struct mconf mc; | ||||||
|  |  | ||||||
|  | 	memset(&mc, 0, sizeof(mc)); | ||||||
|  | 	mc.channels = msg_channels; | ||||||
|  | 	mc.stream = msg_stream; | ||||||
|  | 	mc.output = msg_output; | ||||||
|  |  | ||||||
|  | 	while (1) { | ||||||
|  | 		int cur_optind = optind ? optind : 1; | ||||||
|  | 		int option_index = 0; | ||||||
|  | 		int c; | ||||||
|  | 		static struct option long_options[] = { | ||||||
|  | 			{"device", required_argument, 0, 'd'}, | ||||||
|  | 			{"config", required_argument, 0, 'c'}, | ||||||
|  | 			{"help", no_argument, 0, 'h'}, | ||||||
|  | 			{0, 0, 0, 0} | ||||||
|  | 		}; | ||||||
|  | 								c = getopt_long(argc, argv, "d:c:", | ||||||
|  | 				long_options, &option_index); | ||||||
|  | 		if (c == -1) | ||||||
|  | 			break; | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'd': | ||||||
|  | 			device = strtoul(optarg, NULL, 0); | ||||||
|  | 			break; | ||||||
|  | 		case 'c': | ||||||
|  | 			configname = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 			dprintf(2, "modconfig [-d device_number] [-c config_file]\n"); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (optind < argc) { | ||||||
|  | 		printf("too many arguments\n"); | ||||||
|  | 		exit(1); | ||||||
|  | 	} | ||||||
|  | 	snprintf(fn, 127, "/dev/ddbridge/card%u", device); | ||||||
|  | 	fd = open(fn, O_RDWR); | ||||||
|  | 	if (fd < 0) { | ||||||
|  | 		dprintf(2, "Could not open %s\n", fn); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	mc.fd = fd; | ||||||
|  | 	parse(configname, "channels", (void *) &mc, channels_cb); | ||||||
|  | 	if (mc.set_channels) | ||||||
|  | 		mci_cmd(fd, &mc.channels); | ||||||
|  | 	parse(configname, "streams", (void *) &mc, streams_cb); | ||||||
|  | 	parse(configname, "output", (void *) &mc, output_cb); | ||||||
|  | 	if (mc.set_output) | ||||||
|  | 		mci_cmd(fd, &mc.output); | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								apps/modulator.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								apps/modulator.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | [output] | ||||||
|  | # connector = OFF, SMA or F | ||||||
|  | connector = F | ||||||
|  | # number of total channels to be used at the same time | ||||||
|  | # use lower number to have fewer channels but stronger signal per channel | ||||||
|  | channels = 16 | ||||||
|  | # unit of power in DBUV or DBM | ||||||
|  | unit = DBUV | ||||||
|  | # power output in units of above unit | ||||||
|  | power = 50.0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # define channels: | ||||||
|  | # channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned | ||||||
|  |  | ||||||
|  | [channels] | ||||||
|  | # standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz  | ||||||
|  | standard = 1 | ||||||
|  |  | ||||||
|  | # numbers of channels to allocate, starting from frequency below | ||||||
|  | # this defines 25 channels at 474, 474+8, 474+16, etc. Mhz | ||||||
|  | channels = 25 | ||||||
|  | # frequency of channel 0, following channels are spaced according to set standard | ||||||
|  | frequency = 474.0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | [streams] | ||||||
|  | # number of streams depends on the card hardware | ||||||
|  | # streams correspond to devices mod0, mod1, ... | ||||||
|  | # channels are defined above in channels section | ||||||
|  |  | ||||||
|  | # 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4  | ||||||
|  | guard_interval = 0 | ||||||
|  | # 0 = 2K, 1 = 8K  (2K not yet supported) | ||||||
|  | fft_size = 1 | ||||||
|  |  | ||||||
|  | # all following streams will be set according to the last set other parameters | ||||||
|  |  | ||||||
|  | # example: | ||||||
|  | # this would set mod 1 to 474 MHz and mod0 to 482 MHz (474 + 8 MHz) | ||||||
|  | # both with guard interval 1/32 and 8K FFT | ||||||
|  | # and mod2 to 490MHz, guard interval 1/16 and 8K FFT | ||||||
|  | channel = 1 | ||||||
|  | stream = 0 | ||||||
|  | # | ||||||
|  | channel = 0 | ||||||
|  | stream = 1 | ||||||
|  | # | ||||||
|  | guard_interval = 1 | ||||||
|  | channel = 2 | ||||||
|  | stream = 2 | ||||||
| @@ -119,7 +119,7 @@ static int update_flash(struct ddflash *ddf) | |||||||
| 			printf("Flash:    %s\n", ddf->flash_name); | 			printf("Flash:    %s\n", ddf->flash_name); | ||||||
| 		printf("Version:  %08x\n", ddf->id.hw); | 		printf("Version:  %08x\n", ddf->id.hw); | ||||||
| 		printf("REGMAP :  %08x\n", ddf->id.regmap); | 		printf("REGMAP :  %08x\n", ddf->id.regmap); | ||||||
| 		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1) | 		if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1) | ||||||
| 			stat |= 1; | 			stat |= 1; | ||||||
| 		return stat; | 		return stat; | ||||||
| 	} | 	} | ||||||
| @@ -200,6 +200,7 @@ static int usage() | |||||||
| 	       "-n N\n  only update card N (default with N=0)\n\n" | 	       "-n N\n  only update card N (default with N=0)\n\n" | ||||||
| 	       "-a \n   update all cards\n\n" | 	       "-a \n   update all cards\n\n" | ||||||
| 	       "-b file\n  fpga image file override (ignored if -a is used)\n\n" | 	       "-b file\n  fpga image file override (ignored if -a is used)\n\n" | ||||||
|  | 	       "-f  \n  force  update\n\n" | ||||||
| 	       "-v \n   more verbose (up to -v -v -v)\n\n" | 	       "-v \n   more verbose (up to -v -v -v)\n\n" | ||||||
| 		); | 		); | ||||||
| } | } | ||||||
| @@ -250,7 +251,7 @@ int main(int argc, char **argv) | |||||||
| 			break; | 			break; | ||||||
| 		case 'h': | 		case 'h': | ||||||
| 			usage(); | 			usage(); | ||||||
| 			break; | 			return 0; | ||||||
| 		default: | 		default: | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -50,15 +50,15 @@ struct flash_info flashs[] = { | |||||||
| 	{ { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" }, | 	{ { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" }, | ||||||
| 	{ { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" }, | 	{ { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" }, | ||||||
| 	{ { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" }, | 	{ { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" }, | ||||||
| 	{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, | 	{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" }, | ||||||
| 	{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, | 	{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" }, | ||||||
| 	{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, | 	{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" }, | ||||||
| 	{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, | 	{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" }, | ||||||
| 	{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, | 	{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" }, | ||||||
| 	{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, | 	{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" }, | ||||||
| 	{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, | 	{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" }, | ||||||
| 	{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, | 	{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" }, | ||||||
| 	{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D  64 MBit" }, | 	{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" }, | ||||||
| 	{ { 0x00, 0x00, 0x00 }, UNKNOWN_FLASH, 0, 0, "Unknown" }, | 	{ { 0x00, 0x00, 0x00 }, UNKNOWN_FLASH, 0, 0, "Unknown" }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -68,7 +68,7 @@ static struct flash_info *flash_getinfo(uint8_t *id) | |||||||
|  |  | ||||||
| 	while (f->id[0]) { | 	while (f->id[0]) { | ||||||
| 		if ((f->id[0] == id[0]) && (f->id[1] == id[1]) && | 		if ((f->id[0] == id[0]) && (f->id[1] == id[1]) && | ||||||
| 		    ((id[0] == 0xff) || (f->id[0] == id[0]))) | 		    ((id[2] == 0xff) || (f->id[2] == id[2]))) | ||||||
| 			break; | 			break; | ||||||
| 		f++; | 		f++; | ||||||
| 	} | 	} | ||||||
| @@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, | |||||||
| 		return -1; | 		return -1; | ||||||
| 	len = off - fw_off; | 	len = off - fw_off; | ||||||
| 	lseek(fs, fw_off, SEEK_SET); | 	lseek(fs, fw_off, SEEK_SET); | ||||||
| #if 0 |  | ||||||
| 	if (len > maxlen) { | 	if (len > maxlen) { | ||||||
| 		printf("file too big\n"); | 		printf("file too big\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| #endif |  | ||||||
| 	//printf("flash file len %u, compare to %08x in flash: ", len, addr); | 	//printf("flash file len %u, compare to %08x in flash: ", len, addr); | ||||||
| 	for (j = 0; j < len; j += bl, addr += bl) { | 	for (j = 0; j < len; j += bl, addr += bl) { | ||||||
| 		if (len - j < bl) | 		if (len - j < bl) | ||||||
| @@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) | |||||||
| 		return -4; | 		return -4; | ||||||
| 	} | 	} | ||||||
| 	if (devid == ddf->id.device) { | 	if (devid == ddf->id.device) { | ||||||
| 		if (version <= (ddf->id.hw & 0xffffff)) { | 		if (version < (ddf->id.hw & 0xffffff)) { | ||||||
| 			printf("%s is older or same version as flash\n", fn); | 			printf("%s is older version than flash\n", fn); | ||||||
| 			ret = -3; /* same id but no newer version */ | 			if (!ddf->force) | ||||||
|  | 				ret = -3; /* same id but older newer version */ | ||||||
|  | 		} | ||||||
|  | 		if (version == (ddf->id.hw & 0xffffff)) { | ||||||
|  | 			printf("%s is same version as flash\n", fn); | ||||||
|  | 			if (!ddf->force) | ||||||
|  | 				ret = 2; /* same and same version */ | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| @@ -1147,7 +1151,7 @@ out: | |||||||
| } | } | ||||||
|  |  | ||||||
| static int update_image(struct ddflash *ddf, char *fn,  | static int update_image(struct ddflash *ddf, char *fn,  | ||||||
| 			uint32_t adr, uint32_t len, | 			uint32_t adr, uint32_t maxlen, | ||||||
| 			int has_header, int no_change) | 			int has_header, int no_change) | ||||||
| { | { | ||||||
| 	int fs, res = 0; | 	int fs, res = 0; | ||||||
| @@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn, | |||||||
| 		printf("File %s not found \n", fn); | 		printf("File %s not found \n", fn); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	res = flashcmp(ddf, fs, adr, len, fw_off); | 	res = flashcmp(ddf, fs, adr, maxlen, fw_off); | ||||||
| 	if (res == -2) { | 	if (res == -2) { | ||||||
| 		printf("Flash already identical to %s\n", fn); | 		printf("Flash already identical to %s\n", fn); | ||||||
| 		if (ddf->force) { | 		if (ddf->force) { | ||||||
| @@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn, | |||||||
| 	} | 	} | ||||||
| 	if (res < 0)  | 	if (res < 0)  | ||||||
| 		goto out; | 		goto out; | ||||||
| 	res = flashwrite(ddf, fs, adr, len, fw_off); | 	res = flashwrite(ddf, fs, adr, maxlen, fw_off); | ||||||
| 	if (res == 0) { | 	if (res == 0) { | ||||||
| 		res = flashcmp(ddf, fs, adr, len, fw_off); | 		res = flashcmp(ddf, fs, adr, maxlen, fw_off); | ||||||
| 		if (res == -2) { | 		if (res == -2) { | ||||||
| 			res = 1; | 			res = 1; | ||||||
| 			printf("Flash verify OK!\n"); | 			printf("Flash verify OK!\n"); | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ int main(int argc, char*argv[]) | |||||||
| 	struct dvb_mod_params mp; | 	struct dvb_mod_params mp; | ||||||
| 	struct dvb_mod_channel_params mc; | 	struct dvb_mod_channel_params mc; | ||||||
| 	uint32_t data; | 	uint32_t data; | ||||||
| 	int adapter = 0, channel = 0, gain = -1; | 	int32_t adapter = 0, channel = 0, gain = -1; | ||||||
| 	int32_t base = -1, freq = -1, rate = -1; | 	int32_t base = -1, freq = -1, rate = -1; | ||||||
| 	char mod_name[128]; | 	char mod_name[128]; | ||||||
| 	 | 	 | ||||||
| @@ -113,7 +113,7 @@ int main(int argc, char*argv[]) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (optind < argc) { | 	if (optind < argc) { | ||||||
| 		printf("too man arguments\n"); | 		printf("too many arguments\n"); | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -134,6 +134,8 @@ int main(int argc, char*argv[]) | |||||||
| 	//get_property(fd, MODULATOR_ATTENUATOR, &data); | 	//get_property(fd, MODULATOR_ATTENUATOR, &data); | ||||||
| 	//printf("Modulator attenuator = %u\n", data); | 	//printf("Modulator attenuator = %u\n", data); | ||||||
|  |  | ||||||
|  | 	if (gain > 0) | ||||||
|  | 		set_property(fd, MODULATOR_GAIN, gain); | ||||||
| 	if (base > 0) | 	if (base > 0) | ||||||
| 		set_property(fd, MODULATOR_BASE_FREQUENCY, base); | 		set_property(fd, MODULATOR_BASE_FREQUENCY, base); | ||||||
| 	if (freq > 0) | 	if (freq > 0) | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ | |||||||
| #include "ddbridge.h" | #include "ddbridge.h" | ||||||
| #include "ddbridge-i2c.h" | #include "ddbridge-i2c.h" | ||||||
| #include "ddbridge-io.h" | #include "ddbridge-io.h" | ||||||
|  | #include "ddbridge-ioctl.h" | ||||||
| #include <media/dvb_net.h> | #include <media/dvb_net.h> | ||||||
|  |  | ||||||
| struct workqueue_struct *ddb_wq; | struct workqueue_struct *ddb_wq; | ||||||
| @@ -281,9 +282,9 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) | |||||||
| 	for (i = 0; i < dma->num; i++) { | 	for (i = 0; i < dma->num; i++) { | ||||||
| 		if (alt_dma) { | 		if (alt_dma) { | ||||||
| #if (KERNEL_VERSION(4, 13, 0) > LINUX_VERSION_CODE) | #if (KERNEL_VERSION(4, 13, 0) > LINUX_VERSION_CODE) | ||||||
| 			dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT); | 			dma->vbuf[i] = kzalloc(dma->size, __GFP_REPEAT); | ||||||
| #else | #else | ||||||
| 			dma->vbuf[i] = kmalloc(dma->size, __GFP_RETRY_MAYFAIL); | 			dma->vbuf[i] = kzalloc(dma->size, __GFP_RETRY_MAYFAIL); | ||||||
| #endif | #endif | ||||||
| 			if (!dma->vbuf[i]) | 			if (!dma->vbuf[i]) | ||||||
| 				return -ENOMEM; | 				return -ENOMEM; | ||||||
| @@ -301,10 +302,12 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) | |||||||
| 			dma->vbuf[i] = dma_alloc_coherent(&pdev->dev, | 			dma->vbuf[i] = dma_alloc_coherent(&pdev->dev, | ||||||
| 							  dma->size, | 							  dma->size, | ||||||
| 							  &dma->pbuf[i], | 							  &dma->pbuf[i], | ||||||
| 							  GFP_KERNEL); | 							  GFP_KERNEL | __GFP_ZERO); | ||||||
| 			if (!dma->vbuf[i]) | 			if (!dma->vbuf[i]) | ||||||
| 				return -ENOMEM; | 				return -ENOMEM; | ||||||
| 		} | 		} | ||||||
|  | 		if (((u64)dma->vbuf[i] & 0xfff)) | ||||||
|  | 			dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]); | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @@ -527,6 +530,18 @@ static void ddb_output_stop(struct ddb_output *output) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void update_loss(struct ddb_dma *dma) | ||||||
|  | { | ||||||
|  | 	struct ddb_input *input = (struct ddb_input *)dma->io; | ||||||
|  | 	u32 packet_loss = dma->packet_loss; | ||||||
|  | 	u32 cur_counter = ddbreadl(input->port->dev, TS_STAT(input)) & 0xffff; | ||||||
|  | 	 | ||||||
|  | 	if (cur_counter < (packet_loss & 0xffff)) | ||||||
|  | 		packet_loss += 0x10000; | ||||||
|  | 	packet_loss = ((packet_loss & 0xffff0000) | cur_counter); | ||||||
|  | 	dma->packet_loss = packet_loss; | ||||||
|  | } | ||||||
|  |  | ||||||
| static void ddb_input_stop_unlocked(struct ddb_input *input) | static void ddb_input_stop_unlocked(struct ddb_input *input) | ||||||
| { | { | ||||||
| 	struct ddb *dev = input->port->dev; | 	struct ddb *dev = input->port->dev; | ||||||
| @@ -540,7 +555,8 @@ static void ddb_input_stop_unlocked(struct ddb_input *input) | |||||||
| 			dev_warn(input->port->dev->dev, | 			dev_warn(input->port->dev->dev, | ||||||
| 				 "DMA stalled %u times!\n", | 				 "DMA stalled %u times!\n", | ||||||
| 				 input->dma->stall_count); | 				 input->dma->stall_count); | ||||||
| 		if (input->dma->packet_loss) | 		update_loss(input->dma); | ||||||
|  | 		if (input->dma->packet_loss > 1) | ||||||
| 			dev_warn(input->port->dev->dev, | 			dev_warn(input->port->dev->dev, | ||||||
| 				 "%u packets lost due to low DMA performance!\n", | 				 "%u packets lost due to low DMA performance!\n", | ||||||
| 				 input->dma->packet_loss); | 				 input->dma->packet_loss); | ||||||
| @@ -1068,7 +1084,11 @@ static int demod_attach_dummy(struct ddb_input *input) | |||||||
| { | { | ||||||
| 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; | 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
| 	dvb->fe = dvb_attach(dummy_attach); | 	dvb->fe = dvb_attach(dummy_attach); | ||||||
|  | #else | ||||||
|  | 	dvb->fe = dummy_attach(); | ||||||
|  | #endif | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -2277,20 +2297,35 @@ static void input_write_dvb(struct ddb_input *input, | |||||||
| 	} | 	} | ||||||
| 	while (dma->cbuf != ((dma->stat >> 11) & 0x1f) || (4 & dma->ctrl)) { | 	while (dma->cbuf != ((dma->stat >> 11) & 0x1f) || (4 & dma->ctrl)) { | ||||||
| 		if (4 & dma->ctrl) { | 		if (4 & dma->ctrl) { | ||||||
| 			/*dev_err(dev->dev, "Overflow dma %d\n", dma->nr);*/ | 			dev_warn(dev->dev, "Overflow dma input %u\n", input->nr); | ||||||
| 			ack = 1; | 			ack = 1; | ||||||
| 		} | 		} | ||||||
| 		if (alt_dma) | 		if (alt_dma) | ||||||
| 			dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], | 			dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], | ||||||
| 						dma2->size, DMA_FROM_DEVICE); | 						dma2->size, DMA_FROM_DEVICE); | ||||||
| 		if (raw_stream || input->con) | 		if (raw_stream || input->con) { | ||||||
| 			dvb_dmx_swfilter_raw(&dvb->demux, | 			dvb_dmx_swfilter_raw(&dvb->demux, | ||||||
| 					     dma2->vbuf[dma->cbuf], | 					     dma2->vbuf[dma->cbuf], | ||||||
| 					     dma2->size); | 					     dma2->size); | ||||||
| 		else | 		} else { | ||||||
| 			dvb_dmx_swfilter_packets(&dvb->demux, | 			if (dma2->unaligned || (dma2->vbuf[dma->cbuf][0] != 0x47)) { | ||||||
|  | 				if (!dma2->unaligned) { | ||||||
|  | 					dma2->unaligned++; | ||||||
|  | 					dev_warn(dev->dev, "Input %u dma buffer unaligned, " | ||||||
|  | 						 "switching to unaligned processing.\n", | ||||||
|  | 						 input->nr); | ||||||
|  | 					print_hex_dump(KERN_INFO, "TS: ", DUMP_PREFIX_OFFSET, 32, 1, | ||||||
|  | 						       dma2->vbuf[dma->cbuf], | ||||||
|  | 						       512, false); | ||||||
|  | 				} | ||||||
|  | 				dvb_dmx_swfilter(&dvb->demux, | ||||||
| 						 dma2->vbuf[dma->cbuf], | 						 dma2->vbuf[dma->cbuf], | ||||||
| 						 dma2->size / 188); | 						 dma2->size); | ||||||
|  | 			} else | ||||||
|  | 				dvb_dmx_swfilter_packets(&dvb->demux, | ||||||
|  | 							 dma2->vbuf[dma->cbuf], | ||||||
|  | 							 dma2->size / 188); | ||||||
|  | 		} | ||||||
| 		 | 		 | ||||||
| 		dma->cbuf = (dma->cbuf + 1) % dma2->num; | 		dma->cbuf = (dma->cbuf + 1) % dma2->num; | ||||||
| 		if (ack) | 		if (ack) | ||||||
| @@ -2321,16 +2356,7 @@ static void input_tasklet(unsigned long data) | |||||||
| 	} | 	} | ||||||
| 	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma)); | 	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma)); | ||||||
| 	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma)); | 	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma)); | ||||||
|  | 	update_loss(dma); | ||||||
| 	{ |  | ||||||
| 		u32 packet_loss = dma->packet_loss; |  | ||||||
| 		u32 cur_counter = ddbreadl(dev, TS_STAT(input)) & 0xffff; |  | ||||||
|  |  | ||||||
| 		if (cur_counter < (packet_loss & 0xffff)) |  | ||||||
| 			packet_loss += 0x10000; |  | ||||||
| 		packet_loss = ((packet_loss & 0xffff0000) | cur_counter); |  | ||||||
| 		dma->packet_loss = packet_loss; |  | ||||||
| 	} |  | ||||||
| 	if (4 & dma->ctrl) | 	if (4 & dma->ctrl) | ||||||
| 		dma->stall_count++; | 		dma->stall_count++; | ||||||
| 	if (input->redi) | 	if (input->redi) | ||||||
| @@ -2576,7 +2602,7 @@ static int ddb_port_match_link_i2c(struct ddb_port *port) | |||||||
|  |  | ||||||
| static void ddb_ports_init(struct ddb *dev) | static void ddb_ports_init(struct ddb *dev) | ||||||
| { | { | ||||||
| 	u32 i, l, p; | 	u32 i, l, p, ports; | ||||||
| 	struct ddb_port *port; | 	struct ddb_port *port; | ||||||
| 	const struct ddb_info *info; | 	const struct ddb_info *info; | ||||||
| 	const struct ddb_regmap *rm; | 	const struct ddb_regmap *rm; | ||||||
| @@ -2588,7 +2614,12 @@ static void ddb_ports_init(struct ddb *dev) | |||||||
| 		rm = info->regmap; | 		rm = info->regmap; | ||||||
| 		if (!rm) | 		if (!rm) | ||||||
| 			continue; | 			continue; | ||||||
| 		for (i = 0; i < info->port_num; i++, p++) { | 		ports = info->port_num; | ||||||
|  | 		if ((l == 0) && (dev->link[l].info->type == DDB_MOD) && | ||||||
|  | 		    (dev->link[0].ids.revision == 1)) { | ||||||
|  | 			ports = ddbreadl(dev, 0x260) >> 24; | ||||||
|  | 		} | ||||||
|  | 		for (i = 0; i < ports; i++, p++) { | ||||||
| 			port = &dev->port[p]; | 			port = &dev->port[p]; | ||||||
| 			port->dev = dev; | 			port->dev = dev; | ||||||
| 			port->nr = i; | 			port->nr = i; | ||||||
| @@ -3162,76 +3193,6 @@ static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg, u32 mdio_base) | |||||||
| 	return ddbreadl(dev, MDIO_VAL_OFF + mdio_base); | 	return ddbreadl(dev, MDIO_VAL_OFF + mdio_base); | ||||||
| } | } | ||||||
|  |  | ||||||
| #define DDB_MAGIC 'd' |  | ||||||
|  |  | ||||||
| struct ddb_flashio { |  | ||||||
| 	__u8 *write_buf; |  | ||||||
| 	__u32 write_len; |  | ||||||
| 	__u8 *read_buf; |  | ||||||
| 	__u32 read_len; |  | ||||||
| 	__u32 link; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_gpio { |  | ||||||
| 	__u32 mask; |  | ||||||
| 	__u32 data; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_id { |  | ||||||
| 	__u16 vendor; |  | ||||||
| 	__u16 device; |  | ||||||
| 	__u16 subvendor; |  | ||||||
| 	__u16 subdevice; |  | ||||||
| 	__u32 hw; |  | ||||||
| 	__u32 regmap; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_reg { |  | ||||||
| 	__u32 reg; |  | ||||||
| 	__u32 val; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_mem { |  | ||||||
| 	__u32  off; |  | ||||||
| 	__u8  *buf; |  | ||||||
| 	__u32  len; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_mdio { |  | ||||||
| 	__u8   adr; |  | ||||||
| 	__u8   reg; |  | ||||||
| 	__u16  val; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_i2c_msg { |  | ||||||
| 	__u8   bus; |  | ||||||
| 	__u8   adr; |  | ||||||
| 	__u8  *hdr; |  | ||||||
| 	__u32  hlen; |  | ||||||
| 	__u8  *msg; |  | ||||||
| 	__u32  mlen; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct ddb_mci_msg { |  | ||||||
| 	__u32 link; |  | ||||||
| 	struct mci_command cmd; |  | ||||||
| 	struct mci_result res; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #define IOCTL_DDB_FLASHIO    _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) |  | ||||||
| #define IOCTL_DDB_GPIO_IN    _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) |  | ||||||
| #define IOCTL_DDB_GPIO_OUT   _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) |  | ||||||
| #define IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id) |  | ||||||
| #define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) |  | ||||||
| #define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg) |  | ||||||
| #define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) |  | ||||||
| #define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem) |  | ||||||
| #define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) |  | ||||||
| #define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) |  | ||||||
| #define IOCTL_DDB_READ_I2C   _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) |  | ||||||
| #define IOCTL_DDB_WRITE_I2C  _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) |  | ||||||
| #define IOCTL_DDB_MCI_CMD    _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg) |  | ||||||
|  |  | ||||||
| #define DDB_NAME "ddbridge" | #define DDB_NAME "ddbridge" | ||||||
|  |  | ||||||
| static u32 ddb_num; | static u32 ddb_num; | ||||||
| @@ -3310,8 +3271,8 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||||||
| 		ddbid.device = dev->link[0].ids.device; | 		ddbid.device = dev->link[0].ids.device; | ||||||
| 		ddbid.subvendor = dev->link[0].ids.subvendor; | 		ddbid.subvendor = dev->link[0].ids.subvendor; | ||||||
| 		ddbid.subdevice = dev->link[0].ids.subdevice; | 		ddbid.subdevice = dev->link[0].ids.subdevice; | ||||||
| 		ddbid.hw = ddbreadl(dev, 0); | 		ddbid.hw = dev->link[0].ids.hwid; | ||||||
| 		ddbid.regmap = ddbreadl(dev, 4); | 		ddbid.regmap = dev->link[0].ids.regmapid; | ||||||
| 		if (copy_to_user(parg, &ddbid, sizeof(ddbid))) | 		if (copy_to_user(parg, &ddbid, sizeof(ddbid))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		break; | 		break; | ||||||
| @@ -3453,8 +3414,6 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||||||
| 		if (msg.link > 3) | 		if (msg.link > 3) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		link = &dev->link[msg.link]; | 		link = &dev->link[msg.link]; | ||||||
| 		if (!link->mci_base) |  | ||||||
| 			return -EFAULT; |  | ||||||
| 		res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res); | 		res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res); | ||||||
| 		if (copy_to_user(parg, &msg, sizeof(msg))) | 		if (copy_to_user(parg, &msg, sizeof(msg))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								ddbridge/ddbridge-ioctl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								ddbridge/ddbridge-ioctl.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | #ifndef _DDBRIDGE_IOCTL_H_ | ||||||
|  | #define _DDBRIDGE_IOCTL_H_ | ||||||
|  |  | ||||||
|  | #define DDB_MAGIC 'd' | ||||||
|  |  | ||||||
|  | struct ddb_flashio { | ||||||
|  | 	__u8 *write_buf; | ||||||
|  | 	__u32 write_len; | ||||||
|  | 	__u8 *read_buf; | ||||||
|  | 	__u32 read_len; | ||||||
|  | 	__u32 link; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_gpio { | ||||||
|  | 	__u32 mask; | ||||||
|  | 	__u32 data; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_id { | ||||||
|  | 	__u16 vendor; | ||||||
|  | 	__u16 device; | ||||||
|  | 	__u16 subvendor; | ||||||
|  | 	__u16 subdevice; | ||||||
|  | 	__u32 hw; | ||||||
|  | 	__u32 regmap; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_reg { | ||||||
|  | 	__u32 reg; | ||||||
|  | 	__u32 val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_mem { | ||||||
|  | 	__u32  off; | ||||||
|  | 	__u8  *buf; | ||||||
|  | 	__u32  len; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_mdio { | ||||||
|  | 	__u8   adr; | ||||||
|  | 	__u8   reg; | ||||||
|  | 	__u16  val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_i2c_msg { | ||||||
|  | 	__u8   bus; | ||||||
|  | 	__u8   adr; | ||||||
|  | 	__u8  *hdr; | ||||||
|  | 	__u32  hlen; | ||||||
|  | 	__u8  *msg; | ||||||
|  | 	__u32  mlen; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ddb_mci_msg { | ||||||
|  | 	__u32 link; | ||||||
|  | 	struct mci_command cmd; | ||||||
|  | 	struct mci_result res; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define IOCTL_DDB_FLASHIO    _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) | ||||||
|  | #define IOCTL_DDB_GPIO_IN    _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) | ||||||
|  | #define IOCTL_DDB_GPIO_OUT   _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) | ||||||
|  | #define IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id) | ||||||
|  | #define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) | ||||||
|  | #define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg) | ||||||
|  | #define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) | ||||||
|  | #define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem) | ||||||
|  | #define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) | ||||||
|  | #define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) | ||||||
|  | #define IOCTL_DDB_READ_I2C   _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) | ||||||
|  | #define IOCTL_DDB_WRITE_I2C  _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) | ||||||
|  | #define IOCTL_DDB_MCI_CMD    _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg) | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -392,19 +392,23 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) | |||||||
| 	struct m4 *state = fe->demodulator_priv; | 	struct m4 *state = fe->demodulator_priv; | ||||||
| 	struct mci_result res; | 	struct mci_result res; | ||||||
|  |  | ||||||
|  | 	*status = 0x00; | ||||||
|  | 	if (!state->started) | ||||||
|  | 		return 0; | ||||||
| 	stat = ddb_mci_get_status(&state->mci, &res); | 	stat = ddb_mci_get_status(&state->mci, &res); | ||||||
| 	if (stat) | 	if (stat) | ||||||
| 		return stat; | 		return stat; | ||||||
| 	*status = 0x00; |  | ||||||
| 	stat = ddb_mci_get_info(&state->mci); | 	stat = ddb_mci_get_info(&state->mci); | ||||||
| 	if (stat) | 	if (stat) | ||||||
| 		return stat; | 		return stat; | ||||||
| 	ddb_mci_get_strength(fe); | 	ddb_mci_get_strength(fe); | ||||||
| 	if (res.status == MCI_DEMOD_WAIT_SIGNAL) | 	if (res.status == MCI_DEMOD_WAIT_SIGNAL) | ||||||
| 		*status = 0x01; | 		*status = 0x01; | ||||||
| 	if (res.status == M4_DEMOD_WAIT_TS) | 	else if (res.status == M4_DEMOD_WAIT_TS) | ||||||
| 		*status = 0x03; | 		*status = 0x03; | ||||||
| 	if (res.status == MCI_DEMOD_LOCKED) { | 	else if (res.status == MCI_DEMOD_TIMEOUT) | ||||||
|  | 		*status = FE_TIMEDOUT; | ||||||
|  | 	else if (res.status == MCI_DEMOD_LOCKED) { | ||||||
| 		*status = 0x1f; | 		*status = 0x1f; | ||||||
| 		ddb_mci_get_snr(fe); | 		ddb_mci_get_snr(fe); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -139,6 +139,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev) | |||||||
| 	ddb_buffers_free(dev); | 	ddb_buffers_free(dev); | ||||||
|  |  | ||||||
| 	ddb_unmap(dev); | 	ddb_unmap(dev); | ||||||
|  | 	pci_clear_master(pdev); | ||||||
| 	pci_set_drvdata(pdev, NULL); | 	pci_set_drvdata(pdev, NULL); | ||||||
| 	pci_disable_device(pdev); | 	pci_disable_device(pdev); | ||||||
| } | } | ||||||
| @@ -311,6 +312,7 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | |||||||
| 	dev->link[0].ids.subvendor = id->subvendor; | 	dev->link[0].ids.subvendor = id->subvendor; | ||||||
| 	dev->link[0].ids.subdevice = pdev->subsystem_device; | 	dev->link[0].ids.subdevice = pdev->subsystem_device; | ||||||
| 	dev->link[0].ids.devid = (id->device << 16) | id->vendor; | 	dev->link[0].ids.devid = (id->device << 16) | id->vendor; | ||||||
|  | 	dev->link[0].ids.revision = pdev->revision; | ||||||
|  |  | ||||||
| 	dev->link[0].dev = dev; | 	dev->link[0].dev = dev; | ||||||
| 	dev->link[0].info = get_ddb_info(id->vendor, id->device, | 	dev->link[0].info = get_ddb_info(id->vendor, id->device, | ||||||
| @@ -335,8 +337,10 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | |||||||
| 	dev->link[0].ids.hwid = ddbreadl(dev, 0); | 	dev->link[0].ids.hwid = ddbreadl(dev, 0); | ||||||
| 	dev->link[0].ids.regmapid = ddbreadl(dev, 4); | 	dev->link[0].ids.regmapid = ddbreadl(dev, 4); | ||||||
|  |  | ||||||
| 	dev_info(dev->dev, "HW %08x REGMAP %08x\n", | 	dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n", | ||||||
| 		 dev->link[0].ids.hwid, dev->link[0].ids.regmapid); | 		 dev->link[0].ids.hwid, dev->link[0].ids.regmapid, | ||||||
|  | 		 (dev->link[0].ids.hwid & 0xff0000) >> 16, | ||||||
|  | 		 dev->link[0].ids.hwid & 0xffff); | ||||||
| 	if ((dev->link[0].ids.hwid & 0xffffff) < | 	if ((dev->link[0].ids.hwid & 0xffffff) < | ||||||
| 	    dev->link[0].info->hw_min) { | 	    dev->link[0].info->hw_min) { | ||||||
| 		u32 min = dev->link[0].info->hw_min; | 		u32 min = dev->link[0].info->hw_min; | ||||||
|   | |||||||
| @@ -40,6 +40,10 @@ static int old_quattro; | |||||||
| module_param(old_quattro, int, 0444); | module_param(old_quattro, int, 0444); | ||||||
| MODULE_PARM_DESC(old_quattro, "old quattro LNB input order "); | MODULE_PARM_DESC(old_quattro, "old quattro LNB input order "); | ||||||
|  |  | ||||||
|  | static int no_voltage; | ||||||
|  | module_param(no_voltage, int, 0444); | ||||||
|  | MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone)."); | ||||||
|  |  | ||||||
| /* MAX LNB interface related functions */ | /* MAX LNB interface related functions */ | ||||||
|  |  | ||||||
| static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) | static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) | ||||||
| @@ -61,7 +65,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int max_set_input_unlocked(struct dvb_frontend *fe, int in); | static int max_set_input(struct dvb_frontend *fe, int in); | ||||||
|  |  | ||||||
| static int max_emulate_switch(struct dvb_frontend *fe, | static int max_emulate_switch(struct dvb_frontend *fe, | ||||||
| 			      u8 *cmd, u32 len) | 			      u8 *cmd, u32 len) | ||||||
| @@ -75,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe, | |||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| 	input = cmd[3] & 3; | 	input = cmd[3] & 3; | ||||||
| 	max_set_input_unlocked(fe, input); | 	max_set_input(fe, input); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -94,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe, | |||||||
| 		return 0; | 		return 0; | ||||||
|  |  | ||||||
| 	if (fmode == 4) | 	if (fmode == 4) | ||||||
| 		max_emulate_switch(fe, cmd->msg, cmd->msg_len); | 		if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len)) | ||||||
|  | 			return 0; | ||||||
|  |  | ||||||
| 	if (dvb->diseqc_send_master_cmd) | 	if (dvb->diseqc_send_master_cmd) | ||||||
| 		dvb->diseqc_send_master_cmd(fe, cmd); | 		dvb->diseqc_send_master_cmd(fe, cmd); | ||||||
| @@ -164,6 +169,8 @@ static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input, | |||||||
| { | { | ||||||
| 	int s = 0; | 	int s = 0; | ||||||
|  |  | ||||||
|  | 	if (no_voltage) | ||||||
|  | 		voltage = SEC_VOLTAGE_OFF; | ||||||
| 	if (dev->link[link].lnb.oldvoltage[input] == voltage) | 	if (dev->link[link].lnb.oldvoltage[input] == voltage) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	switch (voltage) { | 	switch (voltage) { | ||||||
|   | |||||||
| @@ -34,10 +34,16 @@ static int mci_reset(struct ddb_link *link) | |||||||
| 	u32 control; | 	u32 control; | ||||||
| 	u32 status = 0; | 	u32 status = 0; | ||||||
| 	u32 timeout = 40; | 	u32 timeout = 40; | ||||||
|  | 	union { | ||||||
|  | 		u32 u[4]; | ||||||
|  | 		char s[16]; | ||||||
|  | 	} version; | ||||||
|  | 	u32 vaddr; | ||||||
| 	 | 	 | ||||||
| 	if (!regmap || ! regmap->mci) | 	if (!regmap || !regmap->mci) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	control = regmap->mci->base; | 	control = regmap->mci->base; | ||||||
|  | 	vaddr = regmap->mci_buf->base + 0xf0; | ||||||
|  |  | ||||||
| 	if ((link->info->type == DDB_OCTOPUS_MCI) && | 	if ((link->info->type == DDB_OCTOPUS_MCI) && | ||||||
| 	    (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { | 	    (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { | ||||||
| @@ -55,11 +61,17 @@ static int mci_reset(struct ddb_link *link) | |||||||
| 		msleep(50); | 		msleep(50); | ||||||
| 	} | 	} | ||||||
| 	dev_info(link->dev->dev, "MCI control port @ %08x\n", control); | 	dev_info(link->dev->dev, "MCI control port @ %08x\n", control); | ||||||
|  |  | ||||||
| 	if ((status & MCI_CONTROL_READY) == 0) { | 	if ((status & MCI_CONTROL_READY) == 0) { | ||||||
| 		dev_err(link->dev->dev, "MCI init failed!\n"); | 		dev_err(link->dev->dev, "MCI init failed!\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40-timeout)*50); | 	version.u[0] = ddblreadl(link, vaddr); | ||||||
|  | 	version.u[1] = ddblreadl(link, vaddr + 4); | ||||||
|  | 	version.u[2] = ddblreadl(link, vaddr + 8); | ||||||
|  | 	version.u[3] = ddblreadl(link, vaddr + 12); | ||||||
|  | 	dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50); | ||||||
|  | 	dev_info(link->dev->dev, "MCI firmware version %s.%d\n", version.s, version.s[15]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -108,6 +120,7 @@ static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link, | |||||||
| 					  0xffffff, INTERRUPT_ACK); | 					  0xffffff, INTERRUPT_ACK); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false); | ||||||
| 	if (res && res_len) | 	if (res && res_len) | ||||||
| 		for (i = 0; i < res_len; i++) | 		for (i = 0; i < res_len; i++) | ||||||
| 			res[i] = ddblreadl(link, result + i * 4); | 			res[i] = ddblreadl(link, result + i * 4); | ||||||
| @@ -166,11 +179,10 @@ int mci_init(struct ddb_link *link) | |||||||
| int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val) | int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val) | ||||||
| { | { | ||||||
| 	struct mci_result result; | 	struct mci_result result; | ||||||
| 	struct mci_command command = { | 	struct mci_command command; | ||||||
| 		.command_word = cmd, |  | ||||||
| 		.params = { val }, |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
|  | 	command.command_word = cmd; | ||||||
|  | 	command.params[0] = val; | ||||||
| 	return ddb_mci_cmd_link(link, &command, &result); | 	return ddb_mci_cmd_link(link, &command, &result); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -209,6 +221,21 @@ int ddb_mci_get_status(struct mci *mci, struct mci_result *res) | |||||||
| 	return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1); | 	return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void ddb_mci_print_info(struct mci *mci) | ||||||
|  | { | ||||||
|  | 	struct ddb_link *link = mci->base->link; | ||||||
|  | 	const struct ddb_regmap *regmap = link->info->regmap; | ||||||
|  | 	struct mci_command cmd; | ||||||
|  | 	struct mci_result res; | ||||||
|  | 	 | ||||||
|  | 	cmd.command = 0x0f; | ||||||
|  | 	if (ddb_mci_cmd_raw(mci, &cmd, 1, &res, 1) < 0) | ||||||
|  | 		return; | ||||||
|  | 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, | ||||||
|  | 		       link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE, | ||||||
|  | 		       16, false); | ||||||
|  | } | ||||||
|  |  | ||||||
| int ddb_mci_get_snr(struct dvb_frontend *fe) | int ddb_mci_get_snr(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	struct mci *mci = fe->demodulator_priv; | 	struct mci *mci = fe->demodulator_priv; | ||||||
|   | |||||||
| @@ -132,6 +132,7 @@ | |||||||
| #define MCI_BANDWIDTH_7MHZ       (7) | #define MCI_BANDWIDTH_7MHZ       (7) | ||||||
| #define MCI_BANDWIDTH_8MHZ       (8) | #define MCI_BANDWIDTH_8MHZ       (8) | ||||||
|  |  | ||||||
|  | #define SX8_CMD_GETBIST          (0x0F) | ||||||
| #define SX8_CMD_INPUT_ENABLE     (0x40) | #define SX8_CMD_INPUT_ENABLE     (0x40) | ||||||
| #define SX8_CMD_INPUT_DISABLE    (0x41) | #define SX8_CMD_INPUT_DISABLE    (0x41) | ||||||
| #define SX8_CMD_START_IQ         (0x42) | #define SX8_CMD_START_IQ         (0x42) | ||||||
| @@ -185,6 +186,82 @@ | |||||||
|  |  | ||||||
| #define MCI_SUCCESS(status)     ((status & MCI_STATUS_UNSUPPORTED) == 0) | #define MCI_SUCCESS(status)     ((status & MCI_STATUS_UNSUPPORTED) == 0) | ||||||
|  |  | ||||||
|  | /********************************************************/ | ||||||
|  |  | ||||||
|  | #define MOD_SETUP_CHANNELS      (0x60) | ||||||
|  | #define MOD_SETUP_OUTPUT        (0x61) | ||||||
|  | #define MOD_SETUP_STREAM        (0x62) | ||||||
|  | #define MOD_SET_STREAM_CHANNEL  (0x63) | ||||||
|  |  | ||||||
|  | #define MOD_SETUP_FLAG_FIRST    (0x01) | ||||||
|  | #define MOD_SETUP_FLAG_LAST     (0x02) | ||||||
|  | #define MOD_SETUP_FLAG_VALID    (0x80) | ||||||
|  |  | ||||||
|  | #define MOD_STANDARD_GENERIC    (0x00) | ||||||
|  | #define MOD_STANDARD_DVBT_8     (0x01) | ||||||
|  | #define MOD_STANDARD_DVBT_7     (0x02) | ||||||
|  | #define MOD_STANDARD_DVBT_6     (0x03) | ||||||
|  | #define MOD_STANDARD_DVBT_5     (0x04) | ||||||
|  |  | ||||||
|  | #define MOD_CONNECTOR_OFF       (0x00) | ||||||
|  | #define MOD_CONNECTOR_F         (0x01) | ||||||
|  | #define MOD_CONNECTOR_SMA       (0x02) | ||||||
|  |  | ||||||
|  | #define MOD_UNIT_DBUV           (0x00) | ||||||
|  | #define MOD_UNIT_DBM            (0x01) | ||||||
|  |  | ||||||
|  | #define MOD_FORMAT_DEFAULT      (0x00) | ||||||
|  | #define MOD_FORMAT_IQ16         (0x01) | ||||||
|  | #define MOD_FORMAT_IQ8          (0x02) | ||||||
|  | #define MOD_FORMAT_IDX8         (0x03) | ||||||
|  | #define MOD_FORMAT_TS           (0x04) | ||||||
|  |  | ||||||
|  | #define MOD_DVBT_FFT_8K         (0x01) | ||||||
|  | #define MOD_DVBT_GI_1_32        (0x00) | ||||||
|  | #define MOD_DVBT_GI_1_16        (0x01) | ||||||
|  | #define MOD_DVBT_GI_1_8         (0x02) | ||||||
|  | #define MOD_DVBT_GI_1_4         (0x03) | ||||||
|  |  | ||||||
|  | #define MOD_DVBT_PR_1_2         (0x00) | ||||||
|  | #define MOD_DVBT_PR_2_3         (0x01) | ||||||
|  | #define MOD_DVBT_PR_3_4         (0x02) | ||||||
|  | #define MOD_DVBT_PR_5_6         (0x03) | ||||||
|  | #define MOD_DVBT_PR_7_8         (0x04) | ||||||
|  |  | ||||||
|  | #define MOD_DVBT_QPSK           (0x00) | ||||||
|  | #define MOD_DVBT_16QAM          (0x01) | ||||||
|  | #define MOD_DVBT_64QAM          (0x02) | ||||||
|  |  | ||||||
|  | struct mod_setup_channels { | ||||||
|  | 	u8   flags; | ||||||
|  | 	u8   standard; | ||||||
|  | 	u8   num_channels; | ||||||
|  | 	u8   rsvd; | ||||||
|  | 	u32  frequency; | ||||||
|  | 	u32  offset;            /* used only when Standard == 0 */ | ||||||
|  | 	u32  bandwidth;         /* used only when Standard == 0 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mod_setup_stream { | ||||||
|  | 	u8   standard; | ||||||
|  | 	u8   stream_format; | ||||||
|  | 	u8   rsvd1[2]; | ||||||
|  | 	u32  symbol_rate;        /* only used when Standard doesn't define a fixed symbol rate */ | ||||||
|  | 	u8   fft_size;           /* 0 = 2K, 1 = 8K  (2K yet supported) */ | ||||||
|  | 	u8   guard_interval;     /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4  (DVB-T Encoding) */ | ||||||
|  | 	u8   puncture_rate;      /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8  (DVB-T Encoding) */ | ||||||
|  | 	u8   constellation; | ||||||
|  | 	u8   rsvd2[2];           /* Reserved for DVB-T hierarchical */ | ||||||
|  | 	u16  cell_identifier; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mod_setup_output { | ||||||
|  | 	u8   connector;         /* 0 = OFF, 1 = F, 2 = SMA */ | ||||||
|  | 	u8   num_channels;      /* max active channels, determines max power for each channel. */ | ||||||
|  | 	u8   unit;              /* 0 = dBµV, 1 = dBm, */ | ||||||
|  | 	u8   rsvd; | ||||||
|  | 	s16  channel_power; | ||||||
|  | }; | ||||||
|  |  | ||||||
| /********************************************************/ | /********************************************************/ | ||||||
|  |  | ||||||
| @@ -197,6 +274,12 @@ struct mci_command { | |||||||
| 			u8 demod; | 			u8 demod; | ||||||
| 			u8 output; | 			u8 output; | ||||||
| 		}; | 		}; | ||||||
|  | 		struct { | ||||||
|  | 			u8 mod_command; | ||||||
|  | 			u8 mod_channel; | ||||||
|  | 			u8 mod_stream; | ||||||
|  | 			u8 mod_rsvd1; | ||||||
|  | 		}; | ||||||
| 	}; | 	}; | ||||||
| 	union { | 	union { | ||||||
| 		u32 params[31]; | 		u32 params[31]; | ||||||
| @@ -297,7 +380,7 @@ struct mci_command { | |||||||
| 		} j83b_search; | 		} j83b_search; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8   flags;              //  Bit 0 : 1 = short info (1st 4 Bytes) | 			u8   flags; /*  Bit 0 : 1 = short info (1st 4 Bytes) */ | ||||||
| 		} get_signalinfo; | 		} get_signalinfo; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| @@ -307,43 +390,47 @@ struct mci_command { | |||||||
| 		} get_iq_symbol; | 		} get_iq_symbol; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			uint8_t   flags; /*  Bit 0 : 0 = VTM/SDR, 1 = SCAN, | 			u8   flags; /*  Bit 0 : 0 = VTM/SDR, 1 = SCAN, | ||||||
| 					     Bit 1: 1 = Disable AGC, | 					     Bit 1: 1 = Disable AGC, | ||||||
| 					     Bit 2: 1 = Set Gain.   */ | 					     Bit 2: 1 = Set Gain.   */ | ||||||
| 			uint8_t   roll_off; | 			u8   roll_off; | ||||||
| 			uint8_t   rsvd1; | 			u8   rsvd1; | ||||||
| 			uint8_t   rsvd2; | 			u8   rsvd2; | ||||||
| 			uint32_t  frequency; | 			u32  frequency; | ||||||
| 			uint32_t  symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ | 			u32  symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ | ||||||
| 			uint8_t   gain;         /* Gain in 0.25 dB Steps */ | 			u8   gain;         /* Gain in 0.25 dB Steps */ | ||||||
| 			/* Frequency, symbolrate and gain can be schanged while running */ | 			/* Frequency, symbolrate and gain can be schanged while running */ | ||||||
| 		} sx8_start_iq; | 		} sx8_start_iq; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			uint8_t   flags; | 			u8   flags; | ||||||
|                         /*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | 			/*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||||
| 			     2 = Medium, 3 = Maximum gain {~ 15dB} | 			     2 = Medium, 3 = Maximum gain {~ 15dB} | ||||||
| 			     Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) | 			     Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) | ||||||
| 			     Bit 4: Set RF Gain | 			     Bit 4: Set RF Gain | ||||||
| 			     Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) | 			     Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) | ||||||
| 			     Bit 7: Optimize RF Gain and freeze for FFT */ | 			     Bit 7: Optimize RF Gain and freeze for FFT */ | ||||||
| 			uint8_t   rf_gain;       /*   0 .. 50 dB */ | 			u8   rf_gain;       /*   0 .. 50 dB */ | ||||||
| 		} sx8_input_enable; | 		} sx8_input_enable; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8   offset;        // Offset into list, must be multiple of 64 | 			u8   offset;        /* Offset into list, must be multiple of 64 */ | ||||||
| 			u8   select;        // 0 = Slices, 1 = PLPs  (C2 Only) | 			u8   select;        /* 0 = Slices, 1 = PLPs  (C2 Only) */ | ||||||
| 			u8   data_slice;    // DataSlice to get PLPList (C2 Only) | 			u8   data_slice;    /* DataSlice to get PLPList (C2 Only) */ | ||||||
| 		} get_ids; | 		} get_ids; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8   select;        // 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID | 			u8   select;        /* 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID */ | ||||||
| 			u8   id;            // DataSliceID, PLPId  | 			u8   id;            /* DataSliceID, PLPId */ | ||||||
| 		} get_l1_info; | 		} get_l1_info; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8   select;        // 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 | 			u8   select;        /* 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 */ | ||||||
| 		} get_bb_header; | 		} get_bb_header; | ||||||
|  |  | ||||||
|  | 		struct mod_setup_channels mod_setup_channels[4]; | ||||||
|  | 		struct mod_setup_stream mod_setup_stream; | ||||||
|  | 		struct mod_setup_output mod_setup_output; | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -359,20 +446,21 @@ struct mci_result { | |||||||
|  |  | ||||||
| 	union { | 	union { | ||||||
| 		u32 result[27]; | 		u32 result[27]; | ||||||
|  | 		u8 result8[27 * 4]; | ||||||
| 		struct { | 		struct { | ||||||
| 			u8  Rsvd0[3]; | 			u8  Rsvd0[3]; | ||||||
| 			u8  Flags; | 			u8  Flags; | ||||||
|  |  | ||||||
| 			u32 frequency;         // actual frequency in Hz | 			u32 frequency;          /* actual frequency in Hz */ | ||||||
| 			u32 rsvd1; | 			u32 rsvd1; | ||||||
| 			s16 channel_power;      // channel power in dBm x 100 | 			s16 channel_power;      /* channel power in dBm x 100 */ | ||||||
| 			s16 rsvd2; | 			s16 rsvd2; | ||||||
| 			s16 signal_to_noise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | 			s16 signal_to_noise;    /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ | ||||||
| 			s16 rsvd3; | 			s16 rsvd3; | ||||||
| 			u32 rsvd4; | 			u32 rsvd4; | ||||||
| 			u32 ber_numerator;     /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ | 			u32 ber_numerator;      /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ | ||||||
| 			u32 ber_denominator; | 			u32 ber_denominator; | ||||||
| 			u32 ber_rsvd1;          // Place holder for modulation bit error rate | 			u32 ber_rsvd1;          /* Place holder for modulation bit error rate */ | ||||||
| 			u32 ber_rsvd2; | 			u32 ber_rsvd2; | ||||||
| 		} common_signal_info; | 		} common_signal_info; | ||||||
|  |  | ||||||
| @@ -425,8 +513,8 @@ struct mci_result { | |||||||
| 		struct { | 		struct { | ||||||
| 			u8  modulation1;        // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High | 			u8  modulation1;        // bit 7..6: Constellation, bit 5..3 Hierachy, bit 2..0 CodeRate High | ||||||
| 			u8  modulation2;        // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode | 			u8  modulation2;        // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode | ||||||
| 			u8  Rsvd0; | 			u8  rsvd0; | ||||||
| 			u8  Flags; | 			u8  flags; | ||||||
| 			u32 frequency;         /* actual frequency in Hz */ | 			u32 frequency;         /* actual frequency in Hz */ | ||||||
| 			u32 rsvd1; | 			u32 rsvd1; | ||||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||||
| @@ -487,37 +575,37 @@ struct mci_result { | |||||||
| 		} isdbt_signal_info; | 		} isdbt_signal_info; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8  Constellation; | 			u8  constellation; | ||||||
| 			u8  Rsvd0[2]; | 			u8  rsvd0[2]; | ||||||
| 			u8  Flags; | 			u8  flags; | ||||||
|  |  | ||||||
| 			u32 Frequency;         // actual frequency in Hz | 			u32 frequency;         // actual frequency in Hz | ||||||
| 			u32 SymbolRate;        // actual symbolrate in Hz | 			u32 symbol_rate;       // actual symbolrate in Hz | ||||||
| 			s16  ChannelPower;      // channel power in dBm x 100 | 			s16 channel_power;     // channel power in dBm x 100 | ||||||
| 			s16  BandPower;         // band power in dBm x 100 | 			s16 band_power;        // band power in dBm x 100 | ||||||
| 			s16  SignalToNoise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||||
| 			s16  Rsvd2; | 			s16 rsvd2; | ||||||
| 			u32 PacketErrors;      // Counter for packet errors. (set to 0 on Start command) | 			u32 packet_errors;     // Counter for packet errors. (set to 0 on Start command) | ||||||
| 			u32 BERNumerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | 			u32 ber_numerator;     // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||||
| 			u32 BERDenominator; | 			u32 ber_denominator; | ||||||
| 		} ISDBC_SignalInfo; | 		} isdbc_signal_info; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8  Constellation; | 			u8  constellation; | ||||||
| 			u8  Interleaving; | 			u8  interleaving; | ||||||
| 			u8  Rsvd0; | 			u8  rsvd0; | ||||||
| 			u8  Flags; | 			u8  flags; | ||||||
|  |  | ||||||
| 			u32 Frequency;         // actual frequency in Hz | 			u32 frequency;         // actual frequency in Hz | ||||||
| 			u32 SymbolRate;        // actual symbolrate in Hz | 			u32 symbol_rate;        // actual symbolrate in Hz | ||||||
| 			s16  ChannelPower;      // channel power in dBm x 100 | 			s16 channel_power;      // channel power in dBm x 100 | ||||||
| 			s16  BandPower;         // band power in dBm x 100 | 			s16 band_power;         // band power in dBm x 100 | ||||||
| 			s16  SignalToNoise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||||
| 			s16  Rsvd2; | 			s16 rsvd2; | ||||||
| 			u32 PacketErrors;      // Counter for packet errors. (set to 0 on Start command) | 			u32 packet_errors;      // Counter for packet errors. (set to 0 on Start command) | ||||||
| 			u32 BERNumerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | 			u32 ber_numerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||||
| 			u32 BERDenominator; | 			u32 ber_denominator; | ||||||
| 		} J83B_SignalInfo; | 		} j83b_signal_info; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			s16 i; | 			s16 i; | ||||||
| @@ -525,13 +613,13 @@ struct mci_result { | |||||||
| 		} iq_symbol; | 		} iq_symbol; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			u8   TPSInfo[7]; | 			u8   tps_info[7]; | ||||||
|                         // uint16_t TPS_CellID;        // Cell Identifier | 			// uint16_t tps_cell_id; | ||||||
| 		} DVBT_TPSInfo; | 		} DVBT_TPSInfo; | ||||||
|  |  | ||||||
| 		struct { | 		struct { | ||||||
| 			struct  { | 			struct  { | ||||||
| 				u8 Type; | 				u8 type; | ||||||
| 				u8 BWExtension; | 				u8 BWExtension; | ||||||
| 				u8 S1; | 				u8 S1; | ||||||
| 				u8 S2; | 				u8 S2; | ||||||
| @@ -557,6 +645,7 @@ struct mci_result { | |||||||
| 				u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit | 				u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit | ||||||
| 				u8 CRC32[4]; | 				u8 CRC32[4]; | ||||||
| 			} DVBT2_L1Pre; | 			} DVBT2_L1Pre; | ||||||
|  |  | ||||||
| 			struct  { | 			struct  { | ||||||
| 				u8 SubSlicesPerFrame[2]; | 				u8 SubSlicesPerFrame[2]; | ||||||
| 				u8 NumPLP; | 				u8 NumPLP; | ||||||
| @@ -679,6 +768,13 @@ struct mci_result { | |||||||
| 			u8   Flags;  // Bit 5: EWS flag, bit 4: Site Diversity flag, bit 3..1: Site Diversity information, bit 0: Extension flag | 			u8   Flags;  // Bit 5: EWS flag, bit 4: Site Diversity flag, bit 3..1: Site Diversity information, bit 0: Extension flag | ||||||
| 			u8   Extension[8];   // 61 bits, right aligned | 			u8   Extension[8];   // 61 bits, right aligned | ||||||
| 		} ISDBS_TMCCInfo; | 		} ISDBS_TMCCInfo; | ||||||
|  |  | ||||||
|  | 		struct { | ||||||
|  | 			uint8_t  cut; | ||||||
|  | 			uint8_t  avs_code; | ||||||
|  | 			uint8_t  temperature; | ||||||
|  | 			uint8_t  rsvd[13]; | ||||||
|  | 		} sx8_bist; | ||||||
| 	}; | 	}; | ||||||
| 	u32 version[3]; | 	u32 version[3]; | ||||||
| 	u8  version_rsvd; | 	u8  version_rsvd; | ||||||
| @@ -758,6 +854,8 @@ struct mci_result { | |||||||
| #define L1POST_STATIC_FLAG(p)              (((p)[18] >> 1) & 0x01) | #define L1POST_STATIC_FLAG(p)              (((p)[18] >> 1) & 0x01) | ||||||
| #define L1POST_STATIC_PADDING_FLAG(p)      (((p)[18] >> 1) & 0x01) | #define L1POST_STATIC_PADDING_FLAG(p)      (((p)[18] >> 1) & 0x01) | ||||||
|  |  | ||||||
|  | #ifdef __KERNEL__ | ||||||
|  |  | ||||||
| struct mci_base { | struct mci_base { | ||||||
| 	struct list_head     mci_list; | 	struct list_head     mci_list; | ||||||
| 	void                *key; | 	void                *key; | ||||||
| @@ -797,9 +895,10 @@ int ddb_mci_get_info(struct mci *mci); | |||||||
| int ddb_mci_get_strength(struct dvb_frontend *fe); | int ddb_mci_get_strength(struct dvb_frontend *fe); | ||||||
| void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); | void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); | ||||||
| int mci_init(struct ddb_link *link); | int mci_init(struct ddb_link *link); | ||||||
| int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val); | int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val); | ||||||
|  |  | ||||||
| extern struct mci_cfg ddb_max_sx8_cfg; | extern struct mci_cfg ddb_max_sx8_cfg; | ||||||
| extern struct mci_cfg ddb_max_m4_cfg; | extern struct mci_cfg ddb_max_m4_cfg; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -644,7 +644,6 @@ static int mod_set_sdr_attenuator(struct ddb *dev, u32 value) | |||||||
| static int mod_set_sdr_gain(struct ddb *dev, u32 gain) | static int mod_set_sdr_gain(struct ddb *dev, u32 gain) | ||||||
| { | { | ||||||
| 	u32 control = ddbreadl(dev, SDR_CONTROL); | 	u32 control = ddbreadl(dev, SDR_CONTROL); | ||||||
| 	struct ddb_link *link = &dev->link[0]; |  | ||||||
|  |  | ||||||
| 	if (control & 0x01000000) { | 	if (control & 0x01000000) { | ||||||
| 		if (gain > 511) | 		if (gain > 511) | ||||||
| @@ -659,8 +658,6 @@ static int mod_set_sdr_gain(struct ddb *dev, u32 gain) | |||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		ddbwritel(dev, gain, SDR_GAIN_F); | 		ddbwritel(dev, gain, SDR_GAIN_F); | ||||||
| 	} | 	} | ||||||
| 	if (link->mci_ok) |  | ||||||
| 		mci_cmd_val(link, 0xc0, gain); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1866,6 +1863,8 @@ static int mod_init_2(struct ddb *dev, u32 Frequency) | |||||||
| 		dev_err(dev->dev, "FSM setup failed!\n"); | 		dev_err(dev->dev, "FSM setup failed!\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  | 	if (dev->link[0].ids.revision == 1) | ||||||
|  | 		return 0; | ||||||
| 	for (i = 0; i < streams; i++) { | 	for (i = 0; i < streams; i++) { | ||||||
| 		struct ddb_mod *mod = &dev->mod[i]; | 		struct ddb_mod *mod = &dev->mod[i]; | ||||||
|  |  | ||||||
| @@ -2032,6 +2031,9 @@ static int mod_init_sdr_iq(struct ddb *dev) | |||||||
| 	 | 	 | ||||||
| 	ddbwritel(dev, 0x01, 0x240); | 	ddbwritel(dev, 0x01, 0x240); | ||||||
|  |  | ||||||
|  | 	if (dev->link[0].ids.revision == 1) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
| 	//mod3_set_base_frequency(dev, 602000000); | 	//mod3_set_base_frequency(dev, 602000000); | ||||||
| 	dev->mod_base.frequency = 570000000; | 	dev->mod_base.frequency = 570000000; | ||||||
| 	for (i = 0; i < streams; i++) { | 	for (i = 0; i < streams; i++) { | ||||||
| @@ -2049,6 +2051,23 @@ static int mod_init_sdr_iq(struct ddb *dev) | |||||||
|  |  | ||||||
| int ddbridge_mod_init(struct ddb *dev) | int ddbridge_mod_init(struct ddb *dev) | ||||||
| { | { | ||||||
|  | 	dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision); | ||||||
|  | 	if (dev->link[0].ids.revision == 1) { | ||||||
|  | 		switch (dev->link[0].info->version) { | ||||||
|  | 		case 0: | ||||||
|  | 		case 1: | ||||||
|  | 			return mod_init_1(dev, 722000000); | ||||||
|  | 		case 2: /* FSM */ | ||||||
|  | 			return mod_init_2(dev, 114000000); | ||||||
|  | 		case 16: /* PAL */ | ||||||
|  | 			return mod_init_3(dev, 503250000); | ||||||
|  | 		case 17: /* raw IQ */ | ||||||
|  | 		case 18: /* IQ+FFT */ | ||||||
|  | 			return mod_init_sdr_iq(dev); | ||||||
|  | 		default: | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	switch (dev->link[0].info->version) { | 	switch (dev->link[0].info->version) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 	case 1: | 	case 1: | ||||||
|   | |||||||
| @@ -30,6 +30,10 @@ static int default_mod = 3; | |||||||
| module_param(default_mod, int, 0444); | module_param(default_mod, int, 0444); | ||||||
| MODULE_PARM_DESC(default_mod, "default modulations enabled, default is  3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); | MODULE_PARM_DESC(default_mod, "default modulations enabled, default is  3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); | ||||||
|  |  | ||||||
|  | static int direct_mode; | ||||||
|  | module_param(direct_mode, int, 0444); | ||||||
|  | MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate."); | ||||||
|  |  | ||||||
| static const u32 MCLK = (1550000000 / 12); | static const u32 MCLK = (1550000000 / 12); | ||||||
|  |  | ||||||
| /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ | /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ | ||||||
| @@ -44,25 +48,19 @@ struct sx8_base { | |||||||
| 	struct mci_base      mci_base; | 	struct mci_base      mci_base; | ||||||
|  |  | ||||||
| 	u8                   tuner_use_count[SX8_TUNER_NUM]; | 	u8                   tuner_use_count[SX8_TUNER_NUM]; | ||||||
| 	u32                  gain_mode[SX8_TUNER_NUM]; |  | ||||||
|  |  | ||||||
| 	u32                  used_ldpc_bitrate[SX8_DEMOD_NUM]; | 	u32                  used_ldpc_bitrate[SX8_DEMOD_NUM]; | ||||||
| 	u8                   demod_in_use[SX8_DEMOD_NUM]; | 	u8                   demod_in_use[SX8_DEMOD_NUM]; | ||||||
| 	u32                  iq_mode; | 	u32                  iq_mode; | ||||||
| 	u32                  burst_size; |  | ||||||
| 	u32                  direct_mode; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct sx8 { | struct sx8 { | ||||||
| 	struct mci           mci; | 	struct mci           mci; | ||||||
|  | 	struct mutex         lock; | ||||||
|  |  | ||||||
| 	int                  first_time_lock; | 	int                  first_time_lock; | ||||||
| 	int                  started; | 	int                  started; | ||||||
| 	int                  iq_started; | 	int                  iq_started; | ||||||
|  |  | ||||||
| 	u32                  bb_mode; |  | ||||||
| 	u32                  local_frequency; |  | ||||||
| 	 |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static const u8 dvbs2_bits_per_symbol[] = { | static const u8 dvbs2_bits_per_symbol[] = { | ||||||
| @@ -126,31 +124,47 @@ static int ddb_mci_tsconfig(struct mci *state, u32 config) | |||||||
|  |  | ||||||
| static int read_status(struct dvb_frontend *fe, enum fe_status *status) | static int read_status(struct dvb_frontend *fe, enum fe_status *status) | ||||||
| { | { | ||||||
| 	int stat; | 	int stat = 0; | ||||||
| 	struct sx8 *state = fe->demodulator_priv; | 	struct sx8 *state = fe->demodulator_priv; | ||||||
| 	struct mci_base *mci_base = state->mci.base; | 	struct mci_base *mci_base = state->mci.base; | ||||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||||
| 	struct mci_result res; | 	struct mci_result res; | ||||||
|  |  | ||||||
|  | 	*status = 0x00; | ||||||
|  | 	mutex_lock(&state->lock); | ||||||
|  | 	if (!state->started && !state->iq_started) | ||||||
|  | 		goto unlock; | ||||||
| 	stat = ddb_mci_get_status(&state->mci, &res); | 	stat = ddb_mci_get_status(&state->mci, &res); | ||||||
| 	if (stat) | 	if (stat) | ||||||
| 		return stat; | 		goto unlock; | ||||||
| 	*status = 0x00; |  | ||||||
| 	ddb_mci_get_info(&state->mci); | 	ddb_mci_get_info(&state->mci); | ||||||
| 	if (res.status == SX8_DEMOD_WAIT_MATYPE) | 	if (stat) | ||||||
| 		*status = 0x0f; | 		goto unlock; | ||||||
| 	if (res.status == MCI_DEMOD_LOCKED) { | 	if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { | ||||||
| 		*status = 0x1f; | 		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | | ||||||
| 		if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | 			FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = | 		if (res.status == MCI_DEMOD_LOCKED) { | ||||||
| 				p->symbol_rate * | 			mutex_lock(&mci_base->tuner_lock); | ||||||
| 				dvbs2_bits_per_symbol[ | 			if (state->first_time_lock && state->started) { | ||||||
| 					state->mci.signal_info. | 				if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | ||||||
| 					dvbs2_signal_info.pls_code]; | 					sx8_base->used_ldpc_bitrate[state->mci.nr] = | ||||||
| 		} else  | 						p->symbol_rate * | ||||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; | 						dvbs2_bits_per_symbol[ | ||||||
| 	} | 							state->mci.signal_info. | ||||||
|  | 							dvbs2_signal_info.pls_code]; | ||||||
|  | 				} else | ||||||
|  | 					sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; | ||||||
|  | 				state->first_time_lock = 0; | ||||||
|  | 			} | ||||||
|  | 			mutex_unlock(&mci_base->tuner_lock); | ||||||
|  | 		} | ||||||
|  | 	} else if (res.status == MCI_DEMOD_TIMEOUT) | ||||||
|  | 		*status = FE_TIMEDOUT; | ||||||
|  | 	else if (res.status >= SX8_DEMOD_WAIT_MATYPE) | ||||||
|  | 		*status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||||||
|  | unlock: | ||||||
|  | 	mutex_unlock(&state->lock); | ||||||
| 	return stat; | 	return stat; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,14 +172,12 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on, | |||||||
| 			 u8 flags, u8 gain) | 			 u8 flags, u8 gain) | ||||||
| { | { | ||||||
| 	struct sx8 *state = fe->demodulator_priv; | 	struct sx8 *state = fe->demodulator_priv; | ||||||
| 	struct mci_base *mci_base = state->mci.base; |  | ||||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; |  | ||||||
| 	struct mci_command cmd; | 	struct mci_command cmd; | ||||||
|  |  | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); | 	memset(&cmd, 0, sizeof(cmd)); | ||||||
| 	cmd.tuner = state->mci.tuner; | 	cmd.tuner = state->mci.tuner; | ||||||
| 	cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; | 	cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; | ||||||
| 	cmd.sx8_input_enable.flags = flags;//sx8_base->gain_mode[state->mci.tuner]; | 	cmd.sx8_input_enable.flags = flags; | ||||||
| 	cmd.sx8_input_enable.rf_gain = gain; | 	cmd.sx8_input_enable.rf_gain = gain; | ||||||
| 	return ddb_mci_cmd(&state->mci, &cmd, NULL); | 	return ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||||
| } | } | ||||||
| @@ -195,9 +207,9 @@ static int stop_iq(struct dvb_frontend *fe) | |||||||
| 		state->mci.demod = SX8_DEMOD_NONE; | 		state->mci.demod = SX8_DEMOD_NONE; | ||||||
| 	} | 	} | ||||||
| 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | ||||||
|  | 	mutex_unlock(&mci_base->tuner_lock); | ||||||
| 	sx8_base->iq_mode = 0; | 	sx8_base->iq_mode = 0; | ||||||
| 	state->iq_started = 0; | 	state->iq_started = 0; | ||||||
| 	mutex_unlock(&mci_base->tuner_lock); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -207,12 +219,13 @@ static int stop(struct dvb_frontend *fe) | |||||||
| 	struct mci_base *mci_base = state->mci.base; | 	struct mci_base *mci_base = state->mci.base; | ||||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||||
| 	struct mci_command cmd; | 	struct mci_command cmd; | ||||||
| 	u32 input = state->mci.tuner; | 	u32 input; | ||||||
|  |  | ||||||
|  | 	input = state->mci.tuner; | ||||||
| 	if (!state->started) | 	if (!state->started) | ||||||
| 		return -1; | 		return -1; | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); |  | ||||||
| 	if (state->mci.demod != SX8_DEMOD_NONE) { | 	if (state->mci.demod != SX8_DEMOD_NONE) { | ||||||
|  | 		memset(&cmd, 0, sizeof(cmd)); | ||||||
| 		cmd.command = MCI_CMD_STOP; | 		cmd.command = MCI_CMD_STOP; | ||||||
| 		cmd.demod = state->mci.demod; | 		cmd.demod = state->mci.demod; | ||||||
| 		ddb_mci_cmd(&state->mci, &cmd, NULL); | 		ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||||
| @@ -234,8 +247,8 @@ static int stop(struct dvb_frontend *fe) | |||||||
| 	} | 	} | ||||||
| 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | ||||||
| 	sx8_base->iq_mode = 0; | 	sx8_base->iq_mode = 0; | ||||||
| 	mutex_unlock(&mci_base->tuner_lock); |  | ||||||
| 	state->started = 0; | 	state->started = 0; | ||||||
|  | 	mutex_unlock(&mci_base->tuner_lock); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -253,6 +266,10 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | |||||||
| 	u32 bits_per_symbol = 0; | 	u32 bits_per_symbol = 0; | ||||||
| 	int i = -1, stat = 0; | 	int i = -1, stat = 0; | ||||||
| 	struct ddb_link *link = state->mci.base->link; | 	struct ddb_link *link = state->mci.base->link; | ||||||
|  | 	const u8 ro_lut[8] = { | ||||||
|  | 		8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0, | ||||||
|  | 		8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0, | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	if (link->ids.device == 0x000b) { | 	if (link->ids.device == 0x000b) { | ||||||
| 		/* Mask out higher modulations and MIS for Basic | 		/* Mask out higher modulations and MIS for Basic | ||||||
| @@ -280,7 +297,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | |||||||
| 		goto unlock; | 		goto unlock; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sx8_base->direct_mode) { | 	if (direct_mode) { | ||||||
| 		if (p->symbol_rate >= MCLK / 2) { | 		if (p->symbol_rate >= MCLK / 2) { | ||||||
| 			if (state->mci.nr < 4) | 			if (state->mci.nr < 4) | ||||||
| 				i = state->mci.nr; | 				i = state->mci.nr; | ||||||
| @@ -309,9 +326,8 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | |||||||
| 			stat = -EBUSY; | 			stat = -EBUSY; | ||||||
| 			goto unlock; | 			goto unlock; | ||||||
| 		} | 		} | ||||||
| 		 |  | ||||||
| 		modmask &= ((1 << (bits_per_symbol - 1)) - 1); | 		modmask &= ((1 << (bits_per_symbol - 1)) - 1); | ||||||
| 		if( ((flags & 0x02) != 0)  &&  (modmask == 0)) { | 		if (((flags & 0x02) != 0) && (modmask == 0)) { | ||||||
| 			stat = -EBUSY; | 			stat = -EBUSY; | ||||||
| 			goto unlock; | 			goto unlock; | ||||||
| 		} | 		} | ||||||
| @@ -337,11 +353,10 @@ unlock: | |||||||
| 	if (stat) | 	if (stat) | ||||||
| 		return stat; | 		return stat; | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); | 	memset(&cmd, 0, sizeof(cmd)); | ||||||
| 	 |  | ||||||
| 	if (sx8_base->iq_mode) { | 	if (sx8_base->iq_mode) { | ||||||
| 		cmd.command = SX8_CMD_ENABLE_IQOUTPUT; | 		cmd.command = SX8_CMD_ENABLE_IQOUTPUT; | ||||||
| 		cmd.demod = state->mci.demod; | 		cmd.demod = state->mci.demod; | ||||||
| 		cmd.output = p->stream_id & 7; | 		cmd.output = p->stream_id & 0x0f; | ||||||
| 		ddb_mci_cmd(&state->mci, &cmd, NULL); | 		ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||||
| 		ddb_mci_tsconfig(&state->mci, ts_config); | 		ddb_mci_tsconfig(&state->mci, ts_config); | ||||||
| 	} | 	} | ||||||
| @@ -357,6 +372,7 @@ unlock: | |||||||
| 	cmd.command = MCI_CMD_SEARCH_DVBS; | 	cmd.command = MCI_CMD_SEARCH_DVBS; | ||||||
| 	cmd.dvbs2_search.flags = flags; | 	cmd.dvbs2_search.flags = flags; | ||||||
| 	cmd.dvbs2_search.s2_modulation_mask = modmask; | 	cmd.dvbs2_search.s2_modulation_mask = modmask; | ||||||
|  | 	cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7]; | ||||||
| 	cmd.dvbs2_search.retry = 2; | 	cmd.dvbs2_search.retry = 2; | ||||||
| 	cmd.dvbs2_search.frequency = p->frequency * 1000; | 	cmd.dvbs2_search.frequency = p->frequency * 1000; | ||||||
| 	cmd.dvbs2_search.symbol_rate = p->symbol_rate; | 	cmd.dvbs2_search.symbol_rate = p->symbol_rate; | ||||||
| @@ -370,6 +386,9 @@ unlock: | |||||||
| 	    (p->stream_id & 0x80000000)) | 	    (p->stream_id & 0x80000000)) | ||||||
| 		cmd.output |= 0x80; | 		cmd.output |= 0x80; | ||||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||||
|  | 	state->started = 1; | ||||||
|  | 	state->first_time_lock = 1; | ||||||
|  | 	state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; | ||||||
| 	if (stat) | 	if (stat) | ||||||
| 		stop(fe); | 		stop(fe); | ||||||
| 	return stat; | 	return stat; | ||||||
| @@ -388,8 +407,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | |||||||
| 	u32 input = state->mci.tuner; | 	u32 input = state->mci.tuner; | ||||||
| 	int i, stat = 0; | 	int i, stat = 0; | ||||||
|  |  | ||||||
|  | 	mutex_lock(&mci_base->tuner_lock); | ||||||
| 	if (!state->iq_started) { | 	if (!state->iq_started) { | ||||||
| 		mutex_lock(&mci_base->tuner_lock); |  | ||||||
| 		if (sx8_base->iq_mode) { | 		if (sx8_base->iq_mode) { | ||||||
| 			stat = -EBUSY; | 			stat = -EBUSY; | ||||||
| 			goto unlock; | 			goto unlock; | ||||||
| @@ -402,17 +421,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | |||||||
| 			goto unlock; | 			goto unlock; | ||||||
| 		} | 		} | ||||||
| 		state->mci.demod = 0; | 		state->mci.demod = 0; | ||||||
| 		/* |  | ||||||
| 		  if (!sx8_base->tuner_use_count[input]) |  | ||||||
| 			mci_set_tuner(fe, input, 1); |  | ||||||
| 		*/ |  | ||||||
| 		sx8_base->tuner_use_count[input]++; | 		sx8_base->tuner_use_count[input]++; | ||||||
| 		sx8_base->iq_mode = (ts_config > 1); | 		sx8_base->iq_mode = 2; | ||||||
| 	unlock: | 	} else { | ||||||
| 		mutex_unlock(&mci_base->tuner_lock); | 		if ((state->iq_started & 0x07) != state->mci.nr) { | ||||||
| 		if (stat) | 			stat = -EBUSY; | ||||||
| 			return stat; | 			goto unlock; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | unlock: | ||||||
|  | 	mutex_unlock(&mci_base->tuner_lock); | ||||||
|  | 	if (stat) | ||||||
|  | 		return stat; | ||||||
| 	mci_set_tuner(fe, input, 1, flags & 0xff, 0); | 	mci_set_tuner(fe, input, 1, flags & 0xff, 0); | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); | 	memset(&cmd, 0, sizeof(cmd)); | ||||||
| 	cmd.command = SX8_CMD_START_IQ; | 	cmd.command = SX8_CMD_START_IQ; | ||||||
| @@ -424,6 +444,9 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | |||||||
| 	cmd.tuner = state->mci.tuner; | 	cmd.tuner = state->mci.tuner; | ||||||
| 	cmd.demod = state->mci.demod; | 	cmd.demod = state->mci.demod; | ||||||
| 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | 	stat = ddb_mci_cmd(&state->mci, &cmd, NULL); | ||||||
|  | 	state->iq_started = 8 | state->mci.nr; | ||||||
|  | 	state->first_time_lock = 1; | ||||||
|  | 	state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; | ||||||
| 	if (stat) | 	if (stat) | ||||||
| 		stop_iq(fe); | 		stop_iq(fe); | ||||||
| 	ddb_mci_tsconfig(&state->mci, ts_config); | 	ddb_mci_tsconfig(&state->mci, ts_config); | ||||||
| @@ -436,7 +459,6 @@ static int set_lna(struct dvb_frontend *fe) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static int set_parameters(struct dvb_frontend *fe) | static int set_parameters(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	int stat = 0; | 	int stat = 0; | ||||||
| @@ -452,6 +474,7 @@ static int set_parameters(struct dvb_frontend *fe) | |||||||
| 	state->mci.input->con = ts_mode << 8; | 	state->mci.input->con = ts_mode << 8; | ||||||
| 	if (iq_mode) | 	if (iq_mode) | ||||||
| 		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); | 		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); | ||||||
|  | 	mutex_lock(&state->lock); | ||||||
| 	stop(fe); | 	stop(fe); | ||||||
| 	if (iq_mode < 2) { | 	if (iq_mode < 2) { | ||||||
| 		u32 mask; | 		u32 mask; | ||||||
| @@ -478,19 +501,10 @@ static int set_parameters(struct dvb_frontend *fe) | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		stat = start(fe, 3, mask, ts_config); | 		stat = start(fe, 3, mask, ts_config); | ||||||
| 		if (!stat) { |  | ||||||
| 			state->started = 1; |  | ||||||
| 			state->first_time_lock = 1; |  | ||||||
| 			state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; |  | ||||||
| 		} |  | ||||||
| 	} else { | 	} else { | ||||||
| 		stat = start_iq(fe, isi & 0xffffff, 4, ts_config); | 		stat = start_iq(fe, isi & 0xffffff, 4, ts_config); | ||||||
| 		if (!stat) { |  | ||||||
| 			state->iq_started = 1; |  | ||||||
| 			state->first_time_lock = 1; |  | ||||||
| 			state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  | 	mutex_unlock(&state->lock); | ||||||
| 	return stat; | 	return stat; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -529,16 +543,22 @@ static int set_input(struct dvb_frontend *fe, int input) | |||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (state->mci.tuner == input) | 	if (state->mci.tuner == input) | ||||||
| 		return 0; | 		return 0; | ||||||
|  | 	mutex_lock(&state->lock); | ||||||
| 	stop_iq(fe); | 	stop_iq(fe); | ||||||
| 	stop(fe); | 	stop(fe); | ||||||
| 	state->mci.tuner = p->input = input; | 	state->mci.tuner = p->input = input; | ||||||
|  | 	mutex_unlock(&state->lock); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int sleep(struct dvb_frontend *fe) | static int sleep(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
|  | 	struct sx8 *state = fe->demodulator_priv; | ||||||
|  |  | ||||||
|  | 	mutex_lock(&state->lock); | ||||||
| 	stop_iq(fe); | 	stop_iq(fe); | ||||||
| 	stop(fe); | 	stop(fe); | ||||||
|  | 	mutex_unlock(&state->lock); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -584,6 +604,7 @@ static int init(struct mci *mci) | |||||||
| 	state->mci.demod = SX8_DEMOD_NONE; | 	state->mci.demod = SX8_DEMOD_NONE; | ||||||
| 	mci->fe.ops.xbar[1] = mci->nr; | 	mci->fe.ops.xbar[1] = mci->nr; | ||||||
| 	mci->fe.dtv_property_cache.input = mci->tuner; | 	mci->fe.dtv_property_cache.input = mci->tuner; | ||||||
|  | 	mutex_init(&state->lock); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ | |||||||
| #ifndef _DDBRIDGE_H_ | #ifndef _DDBRIDGE_H_ | ||||||
| #define _DDBRIDGE_H_ | #define _DDBRIDGE_H_ | ||||||
|  |  | ||||||
| #define DDB_USE_WORK | /* #define DDB_USE_WORK */ | ||||||
| /*#define DDB_TEST_THREADED*/ | /*#define DDB_TEST_THREADED*/ | ||||||
|  |  | ||||||
| #include <linux/version.h> | #include <linux/version.h> | ||||||
| @@ -143,6 +143,7 @@ struct ddb_ids { | |||||||
| 	u32 regmapid; | 	u32 regmapid; | ||||||
| 	u32 devid; | 	u32 devid; | ||||||
| 	u32 mac; | 	u32 mac; | ||||||
|  | 	u8 revision; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct ddb_info { | struct ddb_info { | ||||||
| @@ -219,6 +220,7 @@ struct ddb_dma { | |||||||
|  |  | ||||||
| 	u32                    stall_count; | 	u32                    stall_count; | ||||||
| 	u32                    packet_loss; | 	u32                    packet_loss; | ||||||
|  | 	u32                    unaligned; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct ddb_dvb { | struct ddb_dvb { | ||||||
|   | |||||||
| @@ -54,6 +54,7 @@ struct cxd_state { | |||||||
| 	struct dvb_frontend   frontend; | 	struct dvb_frontend   frontend; | ||||||
| 	struct i2c_adapter   *i2c; | 	struct i2c_adapter   *i2c; | ||||||
| 	struct mutex          mutex; | 	struct mutex          mutex; | ||||||
|  | 	int repi2cerr; | ||||||
|  |  | ||||||
| 	u8  adrt; | 	u8  adrt; | ||||||
| 	u8  curbankt; | 	u8  curbankt; | ||||||
| @@ -91,12 +92,13 @@ struct cxd_state { | |||||||
| 	u8    is24MHz; | 	u8    is24MHz; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) | static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len, int flag) | ||||||
| { | { | ||||||
| 	struct i2c_msg msg = { | 	struct i2c_msg msg = { | ||||||
| 		.addr = adr, .flags = 0, .buf = data, .len = len};  | 		.addr = adr, .flags = 0, .buf = data, .len = len};  | ||||||
| 	if (i2c_transfer(adap, &msg, 1) != 1) { | 	if (i2c_transfer(adap, &msg, 1) != 1) { | ||||||
| 		pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); | 		if (flag) | ||||||
|  | 			pr_err("cxd2843: i2c_write error adr %02x data %02x\n", adr, data[0]); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| @@ -113,14 +115,14 @@ static int writeregs(struct cxd_state *state, u8 adr, u8 reg, | |||||||
| 	} | 	} | ||||||
| 	data[0] = reg; | 	data[0] = reg; | ||||||
| 	memcpy(data + 1, regd, len); | 	memcpy(data + 1, regd, len); | ||||||
| 	return i2c_write(state->i2c, adr, data, len + 1); | 	return i2c_write(state->i2c, adr, data, len + 1, state->repi2cerr);  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) | static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) | ||||||
| { | { | ||||||
| 	u8 mm[2] = {reg, dat}; | 	u8 mm[2] = {reg, dat}; | ||||||
|  |  | ||||||
| 	return i2c_write(state->i2c, adr, mm, 2); | 	return i2c_write(state->i2c, adr, mm, 2, state->repi2cerr);  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int i2c_read(struct i2c_adapter *adap, | static int i2c_read(struct i2c_adapter *adap, | ||||||
| @@ -130,17 +132,19 @@ static int i2c_read(struct i2c_adapter *adap, | |||||||
| 				     .buf = msg, .len = len}, | 				     .buf = msg, .len = len}, | ||||||
| 				   { .addr = adr, .flags = I2C_M_RD, | 				   { .addr = adr, .flags = I2C_M_RD, | ||||||
| 				     .buf = answ, .len = alen } }; | 				     .buf = answ, .len = alen } }; | ||||||
| 	if (i2c_transfer(adap, msgs, 2) != 2) { | 	if (i2c_transfer(adap, msgs, 2) != 2) | ||||||
| 		pr_err("cxd2843: i2c_read error\n"); |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int readregs(struct cxd_state *state, u8 adr, u8 reg, | static int readregs(struct cxd_state *state, u8 adr, u8 reg, | ||||||
| 		    u8 *val, int count) | 		    u8 *val, int count) | ||||||
| { | { | ||||||
| 	return i2c_read(state->i2c, adr, ®, 1, val, count); | 	int ret = i2c_read(state->i2c, adr, ®, 1, val, count); | ||||||
|  |  | ||||||
|  | 	if (ret && state->repi2cerr) | ||||||
|  | 		pr_err("cxd2843: i2c_read error\n"); | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int readregst_unlocked(struct cxd_state *cxd, u8 bank, | static int readregst_unlocked(struct cxd_state *cxd, u8 bank, | ||||||
| @@ -1644,7 +1648,7 @@ static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) | |||||||
| 	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ | 	/* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ | ||||||
| 	state->IF_FS = 0x50; | 	state->IF_FS = 0x50; | ||||||
| 	state->is24MHz = (cfg->osc == 24000000) ? 1 : 0; | 	state->is24MHz = (cfg->osc == 24000000) ? 1 : 0; | ||||||
| 	printk("is24Mhz = %u\n", state->is24MHz); | 	printk("is24Mhz = %u, adr = %02x\n", state->is24MHz, cfg->adr); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int get_tune_settings(struct dvb_frontend *fe, | static int get_tune_settings(struct dvb_frontend *fe, | ||||||
| @@ -2647,7 +2651,8 @@ static int probe(struct cxd_state *state) | |||||||
| 	if (status) | 	if (status) | ||||||
| 		return status; | 		return status; | ||||||
| 	 | 	 | ||||||
| 	printk("ChipID  = %02X\n", ChipID); | 	state->repi2cerr = 1; | ||||||
|  | 	//pr_info("cxd2843: ChipID  = %02X\n", ChipID); | ||||||
| 	switch (ChipID) { | 	switch (ChipID) { | ||||||
| 	case 0xa4: | 	case 0xa4: | ||||||
| 		state->type = CXD2843; | 		state->type = CXD2843; | ||||||
| @@ -2682,7 +2687,6 @@ struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, | |||||||
| { | { | ||||||
| 	struct cxd_state *state = NULL; | 	struct cxd_state *state = NULL; | ||||||
|  |  | ||||||
| 	pr_info("attach\n"); |  | ||||||
| 	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); | 	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); | ||||||
| 	if (!state) | 	if (!state) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|   | |||||||
| @@ -208,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val) | |||||||
| 	return write_reg(state, field >> 16, new); | 	return write_reg(state, field >> 16, new); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int read_field(struct stv *state, u32 field, u8 *val) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | 	u8 shift, mask; | ||||||
|  |  | ||||||
|  | 	status = read_reg(state, field >> 16, val); | ||||||
|  | 	if (status) | ||||||
|  | 		return status; | ||||||
|  | 	mask = field & 0xff; | ||||||
|  | 	shift = (field >> 12) & 0xf; | ||||||
|  | 	*val = (*val & mask) >> shift; | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  |  | ||||||
| #define set_field(_reg, _val)					\ | #define set_field(_reg, _val)					\ | ||||||
| 	write_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | 	write_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | ||||||
| 		    FSTV0910_P1_##_reg, _val) | 		    FSTV0910_P1_##_reg, _val) | ||||||
|  |  | ||||||
|  | #define get_field(_reg, _val)					\ | ||||||
|  | 	read_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | ||||||
|  | 		   FSTV0910_P1_##_reg, _val) | ||||||
|  |  | ||||||
| #define set_reg(_reg, _val)					\ | #define set_reg(_reg, _val)					\ | ||||||
| 	write_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | 	write_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||||
| 		  RSTV0910_P1_##_reg, _val) | 		  RSTV0910_P1_##_reg, _val) | ||||||
|  |  | ||||||
| #define get_reg(_reg, _val)					\ | #define get_reg(_reg, _val)					\ | ||||||
| 	read_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | 	read_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||||
| 		 RTV0910_P1_##_reg, _val) | 		 RSTV0910_P1_##_reg, _val) | ||||||
|  |  | ||||||
| static const struct slookup s1_sn_lookup[] = { | static const struct slookup s1_sn_lookup[] = { | ||||||
| 	{   0,    9242  }, /* C/N=  0dB */ | 	{   0,    9242  }, /* C/N=  0dB */ | ||||||
| @@ -1112,8 +1130,9 @@ static int init_diseqc(struct stv *state) | |||||||
| 	u16 offs = state->nr ? 0x40 : 0;  /* Address offset */ | 	u16 offs = state->nr ? 0x40 : 0;  /* Address offset */ | ||||||
| 	u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); | 	u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); | ||||||
|  |  | ||||||
| 	/* Disable receiver */ | 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05); | ||||||
| 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); | 	//write_reg(state, RSTV0910_P1_DISRXF220 + offs, 0x69); 2b? | ||||||
|  |  | ||||||
| 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ | 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ | ||||||
| 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ | 	write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ | ||||||
| 	write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); | 	write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); | ||||||
| @@ -1617,12 +1636,28 @@ static int wait_dis(struct stv *state, u8 flag, u8 val) | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int clear_slave(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct stv *state = fe->demodulator_priv; | ||||||
|  | 	u8 n, d, done; | ||||||
|  |  | ||||||
|  | 	get_field(RXEND, &done); | ||||||
|  | 	get_reg(DISRXBYTES, &n); | ||||||
|  | 	printk("clear: done = %u, %u fifo bytes\n", done, n); | ||||||
|  | 	 | ||||||
|  | 	for (get_reg(DISRXBYTES, &n); n; n--)  | ||||||
|  | 		get_reg(DISRXFIFO, &d); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int send_master_cmd(struct dvb_frontend *fe, | static int send_master_cmd(struct dvb_frontend *fe, | ||||||
| 			   struct dvb_diseqc_master_cmd *cmd) | 			   struct dvb_diseqc_master_cmd *cmd) | ||||||
| { | { | ||||||
| 	struct stv *state = fe->demodulator_priv; | 	struct stv *state = fe->demodulator_priv; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
|  | 	clear_slave(fe); | ||||||
|  | 	set_field(DISRX_ON, 0); | ||||||
| 	set_reg(DISTXCFG, 0x3e); | 	set_reg(DISTXCFG, 0x3e); | ||||||
| 	for (i = 0; i < cmd->msg_len; i++) { | 	for (i = 0; i < cmd->msg_len; i++) { | ||||||
| 		wait_dis(state, 0x40, 0x00); | 		wait_dis(state, 0x40, 0x00); | ||||||
| @@ -1630,12 +1665,59 @@ static int send_master_cmd(struct dvb_frontend *fe, | |||||||
| 	} | 	} | ||||||
| 	set_reg(DISTXCFG, 0x3a); | 	set_reg(DISTXCFG, 0x3a); | ||||||
| 	wait_dis(state, 0x20, 0x20); | 	wait_dis(state, 0x20, 0x20); | ||||||
|  | 	set_field(DISRX_ON, 1); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int recv_slave_reply(struct dvb_frontend *fe, | static int recv_slave_reply(struct dvb_frontend *fe, | ||||||
| 			    struct dvb_diseqc_slave_reply *reply) | 			    struct dvb_diseqc_slave_reply *reply) | ||||||
| { | { | ||||||
|  | 	struct stv *state = fe->demodulator_priv; | ||||||
|  | 	int i, to, flag = 0, max = sizeof(reply->msg); | ||||||
|  | 	u8 done, val, n = 0; | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  | #if 0 | ||||||
|  | 	get_reg(DISRXBYTES, &val); | ||||||
|  | 	get_field(RXEND, &done); | ||||||
|  | 	printk("slave: done = %u, %u fifo bytes\n", done, val); | ||||||
|  | #endif | ||||||
|  | 	to = reply->timeout; | ||||||
|  | 	if (to < 0) { | ||||||
|  | 		to = 100; | ||||||
|  | 		flag = 1; | ||||||
|  | 	} else if (to > 5000) | ||||||
|  | 		to = 100; | ||||||
|  | 	reply->msg_len = 0; | ||||||
|  | 	for (i = 0; i < to; i += 10) { | ||||||
|  | 		get_reg(DISRXBYTES, &val); | ||||||
|  | 		if (flag && val) | ||||||
|  | 			break; | ||||||
|  | 		get_field(RXEND, &done); | ||||||
|  | 		if (val >= max || done) | ||||||
|  | 			break; | ||||||
|  | 		msleep(10); | ||||||
|  | 	} | ||||||
|  | 	get_reg(DISRXBYTES, &val); | ||||||
|  | 	printk("done = %u, %u fifo bytes, i=%u\n", done, val, i); | ||||||
|  | 	if (i == to && !val) | ||||||
|  | 		return -EIO; | ||||||
|  | 	if (done && !val) | ||||||
|  | 		return -EIO; | ||||||
|  | 	for (i = 100; i; i--) { | ||||||
|  | 		get_field(RXEND, &done); | ||||||
|  | 		 | ||||||
|  | 		for (get_reg(DISRXBYTES, &n); n; n--) { | ||||||
|  | 			if (reply->msg_len == max) | ||||||
|  | 				return 0; | ||||||
|  | 			get_reg(DISRXFIFO, &reply->msg[reply->msg_len++]); | ||||||
|  | 		} | ||||||
|  | 		if (!n || done) | ||||||
|  | 			break; | ||||||
|  | 		msleep(10); | ||||||
|  | 	} | ||||||
|  | 	if (!i) | ||||||
|  | 		return -EIO; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -447,9 +447,6 @@ static int attach_init(struct tda_state *state) | |||||||
| 	if (!state->m_isMaster) | 	if (!state->m_isMaster) | ||||||
| 		state->m_bLTEnable = false; | 		state->m_bLTEnable = false; | ||||||
|  |  | ||||||
| 	/*pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID, |  | ||||||
| 	  state->m_isMaster ? "master" : "slave");*/ |  | ||||||
|  |  | ||||||
| 	if (state->m_ID != 18212) | 	if (state->m_ID != 18212) | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| @@ -457,8 +454,6 @@ static int attach_init(struct tda_state *state) | |||||||
| 	if (stat < 0) | 	if (stat < 0) | ||||||
| 		return stat; | 		return stat; | ||||||
| 	 | 	 | ||||||
| 	/*pr_info("tda18212dd: PowerState %02x\n", PowerState);*/ |  | ||||||
|  |  | ||||||
| 	if (state->m_isMaster) { | 	if (state->m_isMaster) { | ||||||
| 		if (PowerState & 0x02) { | 		if (PowerState & 0x02) { | ||||||
| 			/* msleep for XTAL Calibration | 			/* msleep for XTAL Calibration | ||||||
| @@ -539,7 +534,6 @@ static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) | |||||||
| 		if (*pPowerLevel > 110) | 		if (*pPowerLevel > 110) | ||||||
| 			*pPowerLevel = 110; | 			*pPowerLevel = 110; | ||||||
| 	} while (0); | 	} while (0); | ||||||
| 	/* pr_info("PL %d\n", *pPowerLevel); */ |  | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -806,7 +800,6 @@ static int set_params(struct dvb_frontend *fe) | |||||||
|  |  | ||||||
| 	bw = (p->bandwidth_hz + 999999) / 1000000; | 	bw = (p->bandwidth_hz + 999999) / 1000000; | ||||||
| 	state->m_Frequency = p->frequency; | 	state->m_Frequency = p->frequency; | ||||||
| 	/*pr_info("tuner bw=%u  freq=%u\n", bw, state->m_Frequency);*/ |  | ||||||
| 	if (p->delivery_system == SYS_DVBT || | 	if (p->delivery_system == SYS_DVBT || | ||||||
| 	    p->delivery_system == SYS_DVBT2 || | 	    p->delivery_system == SYS_DVBT2 || | ||||||
| 	    p->delivery_system == SYS_ISDBT || | 	    p->delivery_system == SYS_ISDBT || | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								lib/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lib/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | # LIBDDDVB | ||||||
|  | The libdddvb provides a userspace library to simplify tuning and | ||||||
|  | CI use. It detects DVB cards and their capabilities and selects | ||||||
|  | free frontends depending on a given delivery system. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | In order to install the libdddvb library you need the dvben50221. | ||||||
|  |  | ||||||
|  | On an Ubuntu and other Debian based system you can install it like this: | ||||||
|  |  | ||||||
|  | `sudo apt-get install dvb-apps`  | ||||||
|  |  | ||||||
|  | After that you can build the libdddvb: | ||||||
|  |  | ||||||
|  | `git clone https://github.com/DigitalDevices/dddvb.git`  | ||||||
|  |  | ||||||
|  | `cd dddvb/lib/; make`  | ||||||
|  |  | ||||||
|  | `sudo make install`  | ||||||
|  |  | ||||||
|  | If your distribution does not include a dvb-apps package, you can follow the  | ||||||
|  | instructions at  | ||||||
|  |  | ||||||
|  | https://www.linuxtv.org/wiki/index.php/LinuxTV_dvb-apps | ||||||
|  |  | ||||||
|  | on how to build it yourself. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # DDZAP | ||||||
|  |  | ||||||
|  | You can now use the example program ddzap to see how the library | ||||||
|  | is used or to test your cards. | ||||||
|  |  | ||||||
|  | A typical usage example would be the tuning of a | ||||||
|  | sattelite channel with a given LNB configuration. | ||||||
|  |   | ||||||
|  | `ddzap -d S2 -p h -f 11494000  -s 22000000  -c ~/dddvb/lib/config/` | ||||||
|  |  | ||||||
|  | where you would use the example configuration file for a unicable LNB | ||||||
|  | given in the sources. If you leave out the `-c` option a standard universal | ||||||
|  | LNB is assumed to be connected. | ||||||
|  |  | ||||||
|  | Additionally you can use ddzap to open the /dev/dvb/adaptorX/dvrY device | ||||||
|  | that corresponds to the tuner that was automatically selected by the library | ||||||
|  | and pipe it to a media player, e.g. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | `ddzap -d S2 -p h -f 11494000  -s 22000000  -c /home/dmocm/ddzapconf/  -o|vlc -`  | ||||||
|  |  | ||||||
| @@ -271,7 +271,7 @@ int main(int argc, char **argv) | |||||||
| 	struct dddvb_fe *fe; | 	struct dddvb_fe *fe; | ||||||
| 	struct dddvb_params p; | 	struct dddvb_params p; | ||||||
| 	uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF; | 	uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF; | ||||||
| 	uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0; | 	uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = DDDVB_UNDEF; | ||||||
| 	uint32_t mtype= DDDVB_UNDEF; | 	uint32_t mtype= DDDVB_UNDEF; | ||||||
| 	uint32_t verbosity = 0; | 	uint32_t verbosity = 0; | ||||||
| 	uint32_t get_ts = 1; | 	uint32_t get_ts = 1; | ||||||
|   | |||||||
| @@ -288,7 +288,8 @@ static int tune_sat(struct dddvb_fe *fe) | |||||||
| 			freq = lofs - freq; | 			freq = lofs - freq; | ||||||
| 	}  | 	}  | ||||||
| #endif | #endif | ||||||
| 	if (freq > 2100000) { |  | ||||||
|  | 	if (freq > 3000000) { | ||||||
| 		if (lofs) | 		if (lofs) | ||||||
| 			hi = (freq > lofs) ? 1 : 0; | 			hi = (freq > lofs) ? 1 : 0; | ||||||
| 		if (hi)  | 		if (hi)  | ||||||
| @@ -318,14 +319,15 @@ static int tune_sat(struct dddvb_fe *fe) | |||||||
| 			    fe->scif_slot, fe->scif_freq, ds); | 			    fe->scif_slot, fe->scif_freq, ds); | ||||||
| 		pthread_mutex_unlock(&fe->dd->uni_lock); | 		pthread_mutex_unlock(&fe->dd->uni_lock); | ||||||
| 	} else { | 	} else { | ||||||
| 		uint32_t input = lnb; | 		uint32_t input = fe->param.param[PARAM_SRC]; | ||||||
|  |  | ||||||
| 		//if (input != DDDVB_UNDEF) | 		if (input != DDDVB_UNDEF) { | ||||||
| 		//	input = 3 & (input >> 6); | 			input = 3 & (input >> 6); | ||||||
| 		//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6)); | 			printf("input = %u\n", input); | ||||||
|  | 		} | ||||||
| 		diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi); | 		diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi); | ||||||
| 		//set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); | 		set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); | ||||||
| 		set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U)); | 		//set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, DDDVB_UNDEF); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -750,6 +752,8 @@ int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p) | |||||||
| 	memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param)); | 	memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param)); | ||||||
| 	fe->n_tune = 1; | 	fe->n_tune = 1; | ||||||
| 	pthread_mutex_unlock(&fe->mutex); | 	pthread_mutex_unlock(&fe->mutex); | ||||||
|  | 	while(fe->n_tune) usleep(10000); | ||||||
|  | 	while(fe->tune != 2) usleep(10000); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user