drm/msm/sde: add sde_connector kickoff trigger callbacks
Add a callback into the connector framework to allow sending
per-frame parameters at kickoff time. Specifically, this is
needed to support the partial update feature where only a subset
region of interest is updated on the display.
Change-Id: I4a6982a33110e5b114a60b92926d43c8aced950d
Signed-off-by: Lloyd Atkinson <latkinso@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index bcaf428..610d0f6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -3027,6 +3027,12 @@
return rc;
}
+int dsi_display_pre_kickoff(struct dsi_display *display,
+ struct msm_display_kickoff_params *params)
+{
+ return 0;
+}
+
int dsi_display_enable(struct dsi_display *display)
{
int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index cfbb14ec..d2bc7d8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -417,4 +417,14 @@
* Return: error code
*/
int dsi_display_soft_reset(void *display);
+
+/*
+ * dsi_display_pre_kickoff - program kickoff-time features
+ * @display: Pointer to private display structure
+ * @params: Parameters for kickoff-time programming
+ * Returns: Zero on success
+ */
+int dsi_display_pre_kickoff(struct dsi_display *display,
+ struct msm_display_kickoff_params *params);
+
#endif /* _DSI_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 24a740b..556c0d8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -475,6 +475,18 @@
return MODE_OK;
}
+int dsi_conn_pre_kickoff(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params)
+{
+ if (!connector || !display || !params) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ return dsi_display_pre_kickoff(display, params);
+}
+
struct dsi_bridge *dsi_drm_bridge_init(struct dsi_display *display,
struct drm_device *dev,
struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
index 934899b..4339a11 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -80,4 +80,15 @@
void dsi_drm_bridge_cleanup(struct dsi_bridge *bridge);
+/**
+ * dsi_display_pre_kickoff - program kickoff-time features
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display structure
+ * @params: Parameters for kickoff-time programming
+ * Returns: Zero on success
+ */
+int dsi_conn_pre_kickoff(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params);
+
#endif /* _DSI_DRM_H_ */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index da76fbc..4b263d3 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -363,6 +363,29 @@
struct msm_compression_info comp_info;
};
+#define MSM_MAX_ROI 4
+
+/**
+ * struct msm_roi_mapping - Regions of interest structure for mapping CRTC to
+ * Connector output
+ * @num_rects: number of valid rectangles in src and dst arrays
+ * @src: source roi rectangle
+ * @dst: destination roi rectangle
+ */
+struct msm_roi_mapping {
+ uint32_t num_rects;
+ struct drm_clip_rect src[MSM_MAX_ROI];
+ struct drm_clip_rect dst[MSM_MAX_ROI];
+};
+
+/**
+ * struct - msm_display_kickoff_params - info for display features at kickoff
+ * @rois: Regions of interest structure for mapping CRTC to Connector output
+ */
+struct msm_display_kickoff_params {
+ struct msm_roi_mapping *rois;
+};
+
/**
* struct msm_drm_event - defines custom event notification struct
* @base: base object required for event notification by DRM framework.
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 1f39180..6e793d9 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -215,6 +215,38 @@
return c_conn->ops.get_info(info, c_conn->display);
}
+int sde_connector_pre_kickoff(struct drm_connector *connector)
+{
+ struct sde_connector *c_conn;
+ struct sde_connector_state *c_state;
+ struct msm_display_kickoff_params params;
+ int rc;
+
+ if (!connector) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ c_conn = to_sde_connector(connector);
+ c_state = to_sde_connector_state(connector->state);
+
+ if (!c_conn->display) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ if (!c_conn->ops.pre_kickoff)
+ return 0;
+
+ params.rois = &c_state->rois;
+
+ SDE_EVT32_VERBOSE(connector->base.id);
+
+ rc = c_conn->ops.pre_kickoff(connector, c_conn->display, ¶ms);
+
+ return rc;
+}
+
static void sde_connector_destroy(struct drm_connector *connector)
{
struct sde_connector *c_conn;
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 9d36851..70d4952 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -138,6 +138,18 @@
* Return: Zero on success, -ERROR otherwise
*/
int (*soft_reset)(void *display);
+
+ /**
+ * pre_kickoff - trigger display to program kickoff-time features
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display structure
+ * @params: Parameter bundle of connector-stored information for
+ * kickoff-time programming into the display
+ * Returns: Zero on success
+ */
+ int (*pre_kickoff)(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params);
};
/**
@@ -253,12 +265,15 @@
* @out_fb: Pointer to output frame buffer, if applicable
* @mmu_id: MMU ID for accessing frame buffer objects, if applicable
* @property_values: Local cache of current connector property values
+ * @rois: Regions of interest structure for mapping CRTC to Connector output
*/
struct sde_connector_state {
struct drm_connector_state base;
struct drm_framebuffer *out_fb;
int mmu_id;
uint64_t property_values[CONNECTOR_PROP_COUNT];
+
+ struct msm_roi_mapping rois;
};
/**
@@ -403,5 +418,12 @@
int sde_connector_register_custom_event(struct sde_kms *kms,
struct drm_connector *conn_drm, u32 event, bool en);
+/**
+ * sde_connector_pre_kickoff - trigger kickoff time feature programming
+ * @connector: Pointer to drm connector object
+ * Returns: Zero on success
+ */
+int sde_connector_pre_kickoff(struct drm_connector *connector);
+
#endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 20d5e52..04e6b13 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1241,6 +1241,7 @@
struct sde_encoder_phys *phys;
bool needs_hw_reset = false;
unsigned int i;
+ int rc;
if (!drm_enc) {
SDE_ERROR("invalid encoder\n");
@@ -1270,6 +1271,14 @@
phys->ops.hw_reset(phys);
}
}
+
+ if (sde_enc->cur_master && sde_enc->cur_master->connector) {
+ rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
+ if (rc)
+ SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
+ sde_enc->cur_master->connector->base.id,
+ rc);
+ }
}
void sde_encoder_kickoff(struct drm_encoder *drm_enc)
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 7e18a0e..bce494b 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -549,7 +549,8 @@
.mode_valid = dsi_conn_mode_valid,
.get_info = dsi_display_get_info,
.set_backlight = dsi_display_set_backlight,
- .soft_reset = dsi_display_soft_reset
+ .soft_reset = dsi_display_soft_reset,
+ .pre_kickoff = dsi_conn_pre_kickoff
};
static const struct sde_connector_ops wb_ops = {
.post_init = sde_wb_connector_post_init,