On Mon, Sep 24, 2018 at 05:58:25PM +0200, Daniel Vetter wrote: > On Thu, Sep 20, 2018 at 09:51:40PM +0300, Ville Syrjala wrote: > > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > > > Store the infoframes in the crtc state and precompute them in > > .compute_config(). While precomputing we'll also fill out the > > inforames.enable bitmask appropriately. > > > > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > --- > > drivers/gpu/drm/i915/intel_ddi.c | 1 + > > drivers/gpu/drm/i915/intel_drv.h | 5 + > > drivers/gpu/drm/i915/intel_hdmi.c | 249 +++++++++++++++++++++++++++----------- > > 3 files changed, 187 insertions(+), 68 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > > index 19fef88e680e..5f3bd536d261 100644 > > --- a/drivers/gpu/drm/i915/intel_ddi.c > > +++ b/drivers/gpu/drm/i915/intel_ddi.c > > @@ -3391,6 +3391,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, > > intel_dig_port = enc_to_dig_port(&encoder->base); > > > > pipe_config->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_NULL) | > > Misplaced hunk? Assuming I'm reading this correctly, this will give you a > 0. Not exactly sure what's going on here ... I guess I'm not following why > we care about TYPE_NULL, and why we have to reconstruct it here? I rather wanted the infoframes bitmask to be truthful about which packets we're sending out. But not quite sure why I included it in this particular patch. > > I thought TYPE_NULL is equivalent to state->has_hdmi_sink? Comment > (unfortunately not yet kerneldoc) even explains that ... Yeah it's the same thing (apart from the g4x DIP enable thing). Maybe I should remove has_hdmi_sink entirely and just rely on the null packet bit instead... > > Maybe just nuke all the TYPE_NULL tracking here, perhaps with the g4x > (except for g4x itself, because it's shared there) decoder to also take > DIP_ENABLE into account for has_hdmi_sink. That would the other option I suppose. Though I might like the idea of dropping the bool for the bitmask a bit more perhaps. > > Or update the comment in intel_crtc_state. > > Otherwise lgtm, thought admittedly I did clean over the details a bit, > trusting CI and gcc to catch the small stuff :-) > > Reviewed-by: Daniel Vetter <daniel.vetter@xxxxxxxx> with the TYPE_NULL > story somehow figured out. > -Daniel > > > > intel_hdmi_infoframes_enabled(encoder, pipe_config); > > > > if (pipe_config->infoframes.enable) > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > > index 50c0c049ee15..357624a6bfe2 100644 > > --- a/drivers/gpu/drm/i915/intel_drv.h > > +++ b/drivers/gpu/drm/i915/intel_drv.h > > @@ -895,6 +895,10 @@ struct intel_crtc_state { > > > > struct { > > u32 enable; > > + u32 gcp; > > + union hdmi_infoframe avi; > > + union hdmi_infoframe spd; > > + union hdmi_infoframe hdmi; > > } infoframes; > > > > /* HDMI scrambling status */ > > @@ -1862,6 +1866,7 @@ 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); > > u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, > > const struct intel_crtc_state *crtc_state); > > +u32 intel_hdmi_infoframe_enable(unsigned int type); > > > > > > /* intel_lvds.c */ > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c > > index 98a44084324c..491001fc0fad 100644 > > --- a/drivers/gpu/drm/i915/intel_hdmi.c > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > > @@ -446,6 +446,18 @@ static const u8 infoframe_type_to_idx[] = { > > HDMI_INFOFRAME_TYPE_VENDOR, > > }; > > > > +u32 intel_hdmi_infoframe_enable(unsigned int type) > > +{ > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(infoframe_type_to_idx); i++) { > > + if (infoframe_type_to_idx[i] == type) > > + return BIT(i); > > + } > > + > > + return 0; > > +} > > + > > u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, > > const struct intel_crtc_state *crtc_state) > > { > > @@ -491,15 +503,23 @@ u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, > > */ > > static void intel_write_infoframe(struct intel_encoder *encoder, > > const struct intel_crtc_state *crtc_state, > > - union hdmi_infoframe *frame) > > + enum hdmi_infoframe_type type, > > + const union hdmi_infoframe *frame) > > { > > struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); > > u8 buffer[VIDEO_DIP_DATA_SIZE]; > > ssize_t len; > > > > + if ((crtc_state->infoframes.enable & > > + intel_hdmi_infoframe_enable(type)) == 0) > > + return; > > + > > + if (WARN_ON(frame->any.type != type)) > > + return; > > + > > /* see comment above for the reason for this offset */ > > - len = hdmi_infoframe_pack(frame, buffer + 1, sizeof(buffer) - 1); > > - if (len < 0) > > + len = hdmi_infoframe_pack_only(frame, buffer + 1, sizeof(buffer) - 1); > > + if (WARN_ON(len < 0)) > > return; > > > > /* Insert the 'hole' (see big comment above) at position 3 */ > > @@ -507,85 +527,111 @@ static void intel_write_infoframe(struct intel_encoder *encoder, > > buffer[3] = 0; > > len++; > > > > - intel_dig_port->write_infoframe(encoder, > > - crtc_state, > > - frame->any.type, buffer, len); > > + intel_dig_port->write_infoframe(encoder, crtc_state, type, buffer, len); > > } > > > > -static void intel_hdmi_set_avi_infoframe(struct intel_encoder *encoder, > > - const struct intel_crtc_state *crtc_state, > > - const struct drm_connector_state *conn_state) > > +static bool > > +intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, > > + struct intel_crtc_state *crtc_state, > > + struct drm_connector_state *conn_state) > > { > > struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); > > + struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; > > + bool is_hdmi2_sink = conn_state->connector->display_info.hdmi.scdc.supported; > > const struct drm_display_mode *adjusted_mode = > > &crtc_state->base.adjusted_mode; > > - struct drm_connector *connector = &intel_hdmi->attached_connector->base; > > - bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported; > > - union hdmi_infoframe frame; > > int ret; > > > > - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, > > + if (!crtc_state->has_infoframe) > > + return true; > > + > > + crtc_state->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI); > > + > > + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, > > adjusted_mode, > > is_hdmi2_sink); > > - if (ret < 0) { > > - DRM_ERROR("couldn't fill AVI infoframe\n"); > > - return; > > - } > > + if (ret) > > + return false; > > > > if (crtc_state->ycbcr420) > > - frame.avi.colorspace = HDMI_COLORSPACE_YUV420; > > + frame->colorspace = HDMI_COLORSPACE_YUV420; > > else > > - frame.avi.colorspace = HDMI_COLORSPACE_RGB; > > + frame->colorspace = HDMI_COLORSPACE_RGB; > > > > - drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode, > > + drm_hdmi_avi_infoframe_quant_range(frame, adjusted_mode, > > crtc_state->limited_color_range ? > > HDMI_QUANTIZATION_RANGE_LIMITED : > > HDMI_QUANTIZATION_RANGE_FULL, > > intel_hdmi->rgb_quant_range_selectable, > > is_hdmi2_sink); > > > > - drm_hdmi_avi_infoframe_content_type(&frame.avi, > > - conn_state); > > + drm_hdmi_avi_infoframe_content_type(frame, conn_state); > > > > /* TODO: handle pixel repetition for YCBCR420 outputs */ > > - intel_write_infoframe(encoder, crtc_state, > > - &frame); > > + > > + ret = hdmi_avi_infoframe_check(frame); > > + if (WARN_ON(ret)) > > + return false; > > + > > + return true; > > } > > > > -static void intel_hdmi_set_spd_infoframe(struct intel_encoder *encoder, > > - const struct intel_crtc_state *crtc_state) > > +static bool > > +intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, > > + struct intel_crtc_state *crtc_state, > > + struct drm_connector_state *conn_state) > > { > > - union hdmi_infoframe frame; > > + struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd; > > int ret; > > > > - ret = hdmi_spd_infoframe_init(&frame.spd, "Intel", "Integrated gfx"); > > - if (ret < 0) { > > - DRM_ERROR("couldn't fill SPD infoframe\n"); > > - return; > > - } > > + if (!crtc_state->has_infoframe) > > + return true; > > > > - frame.spd.sdi = HDMI_SPD_SDI_PC; > > + crtc_state->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD); > > > > - intel_write_infoframe(encoder, crtc_state, > > - &frame); > > + ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); > > + if (WARN_ON(ret)) > > + return false; > > + > > + frame->sdi = HDMI_SPD_SDI_PC; > > + > > + ret = hdmi_spd_infoframe_check(frame); > > + if (WARN_ON(ret)) > > + return false; > > + > > + return true; > > } > > > > -static void > > -intel_hdmi_set_hdmi_infoframe(struct intel_encoder *encoder, > > - const struct intel_crtc_state *crtc_state, > > - const struct drm_connector_state *conn_state) > > -{ > > - union hdmi_infoframe frame; > > +static bool > > +intel_hdmi_compute_hdmi_infoframe(struct intel_encoder *encoder, > > + struct intel_crtc_state *crtc_state, > > + struct drm_connector_state *conn_state) > > +{ > > + struct hdmi_vendor_infoframe *frame = > > + &crtc_state->infoframes.hdmi.vendor.hdmi; > > + const struct drm_display_info *info = > > + &conn_state->connector->display_info; > > int ret; > > > > - ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, > > + if (!crtc_state->has_infoframe || !info->has_hdmi_infoframe) > > + return true; > > + > > + crtc_state->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR); > > + > > + ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, > > conn_state->connector, > > &crtc_state->base.adjusted_mode); > > - if (ret < 0) > > - return; > > + if (WARN_ON(ret)) > > + return false; > > > > - intel_write_infoframe(encoder, crtc_state, > > - &frame); > > + ret = hdmi_vendor_infoframe_check(frame); > > + if (WARN_ON(ret)) > > + return false; > > + > > + return true; > > } > > > > static void g4x_set_infoframes(struct intel_encoder *encoder, > > @@ -645,9 +691,15 @@ static void g4x_set_infoframes(struct intel_encoder *encoder, > > I915_WRITE(reg, val); > > POSTING_READ(reg); > > > > - intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state); > > - intel_hdmi_set_spd_infoframe(encoder, crtc_state); > > - intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_AVI, > > + &crtc_state->infoframes.avi); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_SPD, > > + &crtc_state->infoframes.spd); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_VENDOR, > > + &crtc_state->infoframes.hdmi); > > } > > > > static bool hdmi_sink_is_deep_color(const struct drm_connector_state *conn_state) > > @@ -713,7 +765,10 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder, > > struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > > struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > > i915_reg_t reg; > > - u32 val = 0; > > + > > + if ((crtc_state->infoframes.enable & > > + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) == 0) > > + return false; > > > > if (HAS_DDI(dev_priv)) > > reg = HSW_TVIDEO_DIP_GCP(crtc_state->cpu_transcoder); > > @@ -724,18 +779,31 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder, > > else > > return false; > > > > + I915_WRITE(reg, crtc_state->infoframes.gcp); > > + > > + return true; > > +} > > + > > +static void intel_hdmi_compute_gcp_infoframe(struct intel_encoder *encoder, > > + struct intel_crtc_state *crtc_state, > > + struct drm_connector_state *conn_state) > > +{ > > + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > > + > > + if (IS_G4X(dev_priv) || !crtc_state->has_infoframe) > > + return; > > + > > + crtc_state->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL); > > + > > /* Indicate color depth whenever the sink supports deep color */ > > if (hdmi_sink_is_deep_color(conn_state)) > > - val |= GCP_COLOR_INDICATION; > > + crtc_state->infoframes.gcp |= GCP_COLOR_INDICATION; > > > > /* Enable default_phase whenever the display mode is suitably aligned */ > > if (gcp_default_phase_possible(crtc_state->pipe_bpp, > > &crtc_state->base.adjusted_mode)) > > - val |= GCP_DEFAULT_PHASE_ENABLE; > > - > > - I915_WRITE(reg, val); > > - > > - return val != 0; > > + crtc_state->infoframes.gcp |= GCP_DEFAULT_PHASE_ENABLE; > > } > > > > static void ibx_set_infoframes(struct intel_encoder *encoder, > > @@ -786,9 +854,15 @@ static void ibx_set_infoframes(struct intel_encoder *encoder, > > I915_WRITE(reg, val); > > POSTING_READ(reg); > > > > - intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state); > > - intel_hdmi_set_spd_infoframe(encoder, crtc_state); > > - intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_AVI, > > + &crtc_state->infoframes.avi); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_SPD, > > + &crtc_state->infoframes.spd); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_VENDOR, > > + &crtc_state->infoframes.hdmi); > > } > > > > static void cpt_set_infoframes(struct intel_encoder *encoder, > > @@ -829,9 +903,15 @@ static void cpt_set_infoframes(struct intel_encoder *encoder, > > I915_WRITE(reg, val); > > POSTING_READ(reg); > > > > - intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state); > > - intel_hdmi_set_spd_infoframe(encoder, crtc_state); > > - intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_AVI, > > + &crtc_state->infoframes.avi); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_SPD, > > + &crtc_state->infoframes.spd); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_VENDOR, > > + &crtc_state->infoframes.hdmi); > > } > > > > static void vlv_set_infoframes(struct intel_encoder *encoder, > > @@ -881,9 +961,15 @@ static void vlv_set_infoframes(struct intel_encoder *encoder, > > I915_WRITE(reg, val); > > POSTING_READ(reg); > > > > - intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state); > > - intel_hdmi_set_spd_infoframe(encoder, crtc_state); > > - intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_AVI, > > + &crtc_state->infoframes.avi); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_SPD, > > + &crtc_state->infoframes.spd); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_VENDOR, > > + &crtc_state->infoframes.hdmi); > > } > > > > static void hsw_set_infoframes(struct intel_encoder *encoder, > > @@ -914,9 +1000,15 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, > > I915_WRITE(reg, val); > > POSTING_READ(reg); > > > > - intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state); > > - intel_hdmi_set_spd_infoframe(encoder, crtc_state); > > - intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_AVI, > > + &crtc_state->infoframes.avi); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_SPD, > > + &crtc_state->infoframes.spd); > > + intel_write_infoframe(encoder, crtc_state, > > + HDMI_INFOFRAME_TYPE_VENDOR, > > + &crtc_state->infoframes.hdmi); > > } > > > > void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) > > @@ -1851,6 +1943,27 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, > > } > > } > > > > + if (pipe_config->has_hdmi_sink) > > + pipe_config->infoframes.enable |= > > + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_NULL); > > + > > + intel_hdmi_compute_gcp_infoframe(encoder, pipe_config, conn_state); > > + > > + if (!intel_hdmi_compute_avi_infoframe(encoder, pipe_config, conn_state)) { > > + DRM_DEBUG_KMS("bad AVI infoframe\n"); > > + return false; > > + } > > + > > + if (!intel_hdmi_compute_spd_infoframe(encoder, pipe_config, conn_state)) { > > + DRM_DEBUG_KMS("bad SPD infoframe\n"); > > + return false; > > + } > > + > > + if (!intel_hdmi_compute_hdmi_infoframe(encoder, pipe_config, conn_state)) { > > + DRM_DEBUG_KMS("bad HDMI infoframe\n"); > > + return false; > > + } > > + > > return true; > > } > > > > -- > > 2.16.4 > > > > _______________________________________________ > > Intel-gfx mailing list > > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch -- Ville Syrjälä Intel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel