In order to pass AVI infoframes to LSPCON devices, a source has to write them in a vendor recommended method and location. This patch series: - adds generic LSPCON infoframe setup functions. - registers these functions into existing AVI infoframe framework. - triggers these functions from modeset sequence. Next patches in the series will add vendor specific code. Signed-off-by: Shashank Sharma <shashank.sharma@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_ddi.c | 16 ++++++++--- drivers/gpu/drm/i915/intel_dp.c | 8 +++++- drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++- drivers/gpu/drm/i915/intel_hdmi.c | 13 ++++++--- drivers/gpu/drm/i915/intel_lspcon.c | 53 +++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index ace674c..9e2ab02 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2231,10 +2231,19 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { intel_ddi_pre_enable_hdmi(encoder, crtc_state, conn_state); - else + } else { intel_ddi_pre_enable_dp(encoder, crtc_state, conn_state); + if (crtc_state->lspcon_active) { + struct intel_digital_port *dig_port = + enc_to_dig_port(&encoder->base); + + dig_port->set_infoframes(&encoder->base, + crtc_state->has_infoframe, + crtc_state, conn_state); + } + } } static void intel_disable_ddi_buf(struct intel_encoder *encoder) @@ -2886,8 +2895,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; - intel_infoframe_init(intel_dig_port); - if (init_dp) { if (!intel_ddi_init_dp_connector(intel_dig_port)) goto err; @@ -2917,6 +2924,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) port_name(port)); } + intel_infoframe_init(intel_dig_port); return; err: diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d27c014..fa9e5e6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1633,7 +1633,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - enum port port = dp_to_dig_port(intel_dp)->port; + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + enum port port = dig_port->port; + struct intel_lspcon *lspcon = &dig_port->lspcon; struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); struct intel_connector *intel_connector = intel_dp->attached_connector; struct intel_digital_connector_state *intel_conn_state = @@ -1654,6 +1656,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, common_len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->max_link_rate); + /* LSPCON needs special handling to drive YCBCR420 outputs */ + if (lspcon->active) + pipe_config->lspcon_active = true; + /* No common link rates between source and sink */ WARN_ON(common_len <= 0); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0741494..a7c1c19 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -798,6 +798,9 @@ struct intel_crtc_state { /* output format is YCBCR 4:2:0 */ bool ycbcr420; + + /* LSPCON is active on port */ + bool lspcon_active; }; struct intel_crtc { @@ -1184,6 +1187,12 @@ static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder) return &enc_to_dig_port(encoder)->dp; } +static inline struct intel_lspcon * +enc_to_intel_lspcon(struct drm_encoder *encoder) +{ + return &enc_to_dig_port(encoder)->lspcon; +} + static inline struct intel_digital_port * dp_to_dig_port(struct intel_dp *intel_dp) { @@ -1696,7 +1705,6 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder, void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); void intel_infoframe_init(struct intel_digital_port *intel_dig_port); - /* intel_lvds.c */ void intel_lvds_init(struct drm_i915_private *dev_priv); struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev); @@ -2029,6 +2037,12 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state); bool lspcon_init(struct intel_digital_port *intel_dig_port); void lspcon_resume(struct intel_lspcon *lspcon); void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); +void lspcon_set_infoframes(struct drm_encoder *encoder, + bool enable, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +bool lspcon_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config); /* intel_pipe_crc.c */ int intel_pipe_crc_create(struct drm_minor *minor); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index fa1c793..023015c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1994,9 +1994,16 @@ void intel_infoframe_init(struct intel_digital_port *intel_dig_port) intel_dig_port->set_infoframes = g4x_set_infoframes; intel_dig_port->infoframe_enabled = g4x_infoframe_enabled; } else if (HAS_DDI(dev_priv)) { - intel_dig_port->write_infoframe = hsw_write_infoframe; - intel_dig_port->set_infoframes = hsw_set_infoframes; - intel_dig_port->infoframe_enabled = hsw_infoframe_enabled; + if (intel_dig_port->lspcon.active) { + intel_dig_port->set_infoframes = lspcon_set_infoframes; + intel_dig_port->infoframe_enabled = + lspcon_infoframe_enabled; + } else { + intel_dig_port->set_infoframes = hsw_set_infoframes; + intel_dig_port->infoframe_enabled = + hsw_infoframe_enabled; + intel_dig_port->write_infoframe = hsw_write_infoframe; + } } else if (HAS_PCH_IBX(dev_priv)) { intel_dig_port->write_infoframe = ibx_write_infoframe; intel_dig_port->set_infoframes = ibx_set_infoframes; diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 946dfd0..bb1365a 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -235,6 +235,59 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n"); } +void lspcon_set_infoframes(struct drm_encoder *encoder, + bool enable, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + ssize_t ret; + union hdmi_infoframe frame; + uint8_t buf[VIDEO_DIP_DATA_SIZE]; + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct intel_dp *intel_dp = &dig_port->dp; + struct drm_connector *connector = &intel_dp->attached_connector->base; + const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode; + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; + + if (!crtc_state->lspcon_active) { + DRM_ERROR("Writing infoframes while LSPCON disabled ?\n"); + return; + } + + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, + mode, is_hdmi2_sink); + if (ret < 0) { + DRM_ERROR("couldn't fill AVI infoframe\n"); + return; + } + + if (crtc_state->ycbcr420) + frame.avi.colorspace = HDMI_COLORSPACE_YUV420; + else + frame.avi.colorspace = HDMI_COLORSPACE_RGB; + + drm_hdmi_avi_infoframe_quant_range(&frame.avi, mode, + crtc_state->limited_color_range ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL, + false); + + ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf)); + if (ret < 0) { + DRM_ERROR("Failed to pack AVI IF\n"); + return; + } + + dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI, + buf, ret); +} + +bool lspcon_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) +{ + return enc_to_intel_lspcon(encoder)->active; +} + void lspcon_resume(struct intel_lspcon *lspcon) { enum drm_lspcon_mode expected_mode; -- 2.7.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx