summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/drm_atomic.c134
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c29
-rw-r--r--drivers/gpu/drm/drm_crtc.c325
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c7
-rw-r--r--drivers/gpu/drm/drm_edid.c206
-rw-r--r--drivers/gpu/drm/drm_flip_work.c4
-rw-r--r--drivers/gpu/drm/drm_prime.c6
-rw-r--r--drivers/gpu/drm/drm_sysfs.c160
-rw-r--r--drivers/gpu/drm/i915/Makefile2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c4
-rw-r--r--include/drm/drm_atomic.h55
-rw-r--r--include/drm/drm_atomic_helper.h4
-rw-r--r--include/drm/drm_crtc.h26
-rw-r--r--include/drm/drm_dp_helper.h6
15 files changed, 696 insertions, 274 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 7d4944e..4de8d9b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -2,8 +2,6 @@
# Makefile for the drm device driver. This driver provides support for the
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-ccflags-y := -Iinclude/drm
-
drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 6e3b78e..cd1b16b 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -30,7 +30,15 @@
#include <drm/drm_atomic.h>
#include <drm/drm_plane_helper.h>
-static void kfree_state(struct drm_atomic_state *state)
+/**
+ * drm_atomic_state_default_release -
+ * release memory initialized by drm_atomic_state_init
+ * @state: atomic state
+ *
+ * Free all the memory allocated by drm_atomic_state_init.
+ * This is useful for drivers that subclass the atomic state.
+ */
+void drm_atomic_state_default_release(struct drm_atomic_state *state)
{
kfree(state->connectors);
kfree(state->connector_states);
@@ -38,24 +46,20 @@ static void kfree_state(struct drm_atomic_state *state)
kfree(state->crtc_states);
kfree(state->planes);
kfree(state->plane_states);
- kfree(state);
}
+EXPORT_SYMBOL(drm_atomic_state_default_release);
/**
- * drm_atomic_state_alloc - allocate atomic state
+ * drm_atomic_state_init - init new atomic state
* @dev: DRM device
+ * @state: atomic state
*
- * This allocates an empty atomic state to track updates.
+ * Default implementation for filling in a new atomic state.
+ * This is useful for drivers that subclass the atomic state.
*/
-struct drm_atomic_state *
-drm_atomic_state_alloc(struct drm_device *dev)
+int
+drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
{
- struct drm_atomic_state *state;
-
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (!state)
- return NULL;
-
/* TODO legacy paths should maybe do a better job about
* setting this appropriately?
*/
@@ -92,31 +96,50 @@ drm_atomic_state_alloc(struct drm_device *dev)
state->dev = dev;
- DRM_DEBUG_ATOMIC("Allocate atomic state %p\n", state);
+ DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
- return state;
+ return 0;
fail:
- kfree_state(state);
+ drm_atomic_state_default_release(state);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(drm_atomic_state_init);
+
+/**
+ * drm_atomic_state_alloc - allocate atomic state
+ * @dev: DRM device
+ *
+ * This allocates an empty atomic state to track updates.
+ */
+struct drm_atomic_state *
+drm_atomic_state_alloc(struct drm_device *dev)
+{
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_atomic_state *state;
- return NULL;
+ if (!config->funcs->atomic_state_alloc) {
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return NULL;
+ if (drm_atomic_state_init(dev, state) < 0) {
+ kfree(state);
+ return NULL;
+ }
+ return state;
+ }
+
+ return config->funcs->atomic_state_alloc(dev);
}
EXPORT_SYMBOL(drm_atomic_state_alloc);
/**
- * drm_atomic_state_clear - clear state object
+ * drm_atomic_state_default_clear - clear base atomic state
* @state: atomic state
*
- * When the w/w mutex algorithm detects a deadlock we need to back off and drop
- * all locks. So someone else could sneak in and change the current modeset
- * configuration. Which means that all the state assembled in @state is no
- * longer an atomic update to the current state, but to some arbitrary earlier
- * state. Which could break assumptions the driver's ->atomic_check likely
- * relies on.
- *
- * Hence we must clear all cached state and completely start over, using this
- * function.
+ * Default implementation for clearing atomic state.
+ * This is useful for drivers that subclass the atomic state.
*/
-void drm_atomic_state_clear(struct drm_atomic_state *state)
+void drm_atomic_state_default_clear(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
struct drm_mode_config *config = &dev->mode_config;
@@ -162,6 +185,32 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
state->plane_states[i] = NULL;
}
}
+EXPORT_SYMBOL(drm_atomic_state_default_clear);
+
+/**
+ * drm_atomic_state_clear - clear state object
+ * @state: atomic state
+ *
+ * When the w/w mutex algorithm detects a deadlock we need to back off and drop
+ * all locks. So someone else could sneak in and change the current modeset
+ * configuration. Which means that all the state assembled in @state is no
+ * longer an atomic update to the current state, but to some arbitrary earlier
+ * state. Which could break assumptions the driver's ->atomic_check likely
+ * relies on.
+ *
+ * Hence we must clear all cached state and completely start over, using this
+ * function.
+ */
+void drm_atomic_state_clear(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct drm_mode_config *config = &dev->mode_config;
+
+ if (config->funcs->atomic_state_clear)
+ config->funcs->atomic_state_clear(state);
+ else
+ drm_atomic_state_default_clear(state);
+}
EXPORT_SYMBOL(drm_atomic_state_clear);
/**
@@ -173,14 +222,25 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
*/
void drm_atomic_state_free(struct drm_atomic_state *state)
{
+ struct drm_device *dev;
+ struct drm_mode_config *config;
+
if (!state)
return;
+ dev = state->dev;
+ config = &dev->mode_config;
+
drm_atomic_state_clear(state);
DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
- kfree_state(state);
+ if (config->funcs->atomic_state_free) {
+ config->funcs->atomic_state_free(state);
+ } else {
+ drm_atomic_state_default_release(state);
+ kfree(state);
+ }
}
EXPORT_SYMBOL(drm_atomic_state_free);
@@ -203,13 +263,12 @@ struct drm_crtc_state *
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
struct drm_crtc *crtc)
{
- int ret, index;
+ int ret, index = drm_crtc_index(crtc);
struct drm_crtc_state *crtc_state;
- index = drm_crtc_index(crtc);
-
- if (state->crtc_states[index])
- return state->crtc_states[index];
+ crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
+ if (crtc_state)
+ return crtc_state;
ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);
if (ret)
@@ -337,13 +396,12 @@ struct drm_plane_state *
drm_atomic_get_plane_state(struct drm_atomic_state *state,
struct drm_plane *plane)
{
- int ret, index;
+ int ret, index = drm_plane_index(plane);
struct drm_plane_state *plane_state;
- index = drm_plane_index(plane);
-
- if (state->plane_states[index])
- return state->plane_states[index];
+ plane_state = drm_atomic_get_existing_plane_state(state, plane);
+ if (plane_state)
+ return plane_state;
ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
if (ret)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5e68c3c..b82ef62 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -624,8 +624,22 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
}
}
-static void
-set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state)
+/**
+ * drm_atomic_helper_update_legacy_modeset_state - update legacy modeset state
+ * @dev: DRM device
+ * @old_state: atomic state object with old state structures
+ *
+ * This function updates all the various legacy modeset state pointers in
+ * connectors, encoders and crtcs. It also updates the timestamping constants
+ * used for precise vblank timestamps by calling
+ * drm_calc_timestamping_constants().
+ *
+ * Drivers can use this for building their own atomic commit if they don't have
+ * a pure helper-based modeset implementation.
+ */
+void
+drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
+ struct drm_atomic_state *old_state)
{
struct drm_connector *connector;
struct drm_connector_state *old_conn_state;
@@ -662,8 +676,13 @@ set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state)
crtc->enabled = crtc->state->enable;
crtc->x = crtc->primary->state->src_x >> 16;
crtc->y = crtc->primary->state->src_y >> 16;
+
+ if (crtc->state->enable)
+ drm_calc_timestamping_constants(crtc,
+ &crtc->state->adjusted_mode);
}
}
+EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state);
static void
crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
@@ -742,7 +761,9 @@ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
struct drm_atomic_state *old_state)
{
disable_outputs(dev, old_state);
- set_routing_links(dev, old_state);
+
+ drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
+
crtc_set_mode(dev, old_state);
}
EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
@@ -1135,8 +1156,6 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
if (!funcs)
continue;
- old_plane_state = old_state->plane_states[i];
-
/*
* Special-case disabling the plane if drivers support it.
*/
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 160647a..4059f06 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -352,7 +352,9 @@ static struct drm_mode_object *_object_find(struct drm_device *dev,
if (obj && obj->id != id)
obj = NULL;
/* don't leak out unref'd fb's */
- if (obj && (obj->type == DRM_MODE_OBJECT_FB))
+ if (obj &&
+ (obj->type == DRM_MODE_OBJECT_FB ||
+ obj->type == DRM_MODE_OBJECT_BLOB))
obj = NULL;
mutex_unlock(&dev->mode_config.idr_mutex);
@@ -377,7 +379,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
/* Framebuffers are reference counted and need their own lookup
* function.*/
- WARN_ON(type == DRM_MODE_OBJECT_FB);
+ WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
obj = _object_find(dev, id, type);
return obj;
}
@@ -4225,7 +4227,7 @@ done:
return ret;
}
-static struct drm_property_blob *
+struct drm_property_blob *
drm_property_create_blob(struct drm_device *dev, size_t length,
const void *data)
{
@@ -4239,29 +4241,238 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
if (!blob)
return NULL;
+ blob->length = length;
+ blob->dev = dev;
+
+ memcpy(blob->data, data, length);
+
+ mutex_lock(&dev->mode_config.blob_lock);
+
ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
if (ret) {
kfree(blob);
+ mutex_unlock(&dev->mode_config.blob_lock);
return NULL;
}
- blob->length = length;
-
- memcpy(blob->data, data, length);
+ kref_init(&blob->refcount);
list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
+
+ mutex_unlock(&dev->mode_config.blob_lock);
+
return blob;
}
+EXPORT_SYMBOL(drm_property_create_blob);
-static void drm_property_destroy_blob(struct drm_device *dev,
- struct drm_property_blob *blob)
+/**
+ * drm_property_free_blob - Blob property destructor
+ *
+ * Internal free function for blob properties; must not be used directly.
+ *
+ * @param kref Reference
+ */
+static void drm_property_free_blob(struct kref *kref)
{
- drm_mode_object_put(dev, &blob->base);
+ struct drm_property_blob *blob =
+ container_of(kref, struct drm_property_blob, refcount);
+
+ WARN_ON(!mutex_is_locked(&blob->dev->mode_config.blob_lock));
+
list_del(&blob->head);
+ drm_mode_object_put(blob->dev, &blob->base);
+
kfree(blob);
}
/**
+ * drm_property_unreference_blob - Unreference a blob property
+ *
+ * Drop a reference on a blob property. May free the object.
+ *
+ * @param blob Pointer to blob property
+ */
+void drm_property_unreference_blob(struct drm_property_blob *blob)
+{
+ struct drm_device *dev;
+
+ if (!blob)
+ return;
+
+ dev = blob->dev;
+
+ DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
+
+ if (kref_put_mutex(&blob->refcount, drm_property_free_blob,
+ &dev->mode_config.blob_lock))
+ mutex_unlock(&dev->mode_config.blob_lock);
+ else
+ might_lock(&dev->mode_config.blob_lock);
+
+}
+EXPORT_SYMBOL(drm_property_unreference_blob);
+
+/**
+ * drm_property_unreference_blob_locked - Unreference a blob property with blob_lock held
+ *
+ * Drop a reference on a blob property. May free the object. This must be
+ * called with blob_lock held.
+ *
+ * @param dev Device the blob was created on
+ * @param blob Pointer to blob property
+ */
+static void drm_property_unreference_blob_locked(struct drm_property_blob *blob)
+{
+ if (!blob)
+ return;
+
+ DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
+
+ kref_put(&blob->refcount, drm_property_free_blob);
+}
+
+/**
+ * drm_property_reference_blob - Take a reference on an existing property
+ *
+ * Take a new reference on an existing blob property.
+ *
+ * @param blob Pointer to blob property
+ */
+struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
+{
+ DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
+ kref_get(&blob->refcount);
+ return blob;
+}
+EXPORT_SYMBOL(drm_property_reference_blob);
+
+/*
+ * Like drm_property_lookup_blob, but does not return an additional reference.
+ * Must be called with blob_lock held.
+ */
+static struct drm_property_blob *__drm_property_lookup_blob(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_mode_object *obj = NULL;
+ struct drm_property_blob *blob;
+
+ WARN_ON(!mutex_is_locked(&dev->mode_config.blob_lock));
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+ obj = idr_find(&dev->mode_config.crtc_idr, id);
+ if (!obj || (obj->type != DRM_MODE_OBJECT_BLOB) || (obj->id != id))
+ blob = NULL;
+ else
+ blob = obj_to_blob(obj);
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return blob;
+}
+
+/**
+ * drm_property_lookup_blob - look up a blob property and take a reference
+ * @dev: drm device
+ * @id: id of the blob property
+ *
+ * If successful, this takes an additional reference to the blob property.
+ * callers need to make sure to eventually unreference the returned property
+ * again, using @drm_property_unreference_blob.
+ */
+struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_property_blob *blob;
+
+ mutex_lock(&dev->mode_config.blob_lock);
+ blob = __drm_property_lookup_blob(dev, id);
+ if (blob) {
+ if (!kref_get_unless_zero(&blob->refcount))
+ blob = NULL;
+ }
+ mutex_unlock(&dev->mode_config.blob_lock);
+
+ return blob;
+}
+EXPORT_SYMBOL(drm_property_lookup_blob);
+
+/**
+ * drm_property_replace_global_blob - atomically replace existing blob property
+ * @dev: drm device
+ * @replace: location of blob property pointer to be replaced
+ * @length: length of data for new blob, or 0 for no data
+ * @data: content for new blob, or NULL for no data
+ * @obj_holds_id: optional object for property holding blob ID
+ * @prop_holds_id: optional property holding blob ID
+ * @return 0 on success or error on failure
+ *
+ * This function will atomically replace a global property in the blob list,
+ * optionally updating a property which holds the ID of that property. It is
+ * guaranteed to be atomic: no caller will be allowed to see intermediate
+ * results, and either the entire operation will succeed and clean up the
+ * previous property, or it will fail and the state will be unchanged.
+ *
+ * If length is 0 or data is NULL, no new blob will be created, and the holding
+ * property, if specified, will be set to 0.
+ *
+ * Access to the replace pointer is assumed to be protected by the caller, e.g.
+ * by holding the relevant modesetting object lock for its parent.
+ *
+ * For example, a drm_connector has a 'PATH' property, which contains the ID
+ * of a blob property with the value of the MST path information. Calling this
+ * function with replace pointing to the connector's path_blob_ptr, length and
+ * data set for the new path information, obj_holds_id set to the connector's
+ * base object, and prop_holds_id set to the path property name, will perform
+ * a completely atomic update. The access to path_blob_ptr is protected by the
+ * caller holding a lock on the connector.
+ */
+static int drm_property_replace_global_blob(struct drm_device *dev,
+ struct drm_property_blob **replace,
+ size_t length,
+ const void *data,
+ struct drm_mode_object *obj_holds_id,
+ struct drm_property *prop_holds_id)
+{
+ struct drm_property_blob *new_blob = NULL;
+ struct drm_property_blob *old_blob = NULL;
+ int ret;
+
+ WARN_ON(replace == NULL);
+
+ old_blob = *replace;
+
+ if (length && data) {
+ new_blob = drm_property_create_blob(dev, length, data);
+ if (!new_blob)
+ return -EINVAL;
+ }
+
+ /* This does not need to be synchronised with blob_lock, as the
+ * get_properties ioctl locks all modesetting objects, and
+ * obj_holds_id must be locked before calling here, so we cannot
+ * have its value out of sync with the list membership modified
+ * below under blob_lock. */
+ if (obj_holds_id) {
+ ret = drm_object_property_set_value(obj_holds_id,
+ prop_holds_id,
+ new_blob ?
+ new_blob->base.id : 0);
+ if (ret != 0)
+ goto err_created;
+ }
+
+ if (old_blob)
+ drm_property_unreference_blob(old_blob);
+
+ *replace = new_blob;
+
+ return 0;
+
+err_created:
+ drm_property_unreference_blob(new_blob);
+ return ret;
+}
+
+/**
* drm_mode_getblob_ioctl - get the contents of a blob property value
* @dev: DRM device
* @data: ioctl data
@@ -4287,7 +4498,8 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
return -EINVAL;
drm_modeset_lock_all(dev);
- blob = drm_property_blob_find(dev, out_resp->blob_id);
+ mutex_lock(&dev->mode_config.blob_lock);
+ blob = __drm_property_lookup_blob(dev, out_resp->blob_id);
if (!blob) {
ret = -ENOENT;
goto done;
@@ -4303,6 +4515,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
out_resp->length = blob->length;
done:
+ mutex_unlock(&dev->mode_config.blob_lock);
drm_modeset_unlock_all(dev);
return ret;
}
@@ -4310,7 +4523,7 @@ done:
/**
* drm_mode_connector_set_path_property - set tile property on connector
* @connector: connector to set property on.
- * @path: path to use for property.
+ * @path: path to use for property; must not be NULL.
*
* This creates a property to expose to userspace to specify a
* connector path. This is mainly used for DisplayPort MST where
@@ -4324,17 +4537,14 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
const char *path)
{
struct drm_device *dev = connector->dev;
- size_t size = strlen(path) + 1;
int ret;
- connector->path_blob_ptr = drm_property_create_blob(connector->dev,
- size, path);
- if (!connector->path_blob_ptr)
- return -EINVAL;
-
- ret = drm_object_property_set_value(&connector->base,
- dev->mode_config.path_property,
- connector->path_blob_ptr->base.id);
+ ret = drm_property_replace_global_blob(dev,
+ &connector->path_blob_ptr,
+ strlen(path) + 1,
+ path,
+ &connector->base,
+ dev->mode_config.path_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_set_path_property);
@@ -4353,16 +4563,16 @@ EXPORT_SYMBOL(drm_mode_connector_set_path_property);
int drm_mode_connector_set_tile_property(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- int ret, size;
char tile[256];
-
- if (connector->tile_blob_ptr)
- drm_property_destroy_blob(dev, connector->tile_blob_ptr);
+ int ret;
if (!connector->has_tile) {
- connector->tile_blob_ptr = NULL;
- ret = drm_object_property_set_value(&connector->base,
- dev->mode_config.tile_property, 0);
+ ret = drm_property_replace_global_blob(dev,
+ &connector->tile_blob_ptr,
+ 0,
+ NULL,
+ &connector->base,
+ dev->mode_config.tile_property);
return ret;
}
@@ -4371,16 +4581,13 @@ int drm_mode_connector_set_tile_property(struct drm_connector *connector)
connector->num_h_tile, connector->num_v_tile,
connector->tile_h_loc, connector->tile_v_loc,
connector->tile_h_size, connector->tile_v_size);
- size = strlen(tile) + 1;
- connector->tile_blob_ptr = drm_property_create_blob(connector->dev,
- size, tile);
- if (!connector->tile_blob_ptr)
- return -EINVAL;
-
- ret = drm_object_property_set_value(&connector->base,
- dev->mode_config.tile_property,
- connector->tile_blob_ptr->base.id);
+ ret = drm_property_replace_global_blob(dev,
+ &connector->tile_blob_ptr,
+ strlen(tile) + 1,
+ tile,
+ &connector->base,
+ dev->mode_config.tile_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
@@ -4400,33 +4607,22 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
const struct edid *edid)
{
struct drm_device *dev = connector->dev;
- size_t size;
+ size_t size = 0;
int ret;
/* ignore requests to set edid when overridden */
if (connector->override_edid)
return 0;
- if (connector->edid_blob_ptr)
- drm_property_destroy_blob(dev, connector->edid_blob_ptr);
-
- /* Delete edid, when there is none. */
- if (!edid) {
- connector->edid_blob_ptr = NULL;
- ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
- return ret;
- }
-
- size = EDID_LENGTH * (1 + edid->extensions);
- connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
- size, edid);
- if (!connector->edid_blob_ptr)
- return -EINVAL;
-
- ret = drm_object_property_set_value(&connector->base,
- dev->mode_config.edid_property,
- connector->edid_blob_ptr->base.id);
+ if (edid)
+ size = EDID_LENGTH + (1 + edid->extensions);
+ ret = drm_property_replace_global_blob(dev,
+ &connector->edid_blob_ptr,
+ size,
+ edid,
+ &connector->base,
+ dev->mode_config.edid_property);
return ret;
}
EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
@@ -4467,8 +4663,18 @@ bool drm_property_change_valid_get(struct drm_property *property,
valid_mask |= (1ULL << property->values[i]);
return !(value & ~valid_mask);
} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
- /* Only the driver knows */
- return true;
+ struct drm_property_blob *blob;
+
+ if (value == 0)
+ return true;
+
+ blob = drm_property_lookup_blob(property->dev, value);
+ if (blob) {
+ *ref = &blob->base;
+ return true;
+ } else {
+ return false;
+ }
} else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
/* a zero value for an object property translates to null: */
if (value == 0)
@@ -5453,6 +5659,7 @@ void drm_mode_config_init(struct drm_device *dev)
drm_modeset_lock_init(&dev->mode_config.connection_mutex);
mutex_init(&dev->mode_config.idr_mutex);
mutex_init(&dev->mode_config.fb_lock);
+ mutex_init(&dev->mode_config.blob_lock);
INIT_LIST_HEAD(&dev->mode_config.fb_list);
INIT_LIST_HEAD(&dev->mode_config.crtc_list);
INIT_LIST_HEAD(&dev->mode_config.connector_list);
@@ -5517,7 +5724,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
head) {
- drm_property_destroy_blob(dev, blob);
+ drm_property_unreference_blob(blob);
}
/*
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ab00286..d727b73 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -959,7 +959,12 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod
if (crtc_funcs->atomic_check) {
ret = crtc_funcs->atomic_check(crtc, crtc_state);
if (ret) {
- kfree(crtc_state);
+ if (crtc->funcs->atomic_destroy_state) {
+ crtc->funcs->atomic_destroy_state(crtc,
+ crtc_state);
+ } else {
+ kfree(crtc_state);
+ }
return ret;
}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index e426223..7087da3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -146,327 +146,359 @@ static struct edid_quirk {
* This table is copied from xfree86/modes/xf86EdidModes.c.
*/
static const struct drm_display_mode drm_dmt_modes[] = {
- /* 640x350@85Hz */
+ /* 0x01 - 640x350@85Hz */
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
736, 832, 0, 350, 382, 385, 445, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 640x400@85Hz */
+ /* 0x02 - 640x400@85Hz */
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
736, 832, 0, 400, 401, 404, 445, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 720x400@85Hz */
+ /* 0x03 - 720x400@85Hz */
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756,
828, 936, 0, 400, 401, 404, 446, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 640x480@60Hz */
+ /* 0x04 - 640x480@60Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
- 752, 800, 0, 480, 489, 492, 525, 0,
+ 752, 800, 0, 480, 490, 492, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 640x480@72Hz */
+ /* 0x05 - 640x480@72Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
704, 832, 0, 480, 489, 492, 520, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 640x480@75Hz */
+ /* 0x06 - 640x480@75Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
720, 840, 0, 480, 481, 484, 500, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 640x480@85Hz */
+ /* 0x07 - 640x480@85Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696,
752, 832, 0, 480, 481, 484, 509, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 800x600@56Hz */
+ /* 0x08 - 800x600@56Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
896, 1024, 0, 600, 601, 603, 625, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 800x600@60Hz */
+ /* 0x09 - 800x600@60Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 800x600@72Hz */
+ /* 0x0a - 800x600@72Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
976, 1040, 0, 600, 637, 643, 666, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 800x600@75Hz */
+ /* 0x0b - 800x600@75Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
896, 1056, 0, 600, 601, 604, 625, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 800x600@85Hz */
+ /* 0x0c - 800x600@85Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832,
896, 1048, 0, 600, 601, 604, 631, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 800x600@120Hz RB */
+ /* 0x0d - 800x600@120Hz RB */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 73250, 800, 848,
880, 960, 0, 600, 603, 607, 636, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 848x480@60Hz */
+ /* 0x0e - 848x480@60Hz */
{ DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864,
976, 1088, 0, 480, 486, 494, 517, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1024x768@43Hz, interlace */
+ /* 0x0f - 1024x768@43Hz, interlace */
{ DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
1208, 1264, 0, 768, 768, 772, 817, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
- DRM_MODE_FLAG_INTERLACE) },
- /* 1024x768@60Hz */
+ DRM_MODE_FLAG_INTERLACE) },
+ /* 0x10 - 1024x768@60Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1024x768@70Hz */
+ /* 0x11 - 1024x768@70Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
1184, 1328, 0, 768, 771, 777, 806, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1024x768@75Hz */
+ /* 0x12 - 1024x768@75Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
1136, 1312, 0, 768, 769, 772, 800, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1024x768@85Hz */
+ /* 0x13 - 1024x768@85Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
1168, 1376, 0, 768, 769, 772, 808, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1024x768@120Hz RB */
+ /* 0x14 - 1024x768@120Hz RB */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 115500, 1024, 1072,
1104, 1184, 0, 768, 771, 775, 813, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1152x864@75Hz */
+ /* 0x15 - 1152x864@75Hz */
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
1344, 1600, 0, 864, 865, 868, 900, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x768@60Hz RB */
+ /* 0x55 - 1280x720@60Hz */
+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x16 - 1280x768@60Hz RB */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 68250, 1280, 1328,
1360, 1440, 0, 768, 771, 778, 790, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x768@60Hz */
+ /* 0x17 - 1280x768@60Hz */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
1472, 1664, 0, 768, 771, 778, 798, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x768@75Hz */
+ /* 0x18 - 1280x768@75Hz */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360,
1488, 1696, 0, 768, 771, 778, 805, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x768@85Hz */
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x19 - 1280x768@85Hz */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360,
1496, 1712, 0, 768, 771, 778, 809, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x768@120Hz RB */
+ /* 0x1a - 1280x768@120Hz RB */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 140250, 1280, 1328,
1360, 1440, 0, 768, 771, 778, 813, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x800@60Hz RB */
+ /* 0x1b - 1280x800@60Hz RB */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 71000, 1280, 1328,
1360, 1440, 0, 800, 803, 809, 823, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x800@60Hz */
+ /* 0x1c - 1280x800@60Hz */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
1480, 1680, 0, 800, 803, 809, 831, 0,
- DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x800@75Hz */
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x1d - 1280x800@75Hz */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360,
1488, 1696, 0, 800, 803, 809, 838, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x800@85Hz */
+ /* 0x1e - 1280x800@85Hz */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360,
1496, 1712, 0, 800, 803, 809, 843, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x800@120Hz RB */
+ /* 0x1f - 1280x800@120Hz RB */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 146250, 1280, 1328,
1360, 1440, 0, 800, 803, 809, 847, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x960@60Hz */
+ /* 0x20 - 1280x960@60Hz */
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
1488, 1800, 0, 960, 961, 964, 1000, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x960@85Hz */
+ /* 0x21 - 1280x960@85Hz */
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344,
1504, 1728, 0, 960, 961, 964, 1011, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x960@120Hz RB */
+ /* 0x22 - 1280x960@120Hz RB */
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 175500, 1280, 1328,
1360, 1440, 0, 960, 963, 967, 1017, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1280x1024@60Hz */
+ /* 0x23 - 1280x1024@60Hz */
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x1024@75Hz */
+ /* 0x24 - 1280x1024@75Hz */
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x1024@85Hz */
+ /* 0x25 - 1280x1024@85Hz */
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344,
1504, 1728, 0, 1024, 1025, 1028, 1072, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1280x1024@120Hz RB */
+ /* 0x26 - 1280x1024@120Hz RB */
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 187250, 1280, 1328,
1360, 1440, 0, 1024, 1027, 1034, 1084, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1360x768@60Hz */
+ /* 0x27 - 1360x768@60Hz */
{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
1536, 1792, 0, 768, 771, 777, 795, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1360x768@120Hz RB */
+ /* 0x28 - 1360x768@120Hz RB */
{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 148250, 1360, 1408,
1440, 1520, 0, 768, 771, 776, 813, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1400x1050@60Hz RB */
+ /* 0x51 - 1366x768@60Hz */
+ { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 85500, 1366, 1436,
+ 1579, 1792, 0, 768, 771, 774, 798, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x56 - 1366x768@60Hz */
+ { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 72000, 1366, 1380,
+ 1436, 1500, 0, 768, 769, 772, 800, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x29 - 1400x1050@60Hz RB */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 101000, 1400, 1448,
1480, 1560, 0, 1050, 1053, 1057, 1080, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1400x1050@60Hz */
+ /* 0x2a - 1400x1050@60Hz */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1400x1050@75Hz */
+ /* 0x2b - 1400x1050@75Hz */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504,
1648, 1896, 0, 1050, 1053, 1057, 1099, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1400x1050@85Hz */
+ /* 0x2c - 1400x1050@85Hz */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504,
1656, 1912, 0, 1050, 1053, 1057, 1105, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1400x1050@120Hz RB */
+ /* 0x2d - 1400x1050@120Hz RB */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 208000, 1400, 1448,
1480, 1560, 0, 1050, 1053, 1057, 1112, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1440x900@60Hz RB */
+ /* 0x2e - 1440x900@60Hz RB */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 88750, 1440, 1488,
1520, 1600, 0, 900, 903, 909, 926, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1440x900@60Hz */
+ /* 0x2f - 1440x900@60Hz */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
1672, 1904, 0, 900, 903, 909, 934, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1440x900@75Hz */
+ /* 0x30 - 1440x900@75Hz */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536,
1688, 1936, 0, 900, 903, 909, 942, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1440x900@85Hz */
+ /* 0x31 - 1440x900@85Hz */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544,
1696, 1952, 0, 900, 903, 909, 948, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1440x900@120Hz RB */
+ /* 0x32 - 1440x900@120Hz RB */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 182750, 1440, 1488,
1520, 1600, 0, 900, 903, 909, 953, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1600x1200@60Hz */
+ /* 0x53 - 1600x900@60Hz */
+ { DRM_MODE("1600x900", DRM_MODE_TYPE_DRIVER, 108000, 1600, 1624,
+ 1704, 1800, 0, 900, 901, 904, 1000, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x33 - 1600x1200@60Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@65Hz */
+ /* 0x34 - 1600x1200@65Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@70Hz */
+ /* 0x35 - 1600x1200@70Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@75Hz */
+ /* 0x36 - 1600x1200@75Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@85Hz */
+ /* 0x37 - 1600x1200@85Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1600x1200@120Hz RB */
+ /* 0x38 - 1600x1200@120Hz RB */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 268250, 1600, 1648,
1680, 1760, 0, 1200, 1203, 1207, 1271, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1680x1050@60Hz RB */
+ /* 0x39 - 1680x1050@60Hz RB */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 119000, 1680, 1728,
1760, 1840, 0, 1050, 1053, 1059, 1080, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1680x1050@60Hz */
+ /* 0x3a - 1680x1050@60Hz */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1680x1050@75Hz */
+ /* 0x3b - 1680x1050@75Hz */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800,
1976, 2272, 0, 1050, 1053, 1059, 1099, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1680x1050@85Hz */
+ /* 0x3c - 1680x1050@85Hz */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808,
1984, 2288, 0, 1050, 1053, 1059, 1105, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1680x1050@120Hz RB */
+ /* 0x3d - 1680x1050@120Hz RB */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 245500, 1680, 1728,
1760, 1840, 0, 1050, 1053, 1059, 1112, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1792x1344@60Hz */
+ /* 0x3e - 1792x1344@60Hz */
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1792x1344@75Hz */
+ /* 0x3f - 1792x1344@75Hz */
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888,
2104, 2456, 0, 1344, 1345, 1348, 1417, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1792x1344@120Hz RB */
+ /* 0x40 - 1792x1344@120Hz RB */
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 333250, 1792, 1840,
1872, 1952, 0, 1344, 1347, 1351, 1423, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1856x1392@60Hz */
+ /* 0x41 - 1856x1392@60Hz */
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1856x1392@75Hz */
+ /* 0x42 - 1856x1392@75Hz */
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984,
- 2208, 2560, 0, 1392, 1395, 1399, 1500, 0,
+ 2208, 2560, 0, 1392, 1393, 1396, 1500, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1856x1392@120Hz RB */
+ /* 0x43 - 1856x1392@120Hz RB */
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 356500, 1856, 1904,
1936, 2016, 0, 1392, 1395, 1399, 1474, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1920x1200@60Hz RB */
+ /* 0x52 - 1920x1080@60Hz */
+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 0x44 - 1920x1200@60Hz RB */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 154000, 1920, 1968,
2000, 2080, 0, 1200, 1203, 1209, 1235, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1920x1200@60Hz */
+ /* 0x45 - 1920x1200@60Hz */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1200@75Hz */
+ /* 0x46 - 1920x1200@75Hz */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056,
2264, 2608, 0, 1200, 1203, 1209, 1255, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1200@85Hz */
+ /* 0x47 - 1920x1200@85Hz */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064,
2272, 2624, 0, 1200, 1203, 1209, 1262, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1200@120Hz RB */
+ /* 0x48 - 1920x1200@120Hz RB */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 317000, 1920, 1968,
2000, 2080, 0, 1200, 1203, 1209, 1271, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 1920x1440@60Hz */
+ /* 0x49 - 1920x1440@60Hz */
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1440@75Hz */
+ /* 0x4a - 1920x1440@75Hz */
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064,
2288, 2640, 0, 1440, 1441, 1444, 1500, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 1920x1440@120Hz RB */
+ /* 0x4b - 1920x1440@120Hz RB */
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 380500, 1920, 1968,
2000, 2080, 0, 1440, 1443, 1447, 1525, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 2560x1600@60Hz RB */
+ /* 0x54 - 2048x1152@60Hz */
+ { DRM_MODE("2048x1152", DRM_MODE_TYPE_DRIVER, 162000, 2048, 2074,
+ 2154, 2250, 0, 1152, 1153, 1156, 1200, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ /* 0x4c - 2560x1600@60Hz RB */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 268500, 2560, 2608,
2640, 2720, 0, 1600, 1603, 1609, 1646, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
- /* 2560x1600@60Hz */
+ /* 0x4d - 2560x1600@60Hz */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 2560x1600@75HZ */
+ /* 0x4e - 2560x1600@75Hz */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768,
3048, 3536, 0, 1600, 1603, 1609, 1672, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 2560x1600@85HZ */
+ /* 0x4f - 2560x1600@85Hz */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768,
3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
- /* 2560x1600@120Hz RB */
+ /* 0x50 - 2560x1600@120Hz RB */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 552750, 2560, 2608,
2640, 2720, 0, 1600, 1603, 1609, 1694, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 0x57 - 4096x2160@60Hz RB */
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 556744, 4096, 4104,
+ 4136, 4176, 0, 2160, 2208, 2216, 2222, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+ /* 0x58 - 4096x2160@59.94Hz RB */
+ { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 556188, 4096, 4104,
+ 4136, 4176, 0, 2160, 2208, 2216, 2222, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
};
/*
@@ -3732,10 +3764,10 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
num_modes += add_cvt_modes(connector, edid);
num_modes += add_standard_modes(connector, edid);
num_modes += add_established_modes(connector, edid);
- if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
- num_modes += add_inferred_modes(connector, edid);
num_modes += add_cea_modes(connector, edid);
num_modes += add_alternate_cea_modes(connector, edid);
+ if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
+ num_modes += add_inferred_modes(connector, edid);
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
edid_fixup_preferred(connector, quirks);
diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
index 43d9b95..12dea16 100644
--- a/drivers/gpu/drm/drm_flip_work.c
+++ b/drivers/gpu/drm/drm_flip_work.c
@@ -21,8 +21,8 @@
* SOFTWARE.
*/
-#include "drmP.h"
-#include "drm_flip_work.h"
+#include <drm/drmP.h>
+#include <drm/drm_flip_work.h>
/**
* drm_flip_work_allocate_task - allocate a flip-work task
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 7fec191..162dd29 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -502,9 +502,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
struct drm_gem_object *obj;
int ret;
- if (!dev->driver->gem_prime_import_sg_table)
- return ERR_PTR(-EINVAL);
-
if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) {
obj = dma_buf->priv;
if (obj->dev == dev) {
@@ -517,6 +514,9 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
}
}
+ if (!dev->driver->gem_prime_import_sg_table)
+ return ERR_PTR(-EINVAL);
+
attach = dma_buf_attach(dma_buf, dev->dev);
if (IS_ERR(attach))
return ERR_CAST(attach);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index ffc305f..487ddf5 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -302,35 +302,43 @@ static ssize_t modes_show(struct device *device,
return written;
}
-static ssize_t subconnector_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
+static ssize_t tv_subconnector_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
struct drm_device *dev = connector->dev;
- struct drm_property *prop = NULL;
+ struct drm_property *prop;
uint64_t subconnector;
- int is_tv = 0;
int ret;
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- prop = dev->mode_config.dvi_i_subconnector_property;
- break;
- case DRM_MODE_CONNECTOR_Composite:
- case DRM_MODE_CONNECTOR_SVIDEO:
- case DRM_MODE_CONNECTOR_Component:
- case DRM_MODE_CONNECTOR_TV:
- prop = dev->mode_config.tv_subconnector_property;
- is_tv = 1;
- break;
- default:
- DRM_ERROR("Wrong connector type for this property\n");
- return 0;
+ prop = dev->mode_config.tv_subconnector_property;
+ if (!prop) {
+ DRM_ERROR("Unable to find subconnector property\n");
+ return 0;
}
+ ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
+ if (ret)
+ return 0;
+
+ return snprintf(buf, PAGE_SIZE, "%s",
+ drm_get_tv_subconnector_name((int)subconnector));
+}
+
+static ssize_t tv_select_subconnector_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_connector *connector = to_drm_connector(device);
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+ uint64_t subconnector;
+ int ret;
+
+ prop = dev->mode_config.tv_select_subconnector_property;
if (!prop) {
- DRM_ERROR("Unable to find subconnector property\n");
+ DRM_ERROR("Unable to find select subconnector property\n");
return 0;
}
@@ -338,38 +346,45 @@ static ssize_t subconnector_show(struct device *device,
if (ret)
return 0;
- return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
- drm_get_tv_subconnector_name((int)subconnector) :
- drm_get_dvi_i_subconnector_name((int)subconnector));
+ return snprintf(buf, PAGE_SIZE, "%s",
+ drm_get_tv_select_name((int)subconnector));
}
-static ssize_t select_subconnector_show(struct device *device,
- struct device_attribute *attr,
- char *buf)
+static ssize_t dvii_subconnector_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
struct drm_device *dev = connector->dev;
- struct drm_property *prop = NULL;
+ struct drm_property *prop;
uint64_t subconnector;
- int is_tv = 0;
int ret;
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- prop = dev->mode_config.dvi_i_select_subconnector_property;
- break;
- case DRM_MODE_CONNECTOR_Composite:
- case DRM_MODE_CONNECTOR_SVIDEO:
- case DRM_MODE_CONNECTOR_Component:
- case DRM_MODE_CONNECTOR_TV:
- prop = dev->mode_config.tv_select_subconnector_property;
- is_tv = 1;
- break;
- default:
- DRM_ERROR("Wrong connector type for this property\n");
- return 0;
+ prop = dev->mode_config.dvi_i_subconnector_property;
+ if (!prop) {
+ DRM_ERROR("Unable to find subconnector property\n");
+ return 0;
}
+ ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
+ if (ret)
+ return 0;
+
+ return snprintf(buf, PAGE_SIZE, "%s",
+ drm_get_dvi_i_subconnector_name((int)subconnector));
+}
+
+static ssize_t dvii_select_subconnector_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_connector *connector = to_drm_connector(device);
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+ uint64_t subconnector;
+ int ret;
+
+ prop = dev->mode_config.dvi_i_select_subconnector_property;
if (!prop) {
DRM_ERROR("Unable to find select subconnector property\n");
return 0;
@@ -379,8 +394,7 @@ static ssize_t select_subconnector_show(struct device *device,
if (ret)
return 0;
- return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
- drm_get_tv_select_name((int)subconnector) :
+ return snprintf(buf, PAGE_SIZE, "%s",
drm_get_dvi_i_select_name((int)subconnector));
}
@@ -397,28 +411,44 @@ static struct attribute *connector_dev_attrs[] = {
NULL
};
-/* These attributes are for both DVI-I connectors and all types of tv-out. */
-static DEVICE_ATTR_RO(subconnector);
-static DEVICE_ATTR_RO(select_subconnector);
+static DEVICE_ATTR_RO(tv_subconnector);
+static DEVICE_ATTR_RO(tv_select_subconnector);
-static struct attribute *connector_opt_dev_attrs[] = {
- &dev_attr_subconnector.attr,
- &dev_attr_select_subconnector.attr,
+static struct attribute *connector_tv_dev_attrs[] = {
+ &dev_attr_tv_subconnector.attr,
+ &dev_attr_tv_select_subconnector.attr,
NULL
};
-static umode_t connector_opt_dev_is_visible(struct kobject *kobj,
- struct attribute *attr, int idx)
+static DEVICE_ATTR_RO(dvii_subconnector);
+static DEVICE_ATTR_RO(dvii_select_subconnector);
+
+static struct attribute *connector_dvii_dev_attrs[] = {
+ &dev_attr_dvii_subconnector.attr,
+ &dev_attr_dvii_select_subconnector.attr,
+ NULL
+};
+
+/* Connector type related helpers */
+static int kobj_connector_type(struct kobject *kobj)
{
struct device *dev = kobj_to_dev(kobj);
struct drm_connector *connector = to_drm_connector(dev);
- /*
- * In the long run it maybe a good idea to make one set of
- * optionals per connector type.
- */
- switch (connector->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
+ return connector->connector_type;
+}
+
+static umode_t connector_is_dvii(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ return kobj_connector_type(kobj) == DRM_MODE_CONNECTOR_DVII ?
+ attr->mode : 0;
+}
+
+static umode_t connector_is_tv(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ switch (kobj_connector_type(kobj)) {
case DRM_MODE_CONNECTOR_Composite:
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_Component:
@@ -446,14 +476,20 @@ static const struct attribute_group connector_dev_group = {
.bin_attrs = connector_bin_attrs,
};
-static const struct attribute_group connector_opt_dev_group = {
- .attrs = connector_opt_dev_attrs,
- .is_visible = connector_opt_dev_is_visible,
+static const struct attribute_group connector_tv_dev_group = {
+ .attrs = connector_tv_dev_attrs,
+ .is_visible = connector_is_tv,
+};
+
+static const struct attribute_group connector_dvii_dev_group = {
+ .attrs = connector_dvii_dev_attrs,
+ .is_visible = connector_is_dvii,
};
static const struct attribute_group *connector_dev_groups[] = {
&connector_dev_group,
- &connector_opt_dev_group,
+ &connector_tv_dev_group,
+ &connector_dvii_dev_group,
NULL
};
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5238deb..b7ddf48 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -2,8 +2,6 @@
# Makefile for the drm device driver. This driver provides support for the
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-ccflags-y := -Iinclude/drm
-
# Please keep these build lists sorted!
# core driver code
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index 1719078..4039ede 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -22,8 +22,8 @@
*
*/
-#include "drmP.h"
-#include "i915_drm.h"
+#include <drm/drmP.h>
+#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_trace.h"
#include "intel_drv.h"
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index c1571034..f0d3a73 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -35,6 +35,11 @@ drm_atomic_state_alloc(struct drm_device *dev);
void drm_atomic_state_clear(struct drm_atomic_state *state);
void drm_atomic_state_free(struct drm_atomic_state *state);
+int __must_check
+drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state);
+void drm_atomic_state_default_clear(struct drm_atomic_state *state);
+void drm_atomic_state_default_release(struct drm_atomic_state *state);
+
struct drm_crtc_state * __must_check
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
struct drm_crtc *crtc);
@@ -54,6 +59,56 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
struct drm_connector_state *state, struct drm_property *property,
uint64_t val);
+/**
+ * drm_atomic_get_existing_crtc_state - get crtc state, if it exists
+ * @state: global atomic state object
+ * @crtc: crtc to grab
+ *
+ * This function returns the crtc state for the given crtc, or NULL
+ * if the crtc is not part of the global atomic state.
+ */
+static inline struct drm_crtc_state *
+drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+ return state->crtc_states[drm_crtc_index(crtc)];
+}
+
+/**
+ * drm_atomic_get_existing_plane_state - get plane state, if it exists
+ * @state: global atomic state object
+ * @plane: plane to grab
+ *
+ * This function returns the plane state for the given plane, or NULL
+ * if the plane is not part of the global atomic state.
+ */
+static inline struct drm_plane_state *
+drm_atomic_get_existing_plane_state(struct drm_atomic_state *state,
+ struct drm_plane *plane)
+{
+ return state->plane_states[drm_plane_index(plane)];
+}
+
+/**
+ * drm_atomic_get_existing_connector_state - get connector state, if it exists
+ * @state: global atomic state object
+ * @connector: connector to grab
+ *
+ * This function returns the connector state for the given connector,
+ * or NULL if the connector is not part of the global atomic state.
+ */
+static inline struct drm_connector_state *
+drm_atomic_get_existing_connector_state(struct drm_atomic_state *state,
+ struct drm_connector *connector)
+{
+ int index = drm_connector_index(connector);
+
+ if (index >= state->num_connector)
+ return NULL;
+
+ return state->connector_states[index];
+}
+
int __must_check
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index d665781..6ee0ee5 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -43,6 +43,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
struct drm_atomic_state *old_state);
+void
+drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
+ struct drm_atomic_state *old_state);
+
void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
struct drm_atomic_state *state);
void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0a4a040..bff25b0 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -216,6 +216,8 @@ struct drm_framebuffer {
struct drm_property_blob {
struct drm_mode_object base;
+ struct drm_device *dev;
+ struct kref refcount;
struct list_head head;
size_t length;
unsigned char data[];
@@ -983,6 +985,9 @@ struct drm_mode_set {
* @atomic_check: check whether a given atomic state update is possible
* @atomic_commit: commit an atomic state update previously verified with
* atomic_check()
+ * @atomic_state_alloc: allocate a new atomic state
+ * @atomic_state_clear: clear the atomic state
+ * @atomic_state_free: free the atomic state
*
* Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
* involve drivers.
@@ -998,6 +1003,9 @@ struct drm_mode_config_funcs {
int (*atomic_commit)(struct drm_device *dev,
struct drm_atomic_state *a,
bool async);
+ struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
+ void (*atomic_state_clear)(struct drm_atomic_state *state);
+ void (*atomic_state_free)(struct drm_atomic_state *state);
};
/**
@@ -1054,6 +1062,7 @@ struct drm_mode_group {
* @poll_running: track polling status for this device
* @output_poll_work: delayed work for polling in process context
* @property_blob_list: list of all the blob property objects
+ * @blob_lock: mutex for blob property allocation and management
* @*_property: core property tracking
* @preferred_depth: preferred RBG pixel depth, used by fb helpers
* @prefer_shadow: hint to userspace to prefer shadow-fb rendering
@@ -1109,6 +1118,8 @@ struct drm_mode_config {
bool delayed_event;
struct delayed_work output_poll_work;
+ struct mutex blob_lock;
+
/* pointers to standard properties */
struct list_head property_blob_list;
struct drm_property *edid_property;
@@ -1369,6 +1380,13 @@ struct drm_property *drm_property_create_object(struct drm_device *dev,
int flags, const char *name, uint32_t type);
struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
const char *name);
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+ size_t length,
+ const void *data);
+struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
+ uint32_t id);
+struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
+void drm_property_unreference_blob(struct drm_property_blob *blob);
extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
extern int drm_property_add_enum(struct drm_property *property, int index,
uint64_t value, const char *name);
@@ -1533,14 +1551,6 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev,
return mo ? obj_to_property(mo) : NULL;
}
-static inline struct drm_property_blob *
-drm_property_blob_find(struct drm_device *dev, uint32_t id)
-{
- struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
- return mo ? obj_to_blob(mo) : NULL;
-}
-
/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, planelist) \
list_for_each_entry(plane, planelist, head) \
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 523f04c..2e86f64 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -679,9 +679,9 @@ struct drm_dp_aux_msg {
* An AUX channel can also be used to transport I2C messages to a sink. A
* typical application of that is to access an EDID that's present in the
* sink device. The .transfer() function can also be used to execute such
- * transactions. The drm_dp_aux_register_i2c_bus() function registers an
- * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
- * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
+ * transactions. The drm_dp_aux_register() function registers an I2C
+ * adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
+ * should call drm_dp_aux_unregister() to remove the I2C adapter.
* The I2C adapter uses long transfers by default; if a partial response is
* received, the adapter will drop down to the size given by the partial
* response for this transaction only.