summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c52
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h15
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h1
4 files changed, 71 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 28e8cbc2b049..d95068b13948 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -32,6 +32,7 @@ static void sde_connector_destroy(struct drm_connector *connector)
msm_property_destroy(&c_conn->property_info);
drm_connector_unregister(connector);
+ sde_fence_deinit(&c_conn->retire_fence);
drm_connector_cleanup(connector);
kfree(c_conn);
}
@@ -258,10 +259,12 @@ static int sde_connector_atomic_get_property(struct drm_connector *connector,
c_state = to_sde_connector_state(state);
idx = msm_property_index(&c_conn->property_info, property);
-
- /* get cached property value */
- rc = msm_property_atomic_get(&c_conn->property_info,
- c_state->property_values, 0, property, val);
+ if (idx == CONNECTOR_PROP_RETIRE_FENCE)
+ rc = sde_fence_create(&c_conn->retire_fence, val);
+ else
+ /* get cached property value */
+ rc = msm_property_atomic_get(&c_conn->property_info,
+ c_state->property_values, 0, property, val);
/* allow for custom override */
if (c_conn->ops.get_property)
@@ -273,6 +276,27 @@ static int sde_connector_atomic_get_property(struct drm_connector *connector,
return rc;
}
+void sde_connector_prepare_fence(struct drm_connector *connector)
+{
+ if (!connector) {
+ SDE_ERROR("invalid connector\n");
+ return;
+ }
+
+ sde_fence_prepare(&to_sde_connector(connector)->retire_fence);
+}
+
+void sde_connector_complete_commit(struct drm_connector *connector)
+{
+ if (!connector) {
+ SDE_ERROR("invalid connector\n");
+ return;
+ }
+
+ /* signal connector's retire fence */
+ sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
+}
+
static enum drm_connector_status
sde_connector_detect(struct drm_connector *connector, bool force)
{
@@ -429,10 +453,23 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
"conn%u",
c_conn->base.base.id);
+ /*
+ * Initialize retire fence support. Set fence offset to 0 for virtual
+ * connectors so that the fence signals at the end of the current commit
+ * and 1 for others so that the fence signals after one additional
+ * commit.
+ */
+ rc = sde_fence_init(dev, &c_conn->retire_fence, c_conn->name,
+ connector_type == DRM_MODE_CONNECTOR_VIRTUAL ? 0 : 1);
+ if (rc) {
+ SDE_ERROR("failed to init fence, %d\n", rc);
+ goto error_cleanup_conn;
+ }
+
rc = drm_connector_register(&c_conn->base);
if (rc) {
SDE_ERROR("failed to register drm connector, %d\n", rc);
- goto error_cleanup_conn;
+ goto error_cleanup_fence;
}
rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
@@ -476,6 +513,9 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
kfree(info);
}
+ msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
+ 0, ~0, ~0, CONNECTOR_PROP_RETIRE_FENCE);
+
rc = msm_property_install_get_status(&c_conn->property_info);
if (rc) {
SDE_ERROR("failed to create one or more properties\n");
@@ -492,6 +532,8 @@ error_destroy_property:
msm_property_destroy(&c_conn->property_info);
error_unregister_conn:
drm_connector_unregister(&c_conn->base);
+error_cleanup_fence:
+ sde_fence_deinit(&c_conn->retire_fence);
error_cleanup_conn:
drm_connector_cleanup(&c_conn->base);
error_free_conn:
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index a4dbc2e4a2df..3a848a5b190b 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -19,6 +19,7 @@
#include "msm_prop.h"
#include "sde_kms.h"
+#include "sde_fence.h"
#define SDE_CONNECTOR_NAME_SIZE 16
@@ -112,6 +113,7 @@ struct sde_connector_ops {
* @display: Pointer to private display data structure
* @mmu_id: MMU is for buffer mapping
* @name: ASCII name of connector
+ * @retire_fence: Retire fence reference
* @ops: Local callback function pointer table
* @property_info: Private structure for generic property handling
* @property_data: Array of private data for generic property handling
@@ -130,6 +132,7 @@ struct sde_connector {
char name[SDE_CONNECTOR_NAME_SIZE];
+ struct sde_fence retire_fence;
struct sde_connector_ops ops;
struct msm_property_info property_info;
@@ -236,5 +239,17 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
int connector_poll,
int connector_type);
+/**
+ * sde_connector_prepare_fence - prepare fence support for current commit
+ * @connector: Pointer to drm connector object
+ */
+void sde_connector_prepare_fence(struct drm_connector *connector);
+
+/**
+ * sde_connector_complete_commit - signal completion of current commit
+ * @connector: Pointer to drm connector object
+ */
+void sde_connector_complete_commit(struct drm_connector *connector);
+
#endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 76af87a7d1f0..fc20d8ea8b76 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -192,10 +192,14 @@ static void sde_complete_commit(struct msm_kms *kms,
struct sde_kms *sde_kms = to_sde_kms(kms);
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
int i;
for_each_crtc_in_state(state, crtc, crtc_state, i)
sde_crtc_complete_commit(crtc);
+ for_each_connector_in_state(state, connector, conn_state, i)
+ sde_connector_complete_commit(connector);
sde_disable(sde_kms);
MSM_EVT(sde_kms->dev, 0, 0);
@@ -212,10 +216,14 @@ static void sde_kms_prepare_fence(struct msm_kms *kms,
{
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
int i;
for_each_crtc_in_state(state, crtc, crtc_state, i)
sde_crtc_prepare_fence(crtc);
+ for_each_connector_in_state(state, connector, conn_state, i)
+ sde_connector_prepare_fence(connector);
}
static int modeset_init(struct sde_kms *sde_kms)
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 154edf3468b5..1b63d18bdbe2 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -20,6 +20,7 @@
#include "sde_hw_ctl.h"
#include "sde_hw_lm.h"
#include "sde_hw_interrupts.h"
+#include "sde_connector.h"
/**
* SDE_DEBUG - macro for kms/plane/crtc/encoder/connector logs