summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-05-20 09:19:58 +1000
committerDave Airlie <airlied@redhat.com>2015-05-20 09:19:58 +1000
commit9c37bf2db0a707be4a3025240b009cf63691e0d7 (patch)
treefc260893c8b391d2b559317554d555b16cab711e
parentd0093404f808e23a480dbb4e05c083f1cfeddfd9 (diff)
parent036ef5733ba433760a3512bb5f7a155946e2df05 (diff)
downloadlinux-stable-9c37bf2db0a707be4a3025240b009cf63691e0d7.tar.gz
linux-stable-9c37bf2db0a707be4a3025240b009cf63691e0d7.tar.bz2
linux-stable-9c37bf2db0a707be4a3025240b009cf63691e0d7.zip
Merge tag 'topic/drm-misc-2015-05-19' of git://anongit.freedesktop.org/drm-intel into drm-next
Scattering of random drm core patches. Bunch of atomic prep work too, but the final bits for blob properties, atomic modesets and lifting the experimental tag on the atomic ioctl are still blocked on Daniel Stone finalizing and testing the weston support for it. I hope that we can get it all ready for 4.2 though. * tag 'topic/drm-misc-2015-05-19' of git://anongit.freedesktop.org/drm-intel: (22 commits) drm/atomic: Allow drivers to subclass drm_atomic_state, v3 drm/atomic: remove duplicated assignment of old_plane_state drm/dp: Fix comment in DP helper drm/atomic: add drm_atomic_get_existing_*_state helpers drm/core: get rid of -Iinclude/drm drm/i915: get rid of -Iinclude/drm drm/atomic-helpers: Export drm_atomic_helper_update_legacy_modeset_state drm/atomic-helpers: Update vblank timestamping constants drm/sysfs: remove unnecessary connector type checks drm/sysfs: split DVI-I and TV-out attributes drm/sysfs: make optional attribute groups per connector type drm/sysfs: add a helper for extracting connector type from kobject drm/edid: Add CEA modes before inferred modes drm/prime: Allow internal imports without import_sg_table drm: Add reference counting to blob properties drm: Introduce blob_lock drm: Introduce helper for replacing blob properties drm: Don't leak path blob property when updating drm/atomic: Don't open-code CRTC state destroy drm/edid: Add DMT modes with ID > 0x50 ...
-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 7d4944e1a60c..4de8d9b006ec 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 6e3b78ee7d16..cd1b16b25716 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 5e68c3c7d5cf..b82ef6262469 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 160647a1c584..4059f065c854 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 ab00286aec93..d727b73fba3a 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 e426223482fb..7087da37dae0 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 43d9b950ef9f..12dea16f22a8 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 7fec191b45f7..162dd29b2451 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 ffc305fc2076..487ddf5ffe51 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 5238deb64505..b7ddf48e1d75 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 1719078c763a..4039ede158be 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 c157103492b0..f0d3a7387d99 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 d665781eb542..6ee0ee5b6143 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 0a4a040d6bb7..bff25b0cada9 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 523f04c90dea..2e86f642fc33 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.