summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2015-03-04 14:53:06 -0500
committerChris Michael <cp.michael@samsung.com>2015-03-04 14:53:06 -0500
commit2e319df7b0f72631c2d4d475b3321dc3a7d68ef2 (patch)
tree468551d087fc34aaac0bdb0e49c385d3ff24f083
parent02e7931aeb49fe38123153a20c3dd070eb02d421 (diff)
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>
-rw-r--r--src/lib/ecore_drm/ecore_drm_output.c121
1 files changed, 118 insertions, 3 deletions
diff --git a/src/lib/ecore_drm/ecore_drm_output.c b/src/lib/ecore_drm/ecore_drm_output.c
index a2d7f104fb..a86c4e6e0b 100644
--- a/src/lib/ecore_drm/ecore_drm_output.c
+++ b/src/lib/ecore_drm/ecore_drm_output.c
@@ -3,9 +3,18 @@
3#endif 3#endif
4 4
5#include "ecore_drm_private.h" 5#include "ecore_drm_private.h"
6#include <ctype.h>
6 7
7#define ALEN(array) (sizeof(array) / sizeof(array)[0]) 8#define ALEN(array) (sizeof(array) / sizeof(array)[0])
8 9
10#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
11#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
12#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
13#define EDID_OFFSET_DATA_BLOCKS 0x36
14#define EDID_OFFSET_LAST_BLOCK 0x6c
15#define EDID_OFFSET_PNPID 0x08
16#define EDID_OFFSET_SERIAL 0x0c
17
9static const char *conn_types[] = 18static const char *conn_types[] =
10{ 19{
11 "None", "VGA", "DVI", "DVI", "DVI", 20 "None", "VGA", "DVI", "DVI", "DVI",
@@ -17,6 +26,109 @@ EAPI int ECORE_DRM_EVENT_OUTPUT = 0;
17 26
18/* local functions */ 27/* local functions */
19 28
29static void
30_ecore_drm_output_edid_parse_string(const uint8_t *data, char text[])
31{
32 int i = 0, rep = 0;
33
34 strncpy(text, (const char *)data, 12);
35
36 for (; text[i] != '\0'; i++)
37 {
38 if ((text[i] == '\n') || (text[i] == '\r'))
39 {
40 text[i] = '\0';
41 break;
42 }
43 }
44
45 for (i = 0; text[i] != '\0'; i++)
46 {
47 if (!isprint(text[i]))
48 {
49 text[i] = '-';
50 rep++;
51 }
52 }
53
54 if (rep > 0) text[i] = '\0';
55}
56
57static int
58_ecore_drm_output_edid_parse(Ecore_Drm_Output *output, const uint8_t *data, size_t len)
59{
60 int i = 0;
61 uint32_t serial;
62
63 if (len < 128) return -1;
64 if ((data[0] != 0x00) || (data[1] != 0xff)) return -1;
65
66 output->edid.pnp[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
67 output->edid.pnp[1] =
68 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) +
69 ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
70 output->edid.pnp[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
71 output->edid.pnp[3] = '\0';
72
73 serial = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
74 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
75 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
76 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
77 if (serial > 0)
78 sprintf(output->edid.serial, "%lu", (unsigned long)serial);
79
80 for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18)
81 {
82 if (data[i] != 0) continue;
83 if (data[i + 2] != 0) continue;
84
85 if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME)
86 _ecore_drm_output_edid_parse_string(&data[i+5], output->edid.monitor);
87 else if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER)
88 _ecore_drm_output_edid_parse_string(&data[i+5], output->edid.serial);
89 else if (data[i + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING)
90 _ecore_drm_output_edid_parse_string(&data[i+5], output->edid.eisa);
91 }
92
93 return 0;
94}
95
96static void
97_ecore_drm_output_edid_find(Ecore_Drm_Output *output, drmModeConnector *conn)
98{
99 drmModePropertyBlobPtr blob = NULL;
100 drmModePropertyPtr prop;
101 int i = 0, ret = 0;
102
103 for (; i < conn->count_props && !blob; i++)
104 {
105 if (!(prop = drmModeGetProperty(output->dev->drm.fd, conn->props[i])))
106 continue;
107 if ((prop->flags & DRM_MODE_PROP_BLOB) &&
108 (!strcmp(prop->name, "EDID")))
109 {
110 blob = drmModeGetPropertyBlob(output->dev->drm.fd,
111 conn->prop_values[i]);
112 }
113 drmModeFreeProperty(prop);
114 }
115
116 if (!blob) return;
117
118 ret = _ecore_drm_output_edid_parse(output, blob->data, blob->length);
119 if (!ret)
120 {
121 if (output->edid.pnp[0] != '\0')
122 eina_stringshare_replace(&output->make, output->edid.pnp);
123 if (output->edid.monitor[0] != '\0')
124 eina_stringshare_replace(&output->model, output->edid.monitor);
125 /* if (output->edid.serial[0] != '\0') */
126 /* eina_stringshare_replace(&output->serial, output->edid.serial); */
127 }
128
129 drmModeFreePropertyBlob(blob);
130}
131
20static Eina_Bool 132static Eina_Bool
21_ecore_drm_output_software_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output) 133_ecore_drm_output_software_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output)
22{ 134{
@@ -299,6 +411,8 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
299 output->dev = dev; 411 output->dev = dev;
300 output->x = x; 412 output->x = x;
301 output->y = y; 413 output->y = y;
414 output->phys_width = conn->mmWidth;
415 output->phys_height = conn->mmHeight;
302 416
303 output->subpixel = conn->subpixel; 417 output->subpixel = conn->subpixel;
304 output->make = eina_stringshare_add("unknown"); 418 output->make = eina_stringshare_add("unknown");
@@ -352,6 +466,8 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
352 if (!output->current_mode) goto mode_err; 466 if (!output->current_mode) goto mode_err;
353 } 467 }
354 468
469 _ecore_drm_output_edid_find(output, conn);
470
355 dev->use_hw_accel = EINA_FALSE; 471 dev->use_hw_accel = EINA_FALSE;
356 if (!_ecore_drm_output_software_setup(dev, output)) 472 if (!_ecore_drm_output_software_setup(dev, output))
357 goto mode_err; 473 goto mode_err;
@@ -967,9 +1083,8 @@ ecore_drm_output_physical_size_get(Ecore_Drm_Output *output, int *w, int *h)
967{ 1083{
968 EINA_SAFETY_ON_NULL_RETURN(output); 1084 EINA_SAFETY_ON_NULL_RETURN(output);
969 1085
970 //FIXME: This needs to be set when EDID parsing works 1086 if (w) *w = output->phys_width;
971 if (w) *w = 0; 1087 if (h) *h = output->phys_height;
972 if (h) *h = 0;
973} 1088}
974 1089
975EAPI unsigned int 1090EAPI unsigned int