📄 edid_maker.c
字号:
edid[block + offs++] = 250; // 2 Mbit/sec // 4 edid[block + offs++] = 0x27; // mp3, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 250; // 2 Mbit/sec // 5 edid[block + offs++] = 0x37; // aac, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 250; // 2 Mbit/sec // 6 edid[block + offs++] = 0x3F; // dts, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 250; // 2 Mbit/sec // 7 edid[block + offs++] = 0x4F; // one bit, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 0; // reserved // 8 edid[block + offs++] = 0x57; // DD+, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 0; // reserved // 9 edid[block + offs++] = 0x6F; // dst, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 0; // reserved // 10 edid[block + offs++] = 0x77; // wma pro, up to 8 ch. edid[block + offs++] = 0x7F; // all sample rates edid[block + offs++] = 0; // reserved edid[block + offs++] = 0x83; // speaker allocation edid[block + offs++] = 0x7F; // all speakers edid[block + offs++] = 0x00; // res. edid[block + offs++] = 0x00; // res. edid[block + 2] = offs; return RM_OK;}// CEA extensionstatic RMstatus edid_add_cea_tag(RMuint8 *edid, RMuint32 PhysA, RMuint32 PhysB, RMuint32 PhysC, RMuint32 PhysD, RMbool AI, RMbool DC48, RMbool DC36, RMbool DC30, RMbool DC444, RMbool DVIDual, RMuint32 MaxTMDS, RMbool LatPres, RMbool ILatPres, RMuint8 VLat, RMuint8 ALat, RMuint8 IVLat, RMuint8 IALat){ RMuint32 block, offs; block = (edid[0x7E] << 7); if (edid[block + 3] & 0x0F) { RMDBGPRINT((ENABLE, "Extension already contains DTD!\n")); return RM_ERROR; } offs = edid[block + 2]; // Add HDMI vendor specific block (to identify as HDMI device) edid[block + offs++] = 0x6C; // vendor specific, 12 bytes edid[block + offs++] = HDMI_IEEE_OUI & 0xFF; edid[block + offs++] = (HDMI_IEEE_OUI >> 8) & 0xFF; edid[block + offs++] = (HDMI_IEEE_OUI >> 16) & 0xFF; edid[block + offs++] = (PhysA << 4) | PhysB; // Physical address A, B edid[block + offs++] = (PhysC << 4) | PhysD; // Physical address C, D edid[block + offs++] = (AI ? 0x80 : 0x00) | // Bit 7: Supports_AI (DC48 ? 0x40 : 0x00) | (DC36 ? 0x20 : 0x00) | (DC30 ? 0x10 : 0x00) | (DC444 ? 0x08 : 0x00) | (DVIDual ? 0x01 : 0x00); edid[block + offs++] = MaxTMDS / 5; edid[block + offs++] = (LatPres ? 0x80 : 0x00) | (ILatPres ? 0x40 : 0x00); edid[block + offs++] = VLat; edid[block + offs++] = ALat; edid[block + offs++] = IVLat; edid[block + offs++] = IALat; edid[block + 2] = offs; return RM_OK;}static RMstatus edid_add_quantisation_tag(RMuint8 *edid, RMbool quant, RMbool over, RMbool under){ RMuint32 block, offs; block = (edid[0x7E] << 7); if (edid[block + 3] & 0x0F) { RMDBGPRINT((ENABLE, "Extension already contains DTD!\n")); return RM_ERROR; } offs = edid[block + 2]; // Add HDMI vendor specific block (to identify as HDMI device) edid[block + offs++] = 0xE2; // extended tag block, 2 bytes edid[block + offs++] = 0x00; // video capabilities tag edid[block + offs++] = (quant ? 0x40 : 0) | (over ? 0x15 : 0) | (under ? 0x2A : 0); edid[block + 2] = offs; return RM_OK;}static RMstatus edid_add_colorimetry_tag(RMuint8 *edid, RMbool xvYCC601, RMbool xvYCC709, RMuint32 MD){ RMuint32 block, offs; block = (edid[0x7E] << 7); if (edid[block + 3] & 0x0F) { RMDBGPRINT((ENABLE, "Extension already contains DTD!\n")); return RM_ERROR; } offs = edid[block + 2]; // Add HDMI vendor specific block (to identify as HDMI device) edid[block + offs++] = 0xE3; // extended tag block, 3 bytes edid[block + offs++] = 0x05; // colorimetry tag edid[block + offs++] = (xvYCC601 ? 0x01 : 0) | (xvYCC709 ? 0x02 : 0); edid[block + offs++] = MD & 0x07; edid[block + 2] = offs; return RM_OK;}static RMstatus edid_add_dtd(RMuint8 *edid, RMuint32 *offset, struct RUA *pInstance, enum EMhwlibTVStandard Standard, RMuint32 AspX, RMuint32 AspY){ RMstatus err; struct EMhwlibTVFormatDigital fmt; RMuint32 PixelClock, HorizBlankingPixels, VertBlankingLines, HorizSyncOffset, HorizSyncPulseWidth, VertSyncOffset, VertSyncPulseWidth, HorizImageSize, VertImageSize; if ((*offset < 0x80) && (*offset != 0x36) && (*offset != 0x48)) { RMDBGPRINT((ENABLE, "Wrong offset for DTD: 0x%02lX\n", *offset)); return RM_ERROR; } if ((*offset >> 7) > edid[0x7E]) { RMDBGPRINT((ENABLE, "DTD at %lu in uninitialized extension block!\n", *offset)); return RM_ERROR; } if ((*offset & 0x7F) == 0) { *offset += edid[(*offset & 0xFF80) | 0x02]; } if (((*offset & 0x7F) + 18) > 0x7E) { RMDBGPRINT((ENABLE, "No more room for DTD in extension block %lu!\n", *offset >> 7)); return RM_ERROR; } RMDBGPRINT((ENABLE, "Adding DTD at offset 0x%02lX in block %lu\n", *offset & 0x7F, *offset >> 7)); err = RUAExchangeProperty(pInstance, DisplayBlock, RMDisplayBlockPropertyID_TVFormatDigital, &(Standard), sizeof(Standard), &fmt, sizeof(fmt)); if (RMFAILED(err)) { RMDBGPRINT((ENABLE, "Failed to get TV format, %s\n", RMstatusToString(err))); return err; } PixelClock = (fmt.PixelClock + 5000) / 10000; HorizBlankingPixels = fmt.HTotalSize - fmt.ActiveWidth; VertBlankingLines = fmt.VTotalSize - fmt.ActiveHeight; HorizSyncOffset = HorizBlankingPixels - fmt.XOffset; VertSyncOffset = VertBlankingLines - fmt.YOffsetTop; HorizSyncPulseWidth = fmt.HSyncWidth; VertSyncPulseWidth = fmt.VSyncWidth / 2; HorizImageSize = edid[0x15] * 10; VertImageSize = edid[0x16] * 10; if (HorizImageSize * AspY < VertImageSize * AspX) { HorizImageSize = VertImageSize * AspX / AspY; } else if (HorizImageSize * AspY > VertImageSize * AspX) { VertImageSize = HorizImageSize * AspY / AspX; } edid[(*offset)++] = PixelClock & 0xFF; edid[(*offset)++] = PixelClock >> 8; edid[(*offset)++] = fmt.ActiveWidth & 0xFF; edid[(*offset)++] = HorizBlankingPixels & 0xFF; edid[(*offset)++] = ((fmt.ActiveWidth >> 4)& 0xF0) | ((HorizBlankingPixels >> 8) & 0x0F); edid[(*offset)++] = fmt.ActiveHeight & 0xFF; edid[(*offset)++] = VertBlankingLines & 0xFF; edid[(*offset)++] = ((fmt.ActiveHeight >> 4)& 0xF0) | ((VertBlankingLines >> 8) & 0x0F); edid[(*offset)++] = HorizSyncOffset & 0xFF; edid[(*offset)++] = HorizSyncPulseWidth & 0xFF; edid[(*offset)++] = ((VertSyncOffset & 0x0F) << 4) | (VertSyncPulseWidth & 0x0F); edid[(*offset)++] = ((HorizSyncOffset >> 2) & 0xC0) | ((HorizSyncPulseWidth >> 4) & 0x30) | ((VertSyncOffset >> 2) & 0x0C) | ((VertSyncPulseWidth >> 4) & 0x03); edid[(*offset)++] = HorizImageSize & 0xFF; edid[(*offset)++] = VertImageSize & 0xFF; edid[(*offset)++] = ((HorizImageSize >> 4) & 0xF0) | ((VertImageSize >> 8) & 0x0F); edid[(*offset)++] = 0; edid[(*offset)++] = 0; edid[(*offset)++] = (fmt.Progressive ? 0x00 : 0x80) | 0x18 | (fmt.VSyncActiveLow ? 0x00 : 0x04) | (fmt.HSyncActiveLow ? 0x00 : 0x02); if (*offset == 0x5A) *offset = 0x80; if (((*offset + 0x18) & 0xFF80) != (*offset & 0xFF80)) *offset = (*offset & 0xFF80) + 0x80; return RM_OK;}static RMstatus edid_calc_checksum(RMuint8 *edid){ RMuint32 size, i, sum = 0; size = (edid[0x7E] + 1) * 0x80; for (i = 0; i < size; i++) { if ((i & 0x7F) == 0x7F) { edid[i] = (256 - (sum & 0xFF)) & 0xFF; sum = 0; RMDBGLOG((ENABLE, "Checksum of EDID block %lu: 0x%02X\n", i >> 7, edid[i])); } else { sum += edid[i]; } } return RM_OK;}enum target { Sigma000 = 0, Sigma844DTV8624, };int main(int argc, char *argv[]){ RMstatus err; struct RUA *pInstance; RMascii *endptr; RMuint32 chipnum = 0; RMascii *filename = NULL; int argi = 1; enum target target = Sigma000; RMuint8 edid[256]; RMuint32 offset, i; RMfile fd; enum EMhwlibTVStandard std1 = EMhwlibTVStandard_HDMI_720p59; enum EMhwlibTVStandard std2 = EMhwlibTVStandard_HDMI_1080i59; RMbool ws1 = TRUE; RMbool ws2 = TRUE; RMbool yuv = TRUE; RMuint32 native_vic = 4; struct DH_VideoFormatInfo vf_info; RMuint32 input = 1; RMbool AI = FALSE; RMbool DC = FALSE; RMbool H13 = FALSE; RMuint32 audio_conf = 1; RMbool quant = FALSE; while (argi < argc) { if (argv[argi][0] == '-') { if (! strcmp(&(argv[argi][1]), "m")) { chipnum = strtoul(argv[argi], &endptr, 0); if (endptr[0] != '\0') fprintf(stderr, "Please provide chip number after %s!\n", argv[argi]); } else if (! strcmp(&(argv[argi][1]), "f")) { argi++; if (argi < argc) { GetTVStandard(argv[argi], &std1); ws1 = FALSE; } } else if (! strcmp(&(argv[argi][1]), "w")) { ws1 = TRUE; } else if (! strcmp(&(argv[argi][1]), "f2")) { argi++; if (argi < argc) { GetTVStandard(argv[argi], &std2); ws2 = FALSE; } } else if (! strcmp(&(argv[argi][1]), "w2")) { ws2 = TRUE; } else if (! strcmp(&(argv[argi][1]), "rgb")) { yuv = FALSE; } else if (! strcmp(&(argv[argi][1]), "844")) { target = Sigma844DTV8624; } else if (! strcmp(&(argv[argi][1]), "in")) { argi++; if (argi < argc) { input = strtoul(argv[argi], &endptr, 0); if (endptr[0] != '\0') fprintf(stderr, "Please provide input number after %s!\n", argv[argi]); } } else if (! strcmp(&(argv[argi][1]), "ai")) { AI = TRUE; } else if (! strcmp(&(argv[argi][1]), "dc")) { DC = TRUE; } else if (! strcmp(&(argv[argi][1]), "13")) { H13 = TRUE; } else if (! strcmp(&(argv[argi][1]), "a")) { argi++; if (argi < argc) { audio_conf = strtoul(argv[argi], &endptr, 0); if (endptr[0] != '\0') fprintf(stderr, "Please provide audio config number after %s!\n", argv[argi]); } } else if (! strcmp(&(argv[argi][1]), "q")) { quant = TRUE; } else { fprintf(stderr, "Unknown board: %s\n", argv[argi]); } } else { filename = argv[argi]; } argi++; } if ((target == Sigma000) || (filename == NULL)) { fprintf(stderr, "Usage: %s [-m <chip>] \n" "\t\t[-f <preferred/native format> [-w]] \n" "\t\t[-f2 <2nd preferred format> [-w2]] \n" "\t\t[-rgb]: RGB only sink\n" "\t\t[-in <input>]: Input number on device, default: 1\n" "\t\t[-ai]: can accept ACP and ISRC packets\n" "\t\t[-a <n>]: audio config: 0=none, 1=basic, 2=I2S*1, 3=I2S*4, 4=SPDIF96k, 5=SPDIF192k, 6=max\n" "\t\t[-13]: can accept some HDMI 1.3 features\n" "\t\t[-dc]: can accept any DeepColor modes\n" "\t\t[-q]: can handle extended quantisation and over/underscan (CEA 861-D)\n" "\t\t-<product> \n" "\t\t<filename>\n", argv[0]); fprintf(stderr, "\t-f: default HDMI_720p59, wide\n" "\t-f2: default HDMI_1080i59, wide\n" "\tproducts:\n" "\t\t844 (EM8624 DTV board)\n" ); exit(1); } if (RMFAILED(err = RUACreateInstance(&pInstance, chipnum))) { printf("Error creating instance! %s\n", RMstatusToString(err)); exit(1); } if (RMSUCCEEDED(DHGetVideoFormatInfo(std1, ws1 ? 16 : 4, ws1 ? 9 : 3, &vf_info))) { native_vic = vf_info.VIC; } switch (target) { case Sigma844DTV8624: // start initial block (0x00 to 0x7F) err = edid_start(edid, &offset, EDID_PNP_ID, 0x0844, 0, 0, 2005); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_start()!\n")); err = edid_add_display(edid, 64, 36, // roughly 29" panel, 16:9 120, FALSE, FALSE, FALSE, TRUE); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_display()!\n")); err = edid_add_monitor(edid, "SigmaDTV844E2", 23, 90, 15, 90, 166); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_monitor()!\n")); // fit 2 dtd in first block err = edid_add_dtd(edid, &offset, pInstance, std1, ws1 ? 16 : 4, ws1 ? 9 : 3); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_dtd()!\n")); err = edid_add_dtd(edid, &offset, pInstance, std2, ws2 ? 16 : 4, ws2 ? 9 : 3); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_dtd()!\n")); // add first extension block (0x80 to 0xFF) err = edid_add_extension_block(edid, TRUE, (audio_conf > 0), yuv, yuv); // underscan, audio, yuv444, yuv422 if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_extension_block()!\n")); // add up to 62 CEA 861 video ID codes for (i = 1; i <= 59; i++) { err = edid_add_video_tag(edid, i, (native_vic == i)); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_video_tag()!\n")); } // add audio tag switch (audio_conf) { case 0: break; default: case 1: err = edid_add_basic_audio_tag(edid); break; case 2: err = edid_add_1I2S_audio_tag(edid); break; case 3: err = edid_add_4I2S_audio_tag(edid); break; case 4: err = edid_add_SPDIF96_audio_tag(edid); break; case 5: err = edid_add_SPDIF192_audio_tag(edid); break; case 6: err = edid_add_all_audio_tags(edid); break; } if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_audio_tag()!\n")); err = edid_add_quantisation_tag(edid, quant, quant, quant); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_quantisation_tag()!\n")); err = edid_add_colorimetry_tag(edid, quant, quant, 0); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_colorimetry_tag()!\n")); // finish with CEA tag err = edid_add_cea_tag(edid, input, 0, 0, 0, AI, DC, DC, DC, DC, FALSE, H13 ? 225 : 165, H13, H13, 0, 0, 0, 0); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_cea_tag()!\n")); // add more dtds err = edid_add_dtd(edid, &offset, pInstance, EMhwlibTVStandard_HDMI_640x480p60, 4, 3); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_add_dtd()!\n")); break; default: fprintf(stderr, "Unknown board!\n"); RUADestroyInstance(pInstance); exit(1); break; } err = edid_calc_checksum(edid); if (RMFAILED(err)) RMDBGLOG((ENABLE, "Error in edid_calc_checksum()!\n")); { RMnonAscii *naname = RMnonAsciiFromAscii(filename); fd = RMOpenFile(naname, RM_FILE_OPEN_WRITE); RMFreeNonAscii(naname); } if (fd) { RMuint32 written, size, offs = 0; size = (edid[0x7E] + 1) * 0x80; while (offs < size) { err = RMWriteFile(fd, &edid[offs], size - offs, &written); offs += written; if (RMFAILED(err)) break; } fprintf(stderr, "Wrote %lu bytes to %s:\n", size, filename); for (offs = 0; offs < size; offs++) { if (offs % 8 == 0) fprintf(stderr, " EDID[%02lX]: ", offs); fprintf(stderr, "%02X ", edid[offs]); if (offs % 8 == 7) fprintf(stderr, "\n"); if (offs & (offs % 0x7F == 0)) fprintf(stderr, "\n"); } if (offs % 8 != 7) fprintf(stderr, "\n"); RMCloseFile(fd); } RUADestroyInstance(pInstance); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -