Merge "drm/msm/sde: set correct timeline at fence create"
This commit is contained in:
commit
e2a34f151c
2 changed files with 126 additions and 48 deletions
|
@ -428,6 +428,7 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
||||||
struct sde_connector *c_conn;
|
struct sde_connector *c_conn;
|
||||||
struct sde_connector_state *c_state;
|
struct sde_connector_state *c_state;
|
||||||
int idx, rc;
|
int idx, rc;
|
||||||
|
uint64_t fence_fd = 0;
|
||||||
|
|
||||||
if (!connector || !state || !property) {
|
if (!connector || !state || !property) {
|
||||||
SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
|
SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
|
||||||
|
@ -472,6 +473,29 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
||||||
SDE_ERROR("prep fb failed, %d\n", rc);
|
SDE_ERROR("prep fb failed, %d\n", rc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CONNECTOR_PROP_RETIRE_FENCE:
|
||||||
|
if (!val)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update the the offset to a timeline for commit completion
|
||||||
|
*/
|
||||||
|
rc = sde_fence_create(&c_conn->retire_fence, &fence_fd, 1);
|
||||||
|
if (rc) {
|
||||||
|
SDE_ERROR("fence create failed rc:%d\n", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = copy_to_user((uint64_t __user *)val, &fence_fd,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
if (rc) {
|
||||||
|
SDE_ERROR("copy to user failed rc:%d\n", rc);
|
||||||
|
/* fence will be released with timeline update */
|
||||||
|
put_unused_fd(fence_fd);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CONNECTOR_PROP_TOPOLOGY_CONTROL:
|
case CONNECTOR_PROP_TOPOLOGY_CONTROL:
|
||||||
rc = sde_rm_check_property_topctl(val);
|
rc = sde_rm_check_property_topctl(val);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -544,12 +568,14 @@ static int sde_connector_atomic_get_property(struct drm_connector *connector,
|
||||||
c_state = to_sde_connector_state(state);
|
c_state = to_sde_connector_state(state);
|
||||||
|
|
||||||
idx = msm_property_index(&c_conn->property_info, property);
|
idx = msm_property_index(&c_conn->property_info, property);
|
||||||
if (idx == CONNECTOR_PROP_RETIRE_FENCE)
|
if (idx == CONNECTOR_PROP_RETIRE_FENCE) {
|
||||||
rc = sde_fence_create(&c_conn->retire_fence, val, 0);
|
*val = ~0;
|
||||||
else
|
rc = 0;
|
||||||
|
} else {
|
||||||
/* get cached property value */
|
/* get cached property value */
|
||||||
rc = msm_property_atomic_get(&c_conn->property_info,
|
rc = msm_property_atomic_get(&c_conn->property_info,
|
||||||
c_state->property_values, 0, property, val);
|
c_state->property_values, 0, property, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* allow for custom override */
|
/* allow for custom override */
|
||||||
if (c_conn->ops.get_property)
|
if (c_conn->ops.get_property)
|
||||||
|
@ -931,8 +957,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
|
||||||
"hdr_control", 0x0, 0, ~0, 0,
|
"hdr_control", 0x0, 0, ~0, 0,
|
||||||
CONNECTOR_PROP_HDR_CONTROL);
|
CONNECTOR_PROP_HDR_CONTROL);
|
||||||
|
|
||||||
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
|
msm_property_install_volatile_range(&c_conn->property_info,
|
||||||
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
|
"RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE);
|
||||||
|
|
||||||
msm_property_install_volatile_signed_range(&c_conn->property_info,
|
msm_property_install_volatile_signed_range(&c_conn->property_info,
|
||||||
"PLL_DELTA", 0x0, INT_MIN, INT_MAX, 0,
|
"PLL_DELTA", 0x0, INT_MIN, INT_MAX, 0,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
|
@ -1642,8 +1642,8 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
|
||||||
"input_fence_timeout", 0x0, 0, SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT,
|
"input_fence_timeout", 0x0, 0, SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT,
|
||||||
SDE_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
|
SDE_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
|
||||||
|
|
||||||
msm_property_install_range(&sde_crtc->property_info, "output_fence",
|
msm_property_install_volatile_range(&sde_crtc->property_info,
|
||||||
0x0, 0, INR_OPEN_MAX, 0x0, CRTC_PROP_OUTPUT_FENCE);
|
"output_fence", 0x0, 0, ~0, 0, CRTC_PROP_OUTPUT_FENCE);
|
||||||
|
|
||||||
msm_property_install_range(&sde_crtc->property_info,
|
msm_property_install_range(&sde_crtc->property_info,
|
||||||
"output_fence_offset", 0x0, 0, 1, 0,
|
"output_fence_offset", 0x0, 0, 1, 0,
|
||||||
|
@ -1708,6 +1708,28 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
|
||||||
kfree(info);
|
kfree(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
||||||
|
const struct drm_crtc_state *state, uint64_t *val)
|
||||||
|
{
|
||||||
|
struct sde_crtc *sde_crtc;
|
||||||
|
struct sde_crtc_state *cstate;
|
||||||
|
uint32_t offset;
|
||||||
|
|
||||||
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
|
cstate = to_sde_crtc_state(state);
|
||||||
|
|
||||||
|
offset = sde_crtc_get_property(cstate, CRTC_PROP_OUTPUT_FENCE_OFFSET);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hwcomposer now queries the fences using the commit list in atomic
|
||||||
|
* commit ioctl. The offset should be set to next timeline
|
||||||
|
* which will be incremented during the prepare commit phase
|
||||||
|
*/
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
return sde_fence_create(&sde_crtc->output_fence, val, offset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_crtc_atomic_set_property - atomically set a crtc drm property
|
* sde_crtc_atomic_set_property - atomically set a crtc drm property
|
||||||
* @crtc: Pointer to drm crtc structure
|
* @crtc: Pointer to drm crtc structure
|
||||||
|
@ -1724,27 +1746,60 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
|
||||||
struct sde_crtc *sde_crtc;
|
struct sde_crtc *sde_crtc;
|
||||||
struct sde_crtc_state *cstate;
|
struct sde_crtc_state *cstate;
|
||||||
int idx, ret = -EINVAL;
|
int idx, ret = -EINVAL;
|
||||||
|
uint64_t fence_fd = 0;
|
||||||
|
|
||||||
if (!crtc || !state || !property) {
|
if (!crtc || !state || !property) {
|
||||||
SDE_ERROR("invalid argument(s)\n");
|
SDE_ERROR("invalid argument(s)\n");
|
||||||
} else {
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
sde_crtc = to_sde_crtc(crtc);
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
cstate = to_sde_crtc_state(state);
|
cstate = to_sde_crtc_state(state);
|
||||||
|
|
||||||
ret = msm_property_atomic_set(&sde_crtc->property_info,
|
ret = msm_property_atomic_set(&sde_crtc->property_info,
|
||||||
cstate->property_values, cstate->property_blobs,
|
cstate->property_values, cstate->property_blobs,
|
||||||
property, val);
|
property, val);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
idx = msm_property_index(&sde_crtc->property_info,
|
idx = msm_property_index(&sde_crtc->property_info,
|
||||||
property);
|
property);
|
||||||
if (idx == CRTC_PROP_INPUT_FENCE_TIMEOUT)
|
switch (idx) {
|
||||||
|
case CRTC_PROP_INPUT_FENCE_TIMEOUT:
|
||||||
_sde_crtc_set_input_fence_timeout(cstate);
|
_sde_crtc_set_input_fence_timeout(cstate);
|
||||||
|
break;
|
||||||
|
case CRTC_PROP_OUTPUT_FENCE:
|
||||||
|
if (!val)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ret = _sde_crtc_get_output_fence(crtc,
|
||||||
|
state, &fence_fd);
|
||||||
|
if (ret) {
|
||||||
|
SDE_ERROR("fence create failed rc:%d\n", ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = copy_to_user((uint64_t __user *)val, &fence_fd,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
SDE_ERROR("copy to user failed rc:%d\n", ret);
|
||||||
|
put_unused_fd(fence_fd);
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* nothing to do */
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = sde_cp_crtc_set_property(crtc,
|
ret = sde_cp_crtc_set_property(crtc,
|
||||||
property, val);
|
property, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
if (ret)
|
if (ret)
|
||||||
DRM_ERROR("failed to set the property\n");
|
DRM_ERROR("failed to set the property\n");
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1783,19 +1838,16 @@ static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
|
||||||
|
|
||||||
if (!crtc || !state) {
|
if (!crtc || !state) {
|
||||||
SDE_ERROR("invalid argument(s)\n");
|
SDE_ERROR("invalid argument(s)\n");
|
||||||
} else {
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
sde_crtc = to_sde_crtc(crtc);
|
sde_crtc = to_sde_crtc(crtc);
|
||||||
cstate = to_sde_crtc_state(state);
|
cstate = to_sde_crtc_state(state);
|
||||||
|
|
||||||
i = msm_property_index(&sde_crtc->property_info, property);
|
i = msm_property_index(&sde_crtc->property_info, property);
|
||||||
if (i == CRTC_PROP_OUTPUT_FENCE) {
|
if (i == CRTC_PROP_OUTPUT_FENCE) {
|
||||||
int offset = sde_crtc_get_property(cstate,
|
*val = ~0;
|
||||||
CRTC_PROP_OUTPUT_FENCE_OFFSET);
|
ret = 0;
|
||||||
|
|
||||||
ret = sde_fence_create(&sde_crtc->output_fence, val,
|
|
||||||
offset);
|
|
||||||
if (ret)
|
|
||||||
SDE_ERROR("fence create failed\n");
|
|
||||||
} else {
|
} else {
|
||||||
ret = msm_property_atomic_get(&sde_crtc->property_info,
|
ret = msm_property_atomic_get(&sde_crtc->property_info,
|
||||||
cstate->property_values,
|
cstate->property_values,
|
||||||
|
@ -1806,7 +1858,7 @@ static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
DRM_ERROR("get property failed\n");
|
DRM_ERROR("get property failed\n");
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue