[PATCH weston v6 49/73] compositor-drm: move connector fields into drm_head
Pekka Paalanen
ppaalanen at gmail.com
Fri Feb 16 14:57:34 UTC 2018
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Move the connector related fields from drm_output to the drm_head. A
drm_head represents a connector for now.
The code in drm_head_create() to update connector data, monitor
information, etc. is moved into a new function. This will be useful when
DRM-backend starts creating heads for all connectors regardless of their
connection status and will need to update them on hotplug events.
v6:
- adapt to the new places of updating unused_connectors
- free connector in create_output_for_connector() error path
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
libweston/compositor-drm.c | 206 ++++++++++++++++++++++++++-------------------
1 file changed, 120 insertions(+), 86 deletions(-)
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index d386a0d2..63295d2a 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -409,20 +409,22 @@ struct drm_head {
struct drm_output *output; /* XXX: temporary */
+ drmModeConnector *connector;
+ uint32_t connector_id;
+ struct drm_edid edid;
+
+ /* Holds the properties for the connector */
+ struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
+
struct backlight *backlight;
};
struct drm_output {
struct weston_output base;
- drmModeConnector *connector;
uint32_t crtc_id; /* object ID to pass to DRM functions */
int pipe; /* index of CRTC in resource array / bitmasks */
- uint32_t connector_id;
- struct drm_edid edid;
- /* Holds the properties for the connector */
- struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
/* Holds the properties for the CRTC */
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
@@ -813,7 +815,7 @@ drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id)
wl_list_for_each(base,
&backend->compositor->head_list, compositor_link) {
head = to_drm_head(base);
- if (head->output && head->output->connector_id == connector_id)
+ if (head->connector_id == connector_id)
return head;
}
@@ -1836,10 +1838,11 @@ static int
drm_output_apply_state_legacy(struct drm_output_state *state)
{
struct drm_output *output = state->output;
+ struct drm_head *head = to_drm_head(weston_output_get_first_head(&output->base));
struct drm_backend *backend = to_drm_backend(output->base.compositor);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_property_info *dpms_prop =
- &output->props_conn[WDRM_CONNECTOR_DPMS];
+ &head->props_conn[WDRM_CONNECTOR_DPMS];
struct drm_plane_state *scanout_state;
struct drm_plane_state *ps;
struct drm_plane *p;
@@ -1880,7 +1883,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
}
ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, 0, 0, 0,
- &output->connector_id, 0, NULL);
+ &head->connector_id, 0, NULL);
if (ret)
weston_log("drmModeSetCrtc failed disabling: %m\n");
@@ -1915,7 +1918,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
scanout_state->fb->fb_id,
0, 0,
- &output->connector_id, 1,
+ &head->connector_id, 1,
&mode->mode_info);
if (ret) {
weston_log("set mode failed: %m\n");
@@ -1988,7 +1991,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
if (dpms_prop->prop_id && state->dpms != output->state_cur->dpms) {
ret = drmModeConnectorSetProperty(backend->drm.fd,
- output->connector_id,
+ head->connector_id,
dpms_prop->prop_id,
state->dpms);
if (ret) {
@@ -2024,16 +2027,16 @@ crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
}
static int
-connector_add_prop(drmModeAtomicReq *req, struct drm_output *output,
+connector_add_prop(drmModeAtomicReq *req, struct drm_head *head,
enum wdrm_connector_property prop, uint64_t val)
{
- struct drm_property_info *info = &output->props_conn[prop];
+ struct drm_property_info *info = &head->props_conn[prop];
int ret;
if (info->prop_id == 0)
return -1;
- ret = drmModeAtomicAddProperty(req, output->connector_id,
+ ret = drmModeAtomicAddProperty(req, head->connector_id,
info->prop_id, val);
return (ret <= 0) ? -1 : 0;
}
@@ -2077,6 +2080,7 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
uint32_t *flags)
{
struct drm_output *output = state->output;
+ struct drm_head *head = to_drm_head(weston_output_get_first_head(&output->base));
struct drm_backend *backend = to_drm_backend(output->base.compositor);
struct drm_plane_state *plane_state;
struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
@@ -2093,13 +2097,12 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID,
current_mode->blob_id);
ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
- ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
+ ret |= connector_add_prop(req, head, WDRM_CONNECTOR_CRTC_ID,
output->crtc_id);
} else {
ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
- ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
- 0);
+ ret |= connector_add_prop(req, head, WDRM_CONNECTOR_CRTC_ID, 0);
}
if (ret != 0) {
@@ -4314,8 +4317,7 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
/** Parse monitor make, model and serial from EDID
*
- * \param b The backend instance.
- * \param output The output whose \c drm_edid to fill in.
+ * \param head The head whose \c drm_edid to fill in.
* \param props The DRM connector properties to get the EDID from.
* \param make[out] The monitor make (PNP ID).
* \param model[out] The monitor model (name).
@@ -4324,10 +4326,10 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
* Each of \c *make, \c *model and \c *serial_number are set only if the
* information is found in the EDID. The pointers they are set to must not
* be free()'d explicitly, instead they get implicitly freed when the
- * \c drm_output is destroyed.
+ * \c drm_head is destroyed.
*/
static void
-find_and_parse_output_edid(struct drm_backend *b, struct drm_output *output,
+find_and_parse_output_edid(struct drm_head *head,
drmModeObjectPropertiesPtr props,
const char **make,
const char **model,
@@ -4338,29 +4340,29 @@ find_and_parse_output_edid(struct drm_backend *b, struct drm_output *output,
int rc;
blob_id =
- drm_property_get_value(&output->props_conn[WDRM_CONNECTOR_EDID],
+ drm_property_get_value(&head->props_conn[WDRM_CONNECTOR_EDID],
props, 0);
if (!blob_id)
return;
- edid_blob = drmModeGetPropertyBlob(b->drm.fd, blob_id);
+ edid_blob = drmModeGetPropertyBlob(head->backend->drm.fd, blob_id);
if (!edid_blob)
return;
- rc = edid_parse(&output->edid,
+ rc = edid_parse(&head->edid,
edid_blob->data,
edid_blob->length);
if (!rc) {
weston_log("EDID data '%s', '%s', '%s'\n",
- output->edid.pnp_id,
- output->edid.monitor_name,
- output->edid.serial_number);
- if (output->edid.pnp_id[0] != '\0')
- *make = output->edid.pnp_id;
- if (output->edid.monitor_name[0] != '\0')
- *model = output->edid.monitor_name;
- if (output->edid.serial_number[0] != '\0')
- *serial_number = output->edid.serial_number;
+ head->edid.pnp_id,
+ head->edid.monitor_name,
+ head->edid.serial_number);
+ if (head->edid.pnp_id[0] != '\0')
+ *make = head->edid.pnp_id;
+ if (head->edid.monitor_name[0] != '\0')
+ *model = head->edid.monitor_name;
+ if (head->edid.serial_number[0] != '\0')
+ *serial_number = head->edid.serial_number;
}
drmModeFreePropertyBlob(edid_blob);
}
@@ -4587,11 +4589,12 @@ drm_output_set_mode(struct weston_output *base,
{
struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor);
+ struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
struct drm_mode *current;
drmModeModeInfo crtc_mode;
- if (connector_get_current_mode(output->connector, b->drm.fd, &crtc_mode) < 0)
+ if (connector_get_current_mode(head->connector, b->drm.fd, &crtc_mode) < 0)
return -1;
current = drm_output_choose_initial_mode(b, output, mode, modeline, &crtc_mode);
@@ -4806,11 +4809,11 @@ drm_output_enable(struct weston_output *base)
&output->scanout_plane->base,
&b->compositor->primary_plane);
- wl_array_remove_uint32(&b->unused_connectors, output->connector_id);
+ wl_array_remove_uint32(&b->unused_connectors, head->connector_id);
wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id);
weston_log("Output %s, (connector %d, crtc %d)\n",
- output->base.name, output->connector_id, output->crtc_id);
+ output->base.name, head->connector_id, output->crtc_id);
wl_list_for_each(m, &output->base.mode_list, link)
weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f%s%s%s\n",
m->width, m->height, m->refresh / 1000.0,
@@ -4818,7 +4821,7 @@ drm_output_enable(struct weston_output *base)
", preferred" : "",
m->flags & WL_OUTPUT_MODE_CURRENT ?
", current" : "",
- output->connector->count_modes == 0 ?
+ head->connector->count_modes == 0 ?
", built-in" : "");
return 0;
@@ -4831,6 +4834,7 @@ static void
drm_output_deinit(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
+ struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
struct drm_backend *b = to_drm_backend(base->compositor);
uint32_t *unused;
@@ -4856,7 +4860,7 @@ drm_output_deinit(struct weston_output *base)
}
unused = wl_array_add(&b->unused_connectors, sizeof(*unused));
- *unused = output->connector_id;
+ *unused = head->connector_id;
unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
*unused = output->crtc_id;
@@ -4893,9 +4897,6 @@ drm_output_destroy(struct weston_output *base)
drm_output_fini_crtc(output);
- drm_property_info_free(output->props_conn, WDRM_CONNECTOR__COUNT);
- drmModeFreeConnector(output->connector);
-
assert(!output->state_last);
drm_output_state_free(output->state_cur);
@@ -4985,6 +4986,62 @@ drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
}
}
+/** Replace connector data and monitor information
+ *
+ * @param head The head to update.
+ * @param connector The connector data to be owned by the head, must match
+ * the head's connector ID.
+ * @return 0 on success, -1 on failure.
+ *
+ * Takes ownership of @c connector on success, not on failure.
+ *
+ * May schedule a heads changed call.
+ */
+static int
+drm_head_assign_connector_info(struct drm_head *head,
+ drmModeConnector *connector)
+{
+ drmModeObjectProperties *props;
+ const char *make = "unknown";
+ const char *model = "unknown";
+ const char *serial_number = "unknown";
+
+ assert(connector);
+ assert(head->connector_id == connector->connector_id);
+
+ props = drmModeObjectGetProperties(head->backend->drm.fd,
+ head->connector_id,
+ DRM_MODE_OBJECT_CONNECTOR);
+ if (!props) {
+ weston_log("Error: failed to get connector '%s' properties\n",
+ head->base.name);
+ return -1;
+ }
+
+ if (head->connector)
+ drmModeFreeConnector(head->connector);
+ head->connector = connector;
+
+ drm_property_info_populate(head->backend, connector_props,
+ head->props_conn,
+ WDRM_CONNECTOR__COUNT, props);
+ find_and_parse_output_edid(head, props, &make, &model, &serial_number);
+ weston_head_set_monitor_strings(&head->base, make, model, serial_number);
+ weston_head_set_subpixel(&head->base,
+ drm_subpixel_to_wayland(head->connector->subpixel));
+
+ weston_head_set_physical_size(&head->base, head->connector->mmWidth,
+ head->connector->mmHeight);
+
+ drmModeFreeObjectProperties(props);
+
+ /* Unknown connection status is assumed disconnected. */
+ weston_head_set_connection_status(&head->base,
+ head->connector->connection == DRM_MODE_CONNECTED);
+
+ return 0;
+}
+
/**
* Create a Weston head for a connector
*
@@ -5019,23 +5076,29 @@ drm_head_create(struct drm_backend *backend, uint32_t connector_id,
weston_head_init(&head->base, name);
free(name);
+ head->connector_id = connector_id;
head->backend = backend;
head->backlight = backlight_init(drm_device, connector->connector_type);
- /* Unknown connection status is assumed disconnected. */
- weston_head_set_connection_status(&head->base,
- connector->connection == DRM_MODE_CONNECTED);
+ if (drm_head_assign_connector_info(head, connector) < 0)
+ goto err_init;
+
+ if (head->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+ head->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+ weston_head_set_internal(&head->base);
weston_compositor_add_head(backend->compositor, &head->base);
- drmModeFreeConnector(connector);
weston_log("DRM: found head '%s', connector %d %s.\n",
- head->base.name, connector_id,
+ head->base.name, head->connector_id,
head->base.connected ? "connected" : "disconnected");
return head;
+err_init:
+ weston_head_release(&head->base);
+
err_alloc:
if (connector)
drmModeFreeConnector(connector);
@@ -5050,6 +5113,9 @@ drm_head_destroy(struct drm_head *head)
{
weston_head_release(&head->base);
+ drm_property_info_free(head->props_conn, WDRM_CONNECTOR__COUNT);
+ drmModeFreeConnector(head->connector);
+
if (head->backlight)
backlight_destroy(head->backlight);
@@ -5077,31 +5143,21 @@ create_output_for_connector(struct drm_backend *b,
{
struct drm_output *output;
struct drm_head *head;
- drmModeObjectPropertiesPtr props;
struct drm_mode *drm_mode;
- char *name;
- const char *make = "unknown";
- const char *model = "unknown";
- const char *serial_number = "unknown";
int i;
output = zalloc(sizeof *output);
if (output == NULL)
goto err_init;
- output->connector = connector;
- output->connector_id = connector->connector_id;
-
- name = make_connector_name(connector);
- weston_output_init(&output->base, b->compositor, name);
- free(name);
-
/* XXX: temporary */
head = drm_head_create(b, connector->connector_id, drm_device);
if (!head)
abort();
head->output = output;
+ weston_output_init(&output->base, b->compositor, head->base.name);
+
output->base.enable = drm_output_enable;
output->base.destroy = drm_output_destroy;
output->base.disable = drm_output_disable;
@@ -5113,36 +5169,13 @@ create_output_for_connector(struct drm_backend *b,
if (drm_output_init_crtc(output, resources, connector) < 0)
goto err_output;
- props = drmModeObjectGetProperties(b->drm.fd, connector->connector_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!props) {
- weston_log("failed to get connector properties\n");
- goto err_output;
- }
- drm_property_info_populate(b, connector_props, output->props_conn,
- WDRM_CONNECTOR__COUNT, props);
- find_and_parse_output_edid(b, output, props,
- &make, &model, &serial_number);
- weston_head_set_monitor_strings(&head->base, make, model, serial_number);
- weston_head_set_subpixel(&head->base,
- drm_subpixel_to_wayland(output->connector->subpixel));
-
- drmModeFreeObjectProperties(props);
-
- if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
- output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
- weston_head_set_internal(&head->base);
-
if (drm_output_init_gamma_size(output) < 0)
goto err_output;
- weston_head_set_physical_size(&head->base, output->connector->mmWidth,
- output->connector->mmHeight);
-
output->state_cur = drm_output_state_alloc(output, NULL);
- for (i = 0; i < output->connector->count_modes; i++) {
- drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
+ for (i = 0; i < head->connector->count_modes; i++) {
+ drm_mode = drm_output_add_mode(output, &head->connector->modes[i]);
if (!drm_mode) {
weston_log("failed to add mode\n");
goto err_output;
@@ -5151,13 +5184,14 @@ create_output_for_connector(struct drm_backend *b,
weston_compositor_add_pending_output(&output->base, b->compositor);
+ /* drm_head_create() made its own connector */
+ drmModeFreeConnector(connector);
+
return 0;
err_output:
drm_head_destroy(head);
drm_output_destroy(&output->base);
- return -1;
- /* no fallthrough! */
err_init:
drmModeFreeConnector(connector);
@@ -5268,7 +5302,7 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
continue;
for (i = 0; i < resources->count_connectors; i++) {
- if (connected[i] == head->output->connector_id) {
+ if (connected[i] == head->connector_id) {
disconnected = false;
break;
}
@@ -5277,7 +5311,7 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
if (!disconnected)
continue;
- weston_log("connector %d disconnected\n", head->output->connector_id);
+ weston_log("connector %d disconnected\n", head->connector_id);
drm_output_destroy(&head->output->base);
}
--
2.13.6
More information about the wayland-devel
mailing list