summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@quicinc.com>2016-08-11 09:52:52 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-11 09:52:52 -0700
commita7e7d08a9bf598881ba51ead85e453feb2d7064b (patch)
tree02486fb638473adbc10ea717815e48b6eb254fc3 /drivers/gpu
parente61b02b35bc3b2b93f7db12be9e039350b9cacd1 (diff)
parenta578cd5a27ba6f4445bacfb74fa5c093565a6bb6 (diff)
Merge "drm/msm/sde: add support for dirty properties" into dev/msm-4.4-drm_kms
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_prop.c66
-rw-r--r--drivers/gpu/drm/msm/msm_prop.h54
2 files changed, 120 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/msm_prop.c b/drivers/gpu/drm/msm/msm_prop.c
index 2191674ac924..5c930b861822 100644
--- a/drivers/gpu/drm/msm/msm_prop.c
+++ b/drivers/gpu/drm/msm/msm_prop.c
@@ -21,6 +21,8 @@ void msm_property_init(struct msm_property_info *info,
uint32_t blob_count,
uint32_t state_size)
{
+ int i;
+
/* prevent access if any of these are NULL */
if (!base || !dev || !property_array || !property_data) {
property_count = 0;
@@ -49,6 +51,7 @@ void msm_property_init(struct msm_property_info *info,
info->install_request = 0;
info->install_count = 0;
info->recent_idx = 0;
+ info->is_active = false;
info->state_size = state_size;
info->state_cache_size = 0;
mutex_init(&info->property_lock);
@@ -57,6 +60,10 @@ void msm_property_init(struct msm_property_info *info,
0,
sizeof(struct msm_property_data) *
property_count);
+ INIT_LIST_HEAD(&info->dirty_list);
+
+ for (i = 0; i < property_count; ++i)
+ INIT_LIST_HEAD(&property_data[i].dirty_node);
}
}
@@ -65,6 +72,9 @@ void msm_property_destroy(struct msm_property_info *info)
if (!info)
return;
+ /* reset dirty list */
+ INIT_LIST_HEAD(&info->dirty_list);
+
/* free state cache */
while (info->state_cache_size > 0)
kfree(info->state_cache[--(info->state_cache_size)]);
@@ -72,6 +82,58 @@ void msm_property_destroy(struct msm_property_info *info)
mutex_destroy(&info->property_lock);
}
+int msm_property_pop_dirty(struct msm_property_info *info)
+{
+ struct list_head *item;
+ int rc = 0;
+
+ if (!info) {
+ DRM_ERROR("invalid info\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&info->property_lock);
+ if (list_empty(&info->dirty_list)) {
+ rc = -EAGAIN;
+ } else {
+ item = info->dirty_list.next;
+ list_del_init(item);
+ rc = container_of(item, struct msm_property_data, dirty_node)
+ - info->property_data;
+ DRM_DEBUG_KMS("property %d dirty\n", rc);
+ }
+ mutex_unlock(&info->property_lock);
+
+ return rc;
+}
+
+/**
+ * _msm_property_set_dirty_no_lock - flag given property as being dirty
+ * This function doesn't mutex protect the
+ * dirty linked list.
+ * @info: Pointer to property info container struct
+ * @property_idx: Property index
+ */
+static void _msm_property_set_dirty_no_lock(
+ struct msm_property_info *info,
+ uint32_t property_idx)
+{
+ if (!info || property_idx >= info->property_count) {
+ DRM_ERROR("invalid argument(s), info %pK, idx %u\n",
+ info, property_idx);
+ return;
+ }
+
+ /* avoid re-inserting if already dirty */
+ if (!list_empty(&info->property_data[property_idx].dirty_node)) {
+ DRM_DEBUG_KMS("property %u already dirty\n", property_idx);
+ return;
+ }
+
+ list_add_tail(&info->property_data[property_idx].dirty_node,
+ &info->dirty_list);
+}
+
void msm_property_install_range(struct msm_property_info *info,
const char *name, int flags, uint64_t min, uint64_t max,
uint64_t init, uint32_t property_idx)
@@ -312,8 +374,12 @@ int msm_property_atomic_set(struct msm_property_info *info,
property_blobs[property_idx] = blob;
}
}
+
+ /* update value and flag as dirty */
property_values[property_idx] = val;
+ _msm_property_set_dirty_no_lock(info, property_idx);
mutex_unlock(&info->property_lock);
+
DBG("%s - %lld", property->name, val);
rc = 0;
}
diff --git a/drivers/gpu/drm/msm/msm_prop.h b/drivers/gpu/drm/msm/msm_prop.h
index f83013f87e32..c53b6dbd33f7 100644
--- a/drivers/gpu/drm/msm/msm_prop.h
+++ b/drivers/gpu/drm/msm/msm_prop.h
@@ -13,6 +13,7 @@
#ifndef _MSM_PROP_H_
#define _MSM_PROP_H_
+#include <linux/list.h>
#include "msm_drv.h"
#define MSM_PROP_STATE_CACHE_SIZE 2
@@ -21,9 +22,11 @@
* struct msm_property_data - opaque structure for tracking per
* drm-object per property stuff
* @default_value: Default property value for this drm object
+ * @dirty_node: Linked list node to track if property is dirty or not
*/
struct msm_property_data {
uint64_t default_value;
+ struct list_head dirty_node;
};
/**
@@ -37,6 +40,9 @@ struct msm_property_data {
* @install_request: Total number of property 'install' requests
* @install_count: Total number of successful 'install' requests
* @recent_idx: Index of property most recently accessed by set/get
+ * @dirty_list: List of all properties that have been 'atomic_set' but not
+ * yet cleared with 'msm_property_pop_dirty'
+ * @is_active: Whether or not drm component properties are 'active'
* @state_cache: Cache of local states, to prevent alloc/free thrashing
* @state_size: Size of local state structures
* @state_cache_size: Number of state structures currently stored in state_cache
@@ -55,6 +61,9 @@ struct msm_property_info {
int32_t recent_idx;
+ struct list_head dirty_list;
+ bool is_active;
+
void *state_cache[MSM_PROP_STATE_CACHE_SIZE];
uint32_t state_size;
int32_t state_cache_size;
@@ -85,6 +94,51 @@ uint64_t msm_property_get_default(struct msm_property_info *info,
}
/**
+ * msm_property_set_is_active - set overall 'active' status for all properties
+ * @info: Pointer to property info container struct
+ * @is_active: New 'is active' status
+ */
+static inline
+void msm_property_set_is_active(struct msm_property_info *info, bool is_active)
+{
+ if (info) {
+ mutex_lock(&info->property_lock);
+ info->is_active = is_active;
+ mutex_unlock(&info->property_lock);
+ }
+}
+
+/**
+ * msm_property_get_is_active - query property 'is active' status
+ * @info: Pointer to property info container struct
+ * Returns: Current 'is active's status
+ */
+static inline
+bool msm_property_get_is_active(struct msm_property_info *info)
+{
+ bool rc = false;
+
+ if (info) {
+ mutex_lock(&info->property_lock);
+ rc = info->is_active;
+ mutex_unlock(&info->property_lock);
+ }
+
+ return rc;
+}
+
+/**
+ * msm_property_pop_dirty - determine next dirty property and clear
+ * its dirty flag
+ * @info: Pointer to property info container struct
+ * Returns: Valid msm property index on success,
+ * -EAGAIN if no dirty properties are available
+ * Property indicies returned from this function are similar
+ * to those returned by the msm_property_index function.
+ */
+int msm_property_pop_dirty(struct msm_property_info *info);
+
+/**
* msm_property_init - initialize property info structure
* @info: Pointer to property info container struct
* @base: Pointer to base drm object (plane/crtc/etc.)