diff options
author | Dave Airlie <airlied@redhat.com> | 2021-05-21 08:53:38 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2021-05-21 08:55:23 +1000 |
commit | 2ba047855096fff551402a87272b520fe97323f5 (patch) | |
tree | 87ec89187793c422132343278648201f52b49238 /drivers/gpu/drm/i915/display/intel_hdmi.c | |
parent | ae25ec2fc6c5a9e5767bf1922cd648501d0f914c (diff) | |
parent | ec279384c6a02cf04a96054e82b1294a7aad6577 (diff) |
Merge tag 'drm-intel-next-2021-05-19-1' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Core Changes:
- drm: Rename DP_PSR_SELECTIVE_UPDATE to better mach eDP spec (Jose).
Driver Changes:
- Display plane clock rates fixes and improvements (Ville).
- Uninint DMC FW loader state during shutdown (Imre).
- Convert snprintf to sysfs_emit (Xuezhi).
- Fix invalid access to ACPI _DSM objects (Takashi).
- A big refactor around how i915 addresses the graphics
and display IP versions. (Matt, Lucas).
- Backlight fix (Lyude).
- Display watermark and DBUF fixes (Ville).
- HDCP fix (Anshuman).
- Improve cases where display is not available (Jose).
- Defeature PSR2 for RKL and ALD-S (Jose).
- VLV DSI panel power fixes and improvements (Hans).
- display-12 workaround (Jose).
- Fix modesetting (Imre).
- Drop redundant address-of op before lttpr_common_caps array (Imre).
- Fix compiler checks (Jose, Jason).
- GLK display fixes (Ville).
- Fix error code returns (Dan).
- eDP novel: back again to slow and wide link training everywhere (Kai-Heng).
- Abstract DMC FW path (Rodrigo).
- Preparation and changes for upcoming
XeLPD display IP (Jose, Matt, Ville, Juha-Pekka, Animesh).
- Fix comment typo in DSI code (zuoqilin).
- Simplify CCS and UV plane alignment handling (Imre).
- PSR Fixes on TGL (Gwan-gyeong, Jose).
- Add intel_dp_hdcp.h and rename init (Jani).
- Move crtc and dpll declarations around (Jani).
- Fix pre-skl DP AUX precharge length (Ville).
- Remove stray newlines from random files (Ville).
- crtc->index and intel_crtc+drm_crtc pointer clean-up (Ville).
- Add frontbuffer tracking tracepoints (Ville).
- ADL-S PCI ID updates (Anand).
- Use unique backlight device names (Jani).
- A few clean-ups on i915/audio (Jani).
- Use intel_framebuffer instead of drm one on intel_fb functions (Imre).
- Add the missing MC CCS/XYUV8888 format support on display >= 12 (Imre).
- Nuke display error state (Ville).
- ADL-P initial enablement patches
starting to land (Clint, Imre, Jose, Umesh, Vandita, Mika).
- Display clean-up around VBT and the strap bits (Lucas).
- Try YCbCr420 color when RGB fails (Werner).
- More PSR fixes and improvements (Jose).
- Other generic display code clean-up (Jose, Ville).
- Use correct downstream caps for check Src-Ctl mode for PCON (Ankit).
- Disable HiZ Raw Stall Optimization on broken gen7 (Simon).
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YKVioeu0JkUAlR7y@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_hdmi.c | 150 |
1 files changed, 95 insertions, 55 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 3c767bcc47b1..4a1b2d863b0c 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -43,6 +43,7 @@ #include "intel_atomic.h" #include "intel_connector.h" #include "intel_ddi.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_gmbus.h" @@ -531,6 +532,11 @@ void hsw_write_infoframe(struct intel_encoder *encoder, hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2), 0); + /* Wa_14013475917 */ + if (DISPLAY_VER(dev_priv) == 13 && crtc_state->has_psr && + type == DP_SDP_VSC) + return; + val |= hsw_infoframe_enable(type); intel_de_write(dev_priv, ctl_reg, val); intel_de_posting_read(dev_priv, ctl_reg); @@ -542,11 +548,9 @@ void hsw_read_infoframe(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 val, *data = frame; + u32 *data = frame; int i; - val = intel_de_read(dev_priv, HSW_TVIDEO_DIP_CTL(cpu_transcoder)); - for (i = 0; i < len; i += 4) *data++ = intel_de_read(dev_priv, hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2)); @@ -1840,7 +1844,8 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, return MODE_CLOCK_RANGE; /* BXT/GLK DPLL can't generate 223-240 MHz */ - if (IS_GEN9_LP(dev_priv) && clock > 223333 && clock < 240000) + if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && + clock > 223333 && clock < 240000) return MODE_CLOCK_RANGE; /* CHV DPLL can't generate 216-240 MHz */ @@ -1861,6 +1866,32 @@ static int intel_hdmi_port_clock(int clock, int bpc) } static enum drm_mode_status +intel_hdmi_mode_clock_valid(struct intel_hdmi *hdmi, int clock, bool has_hdmi_sink) +{ + struct drm_device *dev = intel_hdmi_to_dev(hdmi); + struct drm_i915_private *dev_priv = to_i915(dev); + enum drm_mode_status status; + + /* check if we can do 8bpc */ + status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 8), + true, has_hdmi_sink); + + if (has_hdmi_sink) { + /* if we can't do 8bpc we may still be able to do 12bpc */ + if (status != MODE_OK && !HAS_GMCH(dev_priv)) + status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12), + true, has_hdmi_sink); + + /* if we can't do 8,12bpc we may still be able to do 10bpc */ + if (status != MODE_OK && DISPLAY_VER(dev_priv) >= 11) + status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10), + true, has_hdmi_sink); + } + + return status; +} + +static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -1871,6 +1902,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, int clock = mode->clock; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); + bool ycbcr_420_only; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -1887,26 +1919,22 @@ intel_hdmi_mode_valid(struct drm_connector *connector, clock *= 2; } - if (drm_mode_is_420_only(&connector->display_info, mode)) + ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode); + if (ycbcr_420_only) clock /= 2; - /* check if we can do 8bpc */ - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 8), - true, has_hdmi_sink); + status = intel_hdmi_mode_clock_valid(hdmi, clock, has_hdmi_sink); + if (status != MODE_OK) { + if (ycbcr_420_only || + !connector->ycbcr_420_allowed || + !drm_mode_is_420_also(&connector->display_info, mode)) + return status; - if (has_hdmi_sink) { - /* if we can't do 8bpc we may still be able to do 12bpc */ - if (status != MODE_OK && !HAS_GMCH(dev_priv)) - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12), - true, has_hdmi_sink); - - /* if we can't do 8,12bpc we may still be able to do 10bpc */ - if (status != MODE_OK && DISPLAY_VER(dev_priv) >= 11) - status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10), - true, has_hdmi_sink); + clock /= 2; + status = intel_hdmi_mode_clock_valid(hdmi, clock, has_hdmi_sink); + if (status != MODE_OK) + return status; } - if (status != MODE_OK) - return status; return intel_mode_valid_max_plane_size(dev_priv, mode, false); } @@ -1976,7 +2004,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, /* Display Wa_1405510057:icl,ehl */ if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && - bpc == 10 && IS_DISPLAY_VER(dev_priv, 11) && + bpc == 10 && DISPLAY_VER(dev_priv) == 11 && (adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start) % 8 == 2) return false; @@ -1987,29 +2015,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, INTEL_OUTPUT_FORMAT_YCBCR420); } -static int -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -{ - struct drm_connector *connector = conn_state->connector; - struct drm_i915_private *i915 = to_i915(connector->dev); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - - if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode)) - return 0; - - if (!connector->ycbcr_420_allowed) { - drm_err(&i915->drm, - "Platform doesn't support YCBCR420 output\n"); - return -EINVAL; - } - - crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; - - return intel_pch_panel_fitting(crtc_state, conn_state); -} - static int intel_hdmi_compute_bpc(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, int clock) @@ -2116,6 +2121,39 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder, return intel_conn_state->force_audio == HDMI_AUDIO_ON; } +static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct drm_connector *connector = conn_state->connector; + struct drm_i915_private *i915 = to_i915(connector->dev); + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int ret; + bool ycbcr_420_only; + + ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, adjusted_mode); + if (connector->ycbcr_420_allowed && ycbcr_420_only) { + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; + } else { + if (!connector->ycbcr_420_allowed && ycbcr_420_only) + drm_dbg_kms(&i915->drm, + "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); + crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB; + } + + ret = intel_hdmi_compute_clock(encoder, crtc_state); + if (ret) { + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 && + connector->ycbcr_420_allowed && + drm_mode_is_420_also(&connector->display_info, adjusted_mode)) { + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; + ret = intel_hdmi_compute_clock(encoder, crtc_state); + } + } + + return ret; +} + int intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -2140,23 +2178,25 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) pipe_config->pixel_multiplier = 2; - ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state); - if (ret) - return ret; - - pipe_config->limited_color_range = - intel_hdmi_limited_color_range(pipe_config, conn_state); - if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv)) pipe_config->has_pch_encoder = true; pipe_config->has_audio = intel_hdmi_has_audio(encoder, pipe_config, conn_state); - ret = intel_hdmi_compute_clock(encoder, pipe_config); + ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state); if (ret) return ret; + if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { + ret = intel_pch_panel_fitting(pipe_config, conn_state); + if (ret) + return ret; + } + + pipe_config->limited_color_range = + intel_hdmi_limited_color_range(pipe_config, conn_state); + if (conn_state->picture_aspect_ratio) adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; @@ -2706,13 +2746,13 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) return ddc_pin; } - if (HAS_PCH_ADP(dev_priv)) + if (IS_ALDERLAKE_S(dev_priv)) ddc_pin = adls_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) ddc_pin = dg1_port_to_ddc_pin(dev_priv, port); else if (IS_ROCKETLAKE(dev_priv)) ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); - else if (IS_GEN9_BC(dev_priv) && HAS_PCH_TGP(dev_priv)) + else if (DISPLAY_VER(dev_priv) == 9 && HAS_PCH_TGP(dev_priv)) ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port); else if (HAS_PCH_MCC(dev_priv)) ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); @@ -2720,7 +2760,7 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) ddc_pin = icl_port_to_ddc_pin(dev_priv, port); else if (HAS_PCH_CNP(dev_priv)) ddc_pin = cnp_port_to_ddc_pin(dev_priv, port); - else if (IS_GEN9_LP(dev_priv)) + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) ddc_pin = bxt_port_to_ddc_pin(dev_priv, port); else if (IS_CHERRYVIEW(dev_priv)) ddc_pin = chv_port_to_ddc_pin(dev_priv, port); |