On Tue, Aug 14, 2018 at 03:23:20PM +0530, Shashank Sharma wrote: > Currently, we are using a bool in CRTC state (state->ycbcr420), > to indicate modeset, that the output format is YCBCR 4:2:0. Now in > order to support other YCBCR formats, we will need more such flags. > > This patch adds a new enum parameter for YCBCR 4:2:0 outputs, in the > CRTC output formats and then plugs it during the modeset. > > V3: Added this patch in the series, to address review comments from > second patchset. > V4: Added r-b from Maarten (on v3) > Addressed review comments from Ville: > - Change the enum name to intel_output_format. > - Start the enum value (INVALID) from 0 instaed of 1. > - Set the crtc's output_format to RGB in encoder's compute_config. > V5: Broke previous patch 1 into two parts, > - first patch to add CRTC output format in general > - second patch (this one) to add YCBCR 4:2:0 output > format specifically. > - Use ARRAY_SIZE(format_str) for output format validity check (Ville) > V6: Added a separate function to calculate crtc_state->output_format, and > calling it from various get_config function (Fix CI build warning) > V7: Fixed checkpatch warnings for alignment > V8: Rebase > V9: Rebase > V10: Rebase > > Cc: Ville Syrjala <ville.syrjala@xxxxxxxxxxxxxxx> > Cc: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> > Reviewed-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> > Signed-off-by: Shashank Sharma <shashank.sharma@xxxxxxxxx> > --- > drivers/gpu/drm/i915/intel_color.c | 2 +- > drivers/gpu/drm/i915/intel_ddi.c | 2 +- > drivers/gpu/drm/i915/intel_display.c | 72 +++++++++++++++++++++--------------- > drivers/gpu/drm/i915/intel_drv.h | 4 +- > drivers/gpu/drm/i915/intel_hdmi.c | 6 +-- > drivers/gpu/drm/i915/intel_panel.c | 2 +- > 6 files changed, 50 insertions(+), 38 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c > index c6a7bea..bf9d8f6 100644 > --- a/drivers/gpu/drm/i915/intel_color.c > +++ b/drivers/gpu/drm/i915/intel_color.c > @@ -149,7 +149,7 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state) > if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) > limited_color_range = intel_crtc_state->limited_color_range; > > - if (intel_crtc_state->ycbcr420) { > + if (intel_crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { > ilk_load_ycbcr_conversion_matrix(intel_crtc); > return; > } else if (crtc_state->ctm) { > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > index 0adc043..a036fe6 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -1442,7 +1442,7 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) > else > dotclock = pipe_config->port_clock; > > - if (pipe_config->ycbcr420) > + if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) > dotclock *= 2; > > if (pipe_config->pixel_multiplier) > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 5e5bc06..e2a1e4f 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -4811,7 +4811,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, > if (pixel_format == DRM_FORMAT_NV12) > need_scaling = true; > > - if (crtc_state->ycbcr420 && scaler_user == SKL_CRTC_INDEX) > + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && > + scaler_user == SKL_CRTC_INDEX) > need_scaling = true; > > /* > @@ -6620,7 +6621,8 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, > return -EINVAL; > } > > - if (pipe_config->ycbcr420 && pipe_config->base.ctm) { > + if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && > + pipe_config->base.ctm) { > /* > * There is only one pipe CSC unit per pipe, and we need that > * for output conversion from RGB->YCBCR. So if CTM is already > @@ -7818,6 +7820,35 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, > pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock); > } > > +static void intel_get_crtc_ycbcr_config(struct intel_crtc *crtc, > + struct intel_crtc_state *pipe_config) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + enum intel_output_format output = INTEL_OUTPUT_FORMAT_RGB; > + > + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { > + u32 tmp = I915_READ(PIPEMISC(crtc->pipe)); > + > + if (tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV) { > + bool ycbcr420_enabled = tmp & PIPEMISC_YUV420_ENABLE; > + bool blend = tmp & PIPEMISC_YUV420_MODE_FULL_BLEND; > + > + if (ycbcr420_enabled) { > + /* We support 4:2:0 in full blend mode only */ > + if (!blend) > + output = INTEL_OUTPUT_FORMAT_INVALID; > + else if (!(IS_GEMINILAKE(dev_priv) || > + INTEL_GEN(dev_priv) >= 10)) > + output = INTEL_OUTPUT_FORMAT_INVALID; > + else > + output = INTEL_OUTPUT_FORMAT_YCBCR420; > + } > + } > + } > + > + pipe_config->output_format = output; > +} > + > static bool i9xx_get_pipe_config(struct intel_crtc *crtc, > struct intel_crtc_state *pipe_config) > { > @@ -7865,6 +7896,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, > > intel_get_pipe_timings(crtc, pipe_config); > intel_get_pipe_src_size(crtc, pipe_config); > + intel_get_crtc_ycbcr_config(crtc, pipe_config); That function is bdw+ only actually, so not much point in calling it here. Just need the patch 1 to be fixed to correcly set output_type=RGB. We'll need to come up with another way to detect the output_format when we start to do yuv output on pre-bdw. > > i9xx_get_pfit_config(crtc, pipe_config); > > @@ -8452,10 +8484,10 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc) > if (intel_crtc->config->dither) > val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP; > > - if (config->ycbcr420) { > - val |= PIPEMISC_OUTPUT_COLORSPACE_YUV | > - PIPEMISC_YUV420_ENABLE | > - PIPEMISC_YUV420_MODE_FULL_BLEND; > + if (config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { > + val |= PIPEMISC_OUTPUT_COLORSPACE_YUV; > + val |= PIPEMISC_YUV420_ENABLE | > + PIPEMISC_YUV420_MODE_FULL_BLEND; > } > > I915_WRITE(PIPEMISC(intel_crtc->pipe), val); > @@ -8953,6 +8985,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, > > intel_get_pipe_timings(crtc, pipe_config); > intel_get_pipe_src_size(crtc, pipe_config); > + intel_get_crtc_ycbcr_config(crtc, pipe_config); ditto > > ironlake_get_pfit_config(crtc, pipe_config); > > @@ -9514,28 +9547,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, > } > > intel_get_pipe_src_size(crtc, pipe_config); > + intel_get_crtc_ycbcr_config(crtc, pipe_config); > > pipe_config->gamma_mode = > I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; > > - if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { > - u32 tmp = I915_READ(PIPEMISC(crtc->pipe)); > - bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV; > - > - if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) { > - bool blend_mode_420 = tmp & > - PIPEMISC_YUV420_MODE_FULL_BLEND; > - > - pipe_config->ycbcr420 = tmp & PIPEMISC_YUV420_ENABLE; > - if (pipe_config->ycbcr420 != clrspace_yuv || > - pipe_config->ycbcr420 != blend_mode_420) > - DRM_DEBUG_KMS("Bad 4:2:0 mode (%08x)\n", tmp); > - } else if (clrspace_yuv) { > - DRM_DEBUG_KMS("YCbCr 4:2:0 Unsupported\n"); > - } > - } > - > - pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; > power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); > if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { > power_domain_mask |= BIT_ULL(power_domain); > @@ -10886,11 +10902,13 @@ static void snprintf_output_types(char *buf, size_t len, > static const char * const output_format_str[] = { > [INTEL_OUTPUT_FORMAT_INVALID] = "Invalid", > [INTEL_OUTPUT_FORMAT_RGB] = "RGB", > + [INTEL_OUTPUT_FORMAT_YCBCR420] = "YCBCR4:2:0", > }; > > static const char *output_formats(enum intel_output_format format) > { > - if (format != INTEL_OUTPUT_FORMAT_RGB) > + if (format < INTEL_OUTPUT_FORMAT_RGB || I think the enum ends up unsigned so this < check is pointless. > + format > ARRAY_SIZE(output_format_str)) This should be >= With this fixed Reviewed-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > format = INTEL_OUTPUT_FORMAT_INVALID; > return output_format_str[format]; > } > @@ -10926,9 +10944,6 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, > pipe_config->fdi_lanes, > &pipe_config->fdi_m_n); > > - if (pipe_config->ycbcr420) > - DRM_DEBUG_KMS("YCbCr 4:2:0 output enabled\n"); > - > if (intel_crtc_has_dp_encoder(pipe_config)) { > intel_dump_m_n_config(pipe_config, "dp m_n", > pipe_config->lane_count, &pipe_config->dp_m_n); > @@ -11515,7 +11530,6 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, > PIPE_CONF_CHECK_BOOL(hdmi_scrambling); > PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio); > PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_infoframe); > - PIPE_CONF_CHECK_BOOL(ycbcr420); > > PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index f704720..cc7a46e 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -711,6 +711,7 @@ struct intel_crtc_wm_state { > enum intel_output_format { > INTEL_OUTPUT_FORMAT_INVALID, > INTEL_OUTPUT_FORMAT_RGB, > + INTEL_OUTPUT_FORMAT_YCBCR420, > }; > > struct intel_crtc_state { > @@ -900,9 +901,6 @@ struct intel_crtc_state { > /* HDMI High TMDS char rate ratio */ > bool hdmi_high_tmds_clock_ratio; > > - /* output format is YCBCR 4:2:0 */ > - bool ycbcr420; > - > /* Output format RGB/YCBCR etc */ > enum intel_output_format output_format; > }; > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c > index 8993e66..f1259a9 100644 > --- a/drivers/gpu/drm/i915/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > @@ -486,7 +486,7 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, > return; > } > > - if (crtc_state->ycbcr420) > + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) > frame.avi.colorspace = HDMI_COLORSPACE_YUV420; > else > frame.avi.colorspace = HDMI_COLORSPACE_RGB; > @@ -1620,7 +1620,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, > if (connector_state->crtc != crtc_state->base.crtc) > continue; > > - if (crtc_state->ycbcr420) { > + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { > const struct drm_hdmi_info *hdmi = &info->hdmi; > > if (bpc == 12 && !(hdmi->y420_dc_modes & > @@ -1665,7 +1665,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector, > *clock_12bpc /= 2; > *clock_10bpc /= 2; > *clock_8bpc /= 2; > - config->ycbcr420 = true; > + config->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; > > /* YCBCR 420 output conversion needs a scaler */ > if (skl_update_scaler_crtc(config)) { > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c > index 4a9f139..5cca04a 100644 > --- a/drivers/gpu/drm/i915/intel_panel.c > +++ b/drivers/gpu/drm/i915/intel_panel.c > @@ -111,7 +111,7 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, > /* Native modes don't need fitting */ > if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && > adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h && > - !pipe_config->ycbcr420) > + pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) > goto done; > > switch (fitting_mode) { > -- > 2.7.4 -- Ville Syrjälä Intel _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx