xfree86: Add a xf86MonitorFindHDMIBlock()
The HDMI CEA vendor specific block has some interesting information, such as the maximum TMDS dot clock. v2: Don't parse CEA blocks with invalid offsets, remove spurious brackets (Chris Wilson) v3: Fix the looping through the CEA data blocks, it had a typo using the wrong variable coming from the code it was ported from. Replace x << 16 + y << 8 + z by x << 16 | y << 8 | z (Chris Wilson) v4: Remove the stray ';' at the end of "if (*end == 0)". (Dominik Behr on IRC) Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
This commit is contained in:
parent
2ea973e12f
commit
a279fb3ff3
|
@ -332,6 +332,97 @@ xf86ForEachVideoBlock(xf86MonPtr mon, handle_video_fn fn, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
cea_db_offsets(Uchar *cea, int *start, int *end)
|
||||||
|
{
|
||||||
|
/* Data block offset in CEA extension block */
|
||||||
|
*start = CEA_EXT_MIN_DATA_OFFSET;
|
||||||
|
*end = cea[2];
|
||||||
|
if (*end == 0)
|
||||||
|
*end = CEA_EXT_MAX_DATA_OFFSET;
|
||||||
|
if (*end < CEA_EXT_MIN_DATA_OFFSET || *end > CEA_EXT_MAX_DATA_OFFSET)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cea_db_len(Uchar *db)
|
||||||
|
{
|
||||||
|
return db[0] & 0x1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cea_db_tag(Uchar *db)
|
||||||
|
{
|
||||||
|
return db[0] >> 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*handle_cea_db_fn) (Uchar *, void *);
|
||||||
|
|
||||||
|
static void
|
||||||
|
cea_for_each_db(xf86MonPtr mon, handle_cea_db_fn fn, void *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(mon->flags & EDID_COMPLETE_RAWDATA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mon->no_sections)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mon->rawData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < mon->no_sections; i++) {
|
||||||
|
int start, end, offset;
|
||||||
|
Uchar *ext;
|
||||||
|
|
||||||
|
ext = mon->rawData + EDID1_LEN * (i + 1);
|
||||||
|
if (ext[EXT_TAG] != CEA_EXT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!cea_db_offsets(ext, &start, &end))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (offset = start;
|
||||||
|
offset < end && offset + cea_db_len(&ext[offset]) < end;
|
||||||
|
offset += cea_db_len(&ext[offset]) + 1)
|
||||||
|
fn(&ext[offset], data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct find_hdmi_block_data {
|
||||||
|
struct cea_data_block *hdmi;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void find_hdmi_block(Uchar *db, void *data)
|
||||||
|
{
|
||||||
|
struct find_hdmi_block_data *result = data;
|
||||||
|
int oui;
|
||||||
|
|
||||||
|
if (cea_db_tag(db) != CEA_VENDOR_BLK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cea_db_len(db) < 5)
|
||||||
|
return;
|
||||||
|
|
||||||
|
oui = (db[3] << 16) | (db[2] << 8) | db[1];
|
||||||
|
if (oui == IEEE_ID_HDMI)
|
||||||
|
result->hdmi = (struct cea_data_block *)db;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cea_data_block *xf86MonitorFindHDMIBlock(xf86MonPtr mon)
|
||||||
|
{
|
||||||
|
struct find_hdmi_block_data result = { NULL };
|
||||||
|
|
||||||
|
cea_for_each_db(mon, find_hdmi_block, &result);
|
||||||
|
|
||||||
|
return result.hdmi;
|
||||||
|
}
|
||||||
|
|
||||||
xf86MonPtr
|
xf86MonPtr
|
||||||
xf86InterpretEEDID(int scrnIndex, Uchar * block)
|
xf86InterpretEEDID(int scrnIndex, Uchar * block)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,4 +98,6 @@ typedef void (*handle_video_fn) (struct cea_video_block *, void *);
|
||||||
|
|
||||||
void xf86ForEachVideoBlock(xf86MonPtr, handle_video_fn, void *);
|
void xf86ForEachVideoBlock(xf86MonPtr, handle_video_fn, void *);
|
||||||
|
|
||||||
|
struct cea_data_block *xf86MonitorFindHDMIBlock(xf86MonPtr mon);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue