|
@@ -721,6 +721,10 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
|
|
|
drm_mode_object_put(dev, &crtc->base);
|
|
|
list_del(&crtc->head);
|
|
|
dev->mode_config.num_crtc--;
|
|
|
+
|
|
|
+ WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
|
|
|
+ if (crtc->state && crtc->funcs->atomic_destroy_state)
|
|
|
+ crtc->funcs->atomic_destroy_state(crtc, crtc->state);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_crtc_cleanup);
|
|
|
|
|
@@ -918,6 +922,11 @@ void drm_connector_cleanup(struct drm_connector *connector)
|
|
|
connector->name = NULL;
|
|
|
list_del(&connector->head);
|
|
|
dev->mode_config.num_connector--;
|
|
|
+
|
|
|
+ WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
|
|
|
+ if (connector->state && connector->funcs->atomic_destroy_state)
|
|
|
+ connector->funcs->atomic_destroy_state(connector,
|
|
|
+ connector->state);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_connector_cleanup);
|
|
|
|
|
@@ -1244,6 +1253,10 @@ void drm_plane_cleanup(struct drm_plane *plane)
|
|
|
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
|
|
|
dev->mode_config.num_overlay_plane--;
|
|
|
drm_modeset_unlock_all(dev);
|
|
|
+
|
|
|
+ WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
|
|
|
+ if (plane->state && plane->funcs->atomic_destroy_state)
|
|
|
+ plane->funcs->atomic_destroy_state(plane, plane->state);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_plane_cleanup);
|
|
|
|
|
@@ -1955,6 +1968,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
|
|
|
+{
|
|
|
+ /* For atomic drivers only state objects are synchronously updated and
|
|
|
+ * protected by modeset locks, so check those first. */
|
|
|
+ if (connector->state)
|
|
|
+ return connector->state->best_encoder;
|
|
|
+ return connector->encoder;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* drm_mode_getconnector - get connector configuration
|
|
|
* @dev: drm device for the ioctl
|
|
@@ -1973,6 +1995,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
|
|
|
{
|
|
|
struct drm_mode_get_connector *out_resp = data;
|
|
|
struct drm_connector *connector;
|
|
|
+ struct drm_encoder *encoder;
|
|
|
struct drm_display_mode *mode;
|
|
|
int mode_count = 0;
|
|
|
int props_count = 0;
|
|
@@ -2028,8 +2051,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
|
|
|
out_resp->subpixel = connector->display_info.subpixel_order;
|
|
|
out_resp->connection = connector->status;
|
|
|
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
|
|
- if (connector->encoder)
|
|
|
- out_resp->encoder_id = connector->encoder->base.id;
|
|
|
+
|
|
|
+ encoder = drm_connector_get_encoder(connector);
|
|
|
+ if (encoder)
|
|
|
+ out_resp->encoder_id = encoder->base.id;
|
|
|
else
|
|
|
out_resp->encoder_id = 0;
|
|
|
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
|
@@ -2099,6 +2124,33 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
|
|
|
+{
|
|
|
+ struct drm_connector *connector;
|
|
|
+ struct drm_device *dev = encoder->dev;
|
|
|
+ bool uses_atomic = false;
|
|
|
+
|
|
|
+ /* For atomic drivers only state objects are synchronously updated and
|
|
|
+ * protected by modeset locks, so check those first. */
|
|
|
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
|
+ if (!connector->state)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ uses_atomic = true;
|
|
|
+
|
|
|
+ if (connector->state->best_encoder != encoder)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ return connector->state->crtc;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Don't return stale data (e.g. pending async disable). */
|
|
|
+ if (uses_atomic)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return encoder->crtc;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* drm_mode_getencoder - get encoder configuration
|
|
|
* @dev: drm device for the ioctl
|
|
@@ -2117,6 +2169,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
|
|
|
{
|
|
|
struct drm_mode_get_encoder *enc_resp = data;
|
|
|
struct drm_encoder *encoder;
|
|
|
+ struct drm_crtc *crtc;
|
|
|
|
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
|
return -EINVAL;
|
|
@@ -2126,7 +2179,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
|
|
|
return -ENOENT;
|
|
|
|
|
|
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
|
|
- if (encoder->crtc)
|
|
|
+ crtc = drm_encoder_get_crtc(encoder);
|
|
|
+ if (crtc)
|
|
|
+ enc_resp->crtc_id = crtc->base.id;
|
|
|
+ else if (encoder->crtc)
|
|
|
enc_resp->crtc_id = encoder->crtc->base.id;
|
|
|
else
|
|
|
enc_resp->crtc_id = 0;
|
|
@@ -2392,7 +2448,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
|
|
struct drm_file *file_priv)
|
|
|
{
|
|
|
struct drm_mode_set_plane *plane_req = data;
|
|
|
- struct drm_mode_object *obj;
|
|
|
struct drm_plane *plane;
|
|
|
struct drm_crtc *crtc = NULL;
|
|
|
struct drm_framebuffer *fb = NULL;
|
|
@@ -2415,14 +2470,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
|
|
* First, find the plane, crtc, and fb objects. If not available,
|
|
|
* we don't bother to call the driver.
|
|
|
*/
|
|
|
- obj = drm_mode_object_find(dev, plane_req->plane_id,
|
|
|
- DRM_MODE_OBJECT_PLANE);
|
|
|
- if (!obj) {
|
|
|
+ plane = drm_plane_find(dev, plane_req->plane_id);
|
|
|
+ if (!plane) {
|
|
|
DRM_DEBUG_KMS("Unknown plane ID %d\n",
|
|
|
plane_req->plane_id);
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
- plane = obj_to_plane(obj);
|
|
|
|
|
|
if (plane_req->fb_id) {
|
|
|
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
|
|
@@ -2432,14 +2485,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
|
|
|
- obj = drm_mode_object_find(dev, plane_req->crtc_id,
|
|
|
- DRM_MODE_OBJECT_CRTC);
|
|
|
- if (!obj) {
|
|
|
+ crtc = drm_crtc_find(dev, plane_req->crtc_id);
|
|
|
+ if (!crtc) {
|
|
|
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
|
|
|
plane_req->crtc_id);
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
- crtc = obj_to_crtc(obj);
|
|
|
}
|
|
|
|
|
|
/*
|