backend-drm: store EDID data
Store the EDID data as-is, so that we can tell when the EDID blob has changed. This is not too useful yet, because all the weston_head_set_*() API raises the device_changed flag only if the information actually changes. However, I want to expose the libdisplay-info di_info structure through weston_head, and those cannot be (as) easily compared. We need to know when the EDID blob changes, so we can call weston_head_set_device_changed() appropriately when updating di_info. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
parent
4a028ade32
commit
2c0a9c064a
@ -616,6 +616,9 @@ struct drm_head {
|
||||
|
||||
/* drm_output::disable_head */
|
||||
struct wl_list disable_head_link;
|
||||
|
||||
void *display_data; /**< EDID or DisplayID blob */
|
||||
size_t display_data_len; /**< bytes */
|
||||
};
|
||||
|
||||
struct drm_crtc {
|
||||
|
@ -2704,6 +2704,7 @@ drm_head_destroy(struct weston_head *base)
|
||||
if (head->backlight)
|
||||
backlight_destroy(head->backlight);
|
||||
|
||||
free(head->display_data);
|
||||
free(head);
|
||||
}
|
||||
|
||||
|
@ -384,37 +384,55 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
||||
|
||||
#endif /* HAVE_LIBDISPLAY_INFO else */
|
||||
|
||||
/** Parse monitor make, model and serial from EDID
|
||||
*
|
||||
* \param head The head whose \c drm_edid to fill in.
|
||||
* \param props The DRM connector properties to get the EDID from.
|
||||
* \param[out] dhi Receives information from EDID.
|
||||
*
|
||||
* \c *dhi must be drm_head_info_fini()'d by the caller.
|
||||
*/
|
||||
static void
|
||||
find_and_parse_output_edid(struct drm_head *head,
|
||||
drmModeObjectPropertiesPtr props,
|
||||
struct drm_head_info *dhi)
|
||||
drm_head_set_display_data(struct drm_head *head, const void *data, size_t len)
|
||||
{
|
||||
free(head->display_data);
|
||||
|
||||
if (!data || len == 0) {
|
||||
head->display_data = NULL;
|
||||
head->display_data_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
head->display_data = xmalloc(len);
|
||||
head->display_data_len = len;
|
||||
memcpy(head->display_data, data, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
drm_head_maybe_update_display_data(struct drm_head *head,
|
||||
drmModeObjectPropertiesPtr props)
|
||||
{
|
||||
struct drm_device *device = head->connector.device;
|
||||
drmModePropertyBlobPtr edid_blob = NULL;
|
||||
uint32_t blob_id;
|
||||
bool changed = false;
|
||||
|
||||
blob_id =
|
||||
drm_property_get_value(
|
||||
&head->connector.props[WDRM_CONNECTOR_EDID],
|
||||
props, 0);
|
||||
if (!blob_id)
|
||||
return;
|
||||
if (blob_id)
|
||||
edid_blob = drmModeGetPropertyBlob(device->drm.fd, blob_id);
|
||||
|
||||
edid_blob = drmModeGetPropertyBlob(device->drm.fd, blob_id);
|
||||
if (!edid_blob)
|
||||
return;
|
||||
|
||||
drm_head_info_from_edid(dhi, edid_blob->data, edid_blob->length);
|
||||
if (edid_blob && edid_blob->length > 0) {
|
||||
if (!head->display_data ||
|
||||
head->display_data_len != edid_blob->length ||
|
||||
memcmp(head->display_data, edid_blob->data, edid_blob->length)) {
|
||||
drm_head_set_display_data(head, edid_blob->data, edid_blob->length);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (head->display_data) {
|
||||
drm_head_set_display_data(head, NULL, 0);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreePropertyBlob(edid_blob);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -597,7 +615,9 @@ update_head_from_connector(struct drm_head *head)
|
||||
drmModeConnector *conn = connector->conn;
|
||||
struct drm_head_info dhi = { .eotf_mask = WESTON_EOTF_MODE_SDR };
|
||||
|
||||
find_and_parse_output_edid(head, props, &dhi);
|
||||
drm_head_maybe_update_display_data(head, props);
|
||||
|
||||
drm_head_info_from_edid(&dhi, head->display_data, head->display_data_len);
|
||||
|
||||
weston_head_set_monitor_strings(&head->base, dhi.make,
|
||||
dhi.model,
|
||||
|
Loading…
Reference in New Issue
Block a user