diff options
| author | Clarence Ip <cip@codeaurora.org> | 2016-07-07 11:47:44 -0400 |
|---|---|---|
| committer | Dhaval Patel <pdhaval@codeaurora.org> | 2016-08-01 12:35:42 -0700 |
| commit | fd7bfc2c6b4c2c866f5b9537d5663952ed68dabb (patch) | |
| tree | 9acd573efe9151b3960c07896ec73d4936352c4a /drivers/gpu | |
| parent | a4df97f78979c15534e6b9b547afb6edcf967c00 (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.h | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_crtc.c | 260 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_crtc.h | 31 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_plane.c | 12 |
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), |
