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 | ||||
| incompatiblities to this driver package. | ||||
|  | ||||
| For installation instructions see: | ||||
|  | ||||
| http://support.digital-devices.eu/index.php?article=152 | ||||
| ### Prepare for Building | ||||
|  | ||||
|    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 | ||||
| 	$(CC) -o cit cit.c -lpthread | ||||
| @@ -15,6 +15,12 @@ setmod2: setmod2.c | ||||
| setmod3: setmod3.c | ||||
| 	$(CC) -o setmod3 setmod3.c -I../include/ | ||||
|  | ||||
| %.o: %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ $< | ||||
| modconfig: modconfig.c | ||||
| 	$(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 <linux/dvb/dmx.h> | ||||
| #include <linux/dvb/frontend.h> | ||||
| #include <linux/dvb/video.h> | ||||
|  | ||||
| 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("Version:  %08x\n", ddf->id.hw); | ||||
| 		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; | ||||
| 		return stat; | ||||
| 	} | ||||
| @@ -200,6 +200,7 @@ static int usage() | ||||
| 	       "-n N\n  only update card N (default with N=0)\n\n" | ||||
| 	       "-a \n   update all cards\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" | ||||
| 		); | ||||
| } | ||||
| @@ -250,7 +251,7 @@ int main(int argc, char **argv) | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 			usage(); | ||||
| 			break; | ||||
| 			return 0; | ||||
| 		default: | ||||
| 			break; | ||||
|  | ||||
|   | ||||
| @@ -50,15 +50,15 @@ struct flash_info flashs[] = { | ||||
| 	{ { 0x01, 0x40, 0x15 }, SPANSION_S25FL116K, 4096, 0x200000, "SPANSION S25FL116K 16 MBit" }, | ||||
| 	{ { 0x01, 0x40, 0x16 }, SPANSION_S25FL132K, 4096, 0x400000, "SPANSION S25FL132K 32 MBit" }, | ||||
| 	{ { 0x01, 0x40, 0x17 }, SPANSION_S25FL164K, 4096, 0x800000, "SPANSION S25FL164K 64 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond 16 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond 32 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond 64 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond 128 MBit" }, | ||||
| 	{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D  64 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" }, | ||||
| 	{ { 0xef, 0x40, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x15 }, WINBOND_W25Q16JV, 4096, 0x200000, "Winbond W25Q16JV 16 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x16 }, WINBOND_W25Q32JV, 4096, 0x400000, "Winbond W25Q32JV 32 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x17 }, WINBOND_W25Q64JV, 4096, 0x800000, "Winbond W25Q64JV 64 MBit" }, | ||||
| 	{ { 0xef, 0x70, 0x18 }, WINBOND_W25Q128JV, 4096, 0x1000000, "Winbond W25Q128JV 128 MBit" }, | ||||
| 	{ { 0x1f, 0x28, 0xff }, ATMEL_AT45DB642D, 1024, 0x800000, "Atmel AT45DB642D 64 MBit" }, | ||||
| 	{ { 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]) { | ||||
| 		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; | ||||
| 		f++; | ||||
| 	} | ||||
| @@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, | ||||
| 		return -1; | ||||
| 	len = off - fw_off; | ||||
| 	lseek(fs, fw_off, SEEK_SET); | ||||
| #if 0 | ||||
| 	if (len > maxlen) { | ||||
| 		printf("file too big\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| #endif | ||||
| 	//printf("flash file len %u, compare to %08x in flash: ", len, addr); | ||||
| 	for (j = 0; j < len; j += bl, addr += bl) { | ||||
| 		if (len - j < bl) | ||||
| @@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) | ||||
| 		return -4; | ||||
| 	} | ||||
| 	if (devid == ddf->id.device) { | ||||
| 		if (version <= (ddf->id.hw & 0xffffff)) { | ||||
| 			printf("%s is older or same version as flash\n", fn); | ||||
| 			ret = -3; /* same id but no newer version */ | ||||
| 		if (version < (ddf->id.hw & 0xffffff)) { | ||||
| 			printf("%s is older version than flash\n", fn); | ||||
| 			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 | ||||
| 		ret = 1; | ||||
| @@ -1147,7 +1151,7 @@ out: | ||||
| } | ||||
|  | ||||
| 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 fs, res = 0; | ||||
| @@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn, | ||||
| 		printf("File %s not found \n", fn); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	res = flashcmp(ddf, fs, adr, len, fw_off); | ||||
| 	res = flashcmp(ddf, fs, adr, maxlen, fw_off); | ||||
| 	if (res == -2) { | ||||
| 		printf("Flash already identical to %s\n", fn); | ||||
| 		if (ddf->force) { | ||||
| @@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn, | ||||
| 	} | ||||
| 	if (res < 0)  | ||||
| 		goto out; | ||||
| 	res = flashwrite(ddf, fs, adr, len, fw_off); | ||||
| 	res = flashwrite(ddf, fs, adr, maxlen, fw_off); | ||||
| 	if (res == 0) { | ||||
| 		res = flashcmp(ddf, fs, adr, len, fw_off); | ||||
| 		res = flashcmp(ddf, fs, adr, maxlen, fw_off); | ||||
| 		if (res == -2) { | ||||
| 			res = 1; | ||||
| 			printf("Flash verify OK!\n"); | ||||
|   | ||||
| @@ -58,7 +58,7 @@ int main(int argc, char*argv[]) | ||||
| 	struct dvb_mod_params mp; | ||||
| 	struct dvb_mod_channel_params mc; | ||||
| 	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; | ||||
| 	char mod_name[128]; | ||||
| 	 | ||||
| @@ -113,7 +113,7 @@ int main(int argc, char*argv[]) | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too man arguments\n"); | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| @@ -134,6 +134,8 @@ int main(int argc, char*argv[]) | ||||
| 	//get_property(fd, MODULATOR_ATTENUATOR, &data); | ||||
| 	//printf("Modulator attenuator = %u\n", data); | ||||
|  | ||||
| 	if (gain > 0) | ||||
| 		set_property(fd, MODULATOR_GAIN, gain); | ||||
| 	if (base > 0) | ||||
| 		set_property(fd, MODULATOR_BASE_FREQUENCY, base); | ||||
| 	if (freq > 0) | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include "ddbridge.h" | ||||
| #include "ddbridge-i2c.h" | ||||
| #include "ddbridge-io.h" | ||||
| #include "ddbridge-ioctl.h" | ||||
| #include <media/dvb_net.h> | ||||
|  | ||||
| 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++) { | ||||
| 		if (alt_dma) { | ||||
| #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 | ||||
| 			dma->vbuf[i] = kmalloc(dma->size, __GFP_RETRY_MAYFAIL); | ||||
| 			dma->vbuf[i] = kzalloc(dma->size, __GFP_RETRY_MAYFAIL); | ||||
| #endif | ||||
| 			if (!dma->vbuf[i]) | ||||
| 				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->size, | ||||
| 							  &dma->pbuf[i], | ||||
| 							  GFP_KERNEL); | ||||
| 							  GFP_KERNEL | __GFP_ZERO); | ||||
| 			if (!dma->vbuf[i]) | ||||
| 				return -ENOMEM; | ||||
| 		} | ||||
| 		if (((u64)dma->vbuf[i] & 0xfff)) | ||||
| 			dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]); | ||||
| 	} | ||||
| 	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) | ||||
| { | ||||
| 	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, | ||||
| 				 "DMA stalled %u times!\n", | ||||
| 				 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, | ||||
| 				 "%u packets lost due to low DMA performance!\n", | ||||
| 				 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]; | ||||
|  | ||||
| #if 0 | ||||
| 	dvb->fe = dvb_attach(dummy_attach); | ||||
| #else | ||||
| 	dvb->fe = dummy_attach(); | ||||
| #endif | ||||
| 	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)) { | ||||
| 		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; | ||||
| 		} | ||||
| 		if (alt_dma) | ||||
| 			dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf], | ||||
| 						dma2->size, DMA_FROM_DEVICE); | ||||
| 		if (raw_stream || input->con) | ||||
| 		if (raw_stream || input->con) { | ||||
| 			dvb_dmx_swfilter_raw(&dvb->demux, | ||||
| 					     dma2->vbuf[dma->cbuf], | ||||
| 					     dma2->size); | ||||
| 		else | ||||
| 			dvb_dmx_swfilter_packets(&dvb->demux, | ||||
| 		} else { | ||||
| 			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->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; | ||||
| 		if (ack) | ||||
| @@ -2321,16 +2356,7 @@ static void input_tasklet(unsigned long data) | ||||
| 	} | ||||
| 	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma)); | ||||
| 	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(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; | ||||
| 	} | ||||
| 	update_loss(dma); | ||||
| 	if (4 & dma->ctrl) | ||||
| 		dma->stall_count++; | ||||
| 	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) | ||||
| { | ||||
| 	u32 i, l, p; | ||||
| 	u32 i, l, p, ports; | ||||
| 	struct ddb_port *port; | ||||
| 	const struct ddb_info *info; | ||||
| 	const struct ddb_regmap *rm; | ||||
| @@ -2588,7 +2614,12 @@ static void ddb_ports_init(struct ddb *dev) | ||||
| 		rm = info->regmap; | ||||
| 		if (!rm) | ||||
| 			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 = dev; | ||||
| 			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); | ||||
| } | ||||
|  | ||||
| #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" | ||||
|  | ||||
| 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.subvendor = dev->link[0].ids.subvendor; | ||||
| 		ddbid.subdevice = dev->link[0].ids.subdevice; | ||||
| 		ddbid.hw = ddbreadl(dev, 0); | ||||
| 		ddbid.regmap = ddbreadl(dev, 4); | ||||
| 		ddbid.hw = dev->link[0].ids.hwid; | ||||
| 		ddbid.regmap = dev->link[0].ids.regmapid; | ||||
| 		if (copy_to_user(parg, &ddbid, sizeof(ddbid))) | ||||
| 			return -EFAULT; | ||||
| 		break; | ||||
| @@ -3453,8 +3414,6 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| 		if (msg.link > 3) | ||||
| 			return -EFAULT; | ||||
| 		link = &dev->link[msg.link]; | ||||
| 		if (!link->mci_base) | ||||
| 			return -EFAULT; | ||||
| 		res = ddb_mci_cmd_link(link, &msg.cmd, &msg.res); | ||||
| 		if (copy_to_user(parg, &msg, sizeof(msg))) | ||||
| 			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 mci_result res; | ||||
|  | ||||
| 	*status = 0x00; | ||||
| 	if (!state->started) | ||||
| 		return 0; | ||||
| 	stat = ddb_mci_get_status(&state->mci, &res); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	*status = 0x00; | ||||
| 	stat = ddb_mci_get_info(&state->mci); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	ddb_mci_get_strength(fe); | ||||
| 	if (res.status == MCI_DEMOD_WAIT_SIGNAL) | ||||
| 		*status = 0x01; | ||||
| 	if (res.status == M4_DEMOD_WAIT_TS) | ||||
| 	else if (res.status == M4_DEMOD_WAIT_TS) | ||||
| 		*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; | ||||
| 		ddb_mci_get_snr(fe); | ||||
| 	} | ||||
|   | ||||
| @@ -139,6 +139,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev) | ||||
| 	ddb_buffers_free(dev); | ||||
|  | ||||
| 	ddb_unmap(dev); | ||||
| 	pci_clear_master(pdev); | ||||
| 	pci_set_drvdata(pdev, NULL); | ||||
| 	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.subdevice = pdev->subsystem_device; | ||||
| 	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].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.regmapid = ddbreadl(dev, 4); | ||||
|  | ||||
| 	dev_info(dev->dev, "HW %08x REGMAP %08x\n", | ||||
| 		 dev->link[0].ids.hwid, dev->link[0].ids.regmapid); | ||||
| 	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 & 0xff0000) >> 16, | ||||
| 		 dev->link[0].ids.hwid & 0xffff); | ||||
| 	if ((dev->link[0].ids.hwid & 0xffffff) < | ||||
| 	    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_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 */ | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| 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, | ||||
| 			      u8 *cmd, u32 len) | ||||
| @@ -75,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe, | ||||
| 		return -1; | ||||
|  | ||||
| 	input = cmd[3] & 3; | ||||
| 	max_set_input_unlocked(fe, input); | ||||
| 	max_set_input(fe, input); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -94,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe, | ||||
| 		return 0; | ||||
|  | ||||
| 	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) | ||||
| 		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; | ||||
|  | ||||
| 	if (no_voltage) | ||||
| 		voltage = SEC_VOLTAGE_OFF; | ||||
| 	if (dev->link[link].lnb.oldvoltage[input] == voltage) | ||||
| 		return 0; | ||||
| 	switch (voltage) { | ||||
|   | ||||
| @@ -34,10 +34,16 @@ static int mci_reset(struct ddb_link *link) | ||||
| 	u32 control; | ||||
| 	u32 status = 0; | ||||
| 	u32 timeout = 40; | ||||
| 	union { | ||||
| 		u32 u[4]; | ||||
| 		char s[16]; | ||||
| 	} version; | ||||
| 	u32 vaddr; | ||||
| 	 | ||||
| 	if (!regmap || ! regmap->mci) | ||||
| 	if (!regmap || !regmap->mci) | ||||
| 		return -EINVAL; | ||||
| 	control = regmap->mci->base; | ||||
| 	vaddr = regmap->mci_buf->base + 0xf0; | ||||
|  | ||||
| 	if ((link->info->type == DDB_OCTOPUS_MCI) && | ||||
| 	    (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { | ||||
| @@ -55,11 +61,17 @@ static int mci_reset(struct ddb_link *link) | ||||
| 		msleep(50); | ||||
| 	} | ||||
| 	dev_info(link->dev->dev, "MCI control port @ %08x\n", control); | ||||
|  | ||||
| 	if ((status & MCI_CONTROL_READY) == 0) { | ||||
| 		dev_err(link->dev->dev, "MCI init failed!\n"); | ||||
| 		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; | ||||
| } | ||||
|  | ||||
| @@ -108,6 +120,7 @@ static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link, | ||||
| 					  0xffffff, INTERRUPT_ACK); | ||||
| 		} | ||||
| 	} | ||||
| 	//print_hex_dump(KERN_INFO, "MCI", DUMP_PREFIX_OFFSET, 16, 1, cmd, cmd_len, false); | ||||
| 	if (res && res_len) | ||||
| 		for (i = 0; i < res_len; i++) | ||||
| 			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) | ||||
| { | ||||
| 	struct mci_result result; | ||||
| 	struct mci_command command = { | ||||
| 		.command_word = cmd, | ||||
| 		.params = { val }, | ||||
| 	}; | ||||
| 	struct mci_command command; | ||||
|  | ||||
| 	command.command_word = cmd; | ||||
| 	command.params[0] = val; | ||||
| 	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); | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	struct mci *mci = fe->demodulator_priv; | ||||
|   | ||||
| @@ -132,6 +132,7 @@ | ||||
| #define MCI_BANDWIDTH_7MHZ       (7) | ||||
| #define MCI_BANDWIDTH_8MHZ       (8) | ||||
|  | ||||
| #define SX8_CMD_GETBIST          (0x0F) | ||||
| #define SX8_CMD_INPUT_ENABLE     (0x40) | ||||
| #define SX8_CMD_INPUT_DISABLE    (0x41) | ||||
| #define SX8_CMD_START_IQ         (0x42) | ||||
| @@ -185,6 +186,82 @@ | ||||
|  | ||||
| #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 output; | ||||
| 		}; | ||||
| 		struct { | ||||
| 			u8 mod_command; | ||||
| 			u8 mod_channel; | ||||
| 			u8 mod_stream; | ||||
| 			u8 mod_rsvd1; | ||||
| 		}; | ||||
| 	}; | ||||
| 	union { | ||||
| 		u32 params[31]; | ||||
| @@ -297,7 +380,7 @@ struct mci_command { | ||||
| 		} j83b_search; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   flags;              //  Bit 0 : 1 = short info (1st 4 Bytes) | ||||
| 			u8   flags; /*  Bit 0 : 1 = short info (1st 4 Bytes) */ | ||||
| 		} get_signalinfo; | ||||
|  | ||||
| 		struct { | ||||
| @@ -307,43 +390,47 @@ struct mci_command { | ||||
| 		} get_iq_symbol; | ||||
|  | ||||
| 		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 2: 1 = Set Gain.   */ | ||||
| 			uint8_t   roll_off; | ||||
| 			uint8_t   rsvd1; | ||||
| 			uint8_t   rsvd2; | ||||
| 			uint32_t  frequency; | ||||
| 			uint32_t  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   roll_off; | ||||
| 			u8   rsvd1; | ||||
| 			u8   rsvd2; | ||||
| 			u32  frequency; | ||||
| 			u32  symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/ | ||||
| 			u8   gain;         /* Gain in 0.25 dB Steps */ | ||||
| 			/* Frequency, symbolrate and gain can be schanged while running */ | ||||
| 		} sx8_start_iq; | ||||
|  | ||||
| 		struct { | ||||
| 			uint8_t   flags; | ||||
|                         /*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||
| 			u8   flags; | ||||
| 			/*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||
| 			     2 = Medium, 3 = Maximum gain {~ 15dB} | ||||
| 			     Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp) | ||||
| 			     Bit 4: Set RF Gain | ||||
| 			     Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled) | ||||
| 			     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; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   offset;        // Offset into list, must be multiple of 64 | ||||
| 			u8   select;        // 0 = Slices, 1 = PLPs  (C2 Only) | ||||
| 			u8   data_slice;    // DataSlice to get PLPList (C2 Only) | ||||
| 			u8   offset;        /* Offset into list, must be multiple of 64 */ | ||||
| 			u8   select;        /* 0 = Slices, 1 = PLPs  (C2 Only) */ | ||||
| 			u8   data_slice;    /* DataSlice to get PLPList (C2 Only) */ | ||||
| 		} get_ids; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   select;        // 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID | ||||
| 			u8   id;            // DataSliceID, PLPId  | ||||
| 			u8   select;        /* 0 = Base, 1 = DataSilce, 2 = PLP,  Bit 7:  Set new ID */ | ||||
| 			u8   id;            /* DataSliceID, PLPId */ | ||||
| 		} get_l1_info; | ||||
|  | ||||
| 		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; | ||||
|  | ||||
| 		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 { | ||||
| 		u32 result[27]; | ||||
| 		u8 result8[27 * 4]; | ||||
| 		struct { | ||||
| 			u8  Rsvd0[3]; | ||||
| 			u8  Flags; | ||||
|  | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 frequency;          /* actual frequency in Hz */ | ||||
| 			u32 rsvd1; | ||||
| 			s16 channel_power;      // channel power in dBm x 100 | ||||
| 			s16 channel_power;      /* channel power in dBm x 100 */ | ||||
| 			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; | ||||
| 			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_rsvd1;          // Place holder for modulation bit error rate | ||||
| 			u32 ber_rsvd1;          /* Place holder for modulation bit error rate */ | ||||
| 			u32 ber_rsvd2; | ||||
| 		} common_signal_info; | ||||
|  | ||||
| @@ -425,8 +513,8 @@ struct mci_result { | ||||
| 		struct { | ||||
| 			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  Rsvd0; | ||||
| 			u8  Flags; | ||||
| 			u8  rsvd0; | ||||
| 			u8  flags; | ||||
| 			u32 frequency;         /* actual frequency in Hz */ | ||||
| 			u32 rsvd1; | ||||
| 			s16 channel_power;     /* channel power in dBm x 100 */ | ||||
| @@ -487,37 +575,37 @@ struct mci_result { | ||||
| 		} isdbt_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  Constellation; | ||||
| 			u8  Rsvd0[2]; | ||||
| 			u8  Flags; | ||||
| 			u8  constellation; | ||||
| 			u8  rsvd0[2]; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 Frequency;         // actual frequency in Hz | ||||
| 			u32 SymbolRate;        // actual symbolrate in Hz | ||||
| 			s16  ChannelPower;      // channel power in dBm x 100 | ||||
| 			s16  BandPower;         // band power in dBm x 100 | ||||
| 			s16  SignalToNoise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16  Rsvd2; | ||||
| 			u32 PacketErrors;      // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 BERNumerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 BERDenominator; | ||||
| 		} ISDBC_SignalInfo; | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 symbol_rate;       // actual symbolrate in Hz | ||||
| 			s16 channel_power;     // channel power in dBm x 100 | ||||
| 			s16 band_power;        // band power in dBm x 100 | ||||
| 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;     // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 ber_numerator;     // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 ber_denominator; | ||||
| 		} isdbc_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			u8  Constellation; | ||||
| 			u8  Interleaving; | ||||
| 			u8  Rsvd0; | ||||
| 			u8  Flags; | ||||
| 			u8  constellation; | ||||
| 			u8  interleaving; | ||||
| 			u8  rsvd0; | ||||
| 			u8  flags; | ||||
|  | ||||
| 			u32 Frequency;         // actual frequency in Hz | ||||
| 			u32 SymbolRate;        // actual symbolrate in Hz | ||||
| 			s16  ChannelPower;      // channel power in dBm x 100 | ||||
| 			s16  BandPower;         // band power in dBm x 100 | ||||
| 			s16  SignalToNoise;     // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16  Rsvd2; | ||||
| 			u32 PacketErrors;      // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 BERNumerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 BERDenominator; | ||||
| 		} J83B_SignalInfo; | ||||
| 			u32 frequency;         // actual frequency in Hz | ||||
| 			u32 symbol_rate;        // actual symbolrate in Hz | ||||
| 			s16 channel_power;      // channel power in dBm x 100 | ||||
| 			s16 band_power;         // band power in dBm x 100 | ||||
| 			s16 signal_to_noise;   // SNR in dB x 100, Note: negativ values are valid in DVB-S2 | ||||
| 			s16 rsvd2; | ||||
| 			u32 packet_errors;      // Counter for packet errors. (set to 0 on Start command) | ||||
| 			u32 ber_numerator;      // Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X | ||||
| 			u32 ber_denominator; | ||||
| 		} j83b_signal_info; | ||||
|  | ||||
| 		struct { | ||||
| 			s16 i; | ||||
| @@ -525,13 +613,13 @@ struct mci_result { | ||||
| 		} iq_symbol; | ||||
|  | ||||
| 		struct { | ||||
| 			u8   TPSInfo[7]; | ||||
|                         // uint16_t TPS_CellID;        // Cell Identifier | ||||
| 			u8   tps_info[7]; | ||||
| 			// uint16_t tps_cell_id; | ||||
| 		} DVBT_TPSInfo; | ||||
|  | ||||
| 		struct { | ||||
| 			struct  { | ||||
| 				u8 Type; | ||||
| 				u8 type; | ||||
| 				u8 BWExtension; | ||||
| 				u8 S1; | ||||
| 				u8 S2; | ||||
| @@ -557,6 +645,7 @@ struct mci_result { | ||||
| 				u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit | ||||
| 				u8 CRC32[4]; | ||||
| 			} DVBT2_L1Pre; | ||||
|  | ||||
| 			struct  { | ||||
| 				u8 SubSlicesPerFrame[2]; | ||||
| 				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   Extension[8];   // 61 bits, right aligned | ||||
| 		} ISDBS_TMCCInfo; | ||||
|  | ||||
| 		struct { | ||||
| 			uint8_t  cut; | ||||
| 			uint8_t  avs_code; | ||||
| 			uint8_t  temperature; | ||||
| 			uint8_t  rsvd[13]; | ||||
| 		} sx8_bist; | ||||
| 	}; | ||||
| 	u32 version[3]; | ||||
| 	u8  version_rsvd; | ||||
| @@ -758,6 +854,8 @@ struct mci_result { | ||||
| #define L1POST_STATIC_FLAG(p)              (((p)[18] >> 1) & 0x01) | ||||
| #define L1POST_STATIC_PADDING_FLAG(p)      (((p)[18] >> 1) & 0x01) | ||||
|  | ||||
| #ifdef __KERNEL__ | ||||
|  | ||||
| struct mci_base { | ||||
| 	struct list_head     mci_list; | ||||
| 	void                *key; | ||||
| @@ -797,9 +895,10 @@ int ddb_mci_get_info(struct mci *mci); | ||||
| int ddb_mci_get_strength(struct dvb_frontend *fe); | ||||
| void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p); | ||||
| 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_m4_cfg; | ||||
| #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) | ||||
| { | ||||
| 	u32 control = ddbreadl(dev, SDR_CONTROL); | ||||
| 	struct ddb_link *link = &dev->link[0]; | ||||
|  | ||||
| 	if (control & 0x01000000) { | ||||
| 		if (gain > 511) | ||||
| @@ -659,8 +658,6 @@ static int mod_set_sdr_gain(struct ddb *dev, u32 gain) | ||||
| 			return -EINVAL; | ||||
| 		ddbwritel(dev, gain, SDR_GAIN_F); | ||||
| 	} | ||||
| 	if (link->mci_ok) | ||||
| 		mci_cmd_val(link, 0xc0, gain); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -1866,6 +1863,8 @@ static int mod_init_2(struct ddb *dev, u32 Frequency) | ||||
| 		dev_err(dev->dev, "FSM setup failed!\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (dev->link[0].ids.revision == 1) | ||||
| 		return 0; | ||||
| 	for (i = 0; i < streams; 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); | ||||
|  | ||||
| 	if (dev->link[0].ids.revision == 1) | ||||
| 		return 0; | ||||
|  | ||||
| 	//mod3_set_base_frequency(dev, 602000000); | ||||
| 	dev->mod_base.frequency = 570000000; | ||||
| 	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) | ||||
| { | ||||
| 	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) { | ||||
| 	case 0: | ||||
| 	case 1: | ||||
|   | ||||
| @@ -30,6 +30,10 @@ static int default_mod = 3; | ||||
| module_param(default_mod, int, 0444); | ||||
| 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); | ||||
|  | ||||
| /* 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; | ||||
|  | ||||
| 	u8                   tuner_use_count[SX8_TUNER_NUM]; | ||||
| 	u32                  gain_mode[SX8_TUNER_NUM]; | ||||
|  | ||||
| 	u32                  used_ldpc_bitrate[SX8_DEMOD_NUM]; | ||||
| 	u8                   demod_in_use[SX8_DEMOD_NUM]; | ||||
| 	u32                  iq_mode; | ||||
| 	u32                  burst_size; | ||||
| 	u32                  direct_mode; | ||||
| }; | ||||
|  | ||||
| struct sx8 { | ||||
| 	struct mci           mci; | ||||
| 	struct mutex         lock; | ||||
|  | ||||
| 	int                  first_time_lock; | ||||
| 	int                  started; | ||||
| 	int                  iq_started; | ||||
|  | ||||
| 	u32                  bb_mode; | ||||
| 	u32                  local_frequency; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	int stat; | ||||
| 	int stat = 0; | ||||
| 	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 dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||
| 	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); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	*status = 0x00; | ||||
| 		goto unlock; | ||||
| 	ddb_mci_get_info(&state->mci); | ||||
| 	if (res.status == SX8_DEMOD_WAIT_MATYPE) | ||||
| 		*status = 0x0f; | ||||
| 	if (res.status == MCI_DEMOD_LOCKED) { | ||||
| 		*status = 0x1f; | ||||
| 		if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = | ||||
| 				p->symbol_rate * | ||||
| 				dvbs2_bits_per_symbol[ | ||||
| 					state->mci.signal_info. | ||||
| 					dvbs2_signal_info.pls_code]; | ||||
| 		} else  | ||||
| 			sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; | ||||
| 	} | ||||
| 	if (stat) | ||||
| 		goto unlock; | ||||
| 	if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { | ||||
| 		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | | ||||
| 			FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||||
| 		if (res.status == MCI_DEMOD_LOCKED) { | ||||
| 			mutex_lock(&mci_base->tuner_lock); | ||||
| 			if (state->first_time_lock && state->started) { | ||||
| 				if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { | ||||
| 					sx8_base->used_ldpc_bitrate[state->mci.nr] = | ||||
| 						p->symbol_rate * | ||||
| 						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; | ||||
| } | ||||
|  | ||||
| @@ -158,14 +172,12 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on, | ||||
| 			 u8 flags, u8 gain) | ||||
| { | ||||
| 	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; | ||||
|  | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	cmd.tuner = state->mci.tuner; | ||||
| 	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; | ||||
| 	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; | ||||
| 	} | ||||
| 	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	 | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	sx8_base->iq_mode = 0; | ||||
| 	state->iq_started = 0; | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -207,12 +219,13 @@ static int stop(struct dvb_frontend *fe) | ||||
| 	struct mci_base *mci_base = state->mci.base; | ||||
| 	struct sx8_base *sx8_base = (struct sx8_base *) mci_base; | ||||
| 	struct mci_command cmd; | ||||
| 	u32 input = state->mci.tuner; | ||||
| 	u32 input; | ||||
|  | ||||
| 	input = state->mci.tuner; | ||||
| 	if (!state->started) | ||||
| 		return -1; | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	if (state->mci.demod != SX8_DEMOD_NONE) { | ||||
| 		memset(&cmd, 0, sizeof(cmd)); | ||||
| 		cmd.command = MCI_CMD_STOP; | ||||
| 		cmd.demod = state->mci.demod; | ||||
| 		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->iq_mode = 0; | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	state->started = 0; | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	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; | ||||
| 	int i = -1, stat = 0; | ||||
| 	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) { | ||||
| 		/* 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; | ||||
| 	} | ||||
|  | ||||
| 	if (sx8_base->direct_mode) { | ||||
| 	if (direct_mode) { | ||||
| 		if (p->symbol_rate >= MCLK / 2) { | ||||
| 			if (state->mci.nr < 4) | ||||
| 				i = state->mci.nr; | ||||
| @@ -309,9 +326,8 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		 | ||||
| 		modmask &= ((1 << (bits_per_symbol - 1)) - 1); | ||||
| 		if( ((flags & 0x02) != 0)  &&  (modmask == 0)) { | ||||
| 		if (((flags & 0x02) != 0) && (modmask == 0)) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| @@ -337,11 +353,10 @@ unlock: | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	 | ||||
| 	if (sx8_base->iq_mode) { | ||||
| 		cmd.command = SX8_CMD_ENABLE_IQOUTPUT; | ||||
| 		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_tsconfig(&state->mci, ts_config); | ||||
| 	} | ||||
| @@ -357,6 +372,7 @@ unlock: | ||||
| 	cmd.command = MCI_CMD_SEARCH_DVBS; | ||||
| 	cmd.dvbs2_search.flags = flags; | ||||
| 	cmd.dvbs2_search.s2_modulation_mask = modmask; | ||||
| 	cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7]; | ||||
| 	cmd.dvbs2_search.retry = 2; | ||||
| 	cmd.dvbs2_search.frequency = p->frequency * 1000; | ||||
| 	cmd.dvbs2_search.symbol_rate = p->symbol_rate; | ||||
| @@ -370,6 +386,9 @@ unlock: | ||||
| 	    (p->stream_id & 0x80000000)) | ||||
| 		cmd.output |= 0x80; | ||||
| 	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) | ||||
| 		stop(fe); | ||||
| 	return stat; | ||||
| @@ -388,8 +407,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | ||||
| 	u32 input = state->mci.tuner; | ||||
| 	int i, stat = 0; | ||||
|  | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	if (!state->iq_started) { | ||||
| 		mutex_lock(&mci_base->tuner_lock); | ||||
| 		if (sx8_base->iq_mode) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| @@ -402,17 +421,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		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->iq_mode = (ts_config > 1); | ||||
| 	unlock: | ||||
| 		mutex_unlock(&mci_base->tuner_lock); | ||||
| 		if (stat) | ||||
| 			return stat; | ||||
| 		sx8_base->iq_mode = 2; | ||||
| 	} else { | ||||
| 		if ((state->iq_started & 0x07) != state->mci.nr) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 	} | ||||
| unlock: | ||||
| 	mutex_unlock(&mci_base->tuner_lock); | ||||
| 	if (stat) | ||||
| 		return stat; | ||||
| 	mci_set_tuner(fe, input, 1, flags & 0xff, 0); | ||||
| 	memset(&cmd, 0, sizeof(cmd)); | ||||
| 	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.demod = state->mci.demod; | ||||
| 	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) | ||||
| 		stop_iq(fe); | ||||
| 	ddb_mci_tsconfig(&state->mci, ts_config); | ||||
| @@ -436,7 +459,6 @@ static int set_lna(struct dvb_frontend *fe) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int set_parameters(struct dvb_frontend *fe) | ||||
| { | ||||
| 	int stat = 0; | ||||
| @@ -452,6 +474,7 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 	state->mci.input->con = ts_mode << 8; | ||||
| 	if (iq_mode) | ||||
| 		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop(fe); | ||||
| 	if (iq_mode < 2) { | ||||
| 		u32 mask; | ||||
| @@ -478,19 +501,10 @@ static int set_parameters(struct dvb_frontend *fe) | ||||
| 			break; | ||||
| 		} | ||||
| 		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 { | ||||
| 		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; | ||||
| } | ||||
|  | ||||
| @@ -529,16 +543,22 @@ static int set_input(struct dvb_frontend *fe, int input) | ||||
| 		return -EINVAL; | ||||
| 	if (state->mci.tuner == input) | ||||
| 		return 0; | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop_iq(fe); | ||||
| 	stop(fe); | ||||
| 	state->mci.tuner = p->input = input; | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int sleep(struct dvb_frontend *fe) | ||||
| { | ||||
| 	struct sx8 *state = fe->demodulator_priv; | ||||
|  | ||||
| 	mutex_lock(&state->lock); | ||||
| 	stop_iq(fe); | ||||
| 	stop(fe); | ||||
| 	mutex_unlock(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -584,6 +604,7 @@ static int init(struct mci *mci) | ||||
| 	state->mci.demod = SX8_DEMOD_NONE; | ||||
| 	mci->fe.ops.xbar[1] = mci->nr; | ||||
| 	mci->fe.dtv_property_cache.input = mci->tuner; | ||||
| 	mutex_init(&state->lock); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #ifndef _DDBRIDGE_H_ | ||||
| #define _DDBRIDGE_H_ | ||||
|  | ||||
| #define DDB_USE_WORK | ||||
| /* #define DDB_USE_WORK */ | ||||
| /*#define DDB_TEST_THREADED*/ | ||||
|  | ||||
| #include <linux/version.h> | ||||
| @@ -143,6 +143,7 @@ struct ddb_ids { | ||||
| 	u32 regmapid; | ||||
| 	u32 devid; | ||||
| 	u32 mac; | ||||
| 	u8 revision; | ||||
| }; | ||||
|  | ||||
| struct ddb_info { | ||||
| @@ -219,6 +220,7 @@ struct ddb_dma { | ||||
|  | ||||
| 	u32                    stall_count; | ||||
| 	u32                    packet_loss; | ||||
| 	u32                    unaligned; | ||||
| }; | ||||
|  | ||||
| struct ddb_dvb { | ||||
|   | ||||
| @@ -54,6 +54,7 @@ struct cxd_state { | ||||
| 	struct dvb_frontend   frontend; | ||||
| 	struct i2c_adapter   *i2c; | ||||
| 	struct mutex          mutex; | ||||
| 	int repi2cerr; | ||||
|  | ||||
| 	u8  adrt; | ||||
| 	u8  curbankt; | ||||
| @@ -91,12 +92,13 @@ struct cxd_state { | ||||
| 	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 = { | ||||
| 		.addr = adr, .flags = 0, .buf = data, .len = len};  | ||||
| 	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 0; | ||||
| @@ -113,14 +115,14 @@ static int writeregs(struct cxd_state *state, u8 adr, u8 reg, | ||||
| 	} | ||||
| 	data[0] = reg; | ||||
| 	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) | ||||
| { | ||||
| 	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, | ||||
| @@ -130,17 +132,19 @@ static int i2c_read(struct i2c_adapter *adap, | ||||
| 				     .buf = msg, .len = len}, | ||||
| 				   { .addr = adr, .flags = I2C_M_RD, | ||||
| 				     .buf = answ, .len = alen } }; | ||||
| 	if (i2c_transfer(adap, msgs, 2) != 2) { | ||||
| 		pr_err("cxd2843: i2c_read error\n"); | ||||
| 	if (i2c_transfer(adap, msgs, 2) != 2) | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int readregs(struct cxd_state *state, u8 adr, u8 reg, | ||||
| 		    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, | ||||
| @@ -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 */ | ||||
| 	state->IF_FS = 0x50; | ||||
| 	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, | ||||
| @@ -2647,7 +2651,8 @@ static int probe(struct cxd_state *state) | ||||
| 	if (status) | ||||
| 		return status; | ||||
| 	 | ||||
| 	printk("ChipID  = %02X\n", ChipID); | ||||
| 	state->repi2cerr = 1; | ||||
| 	//pr_info("cxd2843: ChipID  = %02X\n", ChipID); | ||||
| 	switch (ChipID) { | ||||
| 	case 0xa4: | ||||
| 		state->type = CXD2843; | ||||
| @@ -2682,7 +2687,6 @@ struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, | ||||
| { | ||||
| 	struct cxd_state *state = NULL; | ||||
|  | ||||
| 	pr_info("attach\n"); | ||||
| 	state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); | ||||
| 	if (!state) | ||||
| 		return NULL; | ||||
|   | ||||
| @@ -208,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val) | ||||
| 	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)					\ | ||||
| 	write_field(state, state->nr ? FSTV0910_P2_##_reg :	\ | ||||
| 		    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)					\ | ||||
| 	write_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||
| 		  RSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| #define get_reg(_reg, _val)					\ | ||||
| 	read_reg(state, state->nr ? RSTV0910_P2_##_reg :	\ | ||||
| 		 RTV0910_P1_##_reg, _val) | ||||
| 		 RSTV0910_P1_##_reg, _val) | ||||
|  | ||||
| static const struct slookup s1_sn_lookup[] = { | ||||
| 	{   0,    9242  }, /* C/N=  0dB */ | ||||
| @@ -1112,8 +1130,9 @@ static int init_diseqc(struct stv *state) | ||||
| 	u16 offs = state->nr ? 0x40 : 0;  /* Address offset */ | ||||
| 	u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); | ||||
|  | ||||
| 	/* Disable receiver */ | ||||
| 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); | ||||
| 	write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05); | ||||
| 	//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, 0x3A); /* Reset = 0 */ | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| 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, | ||||
| 			   struct dvb_diseqc_master_cmd *cmd) | ||||
| { | ||||
| 	struct stv *state = fe->demodulator_priv; | ||||
| 	int i; | ||||
|  | ||||
| 	clear_slave(fe); | ||||
| 	set_field(DISRX_ON, 0); | ||||
| 	set_reg(DISTXCFG, 0x3e); | ||||
| 	for (i = 0; i < cmd->msg_len; i++) { | ||||
| 		wait_dis(state, 0x40, 0x00); | ||||
| @@ -1630,12 +1665,59 @@ static int send_master_cmd(struct dvb_frontend *fe, | ||||
| 	} | ||||
| 	set_reg(DISTXCFG, 0x3a); | ||||
| 	wait_dis(state, 0x20, 0x20); | ||||
| 	set_field(DISRX_ON, 1); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int recv_slave_reply(struct dvb_frontend *fe, | ||||
| 			    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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -447,9 +447,6 @@ static int attach_init(struct tda_state *state) | ||||
| 	if (!state->m_isMaster) | ||||
| 		state->m_bLTEnable = false; | ||||
|  | ||||
| 	/*pr_info("tda18212dd: ChipID %04x %s\n", state->m_ID, | ||||
| 	  state->m_isMaster ? "master" : "slave");*/ | ||||
|  | ||||
| 	if (state->m_ID != 18212) | ||||
| 		return -1; | ||||
|  | ||||
| @@ -457,8 +454,6 @@ static int attach_init(struct tda_state *state) | ||||
| 	if (stat < 0) | ||||
| 		return stat; | ||||
| 	 | ||||
| 	/*pr_info("tda18212dd: PowerState %02x\n", PowerState);*/ | ||||
|  | ||||
| 	if (state->m_isMaster) { | ||||
| 		if (PowerState & 0x02) { | ||||
| 			/* msleep for XTAL Calibration | ||||
| @@ -539,7 +534,6 @@ static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) | ||||
| 		if (*pPowerLevel > 110) | ||||
| 			*pPowerLevel = 110; | ||||
| 	} while (0); | ||||
| 	/* pr_info("PL %d\n", *pPowerLevel); */ | ||||
| 	return status; | ||||
| } | ||||
|  | ||||
| @@ -806,7 +800,6 @@ static int set_params(struct dvb_frontend *fe) | ||||
|  | ||||
| 	bw = (p->bandwidth_hz + 999999) / 1000000; | ||||
| 	state->m_Frequency = p->frequency; | ||||
| 	/*pr_info("tuner bw=%u  freq=%u\n", bw, state->m_Frequency);*/ | ||||
| 	if (p->delivery_system == SYS_DVBT || | ||||
| 	    p->delivery_system == SYS_DVBT2 || | ||||
| 	    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_params p; | ||||
| 	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 verbosity = 0; | ||||
| 	uint32_t get_ts = 1; | ||||
|   | ||||
| @@ -288,7 +288,8 @@ static int tune_sat(struct dddvb_fe *fe) | ||||
| 			freq = lofs - freq; | ||||
| 	}  | ||||
| #endif | ||||
| 	if (freq > 2100000) { | ||||
|  | ||||
| 	if (freq > 3000000) { | ||||
| 		if (lofs) | ||||
| 			hi = (freq > lofs) ? 1 : 0; | ||||
| 		if (hi)  | ||||
| @@ -318,14 +319,15 @@ static int tune_sat(struct dddvb_fe *fe) | ||||
| 			    fe->scif_slot, fe->scif_freq, ds); | ||||
| 		pthread_mutex_unlock(&fe->dd->uni_lock); | ||||
| 	} else { | ||||
| 		uint32_t input = lnb; | ||||
| 		uint32_t input = fe->param.param[PARAM_SRC]; | ||||
|  | ||||
| 		//if (input != DDDVB_UNDEF) | ||||
| 		//	input = 3 & (input >> 6); | ||||
| 		//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6)); | ||||
| 		if (input != DDDVB_UNDEF) { | ||||
| 			input = 3 & (input >> 6); | ||||
| 			printf("input = %u\n", input); | ||||
| 		} | ||||
| 		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, ~(0U)); | ||||
| 		set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); | ||||
| 		//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)); | ||||
| 	fe->n_tune = 1; | ||||
| 	pthread_mutex_unlock(&fe->mutex); | ||||
| 	while(fe->n_tune) usleep(10000); | ||||
| 	while(fe->tune != 2) usleep(10000); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user