From 53e624146767ee9ba6e84d3b25f6e75b0012a1e3 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 26 Jun 2017 21:59:30 -0700 Subject: [PATCH] drm/msm/sde: add sde_connector kickoff callbacks Add a callback into the connector framework to allow sending per-frame parameters at kickoff time. This is needed to support the HDR feature where the HDR metadata shall be sent to the sink on a per-frame basis. Change-Id: I48a3616509e2226ea9bf0f490f0f47873ca74781 Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 7 +++++ drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h | 11 ++++++++ drivers/gpu/drm/msm/msm_drv.h | 8 ++++++ drivers/gpu/drm/msm/sde/sde_connector.c | 30 +++++++++++++++++++++ drivers/gpu/drm/msm/sde/sde_connector.h | 20 ++++++++++++++ drivers/gpu/drm/msm/sde/sde_encoder.c | 9 +++++++ drivers/gpu/drm/msm/sde/sde_kms.c | 1 + 7 files changed, 86 insertions(+) diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index d0c3deefabd7..8e60235bfa01 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -2203,6 +2203,13 @@ sde_hdmi_connector_detect(struct drm_connector *connector, return status; } +int sde_hdmi_pre_kickoff(struct drm_connector *connector, + void *display, + struct msm_display_kickoff_params *params) +{ + return 0; +} + int sde_hdmi_connector_get_modes(struct drm_connector *connector, void *display) { struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display; diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index 47f440d617a3..6b9bcfec031b 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -452,6 +452,17 @@ bool sde_hdmi_tx_is_panel_on(struct sde_hdmi *hdmi_ctrl); int sde_hdmi_start_hdcp(struct drm_connector *connector); void sde_hdmi_hdcp_off(struct sde_hdmi *hdmi_ctrl); + +/* + * sde_hdmi_pre_kickoff - program kickoff-time features + * @display: Pointer to private display structure + * @params: Parameters for kickoff-time programming + * Returns: Zero on success + */ +int sde_hdmi_pre_kickoff(struct drm_connector *connector, + void *display, + struct msm_display_kickoff_params *params); + #else /*#ifdef CONFIG_DRM_SDE_HDMI*/ static inline u32 sde_hdmi_get_num_of_displays(void) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 209e90628642..d696f05e0459 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -235,6 +235,14 @@ struct msm_display_info { enum msm_display_compression compression; }; +/** + * struct - msm_display_kickoff_params - info for display features at kickoff + * @hdr_metadata: HDR metadata info passed from userspace + */ +struct msm_display_kickoff_params { + struct drm_msm_ext_panel_hdr_metadata *hdr_metadata; +}; + /** * 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 cf84700d7592..0bb8298c1013 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -60,6 +60,36 @@ int sde_connector_get_info(struct drm_connector *connector, 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.hdr_metadata = &c_state->hdr_meta; + + 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 885f3cf94864..19e2b8a3e41c 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -122,6 +122,19 @@ struct sde_connector_ops { int (*get_info)(struct msm_display_info *info, void *display); int (*set_backlight)(void *display, u32 bl_lvl); + + + /** + * 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); }; /** @@ -307,5 +320,12 @@ void sde_connector_complete_commit(struct drm_connector *connector); int sde_connector_get_info(struct drm_connector *connector, struct msm_display_info *info); +/** + * 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 030b192e5df4..fa03fc8f7ac9 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -795,6 +795,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; unsigned int i; + int rc; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); @@ -811,6 +812,14 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) if (phys && phys->ops.prepare_for_kickoff) phys->ops.prepare_for_kickoff(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 a240ed08da89..031493aa42b8 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -602,6 +602,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_info = sde_hdmi_get_info, .set_property = sde_hdmi_set_property, .get_property = sde_hdmi_get_property, + .pre_kickoff = sde_hdmi_pre_kickoff, }; struct msm_display_info info = {0}; struct drm_encoder *encoder;