diff --git a/apps/octonet/Makefile b/apps/octonet/Makefile index 0d29c03..7b8a469 100644 --- a/apps/octonet/Makefile +++ b/apps/octonet/Makefile @@ -1,10 +1,11 @@ -all: ddtest octonet octokey ddflash +all: ddtest octonet octokey ddflash ddupdate install: all install -m 0755 ddtest $(DESTDIR)/usr/bin install -m 0755 octonet $(DESTDIR)/usr/bin install -m 0755 octokey $(DESTDIR)/usr/bin install -m 0755 ddflash $(DESTDIR)/usr/bin + install -m 0755 ddupdate $(DESTDIR)/usr/bin ddflash: ddflash.c flash.h flash.c $(CC) -o ddflash ddflash.c @@ -12,6 +13,9 @@ ddflash: ddflash.c flash.h flash.c ddtest: ddtest.c flash.h flash.c $(CC) -o ddtest ddtest.c +ddupdate: ddupdate.c flash.h flash.c + $(CC) -o ddupdate ddupdate.c + octonet: octonet.c $(CC) -o octonet octonet.c diff --git a/apps/octonet/ddflash.c b/apps/octonet/ddflash.c index 3d32c42..5841944 100644 --- a/apps/octonet/ddflash.c +++ b/apps/octonet/ddflash.c @@ -38,25 +38,6 @@ #include "flash.h" #include "flash.c" -static int reboot(uint32_t off) -{ - FILE *f; - uint32_t time; - - if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL) - return -1; - fscanf(f, "%u", &time); - fclose(f); - - if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL) - return -1; - fprintf(f, "%u", time + off); - fclose(f); - system("/sbin/poweroff"); - return 0; -} - - static int update_flash(struct ddflash *ddf) { char *fname; diff --git a/apps/octonet/ddupdate.c b/apps/octonet/ddupdate.c index 82a2b91..6129bda 100644 --- a/apps/octonet/ddupdate.c +++ b/apps/octonet/ddupdate.c @@ -11,7 +11,6 @@ #include #include - #include "flash.h" #include "flash.c" @@ -115,11 +114,11 @@ static int update_flash(struct ddflash *ddf) if (!fname) fname = default_fname; if (name) - printf("Card: %s\n", name); + printf("Card: %s\n", name); if (ddf->flash_name) - printf("Flash: %s\n", ddf->flash_name); - printf("Version:%08x\n", ddf->id.hw); - //printf("REGMAPa: %08x\n", ddf->id.regmap); + 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) stat |= 1; return stat; @@ -142,7 +141,7 @@ static int update_link(struct ddflash *ddf) return ret; } -static int update_card(int ddbnum, char *fname) +static int update_card(int ddbnum, char *fname, int force) { struct ddflash ddf; char ddbname[80]; @@ -156,6 +155,7 @@ static int update_card(int ddbnum, char *fname) ddf.fd = ddb; ddf.link = 0; ddf.fname = fname; + ddf.force = force; links = 1; for (link = 0; link < links; link++) { @@ -206,18 +206,20 @@ static int usage() int main(int argc, char **argv) { - int ddbnum = -1, all = 0, i, force = 0; + int ddbnum = -1, all = 0, i, force = 0, reboot_len = -1; char *fname = 0; + int ret; while (1) { int option_index = 0; int c; static struct option long_options[] = { + {"reboot", optional_argument , NULL, 'r'}, {"help", no_argument , NULL, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, - "n:havfb:", + "n:havfb:r::", long_options, &option_index); if (c==-1) break; @@ -232,9 +234,20 @@ int main(int argc, char **argv) case 'a': all = 1; break; + case 'f': + force = 1; + break; case 'v': verbose++; break; + case 'r': + if (optarg) + reboot_len = strtol(optarg, NULL, 0); + else + reboot_len = 40; + if (!reboot_len) + reboot(40); + break; case 'h': usage(); break; @@ -253,17 +266,19 @@ int main(int argc, char **argv) } if (!all) - return update_card(ddbnum, fname); - - for (i = 0; i < 100; i++) { - int ret = update_card(i, 0); - - if (ret == -3) /* could not open, no more cards! */ - break; - if (ret < 0) - return i; /* fatal error */ - if (verbose >= 1) - printf("card %d up to date\n", i); - } + ret = update_card(ddbnum, fname, force); + else + for (i = 0; i < 100; i++) { + ret = update_card(i, 0, 0); + + if (ret == -3) /* could not open, no more cards! */ + break; + if (ret < 0) + return i; /* fatal error */ + if (verbose >= 1) + printf("card %d up to date\n", i); + } + if (reboot_len > 0) + reboot(reboot_len); return 0; } diff --git a/apps/octonet/flash.c b/apps/octonet/flash.c index adad2fc..121ec0d 100644 --- a/apps/octonet/flash.c +++ b/apps/octonet/flash.c @@ -1,7 +1,28 @@ +static int reboot(uint32_t off) +{ + FILE *f; + uint32_t time; + + if ((f = fopen ("/sys/class/rtc/rtc0/since_epoch", "r")) == NULL) + return -1; + fscanf(f, "%u", &time); + fclose(f); + + if ((f = fopen ("/sys/class/rtc/rtc0/wakealarm", "r+")) == NULL) + return -1; + fprintf(f, "%u", time + off); + fclose(f); + system("/sbin/poweroff"); + return 0; +} + + + static uint32_t linknr = 0; int flashio(int ddb, int link, - uint8_t *wbuf, uint32_t wlen, uint8_t *rbuf, uint32_t rlen) + uint8_t *wbuf, uint32_t wlen, + uint8_t *rbuf, uint32_t rlen) { struct ddb_flashio fio = { .write_buf=wbuf, @@ -118,7 +139,7 @@ int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len) uint32_t l; while (len) { - cmd[0] = 3; + cmd[0] = 0x03; cmd[1] = (addr >> 16) & 0xff; cmd[2] = (addr >> 8) & 0xff; cmd[3] = addr & 0xff; @@ -137,12 +158,12 @@ int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len) return 0; } #else -static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len) +static int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t len) { - uint8_t cmd[4]= {0x03, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff}; + uint8_t cmd[5]= {0x0b, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff, 0x00}; - return flashio(ddb, linknr, cmd, 4, buf, len); + return flashio(ddb, link, cmd, 5, buf, len); } #endif @@ -500,10 +521,10 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset, uint8_t Cmd[260]; int i, j; - if( (BufferSize % 4096) != 0 ) return -1; // Must be multiple of sector size + if ((BufferSize % 4096)) + return -1; // Must be multiple of sector size - do - { + do { Cmd[0] = 0x50; // EWSR err = flashio(dev,linknr, Cmd,1,NULL,0); if( err < 0 ) break; @@ -513,8 +534,7 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset, err = flashio(dev,linknr, Cmd,2,NULL,0); if( err < 0 ) break; - for(i = 0; i < BufferSize; i += 4096 ) - { + for(i = 0; i < BufferSize; i += 4096 ) { if( (i & 0xFFFF) == 0 ) { printf(" Erase %08x\n",FlashOffset + i); @@ -588,124 +608,117 @@ int FlashWritePageMode(int dev, uint32_t FlashOffset, return err; } +static int flash_wait(int fd, uint32_t link) +{ + while (1) { + uint8_t rcmd = 0x05; // RDSR + int err = flashio(fd, link, &rcmd, 1, &rcmd, 1); + + if (err < 0) + return err; + if ((rcmd & 0x01) == 0) + break; + } + return 0; +} + + int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset, - uint8_t LockBits, uint32_t fw_off) + uint8_t LockBits, uint32_t fw_off, int be) { int err = 0; uint8_t cmd[260]; int i, j; uint32_t flen, blen; + int blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000); blen = flen = lseek(dev, 0, SEEK_END) - fw_off; if (blen % 0xff) blen = (blen + 0xff) & 0xffffff00; - printf("blen = %u, flen = %u\n", blen, flen); - - do { - cmd[0] = 0x50; // EWSR - err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); - if (err < 0) - break; - - cmd[0] = 0x01; // WRSR - cmd[1] = 0x00; // BPx = 0, Unlock all blocks - err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0); - if (err < 0) - break; - - for (i = 0; i < flen; i += 4096) { - if ((i & 0xFFFF) == 0) - printf(" Erase %08x\n", FlashOffset + i); - - cmd[0] = 0x06; // WREN - err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); - if (err < 0) - break; - - cmd[0] = 0x20; // Sector erase ( 4Kb) - cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF ); - cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF ); - cmd[3] = 0x00; - err = flashio(ddf->fd, ddf->link, cmd, 4, NULL, 0); - if (err < 0) - break; + //printf("blen = %u, flen = %u\n", blen, flen); + setbuf(stdout, NULL); - while (1) { - cmd[0] = 0x05; // RDSR - err = flashio(ddf->fd, ddf->link, cmd, 1, &cmd[0], 1); - if (err < 0) - break; - if ((cmd[0] & 0x01) == 0) - break; - } - if (err < 0) - break; - - } - if (err < 0) - break; - - for (j = blen - 256; j >= 0; j -= 256 ) { - uint32_t len = 256; - ssize_t rlen; - - if (lseek(dev, j + fw_off, SEEK_SET) < 0) { - printf("seek error\n"); - return -1; - } - if (flen - j < 256) { - len = flen - j; - memset(ddf->buffer, 0xff, 256); - } - rlen = read(dev, ddf->buffer, len); - if (rlen < 0 || rlen != len) { - printf("file read error %d,%d at %u\n", rlen, errno, j); - return -1; - } - //printf ("write %u bytes at %08x\n", len, j); - - - if ((j & 0xFFFF) == 0) - printf(" Program %08x\n", FlashOffset + j); - - cmd[0] = 0x06; // WREN - err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); - if (err < 0) - break; - - cmd[0] = 0x02; // PP - cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF ); - cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF ); - cmd[3] = 0x00; - memcpy(&cmd[4], ddf->buffer, 256); - err = flashio(ddf->fd, ddf->link, cmd, 260, NULL, 0); - if (err < 0) - break; - - while(1) { - cmd[0] = 0x05; // RDRS - err = flashio(ddf->fd, ddf->link, cmd,1, &cmd[0], 1); - if (err < 0) - break; - if ((cmd[0] & 0x01) == 0) - break; - } - if (err < 0) - break; - - } - if (err < 0) - break; - - cmd[0] = 0x50; // EWSR + cmd[0] = 0x50; // EWSR + err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); + if (err < 0) + return err; + + cmd[0] = 0x01; // WRSR + cmd[1] = 0x00; // BPx = 0, Unlock all blocks + err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0); + if (err < 0) + return err; + + for (i = 0; i < flen; ) { + printf(" Erase %08x\r", FlashOffset + i); + cmd[0] = 0x06; // WREN err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); if (err < 0) - break; + return err; + cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF ); + cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF ); + cmd[3] = 0x00; + if (blockerase && ((flen - i) >= 0x10000) ) { + cmd[0] = 0xd8; + i += 0x10000; + } else { + cmd[0] = 0x20; // Sector erase ( 4Kb) + i += 0x1000; + } + err = flashio(ddf->fd, ddf->link, cmd, 4, NULL, 0); + if (err < 0) + return err; + err = flash_wait(ddf->fd, ddf->link); + if (err < 0) + return err; + } + for (j = blen - 256; j >= 0; j -= 256 ) { + uint32_t len = 256; + ssize_t rlen; - cmd[0] = 0x01; // WRSR - cmd[1] = LockBits; // BPx = 0, Lock all blocks - err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0); - } while(0); + if (lseek(dev, j + fw_off, SEEK_SET) < 0) { + printf("seek error\n"); + return -1; + } + if (flen - j < 256) { + len = flen - j; + memset(ddf->buffer, 0xff, 256); + } + rlen = read(dev, ddf->buffer, len); + if (rlen < 0 || rlen != len) { + printf("file read error %d,%d at %u\n", rlen, errno, j); + return -1; + } + printf(" Program %08x\r", FlashOffset + j); + + cmd[0] = 0x06; // WREN + err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); + if (err < 0) + goto out; + + cmd[0] = 0x02; // PP + cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF ); + cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF ); + cmd[3] = 0x00; + memcpy(&cmd[4], ddf->buffer, 256); + err = flashio(ddf->fd, ddf->link, cmd, 260, NULL, 0); + if (err < 0) + goto out; + err = flash_wait(ddf->fd, ddf->link); + if (err < 0) + goto out; + } + printf("\n"); + + cmd[0] = 0x50; // EWSR + err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); + if (err < 0) + goto out; + + cmd[0] = 0x01; // WRSR + cmd[1] = LockBits; // BPx = 0, Lock all blocks + err = flashio(ddf->fd, ddf->link, cmd, 2, NULL, 0); +out: return err; } @@ -845,7 +858,7 @@ static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxle case SSTI_SST25VF032B: return flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off); case SSTI_SST25VF064C: - return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off); + return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off, 0); case SPANSION_S25FL116K: case SPANSION_S25FL132K: case SPANSION_S25FL164K: @@ -853,7 +866,8 @@ static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxle case WINBOND_W25Q32JV: case WINBOND_W25Q64JV: case WINBOND_W25Q128JV: - return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off); + default: + return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off, 1); } return -1; } @@ -892,97 +906,55 @@ static int get_id(struct ddflash *ddf) return 0; } +struct devids { + uint16_t id; + char *name; + char *fname; +}; + +#define DEV(_id, _name, _fname) { .id = _id, .name = _name, .fname = _fname } + +static const struct devids ids[] = { + DEV(0x0002, "Octopus 35", "DVBBridgeV1A_DVBBridgeV1A.bit"), + DEV(0x0003, "Octopus", "DVBBridgeV1B_DVBBridgeV1B.fpga"), + DEV(0x0005, "Octopus Classic", "DVBBridgeV2A_DD01_0005_STD.fpga"), + DEV(0x0006, "CineS2 V7", "DVBBridgeV2A_DD01_0006_STD.fpga"), + DEV(0x0007, "Octopus 4/8", "DVBBridgeV2A_DD01_0007_MXL.fpga"), + DEV(0x0008, "Octopus 4/8", "DVBBridgeV2A_DD01_0008_CXD.fpga"), + DEV(0x0009, "Octopus MAXSX8", "DVBBridgeV2A_DD01_0009_SX8.fpga"), + DEV(0x000b, "Octopus MAXSX8 Basic", "DVBBridgeV2A_DD01_000B_SX8.fpga"), + DEV(0x000a, "Octopus MAXM4", "DVBBridgeV2A_DD01_000A_M4.fpga"), + DEV(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"), + DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"), + DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.fpga"), + DEV(0x0020, "Octopus GT Mini", "DVBBridgeV2C_DD01_0020.fpga"), + DEV(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"), + DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"), + DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.fpga"), + DEV(0x0220, "SDRModulator ATV", "SDRModulatorV1A_DD01_0220.fpga"), + DEV(0x0221, "SDRModulator IQ", "SDRModulatorV1A_DD01_0221_IQ.fpga"), + DEV(0x0222, "SDRModulator DVBT", "SDRModulatorV1A_DD01_0222_DVBT.fpga"), + DEV(0x0223, "SDRModulator IQ2", "SDRModulatorV1A_DD01_0223_IQ2.fpga"), + DEV(0x0000, "UNKNOWN", 0), +}; static char *devid2fname(uint16_t devid, char **name) { + int i; char *fname = 0; - switch (devid) { - case 0x0002: - fname="DVBBridgeV1A_DVBBridgeV1A.bit"; - *name = "Octopus 35"; - break; - case 0x0003: - fname="DVBBridgeV1B_DVBBridgeV1B.fpga"; - *name = "Octopus"; - break; - case 0x0005: - fname="DVBBridgeV2A_DD01_0005_STD.fpga"; - *name = "Octopus Classic"; - break; - case 0x0006: - fname="DVBBridgeV2A_DD01_0006_STD.fpga"; - *name = "CineS2 V7"; - break; - case 0x0007: - fname="DVBBridgeV2A_DD01_0007_MXL.fpga"; - *name = "Octopus 4/8"; - break; - case 0x0008: - fname="DVBBridgeV2A_DD01_0008_CXD.fpga"; - *name = "Octopus 4/8"; - break; - case 0x0009: - fname="DVBBridgeV2A_DD01_0009_SX8.fpga"; - *name = "Octopus MAXSX8"; - break; - case 0x000b: - fname="DVBBridgeV2A_DD01_000B_SX8.fpga"; - *name = "Octopus MAXSX8 Basic"; - break; - case 0x000a: - fname="DVBBridgeV2A_DD01_000A_M4.fpga"; - *name = "Octopus MAXM4"; - break; - case 0x0011: - fname="DVBBridgeV2B_DD01_0011.fpga"; - *name = "Octopus CI"; - break; - case 0x0012: - fname="DVBBridgeV2B_DD01_0012_STD.fpga"; - *name = "Octopus CI"; - break; - case 0x0013: - fname="DVBBridgeV2B_DD01_0013_PRO.fpga"; - *name = "Octopus PRO"; - break; - case 0x0020: - fname="DVBBridgeV2C_DD01_0020.fpga"; - *name = "Octopus GT Mini"; - break; - case 0x0201: - fname="DVBModulatorV1B_DVBModulatorV1B.bit"; - *name = "Modulator"; - break; - case 0x0203: - fname="DVBModulatorV1B_DD01_0203.fpga"; - *name = "Modulator Test"; - break; - case 0x0210: - fname="DVBModulatorV2A_DD01_0210.fpga"; - *name = "Modulator V2"; - break; - case 0x0220: - fname="SDRModulatorV1A_DD01_0220.fpga"; - *name = "SDRModulator ATV"; - break; - case 0x0221: - fname="SDRModulatorV1A_DD01_0221_IQ.fpga"; - *name = "SDRModulator IQ"; - break; - case 0x0222: - fname="SDRModulatorV1A_DD01_0222_DVBT.fpga"; - *name = "SDRModulator DVBT"; - break; - default: - *name = "UNKNOWN"; - break; + for (i = 0; ; i++) { + const struct devids *id = &ids[i]; + + if (devid == id->id || !id->id) { + *name = id->name; + fname = id->fname; + break; + } } return fname; } - - static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off) { off_t off; @@ -1015,9 +987,9 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, if (memcmp(buf, buf2, bl)) { printf("flash differs at %08x (offset %u)\n", addr, j); - dump(buf, bl); - printf("\n"); - dump(buf2, bl); + //dump(buf, bl); + //printf("\n"); + //dump(buf2, bl); return addr; } } @@ -1080,7 +1052,7 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) unsigned int devid, version, length; unsigned int cid[8]; int cids = 0; - uint32_t maxlen = 2 * 1024 * 1024, crc; + uint32_t maxlen = 2 * 1024 * 1024, crc, fcrc; fd = open(fn, O_RDONLY); if (fd < 0) { @@ -1148,11 +1120,17 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) } p++; *fw_off = p; - printf(" CRC = %08x\n", crc); - printf(" devid = %04x\n", devid); - printf(" version = %08x (current image = %08x)\n", version, ddf->id.hw); + fcrc = crc32(buf + p, length, 0xffffffff); + printf(" CRC file = %08x\n", fcrc); + printf(" CRC flash = %08x\n", crc); + printf(" devid = %04x\n", devid); + printf(" version = %08x (current image = %08x)\n", version, ddf->id.hw); //printf(" length = %u\n", length); //printf("fsize = %u, p = %u, f-p = %u\n", fsize, p, fsize - p); + if (fcrc != crc) { + printf("CRC error in file %s!\n", fn); + return -4; + } if (devid == ddf->id.device) { if (version <= (ddf->id.hw & 0xffffff)) { printf("%s is older or same version as flash\n", fn); @@ -1175,7 +1153,7 @@ static int update_image(struct ddflash *ddf, char *fn, int fs, res = 0; uint32_t fw_off = 0; - printf("File: %s\n", fn); + printf("File: %s\n", fn); if (has_header) { int ck; ck = check_fw(ddf, fn, &fw_off); @@ -1192,6 +1170,10 @@ static int update_image(struct ddflash *ddf, char *fn, res = flashcmp(ddf, fs, adr, len, fw_off); if (res == -2) { printf("Flash already identical to %s\n", fn); + if (ddf->force) { + printf("but force enabled!\n"); + res = 0; + } } if (res < 0) goto out; @@ -1200,6 +1182,9 @@ static int update_image(struct ddflash *ddf, char *fn, res = flashcmp(ddf, fs, adr, len, fw_off); if (res == -2) { res = 1; + printf("Flash verify OK!\n"); + } else { + printf("Flash verify ERROR!\n"); } } diff --git a/apps/octonet/flash.h b/apps/octonet/flash.h index 350fabe..8271be0 100644 --- a/apps/octonet/flash.h +++ b/apps/octonet/flash.h @@ -89,6 +89,7 @@ struct ddflash { int fd; uint32_t link; char *fname; + int force; struct ddb_id id; uint32_t version; diff --git a/apps/tscheck.c b/apps/tscheck.c index ea132c8..f3947eb 100644 --- a/apps/tscheck.c +++ b/apps/tscheck.c @@ -27,14 +27,16 @@ void proc_ts(int i, uint8_t *buf) { uint16_t pid= 0x1fff& ((buf[1] << 8) | buf[2]); uint8_t ccin = buf[3] & 0x1f; - + if( buf[0] == 0x47 && (buf[1] & 0x80) == 0) { if( pid != 8191 ) { if (ccin & 0x10) { if( cc[pid] != 0 ) { // TODO: 1 repetition allowed - if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) ) + if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) ) { cc_errors += 1; + printf("%04x: %u != %u\n", pid, (cc[pid] + 1) & 0x0F, ccin & 0x0F); + } } cc[pid] = ccin; } diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index d911837..5071bb3 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -2507,8 +2507,10 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr) rm = io_regmap(input, 1); input->regs = DDB_LINK_TAG(port->lnr) | (rm->input->base + rm->input->size * nr); +#if 0 dev_info(dev->dev, "init link %u, input %u, regs %08x\n", port->lnr, nr, input->regs); +#endif if (dev->has_dma) { const struct ddb_regmap *rm0 = io_regmap(input, 0); u32 base = rm0->irq_base_idma; @@ -3210,6 +3212,12 @@ struct ddb_i2c_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) @@ -3222,6 +3230,7 @@ struct ddb_i2c_msg { #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" @@ -3433,6 +3442,24 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EIO; break; } + case IOCTL_DDB_MCI_CMD: + { + struct ddb_mci_msg msg; + struct ddb_link *link; + int res; + + if (copy_from_user(&msg, parg, sizeof(msg))) + return -EFAULT; + 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; + return res; + } default: return -ENOTTY; } @@ -4414,6 +4441,13 @@ static int ddb_init_boards(struct ddb *dev) usleep_range(2000, 3000); } ddb_init_tempmon(link); + + if (info->regmap->mci) { + if (link->info->type == DDB_OCTOPUS_MCI || + ((link->info->type == DDB_MOD) && + (link->ids.regmapid & 0xfff0))) + mci_init(link); + } } return 0; } diff --git a/ddbridge/ddbridge-hw.c b/ddbridge/ddbridge-hw.c index 083eff8..3d61ebb 100644 --- a/ddbridge/ddbridge-hw.c +++ b/ddbridge/ddbridge-hw.c @@ -124,6 +124,32 @@ static const struct ddb_regset octopus_i2c_buf = { /****************************************************************************/ +static const struct ddb_regset max_mci = { + .base = 0x500, + .num = 0x01, + .size = 0x04, +}; + +static const struct ddb_regset max_mci_buf = { + .base = 0x600, + .num = 0x01, + .size = 0x100, +}; + +static const struct ddb_regset sdr_mci = { + .base = 0x260, + .num = 0x01, + .size = 0x04, +}; + +static const struct ddb_regset sdr_mci_buf = { + .base = 0x300, + .num = 0x01, + .size = 0x100, +}; + +/****************************************************************************/ + static const struct ddb_regset octopro_input = { .base = 0x400, .num = 0x14, @@ -224,6 +250,25 @@ static const struct ddb_regmap octopus_map = { .output = &octopus_output, }; +static const struct ddb_regmap octopus_mci_map = { + .irq_version = 1, + .irq_base_i2c = 0, + .irq_base_idma = 8, + .irq_base_odma = 16, + .irq_base_mci = 0, + .i2c = &octopus_i2c, + .i2c_buf = &octopus_i2c_buf, + .idma = &octopus_idma, + .idma_buf = &octopus_idma_buf, + .odma = &octopus_odma, + .odma_buf = &octopus_odma_buf, + .input = &octopus_input, + .output = &octopus_output, + + .mci = &max_mci, + .mci_buf = &max_mci_buf, +}; + static const struct ddb_regmap octopro_map = { .irq_version = 2, .irq_base_i2c = 32, @@ -280,10 +325,14 @@ static const struct ddb_regmap octopus_sdr_map = { .irq_version = 2, .irq_base_odma = 64, .irq_base_rate = 32, + .irq_base_mci = 10, .output = &octopus_sdr_output, .odma = &octopus_mod_2_odma, .odma_buf = &octopus_mod_2_odma_buf, .channel = &octopus_mod_2_channel, + + .mci = &sdr_mci, + .mci_buf = &sdr_mci_buf, }; static const struct ddb_regmap gtl_mini = { @@ -537,6 +586,16 @@ static const struct ddb_info ddb_sdr_iq = { .tempmon_irq = 8, }; +static const struct ddb_info ddb_sdr_iq2 = { + .type = DDB_MOD, + .name = "Digital Devices SDR IQ2", + .version = 17, + .regmap = &octopus_sdr_map, + .port_num = 4, + .temp_num = 1, + .tempmon_irq = 8, +}; + static const struct ddb_info ddb_sdr_dvbt = { .type = DDB_MOD, .name = "Digital Devices DVBT", @@ -568,7 +627,7 @@ static const struct ddb_info ddb_octopro = { static const struct ddb_info ddb_s2_48 = { .type = DDB_OCTOPUS_MAX, .name = "Digital Devices MAX S8 4/8", - .regmap = &octopus_map, + .regmap = &octopus_mci_map, .port_num = 4, .i2c_mask = 0x01, .board_control = 1, @@ -635,10 +694,12 @@ static const struct ddb_info ddb_c2t2i_8 = { .tempmon_irq = 24, }; +/****************************************************************************/ + static const struct ddb_info ddb_s2x_48 = { .type = DDB_OCTOPUS_MCI, .name = "Digital Devices MAX SX8", - .regmap = &octopus_map, + .regmap = &octopus_mci_map, .port_num = 4, .i2c_mask = 0x00, .tempmon_irq = 24, @@ -650,7 +711,7 @@ static const struct ddb_info ddb_s2x_48 = { static const struct ddb_info ddb_s2x_48_b = { .type = DDB_OCTOPUS_MCI, .name = "Digital Devices MAX SX8 Basic", - .regmap = &octopus_map, + .regmap = &octopus_mci_map, .port_num = 4, .i2c_mask = 0x00, .tempmon_irq = 24, @@ -662,7 +723,7 @@ static const struct ddb_info ddb_s2x_48_b = { static const struct ddb_info ddb_m4 = { .type = DDB_OCTOPUS_MCI, .name = "Digital Devices MAX M4", - .regmap = &octopus_map, + .regmap = &octopus_mci_map, .port_num = 2, .i2c_mask = 0x00, .tempmon_irq = 24, @@ -671,6 +732,8 @@ static const struct ddb_info ddb_m4 = { .temp_num = 1, }; +/****************************************************************************/ + static const struct ddb_info ddb_gtl_mini = { .type = DDB_OCTOPUS, .name = "Digital Devices Octopus GT Mini", @@ -813,6 +876,8 @@ static const struct ddb_device_id ddb_device_ids[] = { DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv), DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq), DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt), + DDB_DEVID(0x0223, 0x0001, ddb_sdr_iq2), + DDB_DEVID(0xffff, 0xffff, ddb_sdr_iq2), /* testing on OctopusNet Pro */ DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin), diff --git a/ddbridge/ddbridge-io.c b/ddbridge/ddbridge-io.c index 8844a24..6df9a30 100644 --- a/ddbridge/ddbridge-io.c +++ b/ddbridge/ddbridge-io.c @@ -139,8 +139,8 @@ void gtlcpyfrom(struct ddb *dev, u8 *buf, u32 adr, long count) u32 a = p & 3; if (a) { - val = ddbreadl(dev, p) >> (8 * a); - while (p & 3 && count) { + val = ddbreadl(dev, p & ~3) >> (8 * a); + while ((p & 3) && count) { *buf = val & 0xff; val >>= 8; p++; @@ -177,7 +177,12 @@ void ddbcpyto(struct ddb *dev, u32 adr, void *src, long count) void ddbcpyfrom(struct ddb *dev, void *dst, u32 adr, long count) { + return gtlcpyfrom(dev, dst, adr, count); + /* The possible 64 bit read in memcpy_fromio produces errors + on some platforms, i.e. arm64 rpi4 if (unlikely(adr & 0xf0000000)) return gtlcpyfrom(dev, dst, adr, count); - return memcpy_fromio(dst, dev->regs + adr, count); + return memcpy_fromio(dst, dev->regs + adr, count); + */ + } diff --git a/ddbridge/ddbridge-m4.c b/ddbridge/ddbridge-m4.c index 661ede4..29e0f22 100644 --- a/ddbridge/ddbridge-m4.c +++ b/ddbridge/ddbridge-m4.c @@ -402,6 +402,8 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) ddb_mci_get_strength(fe); if (res.status == MCI_DEMOD_WAIT_SIGNAL) *status = 0x01; + if (res.status == M4_DEMOD_WAIT_TS) + *status = 0x03; if (res.status == MCI_DEMOD_LOCKED) { *status = 0x1f; ddb_mci_get_snr(fe); diff --git a/ddbridge/ddbridge-main.c b/ddbridge/ddbridge-main.c index 94da972..23a414b 100644 --- a/ddbridge/ddbridge-main.c +++ b/ddbridge/ddbridge-main.c @@ -290,9 +290,11 @@ static int __devinit ddb_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) - return -ENODEV; + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + } else return -ENODEV; dev = vzalloc(sizeof(*dev)); if (!dev) @@ -425,6 +427,7 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = { DDB_DEVICE_ANY(0x0220), DDB_DEVICE_ANY(0x0221), DDB_DEVICE_ANY(0x0222), + DDB_DEVICE_ANY(0x0223), DDB_DEVICE_ANY(0x0320), DDB_DEVICE_ANY(0x0321), DDB_DEVICE_ANY(0x0322), diff --git a/ddbridge/ddbridge-mci.c b/ddbridge/ddbridge-mci.c index b617064..760d9f5 100644 --- a/ddbridge/ddbridge-mci.c +++ b/ddbridge/ddbridge-mci.c @@ -28,151 +28,178 @@ static LIST_HEAD(mci_list); -static int mci_reset(struct mci *state) +static int mci_reset(struct ddb_link *link) { - struct ddb_link *link = state->base->link; + const struct ddb_regmap *regmap = link->info->regmap; + u32 control; u32 status = 0; u32 timeout = 40; - ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL); - ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */ - msleep(300); - ddblwritel(link, 0, MCI_CONTROL); + if (!regmap || ! regmap->mci) + return -EINVAL; + control = regmap->mci->base; + if ((link->info->type == DDB_OCTOPUS_MCI) && + (ddblreadl(link, control) & MCI_CONTROL_START_COMMAND)) { + ddblwritel(link, MCI_CONTROL_RESET, control); + ddblwritel(link, 0, control + 4); /* 1= no internal init */ + msleep(300); + } + ddblwritel(link, 0, control); while (1) { - status = ddblreadl(link, MCI_CONTROL); + status = ddblreadl(link, control); if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) break; if (--timeout == 0) break; msleep(50); } - if ((status & MCI_CONTROL_READY) == 0) + 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; - if (link->ids.device == 0x0009 || link->ids.device == 0x000b) - ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); + } + dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40-timeout)*50); return 0; } -int ddb_mci_config(struct mci *state, u32 config) -{ - struct ddb_link *link = state->base->link; - - if (link->ids.device != 0x0009 && link->ids.device != 0x000b) - return -EINVAL; - ddblwritel(link, config, SX8_TSCONFIG); - return 0; -} - - -static int ddb_mci_cmd_raw_unlocked(struct mci *state, +static int ddb_mci_cmd_raw_unlocked(struct ddb_link *link, u32 *cmd, u32 cmd_len, u32 *res, u32 res_len) { - struct ddb_link *link = state->base->link; + const struct ddb_regmap *regmap = link->info->regmap; + u32 control, command, result; u32 i, val; unsigned long stat; - val = ddblreadl(link, MCI_CONTROL); + if (!regmap || ! regmap->mci) + return -EINVAL; + control = regmap->mci->base; + command = regmap->mci_buf->base; + result = command + MCI_COMMAND_SIZE; + val = ddblreadl(link, control); if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) return -EIO; if (cmd && cmd_len) for (i = 0; i < cmd_len; i++) - ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); - val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); - ddblwritel(link, val, MCI_CONTROL); + ddblwritel(link, cmd[i], command + i * 4); + val |= (MCI_CONTROL_START_COMMAND | + MCI_CONTROL_ENABLE_DONE_INTERRUPT); + ddblwritel(link, val, control); - stat = wait_for_completion_timeout(&state->base->completion, HZ); + stat = wait_for_completion_timeout(&link->mci_completion, HZ); if (stat == 0) { u32 istat = ddblreadl(link, INTERRUPT_STATUS); - dev_err(state->base->link->dev->dev, "MCI timeout\n"); - val = ddblreadl(link, MCI_CONTROL); + dev_err(link->dev->dev, "MCI timeout\n"); + val = ddblreadl(link, control); if (val == 0xffffffff) { - dev_err(state->base->link->dev->dev, + dev_err(link->dev->dev, "Lost PCIe link!\n"); return -EIO; } else { - dev_err(state->base->link->dev->dev, - "DDBridge IRS %08x link %u\n", istat, link->nr); + dev_err(link->dev->dev, + "DDBridge IRS %08x link %u\n", + istat, link->nr); if (istat & 1) ddblwritel(link, istat, INTERRUPT_ACK); if (link->nr) - ddbwritel(link->dev, 0xffffff, INTERRUPT_ACK); + ddbwritel(link->dev, + 0xffffff, INTERRUPT_ACK); } } if (res && res_len) for (i = 0; i < res_len; i++) - res[i] = ddblreadl(link, MCI_RESULT + i * 4); + res[i] = ddblreadl(link, result + i * 4); return 0; } -int ddb_mci_cmd_unlocked(struct mci *state, - struct mci_command *command, - struct mci_result *result) +int ddb_mci_cmd_link(struct ddb_link *link, + struct mci_command *command, + struct mci_result *result) { - u32 *cmd = (u32 *) command; - u32 *res = (u32 *) result; - - return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32), - res, sizeof(*result)/sizeof(u32)); -} - -int ddb_mci_cmd(struct mci *state, - struct mci_command *command, - struct mci_result *result) -{ - int stat; struct mci_result res; + int stat; if (!result) result = &res; - mutex_lock(&state->base->mci_lock); - stat = ddb_mci_cmd_raw_unlocked(state, - (u32 *)command, sizeof(*command)/sizeof(u32), - (u32 *)result, sizeof(*result)/sizeof(u32)); - mutex_unlock(&state->base->mci_lock); + mutex_lock(&link->mci_lock); + stat = ddb_mci_cmd_raw_unlocked(link, + (u32 *)command, + sizeof(*command)/sizeof(u32), + (u32 *)result, + sizeof(*result)/sizeof(u32)); + mutex_unlock(&link->mci_lock); if (command && result && (result->status & 0x80)) - dev_warn(state->base->link->dev->dev, + dev_warn(link->dev->dev, "mci_command 0x%02x, error=0x%02x\n", command->command, result->status); return stat; } +static void mci_handler(void *priv) +{ + struct ddb_link *link = (struct ddb_link *) priv; + + complete(&link->mci_completion); +} + +int mci_init(struct ddb_link *link) +{ + int result; + + mutex_init(&link->mci_lock); + init_completion(&link->mci_completion); + result = mci_reset(link); + if (result < 0) + return result; + if (link->ids.device == 0x0009 || link->ids.device == 0x000b) + ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); + + ddb_irq_set(link->dev, link->nr, + link->info->regmap->irq_base_mci, + mci_handler, link); + link->mci_ok = 1; + return result; +} + +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 }, + }; + + return ddb_mci_cmd_link(link, &command, &result); +} + +/****************************************************************************/ +/****************************************************************************/ + +int ddb_mci_cmd(struct mci *state, + struct mci_command *command, + struct mci_result *result) +{ + return ddb_mci_cmd_link(state->base->link, command, result); +} + + int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len, struct mci_result *result, u32 result_len) { + struct ddb_link *link = state->base->link; int stat; - mutex_lock(&state->base->mci_lock); - stat = ddb_mci_cmd_raw_unlocked(state, + mutex_lock(&link->mci_lock); + stat = ddb_mci_cmd_raw_unlocked(link, (u32 *)command, command_len, (u32 *)result, result_len); - mutex_unlock(&state->base->mci_lock); + mutex_unlock(&link->mci_lock); return stat; } -#if 0 -static int ddb_mci_get_iq(struct mci *mci, u32 demod, s16 *i, s16 *q) -{ - int stat; - struct mci_command cmd; - struct mci_result res; - - memset(&cmd, 0, sizeof(cmd)); - memset(&res, 0, sizeof(res)); - cmd.command = MCI_CMD_GET_IQSYMBOL; - cmd.demod = demod; - stat = ddb_mci_cmd(mci, &cmd, &res); - if (!stat) { - *i = res.iq_symbol.i; - *q = res.iq_symbol.q; - } - return stat; -} -#endif - int ddb_mci_get_status(struct mci *mci, struct mci_result *res) { struct mci_command cmd; @@ -189,7 +216,8 @@ int ddb_mci_get_snr(struct dvb_frontend *fe) p->cnr.len = 1; p->cnr.stat[0].scale = FE_SCALE_DECIBEL; - p->cnr.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10; + p->cnr.stat[0].svalue = + (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10; return 0; } @@ -266,6 +294,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) p->delivery_system = (mci->signal_info.dvbs2_signal_info.standard == 2) ? SYS_DVBS2 : SYS_DVBS; + p->inversion = (mci->signal_info.dvbs2_signal_info.roll_off & 0x80) ? + INVERSION_ON : INVERSION_OFF; if (mci->signal_info.dvbs2_signal_info.standard == 2) { u32 modcod; @@ -306,6 +336,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) case SYS_ISDBT: break; } + /* post is correct, we cannot provide both pre and post at the same time */ + /* set pre and post the same for now */ p->pre_bit_error.len = 1; p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; p->pre_bit_error.stat[0].uvalue = @@ -316,6 +348,16 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) p->pre_bit_count.stat[0].uvalue = mci->signal_info.dvbs2_signal_info.ber_denominator; + p->post_bit_error.len = 1; + p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + p->post_bit_error.stat[0].uvalue = + mci->signal_info.dvbs2_signal_info.ber_numerator; + + p->post_bit_count.len = 1; + p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; + p->post_bit_count.stat[0].uvalue = + mci->signal_info.dvbs2_signal_info.ber_denominator; + p->block_error.len = 1; p->block_error.stat[0].scale = FE_SCALE_COUNTER; p->block_error.stat[0].uvalue = @@ -329,17 +371,10 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) p->strength.len = 1; p->strength.stat[0].scale = FE_SCALE_DECIBEL; - p->strength.stat[0].svalue = + p->strength.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.channel_power * 10; } -static void mci_handler(void *priv) -{ - struct mci_base *base = (struct mci_base *)priv; - - complete(&base->completion); -} - static struct mci_base *match_base(void *key) { struct mci_base *p; @@ -350,13 +385,8 @@ static struct mci_base *match_base(void *key) return NULL; } -static int probe(struct mci *state) -{ - mci_reset(state); - return 0; -} - -struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner) +struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, + struct mci_cfg *cfg, int nr, int tuner) { struct ddb_port *port = input->port; struct ddb *dev = port->dev; @@ -380,12 +410,11 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg base->key = key; base->count = 1; base->link = link; - mutex_init(&base->mci_lock); + link->mci_base = base; mutex_init(&base->tuner_lock); - ddb_irq_set(dev, link->nr, 0, mci_handler, base); - init_completion(&base->completion); state->base = base; - if (probe(state) < 0) { + + if (!link->mci_ok) { kfree(base); goto fail; } diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index 2fe37bc..03e167b 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -39,11 +39,6 @@ #define MIC_INTERFACE_OUT (0x0680) #define MIC_INTERFACE_VER (0x06F0) - -#define MCI_CONTROL (0x500) -#define MCI_COMMAND (0x600) -#define MCI_RESULT (0x680) - #define MCI_COMMAND_SIZE (0x80) #define MCI_RESULT_SIZE (0x80) @@ -686,7 +681,7 @@ struct mci_result { } ISDBS_TMCCInfo; }; u32 version[3]; - u32 version_rsvd; + u8 version_rsvd; u8 version_major; u8 version_minor; u8 version_sub; @@ -767,9 +762,9 @@ struct mci_base { struct list_head mci_list; void *key; struct ddb_link *link; - struct completion completion; +// struct completion completion; struct mutex tuner_lock; - struct mutex mci_lock; +// struct mutex mci_lock; int count; int type; }; @@ -795,14 +790,14 @@ struct mci_cfg { }; int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result); -int ddb_mci_cmd_raw(struct mci *state, struct mci_command *command, u32 command_len, - struct mci_result *result, u32 result_len); -int ddb_mci_config(struct mci *state, u32 config); +int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result); int ddb_mci_get_status(struct mci *mci, struct mci_result *res); int ddb_mci_get_snr(struct dvb_frontend *fe); 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); extern struct mci_cfg ddb_max_sx8_cfg; extern struct mci_cfg ddb_max_m4_cfg; diff --git a/ddbridge/ddbridge-modulator.c b/ddbridge/ddbridge-modulator.c index cf12a8a..c5a9b70 100644 --- a/ddbridge/ddbridge-modulator.c +++ b/ddbridge/ddbridge-modulator.c @@ -644,6 +644,7 @@ 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) @@ -658,6 +659,8 @@ 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; } @@ -1516,6 +1519,7 @@ static int mod3_set_ari(struct ddb_mod *mod, u32 rate) static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate) { + struct ddb *dev = mod->port->dev; u32 cic, inc, bypass = 0; switch (rate) { @@ -1556,19 +1560,52 @@ static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate) inc = 0x7684BD82; //1988410754; cic = 7; break; - case SYS_DVBS2_22: + case SYS_DVB_22: inc = 0x72955555; // 1922389333; cic = 5; bypass = 2; break; - case SYS_DVBS2_24: + case SYS_DVB_24: inc = 0x7d000000; cic = 5; bypass = 2; break; + case SYS_DVB_30: + inc = 0x7d000000; + cic = 4; + bypass = 2; + break; + case SYS_ISDBS_2886: + inc = 0x78400000; + cic = 4; + bypass = 2; + break; default: - return -EINVAL; + { + u64 a; + + if (rate < 1000000) + return -EINVAL; + if (rate > 30720000) + return -EINVAL; + + bypass = 2; + if (rate > 24576000) + cic = 4; + else if (rate > 20480000) + cic = 5; + else if (rate > 17554286) + cic = 6; + else if (rate > 15360000) + cic = 7; + else + cic = 8; + a = (1ULL << 31) * rate * 2 * cic; + inc = div_s64(a, 245760000); + break; } + } + dev_info(dev->dev, "inc = %08x, cic = %u, bypass = %u\n", inc, cic, bypass); ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr)); ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4), SDR_CHANNEL_CONFIG(mod->port->nr)); @@ -1596,6 +1633,7 @@ static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp) case MODULATOR_GAIN: return mod_set_sdr_gain(mod->port->dev, tvp->u.data); + } return -EINVAL; } diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index 3566d54..8f062f4 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -114,6 +114,16 @@ static void release(struct dvb_frontend *fe) kfree(state); } +static int ddb_mci_tsconfig(struct mci *state, u32 config) +{ + struct ddb_link *link = state->base->link; + + if (link->ids.device != 0x0009 && link->ids.device != 0x000b) + return -EINVAL; + ddblwritel(link, config, SX8_TSCONFIG); + return 0; +} + static int read_status(struct dvb_frontend *fe, enum fe_status *status) { int stat; @@ -172,7 +182,7 @@ static int stop_iq(struct dvb_frontend *fe) cmd.command = SX8_CMD_STOP_IQ; cmd.demod = state->mci.demod; ddb_mci_cmd(&state->mci, &cmd, NULL); - ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); + ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL); mutex_lock(&mci_base->tuner_lock); sx8_base->tuner_use_count[input]--; @@ -209,7 +219,7 @@ static int stop(struct dvb_frontend *fe) cmd.demod = state->mci.demod; cmd.output = 0; ddb_mci_cmd(&state->mci, &cmd, NULL); - ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL); + ddb_mci_tsconfig(&state->mci, SX8_TSCONFIG_MODE_NORMAL); } } mutex_lock(&mci_base->tuner_lock); @@ -331,7 +341,7 @@ unlock: cmd.demod = state->mci.demod; cmd.output = p->stream_id & 7; ddb_mci_cmd(&state->mci, &cmd, NULL); - ddb_mci_config(&state->mci, ts_config); + ddb_mci_tsconfig(&state->mci, ts_config); } if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000)) flags |= 0x80; @@ -411,7 +421,7 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, stat = ddb_mci_cmd(&state->mci, &cmd, NULL); if (stat) stop_iq(fe); - ddb_mci_config(&state->mci, ts_config); + ddb_mci_tsconfig(&state->mci, ts_config); return stat; } diff --git a/ddbridge/ddbridge.h b/ddbridge/ddbridge.h index 9170dfc..62afb27 100644 --- a/ddbridge/ddbridge.h +++ b/ddbridge/ddbridge.h @@ -114,6 +114,7 @@ struct ddb_regmap { u32 irq_base_odma; u32 irq_base_gtl; u32 irq_base_rate; + u32 irq_base_mci; const struct ddb_regset *i2c; const struct ddb_regset *i2c_buf; @@ -127,6 +128,9 @@ struct ddb_regmap { const struct ddb_regset *channel; const struct ddb_regset *gtl; + + const struct ddb_regset *mci; + const struct ddb_regset *mci_buf; }; struct ddb_ids { @@ -427,6 +431,9 @@ struct ddb_link { struct ddb_irq irq[256]; struct mci_base *mci_base; + struct completion mci_completion; + struct mutex mci_lock; + int mci_ok; }; struct ddb { diff --git a/docs/firmware b/docs/firmware new file mode 100644 index 0000000..6bc8b76 --- /dev/null +++ b/docs/firmware @@ -0,0 +1,13 @@ +Firmware update: + +Copy the firmware file to the dddvb/apps/ directory and +execute "./flashprog". + +The program will try to identify the card version and +check if it finds the corresponding firmware file. +It will then prompt you to confirm to proceed +with the flashing procedure. + +After the update the system needs a power cycle. + + diff --git a/docs/iq_samples b/docs/iq_samples new file mode 100644 index 0000000..f793481 --- /dev/null +++ b/docs/iq_samples @@ -0,0 +1,13 @@ +~The Max SX8 can provide IQ samples in real time. + +They are 8 bit signed values embedded in TS packets with PID 0x200. + +API: + +Currently DTV_STREAM_ID is misused. + +0x10000000 - symbols (locked and tracked) at symbol rate +0x20000000 - samples at ADC rate (1550/24=64.583... MHz) +0x30000000 - samples at symbol rate + +Max. sample rate is 64.583333 MHz. diff --git a/include/linux/dvb/mod.h b/include/linux/dvb/mod.h index 196c481..11c0470 100644 --- a/include/linux/dvb/mod.h +++ b/include/linux/dvb/mod.h @@ -44,8 +44,10 @@ enum mod_output_rate { SYS_ISDBT_6 = 16, SYS_J83B_64_6 = 24, SYS_J83B_256_6 = 25, - SYS_DVBS2_22 = 32, - SYS_DVBS2_24 = 33, + SYS_DVB_22 = 32, + SYS_DVB_24 = 33, + SYS_DVB_30 = 34, + SYS_ISDBS_2886 = 48, }; diff --git a/lib/ddzap.c b/lib/ddzap.c index cf29a41..465452b 100644 --- a/lib/ddzap.c +++ b/lib/ddzap.c @@ -203,7 +203,7 @@ void proc_ts(int i, uint8_t *buf) if (ccin & 0x10) { if ( cc[pid]) { // TODO: 1 repetition allowed - if( ( ccin & 0x10 ) != 0 && (((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) ) + if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F))) cc_errors += 1; } cc[pid] = ccin; @@ -414,6 +414,8 @@ int main(int argc, char **argv) delsys = SYS_ISDBC; if (!strcmp(optarg, "ISDBT")) delsys = SYS_ISDBT; + if (!strcmp(optarg, "ISDBS")) + delsys = SYS_ISDBS; break; case 'p': if (!strcmp(optarg, "h") || !strcmp(optarg, "H")) diff --git a/lib/src/dvb.c b/lib/src/dvb.c index 72e9703..0304236 100644 --- a/lib/src/dvb.c +++ b/lib/src/dvb.c @@ -128,7 +128,7 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr, } if (input != DDDVB_UNDEF) set_property(fd, DTV_INPUT, input); - fprintf(stderr, "bw =%u\n", fe->param.param[PARAM_BW_HZ]); + //fprintf(stderr, "bw =%u\n", fe->param.param[PARAM_BW_HZ]); if (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) set_property(fd, DTV_BANDWIDTH_HZ, fe->param.param[PARAM_BW_HZ]); if (fe->param.param[PARAM_ISI] != DDDVB_UNDEF) @@ -320,11 +320,12 @@ static int tune_sat(struct dddvb_fe *fe) } else { uint32_t input = lnb; - if (input != DDDVB_UNDEF) - input = 3 & (input >> 6); + //if (input != DDDVB_UNDEF) + // input = 3 & (input >> 6); //set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6)); diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi); - set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); + //set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); + set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U)); } } @@ -509,6 +510,32 @@ static int tune_isdbt(struct dddvb_fe *fe) return 0; } +static int tune_isdbs(struct dddvb_fe *fe) +{ + struct dtv_property p[] = { + { .cmd = DTV_CLEAR }, + { .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ]}, + //{ .cmd = DTV_SYMBOL_RATE, .u.data = fe->param.param[PARAM_SR] }, + //{ .cmd = DTV_TUNE }, + }; + struct dtv_properties c; + int ret; + + set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_ISDBS); + + c.num = ARRAY_SIZE(p); + c.props = p; + ret = ioctl(fe->fd, FE_SET_PROPERTY, &c); + if (ret < 0) { + fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret); + return -1; + } + if (fe->param.param[PARAM_ISI] != DDDVB_UNDEF) + set_property(fe->fd, DTV_STREAM_ID, fe->param.param[PARAM_ISI]); + set_property(fe->fd, DTV_TUNE, 0); + return 0; +} + static int tune(struct dddvb_fe *fe) { int ret; @@ -537,6 +564,9 @@ static int tune(struct dddvb_fe *fe) case SYS_ISDBT: ret = tune_isdbt(fe); break; + case SYS_ISDBS: + ret = tune_isdbs(fe); + break; default: break; } @@ -678,7 +708,7 @@ void dddvb_fe_handle(struct dddvb_fe *fe) } else { max = 1; nolock++; - if (nolock > 100) + if (nolock > 10) fe->tune = 1; } break;