Display (Linux): detect refresh rate for DRM method

This commit is contained in:
李通洲
2024-04-18 09:52:55 +08:00
parent 9860fb67d4
commit 64ec76f5a6
3 changed files with 49 additions and 32 deletions
+29 -32
View File
@@ -36,31 +36,28 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
continue;
}
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
char modes[32];
if (ffReadFileData(drmDir.chars, sizeof(modes), modes) < 3)
{
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
unsigned width = 0, height = 0;
double refreshRate = 0;
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
int scanned = sscanf(modes, "%ux%u", &width, &height);
if(scanned == 2 && width > 0 && height > 0)
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/edid");
uint8_t edidData[128];
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
{
ffStrbufSubstrBefore(&drmDir, drmDirLength);
ffStrbufAppendS(&drmDir, entry->d_name);
ffStrbufAppendS(&drmDir, "/edid");
ffEdidGetName(edidData, &name);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
}
else
{
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
uint8_t edidData[128];
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
ffEdidGetName(edidData, &name);
else
char modes[32];
if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3)
{
sscanf(modes, "%ux%u", &width, &height);
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
@@ -69,20 +66,20 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
}
ffStrbufAppendS(&name, plainName);
}
ffdsAppendDisplay(
result,
width, height,
0,
0, 0,
0,
&name,
FF_DISPLAY_TYPE_UNKNOWN,
false,
0
);
}
ffdsAppendDisplay(
result,
width, height,
refreshRate,
0, 0,
0,
&name,
FF_DISPLAY_TYPE_UNKNOWN,
false,
0
);
ffStrbufSubstrBefore(&drmDir, drmDirLength);
}
+19
View File
@@ -7,6 +7,25 @@ void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint3
*height = (((uint32_t) edid[dtd + 7] >> 4) << 8) | edid[dtd + 5];
}
void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate)
{
for (uint32_t i = 0x36; i < 0x7E; i += 0x12)
{ // read through descriptor blocks...
if (edid[i] != 0x00 && edid[i + 1] != 0x00)
{ // a dtd
uint32_t hactive = edid[i+2] + ((edid[i + 4] & 0xf0) << 4);
uint32_t hblank = edid[i+3] + ((edid[i + 4] & 0x0f) << 8);
uint32_t vactive = edid[i+5] + ((edid[i + 7] & 0xf0) << 4);
uint32_t vblank = edid[i+6] + ((edid[i + 7] & 0x0f) << 8);
uint32_t pixclk = (edid[i+1] << 8) | (edid[i]);
*width = hactive;
*height = vactive;
*refreshRate = (double)pixclk * 10000 / (double)(hactive+hblank) / (double)(vactive+vblank);
return;
}
}
}
void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result)
{
// https://github.com/jinksong/read_edid/blob/master/parse-edid/parse-edid.c
+1
View File
@@ -5,6 +5,7 @@
void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result);
bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate);
void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height);
void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm
void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week);