forked from enlightenment/efl
ecore-drm: Implement edid parsing for Ecore_Drm_Output
Summary: This implements edid parsing to obtain output make and model so we can get better output names. This also fixes a false FIXME statement in ecore_drm_output_physical_size_get function. As it turns out, we don't need to get these values from edid parsing as they are already available in the drm connector. @feature Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
parent
02e7931aeb
commit
2e319df7b0
|
@ -3,9 +3,18 @@
|
|||
#endif
|
||||
|
||||
#include "ecore_drm_private.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define ALEN(array) (sizeof(array) / sizeof(array)[0])
|
||||
|
||||
#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
|
||||
#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
|
||||
#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
|
||||
#define EDID_OFFSET_DATA_BLOCKS 0x36
|
||||
#define EDID_OFFSET_LAST_BLOCK 0x6c
|
||||
#define EDID_OFFSET_PNPID 0x08
|
||||
#define EDID_OFFSET_SERIAL 0x0c
|
||||
|
||||
static const char *conn_types[] =
|
||||
{
|
||||
"None", "VGA", "DVI", "DVI", "DVI",
|
||||
|
@ -17,6 +26,109 @@ EAPI int ECORE_DRM_EVENT_OUTPUT = 0;
|
|||
|
||||
/* local functions */
|
||||
|
||||
static void
|
||||
_ecore_drm_output_edid_parse_string(const uint8_t *data, char text[])
|
||||
{
|
||||
int i = 0, rep = 0;
|
||||
|
||||
strncpy(text, (const char *)data, 12);
|
||||
|
||||
for (; text[i] != '\0'; i++)
|
||||
{
|
||||
if ((text[i] == '\n') || (text[i] == '\r'))
|
||||
{
|
||||
text[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; text[i] != '\0'; i++)
|
||||
{
|
||||
if (!isprint(text[i]))
|
||||
{
|
||||
text[i] = '-';
|
||||
rep++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rep > 0) text[i] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_drm_output_edid_parse(Ecore_Drm_Output *output, const uint8_t *data, size_t len)
|
||||
{
|
||||
int i = 0;
|
||||
uint32_t serial;
|
||||
|
||||
if (len < 128) return -1;
|
||||
if ((data[0] != 0x00) || (data[1] != 0xff)) return -1;
|
||||
|
||||
output->edid.pnp[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
|
||||
output->edid.pnp[1] =
|
||||
'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) +
|
||||
((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
|
||||
output->edid.pnp[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
|
||||
output->edid.pnp[3] = '\0';
|
||||
|
||||
serial = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
|
||||
serial += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
|
||||
if (serial > 0)
|
||||
sprintf(output->edid.serial, "%lu", (unsigned long)serial);
|
||||
|
||||
for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18)
|
||||
{
|
||||
if (data[i] != 0) continue;
|
||||
if (data[i + 2] != 0) continue;
|
||||
|
||||
if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME)
|
||||
_ecore_drm_output_edid_parse_string(&data[i+5], output->edid.monitor);
|
||||
else if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER)
|
||||
_ecore_drm_output_edid_parse_string(&data[i+5], output->edid.serial);
|
||||
else if (data[i + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING)
|
||||
_ecore_drm_output_edid_parse_string(&data[i+5], output->edid.eisa);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm_output_edid_find(Ecore_Drm_Output *output, drmModeConnector *conn)
|
||||
{
|
||||
drmModePropertyBlobPtr blob = NULL;
|
||||
drmModePropertyPtr prop;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
for (; i < conn->count_props && !blob; i++)
|
||||
{
|
||||
if (!(prop = drmModeGetProperty(output->dev->drm.fd, conn->props[i])))
|
||||
continue;
|
||||
if ((prop->flags & DRM_MODE_PROP_BLOB) &&
|
||||
(!strcmp(prop->name, "EDID")))
|
||||
{
|
||||
blob = drmModeGetPropertyBlob(output->dev->drm.fd,
|
||||
conn->prop_values[i]);
|
||||
}
|
||||
drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
if (!blob) return;
|
||||
|
||||
ret = _ecore_drm_output_edid_parse(output, blob->data, blob->length);
|
||||
if (!ret)
|
||||
{
|
||||
if (output->edid.pnp[0] != '\0')
|
||||
eina_stringshare_replace(&output->make, output->edid.pnp);
|
||||
if (output->edid.monitor[0] != '\0')
|
||||
eina_stringshare_replace(&output->model, output->edid.monitor);
|
||||
/* if (output->edid.serial[0] != '\0') */
|
||||
/* eina_stringshare_replace(&output->serial, output->edid.serial); */
|
||||
}
|
||||
|
||||
drmModeFreePropertyBlob(blob);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_drm_output_software_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output)
|
||||
{
|
||||
|
@ -299,6 +411,8 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
|
|||
output->dev = dev;
|
||||
output->x = x;
|
||||
output->y = y;
|
||||
output->phys_width = conn->mmWidth;
|
||||
output->phys_height = conn->mmHeight;
|
||||
|
||||
output->subpixel = conn->subpixel;
|
||||
output->make = eina_stringshare_add("unknown");
|
||||
|
@ -352,6 +466,8 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
|
|||
if (!output->current_mode) goto mode_err;
|
||||
}
|
||||
|
||||
_ecore_drm_output_edid_find(output, conn);
|
||||
|
||||
dev->use_hw_accel = EINA_FALSE;
|
||||
if (!_ecore_drm_output_software_setup(dev, output))
|
||||
goto mode_err;
|
||||
|
@ -967,9 +1083,8 @@ ecore_drm_output_physical_size_get(Ecore_Drm_Output *output, int *w, int *h)
|
|||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(output);
|
||||
|
||||
//FIXME: This needs to be set when EDID parsing works
|
||||
if (w) *w = 0;
|
||||
if (h) *h = 0;
|
||||
if (w) *w = output->phys_width;
|
||||
if (h) *h = output->phys_height;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
|
|
Loading…
Reference in New Issue