summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorClarence Ip <cip@codeaurora.org>2016-07-07 11:47:44 -0400
committerDhaval Patel <pdhaval@codeaurora.org>2016-08-01 12:35:42 -0700
commitfd7bfc2c6b4c2c866f5b9537d5663952ed68dabb (patch)
tree9acd573efe9151b3960c07896ec73d4936352c4a /drivers/gpu
parenta4df97f78979c15534e6b9b547afb6edcf967c00 (diff)
drm/msm/sde: add support for crtc properties
Move sync_fence_timeout property from plane to crtc, so that a common wait time can be applied to all planes selected for each crtc. Change-Id: I8108de8882667fad00df000073ddfc23202b15e0 Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h13
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c260
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.h31
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_plane.c12
5 files changed, 284 insertions, 41 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2efc584ad5d4..1e04a244297b 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -85,7 +85,6 @@ enum msm_mdp_plane_property {
PLANE_PROP_ALPHA,
PLANE_PROP_COLOR_FILL,
PLANE_PROP_SYNC_FENCE,
- PLANE_PROP_SYNC_FENCE_TIMEOUT,
/* enum/bitmask properties */
PLANE_PROP_ROTATION,
@@ -96,6 +95,17 @@ enum msm_mdp_plane_property {
PLANE_PROP_COUNT
};
+enum msm_mdp_crtc_property {
+ /* # of blob properties */
+ CRTC_PROP_BLOBCOUNT,
+
+ /* range properties */
+ CRTC_PROP_SYNC_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
+
+ /* total # of properties */
+ CRTC_PROP_COUNT
+};
+
struct msm_vblank_ctrl {
struct work_struct work;
struct list_head event_list;
@@ -173,6 +183,7 @@ struct msm_drm_private {
/* Properties */
struct drm_property *plane_property[PLANE_PROP_COUNT];
+ struct drm_property *crtc_property[CRTC_PROP_COUNT];
/* VRAM carveout, used when no IOMMU: */
struct {
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 25b0ac070460..89a8f31ca99c 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -130,7 +130,13 @@ static void sde_crtc_destroy(struct drm_crtc *crtc)
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
DBG("");
+
+ if (!crtc)
+ return;
+
+ msm_property_destroy(&sde_crtc->property_info);
debugfs_remove_recursive(sde_crtc->debugfs_root);
+
drm_crtc_cleanup(crtc);
kfree(sde_crtc);
}
@@ -523,10 +529,103 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
}
}
-static int sde_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
+/**
+ * sde_crtc_destroy_state - state destroy hook
+ * @crtc: drm CRTC
+ * @state: CRTC state object to release
+ */
+static void sde_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+
+ if (!crtc || !state) {
+ DRM_ERROR("invalid argument(s)\n");
+ return;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+
+ DBG("");
+
+ __drm_atomic_helper_crtc_destroy_state(crtc, state);
+
+ /* destroy value helper */
+ msm_property_destroy_state(&sde_crtc->property_info, cstate,
+ cstate->property_values, cstate->property_blobs);
+}
+
+/**
+ * sde_crtc_duplicate_state - state duplicate hook
+ * @crtc: Pointer to drm crtc structure
+ * @Returns: Pointer to new drm_crtc_state structure
+ */
+static struct drm_crtc_state *sde_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate, *old_cstate;
+
+ if (!crtc || !crtc->state) {
+ DRM_ERROR("invalid argument(s)\n");
+ return NULL;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ old_cstate = to_sde_crtc_state(crtc->state);
+ cstate = msm_property_alloc_state(&sde_crtc->property_info);
+ if (!cstate) {
+ DRM_ERROR("failed to allocate state\n");
+ return NULL;
+ }
+
+ /* duplicate value helper */
+ msm_property_duplicate_state(&sde_crtc->property_info,
+ old_cstate, cstate,
+ cstate->property_values, cstate->property_blobs);
+
+ /* duplicate base helper */
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);
+
+ return &cstate->base;
+}
+
+/**
+ * sde_crtc_reset - reset hook for CRTCs
+ * Resets the atomic state for @crtc by freeing the state pointer (which might
+ * be NULL, e.g. at driver load time) and allocating a new empty state object.
+ * @crtc: Pointer to drm crtc structure
+ */
+static void sde_crtc_reset(struct drm_crtc *crtc)
{
- return -EINVAL;
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+
+ if (!crtc) {
+ DRM_ERROR("invalid crtc\n");
+ return;
+ }
+
+ /* remove previous state, if present */
+ if (crtc->state) {
+ sde_crtc_destroy_state(crtc, crtc->state);
+ crtc->state = 0;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = msm_property_alloc_state(&sde_crtc->property_info);
+ if (!cstate) {
+ DRM_ERROR("failed to allocate state\n");
+ return;
+ }
+
+ /* reset value helper */
+ msm_property_reset_state(&sde_crtc->property_info, cstate,
+ cstate->property_values, cstate->property_blobs);
+
+ cstate->base.crtc = crtc;
+ crtc->state = &cstate->base;
}
static int sde_crtc_cursor_set(struct drm_crtc *crtc,
@@ -665,28 +764,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
}
-static const struct drm_crtc_funcs sde_crtc_funcs = {
- .set_config = drm_atomic_helper_set_config,
- .destroy = sde_crtc_destroy,
- .page_flip = drm_atomic_helper_page_flip,
- .set_property = sde_crtc_set_property,
- .reset = drm_atomic_helper_crtc_reset,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
- .cursor_set = sde_crtc_cursor_set,
- .cursor_move = sde_crtc_cursor_move,
-};
-
-static const struct drm_crtc_helper_funcs sde_crtc_helper_funcs = {
- .mode_fixup = sde_crtc_mode_fixup,
- .mode_set_nofb = sde_crtc_mode_set_nofb,
- .disable = sde_crtc_disable,
- .enable = sde_crtc_enable,
- .atomic_check = sde_crtc_atomic_check,
- .atomic_begin = sde_crtc_atomic_begin,
- .atomic_flush = sde_crtc_atomic_flush,
-};
-
int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
{
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -715,9 +792,104 @@ void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
{
}
-static void sde_crtc_install_properties(struct drm_crtc *crtc,
- struct drm_mode_object *obj)
+/**
+ * sde_crtc_install_properties - install all drm properties for crtc
+ * @crtc: Pointer to drm crtc structure
+ */
+static void sde_crtc_install_properties(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc;
+ struct drm_device *dev;
+
+ DBG("");
+
+ if (!crtc) {
+ DRM_ERROR("invalid crtc\n");
+ return;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ dev = crtc->dev;
+
+ /* range properties */
+ msm_property_install_range(&sde_crtc->property_info,
+ "sync_fence_timeout", 0, ~0, 10000,
+ CRTC_PROP_SYNC_FENCE_TIMEOUT);
+}
+
+/**
+ * sde_crtc_atomic_set_property - atomically set a crtc drm property
+ * @crtc: Pointer to drm crtc structure
+ * @state: Pointer to drm crtc state structure
+ * @property: Pointer to targeted drm property
+ * @val: Updated property value
+ * @Returns: Zero on success
+ */
+static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
+ struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+ int ret = -EINVAL;
+
+ if (!crtc || !state || !property) {
+ DRM_ERROR("invalid argument(s)\n");
+ } else {
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+ ret = msm_property_atomic_set(&sde_crtc->property_info,
+ cstate->property_values, cstate->property_blobs,
+ property, val);
+ }
+
+ return ret;
+}
+
+/**
+ * sde_crtc_set_property - set a crtc drm property
+ * @crtc: Pointer to drm crtc structure
+ * @property: Pointer to targeted drm property
+ * @val: Updated property value
+ * @Returns: Zero on success
+ */
+static int sde_crtc_set_property(struct drm_crtc *crtc,
+ struct drm_property *property, uint64_t val)
{
+ DBG("");
+
+ return sde_crtc_atomic_set_property(crtc, crtc->state, property, val);
+}
+
+/**
+ * sde_crtc_atomic_get_property - retrieve a crtc drm property
+ * @crtc: Pointer to drm crtc structure
+ * @state: Pointer to drm crtc state structure
+ * @property: Pointer to targeted drm property
+ * @val: Pointer to variable for receiving property value
+ * @Returns: Zero on success
+ */
+static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
+ const struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+ int ret = -EINVAL;
+
+ if (!crtc || !state) {
+ DRM_ERROR("invalid argument(s)\n");
+ } else {
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+ ret = msm_property_atomic_get(&sde_crtc->property_info,
+ cstate->property_values, cstate->property_blobs,
+ property, val);
+ }
+
+ return ret;
}
static int _sde_debugfs_mixer_read(struct seq_file *s, void *data)
@@ -761,6 +933,30 @@ static int _sde_debugfs_mixer_open(struct inode *inode, struct file *file)
return single_open(file, _sde_debugfs_mixer_read, inode->i_private);
}
+static const struct drm_crtc_funcs sde_crtc_funcs = {
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = sde_crtc_destroy,
+ .page_flip = drm_atomic_helper_page_flip,
+ .set_property = sde_crtc_set_property,
+ .atomic_set_property = sde_crtc_atomic_set_property,
+ .atomic_get_property = sde_crtc_atomic_get_property,
+ .reset = sde_crtc_reset,
+ .atomic_duplicate_state = sde_crtc_duplicate_state,
+ .atomic_destroy_state = sde_crtc_destroy_state,
+ .cursor_set = sde_crtc_cursor_set,
+ .cursor_move = sde_crtc_cursor_move,
+};
+
+static const struct drm_crtc_helper_funcs sde_crtc_helper_funcs = {
+ .mode_fixup = sde_crtc_mode_fixup,
+ .mode_set_nofb = sde_crtc_mode_set_nofb,
+ .disable = sde_crtc_disable,
+ .enable = sde_crtc_enable,
+ .atomic_check = sde_crtc_atomic_check,
+ .atomic_begin = sde_crtc_atomic_begin,
+ .atomic_flush = sde_crtc_atomic_flush,
+};
+
static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc,
struct sde_kms *sde_kms)
{
@@ -809,8 +1005,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev,
sde_crtc->encoder = encoder;
spin_lock_init(&sde_crtc->lm_lock);
- sde_crtc_install_properties(crtc, &crtc->base);
-
drm_crtc_init_with_planes(dev, crtc, plane, NULL, &sde_crtc_funcs);
drm_crtc_helper_add(crtc, &sde_crtc_helper_funcs);
@@ -827,6 +1021,14 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev,
_sde_crtc_init_debugfs(sde_crtc, kms);
+ /* create CRTC properties */
+ msm_property_init(&sde_crtc->property_info, &crtc->base, dev,
+ priv->crtc_property, sde_crtc->property_data,
+ CRTC_PROP_COUNT, CRTC_PROP_BLOBCOUNT,
+ sizeof(struct sde_crtc_state));
+
+ sde_crtc_install_properties(crtc);
+
DBG("%s: Successfully initialized crtc", sde_crtc->name);
return crtc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index aaad9588bdb0..c069befbf5ad 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -14,6 +14,8 @@
#define _SDE_CRTC_H_
#include "drm_crtc.h"
+#include "msm_prop.h"
+#include "sde_kms.h"
#define CRTC_DUAL_MIXERS 2
#define SDE_CRTC_NAME_SIZE 12
@@ -54,6 +56,8 @@ struct sde_crtc_mixer {
* @pending : Whether or not an update is pending
* @vsync_count : Running count of received vsync events
* @drm_requested_vblank : Whether vblanks have been enabled in the encoder
+ * @property_info : Opaque structure for generic property support
+ * @property_defaults : Array of default values for generic property support
* @stage_cfg : H/w mixer stage configuration
* @debugfs_root : Parent of debugfs node
*/
@@ -76,10 +80,37 @@ struct sde_crtc {
u32 vsync_count;
bool drm_requested_vblank;
+ struct msm_property_info property_info;
+ struct msm_property_data property_data[CRTC_PROP_COUNT];
+
struct sde_hw_stage_cfg stage_cfg;
struct dentry *debugfs_root;
};
#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
+/**
+ * struct sde_crtc_state - sde container for atomic crtc state
+ * @base: Base drm crtc state structure
+ * @property_values: Current crtc property values
+ * @property_blobs: Reference pointers for blob properties
+ */
+struct sde_crtc_state {
+ struct drm_crtc_state base;
+ uint64_t property_values[CRTC_PROP_COUNT];
+ struct drm_property_blob *property_blobs[CRTC_PROP_COUNT];
+};
+
+#define to_sde_crtc_state(x) \
+ container_of(x, struct sde_crtc_state, base)
+
+/**
+ * sde_crtc_get_property - query integer value of crtc property
+ * @S: Pointer to crtc state
+ * @X: Property index, from enum msm_mdp_crtc_property
+ * Returns: Integer value of requested property
+ */
+#define sde_crtc_get_property(S, X) \
+ ((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)]) : 0)
+
#endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 915732ed9bca..afb0444a05b7 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -376,7 +376,14 @@ enum sde_sspp sde_plane_pipe(struct drm_plane *plane);
void sde_plane_complete_flip(struct drm_plane *plane);
struct drm_plane *sde_plane_init(struct drm_device *dev,
uint32_t pipe, bool primary_plane);
-int sde_plane_wait_sync_fence(struct drm_plane *plane);
+
+/**
+ * sde_plane_wait_sync_fence - wait for sync fence object
+ * @plane: Pointer to DRM plane object
+ * @wait_ms: Wait timeout value
+ * Returns: Zero on success
+ */
+int sde_plane_wait_sync_fence(struct drm_plane *plane, uint32_t wait_ms);
/**
* sde_plane_color_fill(): Enables color fill on plane
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 7ce0d0fa9a2f..487078043d64 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -89,11 +89,10 @@ static void _sde_plane_update_sync_fence(struct drm_plane *plane,
DBG("0x%llX", fd);
}
-int sde_plane_wait_sync_fence(struct drm_plane *plane)
+int sde_plane_wait_sync_fence(struct drm_plane *plane, uint32_t wait_ms)
{
struct sde_plane_state *pstate;
void *sync_fence;
- long wait_ms;
int ret = -EINVAL;
if (!plane) {
@@ -105,11 +104,8 @@ int sde_plane_wait_sync_fence(struct drm_plane *plane)
sync_fence = pstate->sync_fence;
if (sync_fence) {
- wait_ms = (long)sde_plane_get_property(pstate,
- PLANE_PROP_SYNC_FENCE_TIMEOUT);
-
DBG("%s", to_sde_plane(plane)->pipe_name);
- ret = sde_sync_wait(sync_fence, wait_ms);
+ ret = sde_sync_wait(sync_fence, (long)wait_ms);
if (!ret)
DBG("signaled");
else if (ret == -ETIME)
@@ -1091,10 +1087,6 @@ static void _sde_plane_install_properties(struct drm_plane *plane)
msm_property_install_range(&psde->property_info, "sync_fence",
0, ~0, ~0, PLANE_PROP_SYNC_FENCE);
- msm_property_install_range(&psde->property_info, "sync_fence_timeout",
- 0, ~0, 10000,
- PLANE_PROP_SYNC_FENCE_TIMEOUT);
-
/* standard properties */
msm_property_install_rotation(&psde->property_info,
BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y),