diff options
author | Dave Airlie <airlied@redhat.com> | 2023-01-17 05:23:07 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-01-17 05:23:08 +1000 |
commit | 0b45ac1170ea6416bc1d36798414c04870cd356d (patch) | |
tree | 637d097b1ba4bc687492fd436b9b0673d347848f | |
parent | c37ea39c1fa880da0d7fd2c719e5c96be19f0fc5 (diff) | |
parent | f71c9b7bc35ff7c1fb68d114903876eec658439b (diff) | |
download | linux-stable-0b45ac1170ea6416bc1d36798414c04870cd356d.tar.gz linux-stable-0b45ac1170ea6416bc1d36798414c04870cd356d.tar.bz2 linux-stable-0b45ac1170ea6416bc1d36798414c04870cd356d.zip |
Merge tag 'drm-intel-next-2023-01-12' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
drm/i915 feature pull #1 for v6.3:
Features and functionality:
- Meteorlake display enabling (Animesh, Luca, Stan, Jouni, Anusha)
- DP MST DSC support (Stan)
- Gamma/degamma readout support for the state checker (Ville)
- Enable SDP split support for DP 2.0 (Vinod)
- Add probe blocking support to i915.force_probe parameter (Rodrigo)
- Enable Xe HP 4tile support (Jonathan)
Refactoring and cleanups:
- Color refactoring, especially related to DSB usage (Ville)
- DSB refactoring (Ville)
- DVO refactoring (Ville)
- Backlight register and logging cleanups (Jani)
- Avoid display direct calls to uncore (Maarten, Jani)
- Add new "soc" sub-directory (Jani)
- Refactor DSC platform support checks (Swati)
Fixes:
- Interlace modes are no longer supported starting at display version 12 (Ankit)
- Use polling read for aux control (Arun)
- DMC firmware no longer requires specific versions (Gustavo)
- Fix PSR flickering and freeze issues (Jouni)
- Fix ICL+ DSI GPIO handling (Jani)
- Ratelimit errors in display engine irqs (Lucas)
- Fix DP MST DSC bpp and timeslot calculations (Stan)
- Fix CDCLK squash and crawl sequences (Ville, Anusha)
- Fix bigjoiner checks for fused pipes (Ville)
- Fix ADP+ degamma LUT size (Ville)
- Fix DVO ch7xxx and sil164 suspend/resume (Ville)
- Fix memory leak in VBT parsing (Xia Fukun)
- Fix VBT packet port selection for dual link DSI (Mikko Kovanen)
- Fix SDP infoframe product string for discrete graphics (Clint)
- Fix VLV/CHV HDMI/DP audio enable (Ville)
- Fix VRR delays and calculations (Ville)
- No longer disable transcoder for PHY test pattern change (Khaled)
- Fix dual PPS handling (Ville)
- Fix timeout and wait for DDI BUF CTL active after enabling (Ankit)
Merges:
- Backmerge drm-next to sync up with v6.2-rc1 (Jani)
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87tu0wez34.fsf@intel.com
65 files changed, 3116 insertions, 1475 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index c6e3792622f2..9c0990c0ec87 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -56,24 +56,33 @@ config DRM_I915 If "M" is selected, the module will be called i915. config DRM_I915_FORCE_PROBE - string "Force probe driver for selected new Intel hardware" + string "Force probe i915 for selected Intel hardware IDs" depends on DRM_I915 help This is the default value for the i915.force_probe module parameter. Using the module parameter overrides this option. - Force probe the driver for new Intel graphics devices that are + Force probe the i915 for Intel graphics devices that are recognized but not properly supported by this kernel version. It is recommended to upgrade to a kernel version with proper support as soon as it is available. + It can also be used to block the probe of recognized and fully + supported devices. + Use "" to disable force probe. If in doubt, use this. - Use "<pci-id>[,<pci-id>,...]" to force probe the driver for listed + Use "<pci-id>[,<pci-id>,...]" to force probe the i915 for listed devices. For example, "4500" or "4500,4571". Use "*" to force probe the driver for all known devices. + Use "!" right before the ID to block the probe of the device. For + example, "4500,!4571" forces the probe of 4500 and blocks the probe of + 4571. + + Use "!*" to block the probe of the driver for all known devices. + config DRM_I915_CAPTURE_ERROR bool "Enable capturing GPU state following a hang" depends on DRM_I915 diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 01974b82d205..7046e435a155 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -48,9 +48,7 @@ i915-y += i915_driver.o \ i915_sysfs.o \ i915_utils.o \ intel_device_info.o \ - intel_dram.o \ intel_memory_region.o \ - intel_pch.o \ intel_pcode.o \ intel_pm.o \ intel_region_ttm.o \ @@ -62,6 +60,11 @@ i915-y += i915_driver.o \ vlv_sideband.o \ vlv_suspend.o +# core peripheral code +i915-y += \ + soc/intel_dram.o \ + soc/intel_pch.o + # core library code i915-y += \ i915_memcpy.o \ diff --git a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c index 54f58ba44b9f..6d948520e9a6 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c @@ -50,15 +50,26 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define CH7xxx_INPUT_CLOCK 0x1d #define CH7xxx_GPIO 0x1e #define CH7xxx_GPIO_HPIR (1<<3) -#define CH7xxx_IDF 0x1f +#define CH7xxx_IDF 0x1f +#define CH7xxx_IDF_IBS (1<<7) +#define CH7xxx_IDF_DES (1<<6) #define CH7xxx_IDF_HSP (1<<3) #define CH7xxx_IDF_VSP (1<<4) #define CH7xxx_CONNECTION_DETECT 0x20 #define CH7xxx_CDET_DVI (1<<5) -#define CH7301_DAC_CNTL 0x21 +#define CH7xxx_DAC_CNTL 0x21 +#define CH7xxx_SYNCO_MASK (3 << 3) +#define CH7xxx_SYNCO_VGA_HSYNC (1 << 3) + +#define CH7xxx_CLOCK_OUTPUT 0x22 +#define CH7xxx_BCOEN (1 << 4) +#define CH7xxx_BCOP (1 << 3) +#define CH7xxx_BCO_MASK (7 << 0) +#define CH7xxx_BCO_VGA_VSYNC (6 << 0) + #define CH7301_HOTPLUG 0x23 #define CH7xxx_TCTL 0x31 #define CH7xxx_TVCO 0x32 @@ -301,6 +312,8 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo, ch7xxx_readb(dvo, CH7xxx_IDF, &idf); + idf |= CH7xxx_IDF_IBS; + idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP); if (mode->flags & DRM_MODE_FLAG_PHSYNC) idf |= CH7xxx_IDF_HSP; @@ -309,6 +322,11 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo, idf |= CH7xxx_IDF_VSP; ch7xxx_writeb(dvo, CH7xxx_IDF, idf); + + ch7xxx_writeb(dvo, CH7xxx_DAC_CNTL, + CH7xxx_SYNCO_VGA_HSYNC); + ch7xxx_writeb(dvo, CH7xxx_CLOCK_OUTPUT, + CH7xxx_BCOEN | CH7xxx_BCO_VGA_VSYNC); } /* set the CH7xxx power state */ diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index 0dfa0a0209ff..4acc8ce29c0b 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -58,6 +58,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SIL164_9_MDI (1<<0) #define SIL164_REGC 0x0c +#define SIL164_C_SCNT (1<<7) +#define SIL164_C_PLLF_MASK (0xf<<1) +#define SIL164_C_PLLF_REC (4<<1) +#define SIL164_C_PFEN (1<<0) struct sil164_priv { //I2CDevRec d; @@ -205,7 +209,13 @@ static void sil164_mode_set(struct intel_dvo_device *dvo, sil164_writeb(sil, 0x0c, 0x89); sil164_writeb(sil, 0x08, 0x31);*/ /* don't do much */ - return; + + sil164_writeb(dvo, SIL164_REG8, + SIL164_8_VEN | SIL164_8_HEN); + sil164_writeb(dvo, SIL164_REG9, + SIL164_9_TSEL); + sil164_writeb(dvo, SIL164_REGC, + SIL164_C_PLLF_REC | SIL164_C_PFEN); } /* set the SIL164 power state */ @@ -224,7 +234,6 @@ static void sil164_dpms(struct intel_dvo_device *dvo, bool enable) ch &= ~SIL164_8_PD; sil164_writeb(dvo, SIL164_REG8, ch); - return; } static bool sil164_get_hw_state(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index d16b30a2dded..ae14c794c4bc 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -2043,7 +2043,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) /* attach connector to encoder */ intel_connector_attach_encoder(intel_connector, encoder); - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL); mutex_lock(&dev_priv->drm.mode_config.mutex); intel_panel_add_vbt_lfp_fixed_mode(intel_connector); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 6621aa245caf..a9a3f3715279 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -41,6 +41,7 @@ #include "intel_global_state.h" #include "intel_hdcp.h" #include "intel_psr.h" +#include "intel_fb.h" #include "skl_universal_plane.h" /** @@ -310,11 +311,11 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, kfree(crtc_state); } -static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, - int num_scalers_need, struct intel_crtc *intel_crtc, - const char *name, int idx, - struct intel_plane_state *plane_state, - int *scaler_id) +static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, + int num_scalers_need, struct intel_crtc *intel_crtc, + const char *name, int idx, + struct intel_plane_state *plane_state, + int *scaler_id) { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); int j; @@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta if (drm_WARN(&dev_priv->drm, *scaler_id < 0, "Cannot find scaler for %s:%d\n", name, idx)) - return; + return -EINVAL; /* set scaler mode */ if (plane_state && plane_state->hw.fb && @@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta mode = SKL_PS_SCALER_MODE_DYN; } + /* + * FIXME: we should also check the scaler factors for pfit, so + * this shouldn't be tied directly to planes. + */ + if (plane_state && plane_state->hw.fb) { + const struct drm_framebuffer *fb = plane_state->hw.fb; + const struct drm_rect *src = &plane_state->uapi.src; + const struct drm_rect *dst = &plane_state->uapi.dst; + int hscale, vscale, max_vscale, max_hscale; + + /* + * FIXME: When two scalers are needed, but only one of + * them needs to downscale, we should make sure that + * the one that needs downscaling support is assigned + * as the first scaler, so we don't reject downscaling + * unnecessarily. + */ + + if (DISPLAY_VER(dev_priv) >= 14) { + /* + * On versions 14 and up, only the first + * scaler supports a vertical scaling factor + * of more than 1.0, while a horizontal + * scaling factor of 3.0 is supported. + */ + max_hscale = 0x30000 - 1; + if (*scaler_id == 0) + max_vscale = 0x30000 - 1; + else + max_vscale = 0x10000; + + } else if (DISPLAY_VER(dev_priv) >= 10 || + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { + max_hscale = 0x30000 - 1; + max_vscale = 0x30000 - 1; + } else { + max_hscale = 0x20000 - 1; + max_vscale = 0x20000 - 1; + } + + /* + * FIXME: We should change the if-else block above to + * support HQ vs dynamic scaler properly. + */ + + /* Check if required scaling is within limits */ + hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale); + vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(&dev_priv->drm, + "Scaler %d doesn't support required plane scaling\n", + *scaler_id); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); + + return -EINVAL; + } + } + drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", intel_crtc->pipe, *scaler_id, name, idx); scaler_state->scalers[*scaler_id].mode = mode; + + return 0; } /** @@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { int *scaler_id; const char *name; - int idx; + int idx, ret; /* skip if scaler not required */ if (!(scaler_state->scaler_users & (1 << i))) @@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, scaler_id = &plane_state->scaler_id; } - intel_atomic_setup_scaler(scaler_state, num_scalers_need, - intel_crtc, name, idx, - plane_state, scaler_id); + ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need, + intel_crtc, name, idx, + plane_state, scaler_id); + if (ret < 0) + return ret; } return 0; diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 98c3322b4549..626c47e96a6d 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -798,6 +798,17 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&i915->display.audio.mutex); } +void intel_audio_sdp_split_update(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum transcoder trans = crtc_state->cpu_transcoder; + + if (HAS_DP20(i915)) + intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, + crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); +} + /** * intel_audio_codec_enable - Enable the audio codec for HD audio * @encoder: encoder on which to enable audio diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 63b22131dc45..1b87257c6a17 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -22,5 +22,7 @@ void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); void intel_audio_init(struct drm_i915_private *dev_priv); void intel_audio_deinit(struct drm_i915_private *dev_priv); +void intel_audio_sdp_split_update(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); #endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 71af88a70461..5b7da72c95b8 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -83,16 +83,16 @@ static u32 scale_hw_to_user(struct intel_connector *connector, u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); - if (dev_priv->params.invert_brightness < 0) + if (i915->params.invert_brightness < 0) return val; - if (dev_priv->params.invert_brightness > 0 || - intel_has_quirk(dev_priv, QUIRK_INVERT_BRIGHTNESS)) { + if (i915->params.invert_brightness > 0 || + intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS)) { return panel->backlight.pwm_level_max - val + panel->backlight.pwm_level_min; } @@ -111,10 +111,10 @@ void intel_backlight_set_pwm_level(const struct drm_connector_state *conn_state, u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&dev_priv->drm, + drm_WARN_ON_ONCE(&i915->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); val = scale(val, panel->backlight.min, panel->backlight.max, @@ -125,14 +125,14 @@ u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&dev_priv->drm, + drm_WARN_ON_ONCE(&i915->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); - if (dev_priv->params.invert_brightness > 0 || - (dev_priv->params.invert_brightness == 0 && intel_has_quirk(dev_priv, QUIRK_INVERT_BRIGHTNESS))) + if (i915->params.invert_brightness > 0 || + (i915->params.invert_brightness == 0 && intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS))) val = panel->backlight.pwm_level_max - (val - panel->backlight.pwm_level_min); return scale(val, panel->backlight.pwm_level_min, panel->backlight.pwm_level_max, @@ -141,32 +141,32 @@ u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) static u32 lpt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return intel_de_read(dev_priv, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 pch_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return intel_de_read(dev_priv, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val; - val = intel_de_read(dev_priv, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (DISPLAY_VER(dev_priv) < 4) + val = intel_de_read(i915, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (DISPLAY_VER(i915) < 4) val >>= 1; if (panel->backlight.combination_mode) { u8 lbpc; - pci_read_config_byte(to_pci_dev(dev_priv->drm.dev), LBPC, &lbpc); + pci_read_config_byte(to_pci_dev(i915->drm.dev), LBPC, &lbpc); val *= lbpc; } @@ -175,21 +175,20 @@ static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unuse static u32 vlv_get_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) return 0; - return intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 bxt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - return intel_de_read(dev_priv, - BXT_BLC_PWM_DUTY(panel->backlight.controller)); + return intel_de_read(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller)); } static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe unused) @@ -204,69 +203,69 @@ static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe un static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + u32 val; - u32 val = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, val | level); + val = intel_de_read(i915, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, BLC_PWM_PCH_CTL2, val | level); } static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, BLC_PWM_CPU_CTL, tmp | level); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, BLC_PWM_CPU_CTL, tmp | level); } static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp, mask; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); if (panel->backlight.combination_mode) { u8 lbpc; lbpc = level * 0xfe / panel->backlight.pwm_level_max + 1; level /= lbpc; - pci_write_config_byte(to_pci_dev(dev_priv->drm.dev), LBPC, lbpc); + pci_write_config_byte(to_pci_dev(i915->drm.dev), LBPC, lbpc); } - if (DISPLAY_VER(dev_priv) == 4) { + if (DISPLAY_VER(i915) == 4) { mask = BACKLIGHT_DUTY_CYCLE_MASK; } else { level <<= 1; mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; } - tmp = intel_de_read(dev_priv, BLC_PWM_CTL) & ~mask; - intel_de_write(dev_priv, BLC_PWM_CTL, tmp | level); + tmp = intel_de_read(i915, BLC_PWM_CTL) & ~mask; + intel_de_write(i915, BLC_PWM_CTL, tmp | level); } static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 tmp; - tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe), tmp | level); + tmp = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), tmp | level); } static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - intel_de_write(dev_priv, - BXT_BLC_PWM_DUTY(panel->backlight.controller), level); + intel_de_write(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller), level); } static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -296,7 +295,7 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 hw_level; @@ -309,9 +308,9 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (!panel->backlight.present || !conn_state->crtc) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); - drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.max == 0); hw_level = clamp_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -325,13 +324,13 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, level); @@ -344,31 +343,29 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta * This needs rework if we need to add support for CPU PWM on PCH split * platforms. */ - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (tmp & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, - "cpu backlight was enabled, disabling\n"); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, - tmp & ~BLM_PWM_ENABLE); + drm_dbg_kms(&i915->drm, "cpu backlight was enabled, disabling\n"); + intel_de_write(i915, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); } - tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); } static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); - tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); } static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) @@ -378,62 +375,59 @@ static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_st static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { - struct drm_i915_private *dev_priv = to_i915(old_conn_state->connector->dev); + struct drm_i915_private *i915 = to_i915(old_conn_state->connector->dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, BLC_PWM_CTL2); - intel_de_write(dev_priv, BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_CTL2); + intel_de_write(i915, BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); } static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), - tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); } static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + tmp = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), tmp & ~BXT_BLC_PWM_ENABLE); if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); val &= ~UTIL_PIN_ENABLE; - intel_de_write(dev_priv, UTIL_PIN_CTL, val); + intel_de_write(i915, UTIL_PIN_CTL, val); } } static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + tmp = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), tmp & ~BXT_BLC_PWM_ENABLE); } @@ -451,7 +445,7 @@ static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn void intel_backlight_disable(const struct drm_connector_state *old_conn_state) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) @@ -463,68 +457,66 @@ void intel_backlight_disable(const struct drm_connector_state *old_conn_state) * backlight. This will leave the backlight on unnecessarily when * another client is not activated. */ - if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { - drm_dbg_kms(&dev_priv->drm, - "Skipping backlight disable on vga switch\n"); + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { + drm_dbg_kms(&i915->drm, "Skipping backlight disable on vga switch\n"); return; } - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (panel->backlight.device) panel->backlight.device->props.power = FB_BLANK_POWERDOWN; panel->backlight.enabled = false; panel->backlight.funcs->disable(old_conn_state, 0); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2, schicken; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "pch backlight already enabled\n"); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); } - if (HAS_PCH_LPT(dev_priv)) { - schicken = intel_de_read(dev_priv, SOUTH_CHICKEN2); + if (HAS_PCH_LPT(i915)) { + schicken = intel_de_read(i915, SOUTH_CHICKEN2); if (panel->backlight.alternate_pwm_increment) schicken |= LPT_PWM_GRANULARITY; else schicken &= ~LPT_PWM_GRANULARITY; - intel_de_write(dev_priv, SOUTH_CHICKEN2, schicken); + intel_de_write(i915, SOUTH_CHICKEN2, schicken); } else { - schicken = intel_de_read(dev_priv, SOUTH_CHICKEN1); + schicken = intel_de_read(i915, SOUTH_CHICKEN1); if (panel->backlight.alternate_pwm_increment) schicken |= SPT_PWM_GRANULARITY; else schicken &= ~SPT_PWM_GRANULARITY; - intel_de_write(dev_priv, SOUTH_CHICKEN1, schicken); + intel_de_write(i915, SOUTH_CHICKEN1, schicken); } pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; /* After LPT, override is the default. */ - if (HAS_PCH_LPT(dev_priv)) + if (HAS_PCH_LPT(i915)) pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, - pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); @@ -534,61 +526,60 @@ static void pch_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (cpu_ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "cpu backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "cpu backlight already enabled\n"); cpu_ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); } - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "pch backlight already enabled\n"); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); } if (cpu_transcoder == TRANSCODER_EDP) cpu_ctl2 = BLM_TRANSCODER_EDP; else cpu_ctl2 = BLM_PIPE(cpu_transcoder); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2); - intel_de_posting_read(dev_priv, BLC_PWM_CPU_CTL2); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_posting_read(i915, BLC_PWM_CPU_CTL2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, - pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); } static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, freq; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); - intel_de_write(dev_priv, BLC_PWM_CTL, 0); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); + intel_de_write(i915, BLC_PWM_CTL, 0); } freq = panel->backlight.pwm_level_max; @@ -598,11 +589,11 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, ctl = freq << 17; if (panel->backlight.combination_mode) ctl |= BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm) + if (IS_PINEVIEW(i915) && panel->backlight.active_low_pwm) ctl |= BLM_POLARITY_PNV; - intel_de_write(dev_priv, BLC_PWM_CTL, ctl); - intel_de_posting_read(dev_priv, BLC_PWM_CTL); + intel_de_write(i915, BLC_PWM_CTL, ctl); + intel_de_posting_read(i915, BLC_PWM_CTL); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -612,24 +603,24 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 * that has backlight. */ - if (DISPLAY_VER(dev_priv) == 2) - intel_de_write(dev_priv, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); + if (DISPLAY_VER(i915) == 2) + intel_de_write(i915, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); } static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 ctl, ctl2, freq; - ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2); + ctl2 = intel_de_read(i915, BLC_PWM_CTL2); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2); + intel_de_write(i915, BLC_PWM_CTL2, ctl2); } freq = panel->backlight.pwm_level_max; @@ -637,16 +628,16 @@ static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, freq /= 0xff; ctl = freq << 16; - intel_de_write(dev_priv, BLC_PWM_CTL, ctl); + intel_de_write(i915, BLC_PWM_CTL, ctl); ctl2 = BLM_PIPE(pipe); if (panel->backlight.combination_mode) ctl2 |= BLM_COMBINATION_MODE; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2); - intel_de_posting_read(dev_priv, BLC_PWM_CTL2); - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_CTL2, ctl2); + intel_de_posting_read(i915, BLC_PWM_CTL2); + intel_de_write(i915, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); intel_backlight_set_pwm_level(conn_state, level); } @@ -655,20 +646,20 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 ctl, ctl2; - ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); } ctl = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe), ctl); + intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), ctl); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -676,50 +667,45 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, ctl2 = 0; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), ctl2); - intel_de_posting_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), - ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_posting_read(i915, VLV_BLC_PWM_CTL2(pipe)); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 pwm_ctl, val; /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); if (val & UTIL_PIN_ENABLE) { - drm_dbg_kms(&dev_priv->drm, - "util pin already enabled\n"); + drm_dbg_kms(&i915->drm, "util pin already enabled\n"); val &= ~UTIL_PIN_ENABLE; - intel_de_write(dev_priv, UTIL_PIN_CTL, val); + intel_de_write(i915, UTIL_PIN_CTL, val); } val = 0; if (panel->backlight.util_pin_active_low) val |= UTIL_PIN_POLARITY; - intel_de_write(dev_priv, UTIL_PIN_CTL, + intel_de_write(i915, UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); } - pwm_ctl = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(dev_priv, - BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -728,11 +714,9 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), - pwm_ctl); - intel_de_posting_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -740,22 +724,19 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; - pwm_ctl = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(dev_priv, - BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -764,11 +745,9 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), - pwm_ctl); - intel_de_posting_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -810,37 +789,37 @@ void intel_backlight_enable(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; if (!panel->backlight.present) return; - drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(pipe)); + drm_dbg_kms(&i915->drm, "pipe %c\n", pipe_name(pipe)); - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) static u32 intel_panel_get_backlight(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val = 0; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (panel->backlight.enabled) val = panel->backlight.funcs->get(connector, intel_connector_get_pipe(connector)); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); - drm_dbg_kms(&dev_priv->drm, "get backlight PWM = %d\n", val); + drm_dbg_kms(&i915->drm, "get backlight PWM = %d\n", val); return val; } @@ -859,16 +838,16 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 hw_level; if (!panel->backlight.present) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); - drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.max == 0); hw_level = scale_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -876,18 +855,19 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - struct drm_device *dev = connector->base.dev; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", - bd->props.brightness, bd->props.max_brightness); + drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); + + drm_dbg_kms(&i915->drm, "updating intel_backlight, brightness=%d/%d\n", + bd->props.brightness, bd->props.max_brightness); intel_panel_set_backlight(connector->base.state, bd->props.brightness, bd->props.max_brightness); @@ -907,28 +887,28 @@ static int intel_backlight_device_update_status(struct backlight_device *bd) bd->props.power = FB_BLANK_POWERDOWN; } - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + return 0; } static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); intel_wakeref_t wakeref; int ret = 0; - with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) { + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { u32 hw_level; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); hw_level = intel_panel_get_backlight(connector); ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); } return ret; @@ -1038,9 +1018,9 @@ void intel_backlight_device_unregister(struct intel_connector *connector) */ static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(i915)->rawclk_freq), pwm_freq_hz); } @@ -1077,7 +1057,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 mul, clock; @@ -1086,7 +1066,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else mul = 128; - if (HAS_PCH_LPT_H(dev_priv)) + if (HAS_PCH_LPT_H(i915)) clock = MHz(135); /* LPT:H */ else clock = MHz(24); /* LPT:LP */ @@ -1100,9 +1080,9 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(i915)->rawclk_freq), pwm_freq_hz * 128); } @@ -1116,13 +1096,13 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int clock; - if (IS_PINEVIEW(dev_priv)) - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + if (IS_PINEVIEW(i915)) + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); else - clock = KHz(dev_priv->display.cdclk.hw.cdclk); + clock = KHz(i915->display.cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); } @@ -1134,13 +1114,13 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int clock; - if (IS_G4X(dev_priv)) - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + if (IS_G4X(i915)) + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); else - clock = KHz(dev_priv->display.cdclk.hw.cdclk); + clock = KHz(i915->display.cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); } @@ -1152,17 +1132,17 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int mul, clock; - if ((intel_de_read(dev_priv, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { - if (IS_CHERRYVIEW(dev_priv)) + if ((intel_de_read(i915, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { + if (IS_CHERRYVIEW(i915)) clock = KHz(19200); else clock = MHz(25); mul = 16; } else { - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); mul = 128; } @@ -1171,16 +1151,16 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u16 get_vbt_pwm_freq(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u16 pwm_freq_hz = connector->panel.vbt.backlight.pwm_freq_hz; if (pwm_freq_hz) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "VBT defined backlight frequency %u Hz\n", pwm_freq_hz); } else { pwm_freq_hz = 200; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "default backlight frequency %u Hz\n", pwm_freq_hz); } @@ -1190,20 +1170,20 @@ static u16 get_vbt_pwm_freq(struct intel_connector *connector) static u32 get_backlight_max_vbt(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u16 pwm_freq_hz = get_vbt_pwm_freq(connector); u32 pwm; if (!panel->backlight.pwm_funcs->hz_to_pwm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "backlight frequency conversion not supported\n"); return 0; } pwm = panel->backlight.pwm_funcs->hz_to_pwm(connector, pwm_freq_hz); if (!pwm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "backlight frequency conversion failed\n"); return 0; } @@ -1216,11 +1196,11 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) */ static u32 get_backlight_min_vbt(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; int min; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); /* * XXX: If the vbt value is 255, it makes min equal to max, which leads @@ -1231,7 +1211,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) */ min = clamp_t(int, connector->panel.vbt.backlight.min_brightness, 0, 64); if (min != connector->panel.vbt.backlight.min_brightness) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "clamping VBT min backlight %d/255 to %d/255\n", connector->panel.vbt.backlight.min_brightness, min); } @@ -1242,24 +1222,24 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; bool alt, cpu_mode; - if (HAS_PCH_LPT(dev_priv)) - alt = intel_de_read(dev_priv, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; + if (HAS_PCH_LPT(i915)) + alt = intel_de_read(i915, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; else - alt = intel_de_read(dev_priv, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; + alt = intel_de_read(i915, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; panel->backlight.alternate_pwm_increment = alt; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1271,22 +1251,22 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.pwm_enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE; - cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(dev_priv) && + cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(i915) && !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) && (cpu_ctl2 & BLM_PWM_ENABLE); if (cpu_mode) { val = pch_get_backlight(connector, unused); - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "CPU backlight register was enabled, switching to PCH override\n"); /* Write converted CPU PWM value to PCH override register */ lpt_set_backlight(connector->base.state, val); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE); } @@ -1295,14 +1275,14 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; if (!panel->backlight.pwm_level_max) @@ -1313,7 +1293,7 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.pwm_level_min = get_backlight_min_vbt(connector); - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); panel->backlight.pwm_enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && (pch_ctl1 & BLM_PCH_PWM_ENABLE); @@ -1322,16 +1302,16 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, val; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); - if (DISPLAY_VER(dev_priv) == 2 || IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) + if (DISPLAY_VER(i915) == 2 || IS_I915GM(i915) || IS_I945GM(i915)) panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev_priv)) + if (IS_PINEVIEW(i915)) panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.pwm_level_max = ctl >> 17; @@ -1360,15 +1340,15 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2); + ctl2 = intel_de_read(i915, BLC_PWM_CTL2); panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1389,17 +1369,17 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) return -ENODEV; - ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)); + ctl = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1418,25 +1398,25 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe static int bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; panel->backlight.controller = connector->panel.vbt.backlight.controller; - pwm_ctl = intel_de_read(dev_priv, + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); panel->backlight.util_pin_active_low = val & UTIL_PIN_POLARITY; } panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(dev_priv, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1454,7 +1434,7 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) static int cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; @@ -1465,12 +1445,12 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) */ panel->backlight.controller = 0; - pwm_ctl = intel_de_read(dev_priv, + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(dev_priv, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1488,23 +1468,22 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) static int ext_pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; const char *desc; u32 level; /* Get the right PWM chip for DSI backlight according to VBT */ if (connector->panel.vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { - panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight"); + panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_pmic_backlight"); desc = "PMIC"; } else { - panel->backlight.pwm = pwm_get(dev->dev, "pwm_soc_backlight"); + panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_soc_backlight"); desc = "SoC"; } if (IS_ERR(panel->backlight.pwm)) { - drm_err(&dev_priv->drm, "Failed to get the %s PWM chip\n", + drm_err(&i915->drm, "Failed to get the %s PWM chip\n", desc); panel->backlight.pwm = NULL; return -ENODEV; @@ -1522,7 +1501,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, level = intel_backlight_invert_pwm_level(connector, level); panel->backlight.pwm_enabled = true; - drm_dbg_kms(&dev_priv->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", + drm_dbg_kms(&i915->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period, get_vbt_pwm_freq(connector), level); } else { @@ -1531,7 +1510,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, NSEC_PER_SEC / get_vbt_pwm_freq(connector); } - drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", + drm_info(&i915->drm, "Using %s PWM for LCD backlight control\n", desc); return 0; } @@ -1594,47 +1573,47 @@ void intel_backlight_update(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (!panel->backlight.enabled) __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; int ret; if (!connector->panel.vbt.backlight.present) { - if (intel_has_quirk(dev_priv, QUIRK_BACKLIGHT_PRESENT)) { - drm_dbg_kms(&dev_priv->drm, + if (intel_has_quirk(i915, QUIRK_BACKLIGHT_PRESENT)) { + drm_dbg_kms(&i915->drm, "no backlight present per VBT, but present per quirk\n"); } else { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "no backlight present per VBT\n"); return 0; } } /* ensure intel_panel has been initialized first */ - if (drm_WARN_ON(&dev_priv->drm, !panel->backlight.funcs)) + if (drm_WARN_ON(&i915->drm, !panel->backlight.funcs)) return -ENODEV; /* set level and max in panel struct */ - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); ret = panel->backlight.funcs->setup(connector, pipe); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); if (ret) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "failed to setup backlight for connector %s\n", connector->base.name); return ret; @@ -1642,7 +1621,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) panel->backlight.present = true; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "Connector %s backlight initialized, %s, brightness %u/%u\n", connector->base.name, str_enabled_disabled(panel->backlight.enabled), @@ -1753,30 +1732,30 @@ void intel_backlight_init_funcs(struct intel_panel *panel) { struct intel_connector *connector = container_of(panel, struct intel_connector, panel); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI && intel_dsi_dcs_init_backlight_funcs(connector) == 0) return; - if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { + if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { panel->backlight.pwm_funcs = &bxt_pwm_funcs; - } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) { + } else if (INTEL_PCH_TYPE(i915) >= PCH_CNP) { panel->backlight.pwm_funcs = &cnp_pwm_funcs; - } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_LPT) { - if (HAS_PCH_LPT(dev_priv)) + } else if (INTEL_PCH_TYPE(i915) >= PCH_LPT) { + if (HAS_PCH_LPT(i915)) panel->backlight.pwm_funcs = &lpt_pwm_funcs; else panel->backlight.pwm_funcs = &spt_pwm_funcs; - } else if (HAS_PCH_SPLIT(dev_priv)) { + } else if (HAS_PCH_SPLIT(i915)) { panel->backlight.pwm_funcs = &pch_pwm_funcs; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) { panel->backlight.pwm_funcs = &ext_pwm_funcs; } else { panel->backlight.pwm_funcs = &vlv_pwm_funcs; } - } else if (DISPLAY_VER(dev_priv) == 4) { + } else if (DISPLAY_VER(i915) == 4) { panel->backlight.pwm_funcs = &i965_pwm_funcs; } else { panel->backlight.pwm_funcs = &i9xx_pwm_funcs; @@ -1786,7 +1765,7 @@ void intel_backlight_init_funcs(struct intel_panel *panel) if (intel_dp_aux_init_backlight_funcs(connector) == 0) return; - if (!intel_has_quirk(dev_priv, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) + if (!intel_has_quirk(i915, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) connector->panel.backlight.power = intel_pps_backlight_power; } diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h index 344eb8096bd2..d0cdfd631d75 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight_regs.h +++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h @@ -8,23 +8,20 @@ #include "intel_display_reg_defs.h" -#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250) -#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350) -#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ - _VLV_BLC_PWM_CTL2_B) +#define _VLV_BLC_PWM_CTL2_A (VLV_DISPLAY_BASE + 0x61250) +#define _VLV_BLC_PWM_CTL2_B (VLV_DISPLAY_BASE + 0x61350) +#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, _VLV_BLC_PWM_CTL2_B) -#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254) -#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354) -#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ - _VLV_BLC_PWM_CTL_B) +#define _VLV_BLC_PWM_CTL_A (VLV_DISPLAY_BASE + 0x61254) +#define _VLV_BLC_PWM_CTL_B (VLV_DISPLAY_BASE + 0x61354) +#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, _VLV_BLC_PWM_CTL_B) -#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260) -#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360) -#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ - _VLV_BLC_HIST_CTL_B) +#define _VLV_BLC_HIST_CTL_A (VLV_DISPLAY_BASE + 0x61260) +#define _VLV_BLC_HIST_CTL_B (VLV_DISPLAY_BASE + 0x61360) +#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, _VLV_BLC_HIST_CTL_B) /* Backlight control */ -#define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */ +#define BLC_PWM_CTL2 _MMIO(0x61250) /* 965+ only */ #define BLM_PWM_ENABLE (1 << 31) #define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ #define BLM_PIPE_SELECT (1 << 29) @@ -47,7 +44,7 @@ #define BLM_PHASE_IN_COUNT_MASK (0xff << 8) #define BLM_PHASE_IN_INCR_SHIFT (0) #define BLM_PHASE_IN_INCR_MASK (0xff << 0) -#define BLC_PWM_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254) +#define BLC_PWM_CTL _MMIO(0x61254) /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. @@ -69,7 +66,7 @@ #define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) #define BLM_POLARITY_PNV (1 << 0) /* pnv only */ -#define BLC_HIST_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260) +#define BLC_HIST_CTL _MMIO(0x61260) #define BLM_HISTOGRAM_ENABLE (1 << 31) /* New registers for PCH-split platforms. Safe where new bits show up, the diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 572a4e3769f3..55544d484318 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -620,14 +620,14 @@ static void dump_pnp_id(struct drm_i915_private *i915, static int opregion_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { return intel_opregion_get_panel_type(i915); } static int vbt_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { const struct bdb_lvds_options *lvds_options; @@ -652,7 +652,7 @@ static int vbt_get_panel_type(struct drm_i915_private *i915, static int pnpid_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_ptrs *ptrs; @@ -701,9 +701,9 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, static int fallback_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { - return 0; + return use_fallback ? 0 : -1; } enum panel_type { @@ -715,13 +715,13 @@ enum panel_type { static int get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { struct { const char *name; int (*get_panel_type)(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid); + const struct edid *edid, bool use_fallback); int panel_type; } panel_types[] = { [PANEL_TYPE_OPREGION] = { @@ -744,7 +744,8 @@ static int get_panel_type(struct drm_i915_private *i915, int i; for (i = 0; i < ARRAY_SIZE(panel_types); i++) { - panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, edid); + panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, + edid, use_fallback); drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf && panel_types[i].panel_type != 0xff); @@ -3183,14 +3184,26 @@ out: kfree(oprom_vbt); } -void intel_bios_init_panel(struct drm_i915_private *i915, - struct intel_panel *panel, - const struct intel_bios_encoder_data *devdata, - const struct edid *edid) +static void intel_bios_init_panel(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid, + bool use_fallback) { - init_vbt_panel_defaults(panel); + /* already have it? */ + if (panel->vbt.panel_type >= 0) { + drm_WARN_ON(&i915->drm, !use_fallback); + return; + } - panel->vbt.panel_type = get_panel_type(i915, devdata, edid); + panel->vbt.panel_type = get_panel_type(i915, devdata, + edid, use_fallback); + if (panel->vbt.panel_type < 0) { + drm_WARN_ON(&i915->drm, use_fallback); + return; + } + + init_vbt_panel_defaults(panel); parse_panel_options(i915, panel); parse_generic_dtd(i915, panel); @@ -3205,6 +3218,21 @@ void intel_bios_init_panel(struct drm_i915_private *i915, parse_mipi_sequence(i915, panel); } +void intel_bios_init_panel_early(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata) +{ + intel_bios_init_panel(i915, panel, devdata, NULL, false); +} + +void intel_bios_init_panel_late(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) +{ + intel_bios_init_panel(i915, panel, devdata, edid, true); +} + /** * intel_bios_driver_remove - Free any resources allocated by intel_bios_init() * @i915: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index e375405a7828..ff1fdd2e0c1c 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -232,10 +232,13 @@ struct mipi_pps_data { } __packed; void intel_bios_init(struct drm_i915_private *dev_priv); -void intel_bios_init_panel(struct drm_i915_private *dev_priv, - struct intel_panel *panel, - const struct intel_bios_encoder_data *devdata, - const struct edid *edid); +void intel_bios_init_panel_early(struct drm_i915_private *dev_priv, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata); +void intel_bios_init_panel_late(struct drm_i915_private *dev_priv, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid); void intel_bios_fini_panel(struct intel_panel *panel); void intel_bios_driver_remove(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b74e36d76013..0c107a38f9d0 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1346,6 +1346,16 @@ static const struct intel_cdclk_vals dg2_cdclk_table[] = { {} }; +static const struct intel_cdclk_vals mtl_cdclk_table[] = { + { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a }, + { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 }, + { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0x0000 }, + {} +}; + static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk) { const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table; @@ -1717,39 +1727,92 @@ static void dg2_cdclk_squash_program(struct drm_i915_private *i915, intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl); } -static void bxt_set_cdclk(struct drm_i915_private *dev_priv, - const struct intel_cdclk_config *cdclk_config, - enum pipe pipe) +static bool cdclk_pll_is_unknown(unsigned int vco) +{ + /* + * Ensure driver does not take the crawl path for the + * case when the vco is set to ~0 in the + * sanitize path. + */ + return vco == ~0; +} + +static int cdclk_squash_divider(u16 waveform) +{ + return hweight16(waveform ?: 0xffff); +} + +static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, + const struct intel_cdclk_config *old_cdclk_config, + const struct intel_cdclk_config *new_cdclk_config, + struct intel_cdclk_config *mid_cdclk_config) +{ + u16 old_waveform, new_waveform, mid_waveform; + int size = 16; + int div = 2; + + /* Return if PLL is in an unknown state, force a complete disable and re-enable. */ + if (cdclk_pll_is_unknown(old_cdclk_config->vco)) + return false; + + /* Return if both Squash and Crawl are not present */ + if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915)) + return false; + + old_waveform = cdclk_squash_waveform(i915, old_cdclk_config->cdclk); + new_waveform = cdclk_squash_waveform(i915, new_cdclk_config->cdclk); + + /* Return if Squash only or Crawl only is the desired action */ + if (old_cdclk_config->vco == 0 || new_cdclk_config->vco == 0 || + old_cdclk_config->vco == new_cdclk_config->vco || + old_waveform == new_waveform) + return false; + + *mid_cdclk_config = *new_cdclk_config; + + /* + * Populate the mid_cdclk_config accordingly. + * - If moving to a higher cdclk, the desired action is squashing. + * The mid cdclk config should have the new (squash) waveform. + * - If moving to a lower cdclk, the desired action is crawling. + * The mid cdclk config should have the new vco. + */ + + if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) { + mid_cdclk_config->vco = old_cdclk_config->vco; + mid_waveform = new_waveform; + } else { + mid_cdclk_config->vco = new_cdclk_config->vco; + mid_waveform = old_waveform; + } + + mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) * + mid_cdclk_config->vco, size * div); + + /* make sure the mid clock came out sane */ + + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk < + min(old_cdclk_config->cdclk, new_cdclk_config->cdclk)); + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk > + i915->display.cdclk.max_cdclk_freq); + drm_WARN_ON(&i915->drm, cdclk_squash_waveform(i915, mid_cdclk_config->cdclk) != + mid_waveform); + + return true; +} + +static void _bxt_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_config *cdclk_config, + enum pipe pipe) { int cdclk = cdclk_config->cdclk; int vco = cdclk_config->vco; u32 val; u16 waveform; int clock; - int ret; - - /* Inform power controller of upcoming frequency change. */ - if (DISPLAY_VER(dev_priv) >= 11) - ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, - SKL_CDCLK_PREPARE_FOR_CHANGE, - SKL_CDCLK_READY_FOR_CHANGE, - SKL_CDCLK_READY_FOR_CHANGE, 3); - else - /* - * BSpec requires us to wait up to 150usec, but that leads to - * timeouts; the 2ms used here is based on experiment. - */ - ret = snb_pcode_write_timeout(&dev_priv->uncore, - HSW_PCODE_DE_WRITE_FREQ_REQ, - 0x80000000, 150, 2); - if (ret) { - drm_err(&dev_priv->drm, - "Failed to inform PCU about cdclk change (err %d, freq %d)\n", - ret, cdclk); - return; - } - if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) { + if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 && + !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) { if (dev_priv->display.cdclk.hw.vco != vco) adlp_cdclk_pll_crawl(dev_priv, vco); } else if (DISPLAY_VER(dev_priv) >= 11) @@ -1782,11 +1845,62 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, if (pipe != INVALID_PIPE) intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); +} - if (DISPLAY_VER(dev_priv) >= 11) { +static void bxt_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_config *cdclk_config, + enum pipe pipe) +{ + struct intel_cdclk_config mid_cdclk_config; + int cdclk = cdclk_config->cdclk; + int ret = 0; + + /* + * Inform power controller of upcoming frequency change. + * Display versions 14 and beyond do not follow the PUnit + * mailbox communication, skip + * this step. + */ + if (DISPLAY_VER(dev_priv) >= 14) + /* NOOP */; + else if (DISPLAY_VER(dev_priv) >= 11) + ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, + SKL_CDCLK_PREPARE_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, 3); + else + /* + * BSpec requires us to wait up to 150usec, but that leads to + * timeouts; the 2ms used here is based on experiment. + */ + ret = snb_pcode_write_timeout(&dev_priv->uncore, + HSW_PCODE_DE_WRITE_FREQ_REQ, + 0x80000000, 150, 2); + + if (ret) { + drm_err(&dev_priv->drm, + "Failed to inform PCU about cdclk change (err %d, freq %d)\n", + ret, cdclk); + return; + } + + if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw, + cdclk_config, &mid_cdclk_config)) { + _bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe); + _bxt_set_cdclk(dev_priv, cdclk_config, pipe); + } else { + _bxt_set_cdclk(dev_priv, cdclk_config, pipe); + } + + if (DISPLAY_VER(dev_priv) >= 14) + /* + * NOOP - No Pcode communication needed for + * Display versions 14 and beyond + */; + else if (DISPLAY_VER(dev_priv) >= 11) ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, cdclk_config->voltage_level); - } else { + else /* * The timeout isn't specified, the 2ms used here is based on * experiment. @@ -1797,7 +1911,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, cdclk_config->voltage_level, 150, 2); - } if (ret) { drm_err(&dev_priv->drm, @@ -1954,6 +2067,28 @@ void intel_cdclk_uninit_hw(struct drm_i915_private *i915) skl_cdclk_uninit_hw(i915); } +static bool intel_cdclk_can_crawl_and_squash(struct drm_i915_private *i915, + const struct intel_cdclk_config *a, + const struct intel_cdclk_config *b) +{ + u16 old_waveform; + u16 new_waveform; + + drm_WARN_ON(&i915->drm, cdclk_pll_is_unknown(a->vco)); + + if (a->vco == 0 || b->vco == 0) + return false; + + if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915)) + return false; + + old_waveform = cdclk_squash_waveform(i915, a->cdclk); + new_waveform = cdclk_squash_waveform(i915, b->cdclk); + + return a->vco != b->vco && + old_waveform != new_waveform; +} + static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *a, const struct intel_cdclk_config *b) @@ -2760,9 +2895,14 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) pipe = INVALID_PIPE; } - if (intel_cdclk_can_squash(dev_priv, - &old_cdclk_state->actual, - &new_cdclk_state->actual)) { + if (intel_cdclk_can_crawl_and_squash(dev_priv, + &old_cdclk_state->actual, + &new_cdclk_state->actual)) { + drm_dbg_kms(&dev_priv->drm, + "Can change cdclk via crawling and squashing\n"); + } else if (intel_cdclk_can_squash(dev_priv, + &old_cdclk_state->actual, + &new_cdclk_state->actual)) { drm_dbg_kms(&dev_priv->drm, "Can change cdclk via squashing\n"); } else if (intel_cdclk_can_crawl(dev_priv, @@ -3060,6 +3200,13 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) return freq; } +static const struct intel_cdclk_funcs mtl_cdclk_funcs = { + .get_cdclk = bxt_get_cdclk, + .set_cdclk = bxt_set_cdclk, + .modeset_calc_cdclk = bxt_modeset_calc_cdclk, + .calc_voltage_level = tgl_calc_voltage_level, +}; + static const struct intel_cdclk_funcs tgl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, @@ -3195,7 +3342,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { */ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) { - if (IS_DG2(dev_priv)) { + if (IS_METEORLAKE(dev_priv)) { + dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs; + dev_priv->display.cdclk.table = mtl_cdclk_table; + } else if (IS_DG2(dev_priv)) { dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->display.cdclk.table = dg2_cdclk_table; } else if (IS_ALDERLAKE_P(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 250e83f1f5ac..d57631b0bb9a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -53,7 +53,18 @@ struct intel_color_funcs { * involved with the same commit. */ void (*load_luts)(const struct intel_crtc_state *crtc_state); + /* + * Read out the LUTs from the hardware into the software state. + * Used by eg. the hardware state checker. + */ void (*read_luts)(struct intel_crtc_state *crtc_state); + /* + * Compare the LUTs + */ + bool (*lut_equal)(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut); }; #define CTM_COEFF_SIGN (1ULL << 63) @@ -143,15 +154,7 @@ static const u16 ilk_csc_postoff_rgb_to_ycbcr[3] = { static bool lut_is_legacy(const struct drm_property_blob *lut) { - return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; -} - -static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state) -{ - return !crtc_state->hw.degamma_lut && - !crtc_state->hw.ctm && - crtc_state->hw.gamma_lut && - lut_is_legacy(crtc_state->hw.gamma_lut); + return lut && drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; } /* @@ -246,17 +249,44 @@ static void icl_update_output_csc(struct intel_crtc *crtc, intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]); } -static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) +static bool ilk_limited_range(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - /* - * FIXME if there's a gamma LUT after the CSC, we should - * do the range compression using the gamma LUT instead. - */ - return crtc_state->limited_color_range && - (IS_HASWELL(i915) || IS_BROADWELL(i915) || - IS_DISPLAY_VER(i915, 9, 10)); + /* icl+ have dedicated output CSC */ + if (DISPLAY_VER(i915) >= 11) + return false; + + /* pre-hsw have PIPECONF_COLOR_RANGE_SELECT */ + if (DISPLAY_VER(i915) < 7 || IS_IVYBRIDGE(i915)) + return false; + + return crtc_state->limited_color_range; +} + +static bool ilk_lut_limited_range(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (!ilk_limited_range(crtc_state)) + return false; + + if (crtc_state->c8_planes) + return false; + + if (DISPLAY_VER(i915) == 10) + return crtc_state->hw.gamma_lut; + else + return crtc_state->hw.gamma_lut && + (crtc_state->hw.degamma_lut || crtc_state->hw.ctm); +} + +static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_limited_range(crtc_state)) + return false; + + return !ilk_lut_limited_range(crtc_state); } static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, @@ -437,6 +467,79 @@ static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val) entry->blue = intel_color_lut_pack(REG_FIELD_GET(PALETTE_BLUE_MASK, val), 8); } +/* i8xx/i9xx+ 10bit slope format "even DW" (low 8 bits) */ +static u32 _i9xx_lut_10_ldw(u16 a) +{ + return drm_color_lut_extract(a, 10) & 0xff; +} + +static u32 i9xx_lut_10_ldw(const struct drm_color_lut *color) +{ + return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_ldw(color[0].red)) | + REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_ldw(color[0].green)) | + REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_ldw(color[0].blue)); +} + +/* i8xx/i9xx+ 10bit slope format "odd DW" (high 2 bits + slope) */ +static u32 _i9xx_lut_10_udw(u16 a, u16 b) +{ + unsigned int mantissa, exponent; + + a = drm_color_lut_extract(a, 10); + b = drm_color_lut_extract(b, 10); + + /* b = a + 8 * m * 2 ^ -e */ + mantissa = clamp(b - a, 0, 0x7f); + exponent = 3; + while (mantissa > 0xf) { + mantissa >>= 1; + exponent--; + } + + return (exponent << 6) | + (mantissa << 2) | + (a >> 8); +} + +static u32 i9xx_lut_10_udw(const struct drm_color_lut *color) +{ + return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_udw(color[0].red, color[1].red)) | + REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_udw(color[0].green, color[1].green)) | + REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_udw(color[0].blue, color[1].blue)); +} + +static void i9xx_lut_10_pack(struct drm_color_lut *color, + u32 ldw, u32 udw) +{ + u16 red = REG_FIELD_GET(PALETTE_10BIT_RED_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_RED_UDW_MASK, udw) << 8; + u16 green = REG_FIELD_GET(PALETTE_10BIT_GREEN_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_GREEN_UDW_MASK, udw) << 8; + u16 blue = REG_FIELD_GET(PALETTE_10BIT_BLUE_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_BLUE_UDW_MASK, udw) << 8; + + color->red = intel_color_lut_pack(red, 10); + color->green = intel_color_lut_pack(green, 10); + color->blue = intel_color_lut_pack(blue, 10); +} + +static void i9xx_lut_10_pack_slope(struct drm_color_lut *color, + u32 ldw, u32 udw) +{ + int r_exp = REG_FIELD_GET(PALETTE_10BIT_RED_EXP_MASK, udw); + int r_mant = REG_FIELD_GET(PALETTE_10BIT_RED_MANT_MASK, udw); + int g_exp = REG_FIELD_GET(PALETTE_10BIT_GREEN_EXP_MASK, udw); + int g_mant = REG_FIELD_GET(PALETTE_10BIT_GREEN_MANT_MASK, udw); + int b_exp = REG_FIELD_GET(PALETTE_10BIT_BLUE_EXP_MASK, udw); + int b_mant = REG_FIELD_GET(PALETTE_10BIT_BLUE_MANT_MASK, udw); + + i9xx_lut_10_pack(color, ldw, udw); + + color->red += r_mant << (3 - r_exp); + color->green += g_mant << (3 - g_exp); + color->blue += b_mant << (3 - b_exp); +} + /* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */ static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color) { @@ -600,9 +703,18 @@ create_linear_lut(struct drm_i915_private *i915, int lut_size) return blob; } +static u16 lut_limited_range(unsigned int value) +{ + unsigned int min = 16 << 8; + unsigned int max = 235 << 8; + + return value * (max - min) / 0xffff + min; +} + static struct drm_property_blob * create_resized_lut(struct drm_i915_private *i915, - const struct drm_property_blob *blob_in, int lut_out_size) + const struct drm_property_blob *blob_in, int lut_out_size, + bool limited_color_range) { int i, lut_in_size = drm_color_lut_size(blob_in); struct drm_property_blob *blob_out; @@ -618,8 +730,18 @@ create_resized_lut(struct drm_i915_private *i915, lut_in = blob_in->data; lut_out = blob_out->data; - for (i = 0; i < lut_out_size; i++) - lut_out[i] = lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)]; + for (i = 0; i < lut_out_size; i++) { + const struct drm_color_lut *entry = + &lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)]; + + if (limited_color_range) { + lut_out[i].red = lut_limited_range(entry->red); + lut_out[i].green = lut_limited_range(entry->green); + lut_out[i].blue = lut_limited_range(entry->blue); + } else { + lut_out[i] = *entry; + } + } return blob_out; } @@ -642,12 +764,38 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc, i9xx_lut_8(&lut[i])); } +static void i9xx_load_lut_10(struct intel_crtc *crtc, + const struct drm_property_blob *blob) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct drm_color_lut *lut = blob->data; + int i, lut_size = drm_color_lut_size(blob); + enum pipe pipe = crtc->pipe; + + for (i = 0; i < lut_size - 1; i++) { + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 0), + i9xx_lut_10_ldw(&lut[i])); + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 1), + i9xx_lut_10_udw(&lut[i])); + } +} + static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - i9xx_load_lut_8(crtc, post_csc_lut); + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + i9xx_load_lut_8(crtc, post_csc_lut); + break; + case GAMMA_MODE_MODE_10BIT: + i9xx_load_lut_10(crtc, post_csc_lut); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static void i965_load_lut_10p6(struct intel_crtc *crtc, @@ -675,16 +823,45 @@ static void i965_load_luts(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: i9xx_load_lut_8(crtc, post_csc_lut); - else + break; + case GAMMA_MODE_MODE_10BIT: i965_load_lut_10p6(crtc, post_csc_lut); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } -static void ilk_load_lut_8(struct intel_crtc *crtc, +static void ilk_lut_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (crtc_state->dsb) + intel_dsb_reg_write(crtc_state->dsb, reg, val); + else + intel_de_write_fw(i915, reg, val); +} + +static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (crtc_state->dsb) + intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val); + else + intel_de_write_fw(i915, reg, val); +} + +static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut; enum pipe pipe = crtc->pipe; int i; @@ -695,36 +872,35 @@ static void ilk_load_lut_8(struct intel_crtc *crtc, lut = blob->data; for (i = 0; i < 256; i++) - intel_de_write_fw(i915, LGC_PALETTE(pipe, i), - i9xx_lut_8(&lut[i])); + ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i), + i9xx_lut_8(&lut[i])); } -static void ilk_load_lut_10(struct intel_crtc *crtc, +static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) - intel_de_write_fw(i915, PREC_PALETTE(pipe, i), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PALETTE(pipe, i), + ilk_lut_10(&lut[i])); } static void ilk_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_10BIT: - ilk_load_lut_10(crtc, blob); + ilk_load_lut_10(crtc_state, blob); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -745,50 +921,56 @@ static int ivb_lut_10_size(u32 prec_index) * "Restriction : Index auto increment mode is not * supported and must not be enabled." */ -static void ivb_load_lut_10(struct intel_crtc *crtc, +static void ivb_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index++); - intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + prec_index + i); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); } /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } /* On BDW+ the index auto increment mode actually works */ -static void bdw_load_lut_10(struct intel_crtc *crtc, +static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + prec_index); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + prec_index); for (i = 0; i < lut_size; i++) - intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) @@ -797,9 +979,9 @@ static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); } static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) @@ -808,31 +990,30 @@ static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); } static void ivb_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_SPLIT: - ivb_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc_state, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - ivb_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: - ivb_load_lut_10(crtc, blob, + ivb_load_lut_10(crtc_state, blob, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; @@ -844,25 +1025,23 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) static void bdw_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_SPLIT: - bdw_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc_state, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: - - bdw_load_lut_10(crtc, blob, + bdw_load_lut_10(crtc_state, blob, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; @@ -894,9 +1073,11 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT | + PRE_CSC_GAMC_INDEX_VALUE(0)); for (i = 0; i < lut_size; i++) { /* @@ -912,32 +1093,31 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < glk_degamma_lut_size(i915)) - intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } static void glk_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (pre_csc_lut) glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, post_csc_lut); + ilk_load_lut_8(crtc_state, post_csc_lut); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); glk_load_lut_ext2_max(crtc_state); break; @@ -955,9 +1135,9 @@ ivb_load_lut_max(const struct intel_crtc_state *crtc_state, enum pipe pipe = crtc->pipe; /* FIXME LUT entries are 16 bit only, so we can prog 0xFFFF max */ - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), color->red); - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), color->green); - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), color->blue); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), color->red); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), color->green); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), color->blue); } static void @@ -976,17 +1156,23 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) * 9 entries, corresponding to values 0, 1/(8 * 128 * 256), * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256). */ - intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_udw(entry)); } + + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); } static void @@ -1009,14 +1195,19 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1], * seg2[0] being unused by the hardware. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_INDEX_VALUE(0)); + for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } /* @@ -1033,12 +1224,16 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) */ for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; ivb_load_lut_max(crtc_state, entry); @@ -1048,23 +1243,22 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (pre_csc_lut) glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, post_csc_lut); + ilk_load_lut_8(crtc_state, post_csc_lut); break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: icl_program_gamma_superfine_segment(crtc_state); icl_program_gamma_multi_segment(crtc_state); ivb_load_lut_ext_max(crtc_state); glk_load_lut_ext2_max(crtc_state); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); glk_load_lut_ext2_max(crtc_state); break; @@ -1073,7 +1267,8 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) break; } - intel_dsb_commit(crtc_state); + if (crtc_state->dsb) + intel_dsb_commit(crtc_state->dsb); } static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color) @@ -1087,6 +1282,13 @@ static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color) return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 14)); } +static void chv_cgm_degamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw) +{ + entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, ldw), 14); + entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_BLUE_LDW_MASK, ldw), 14); + entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_RED_UDW_MASK, udw), 14); +} + static void chv_load_cgm_degamma(struct intel_crtc *crtc, const struct drm_property_blob *blob) { @@ -1182,6 +1384,25 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) i915->display.funcs.color->color_commit_arm(crtc_state); } +void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + /* FIXME DSB has issues loading LUTs, disable it for now */ + return; + + crtc_state->dsb = intel_dsb_prepare(crtc); +} + +void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->dsb) + return; + + intel_dsb_cleanup(crtc_state->dsb); + crtc_state->dsb = NULL; +} + static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); @@ -1224,8 +1445,25 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - if (i915->display.funcs.color->read_luts) - i915->display.funcs.color->read_luts(crtc_state); + i915->display.funcs.color->read_luts(crtc_state); +} + +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + /* + * FIXME c8_planes readout missing thus + * .read_luts() doesn't read out post_csc_lut. + */ + if (!is_pre_csc_lut && crtc_state->c8_planes) + return true; + + return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2, + is_pre_csc_lut); } static bool need_plane_update(struct intel_plane *plane, @@ -1282,6 +1520,42 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) return 0; } +static u32 intel_gamma_lut_tests(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + + if (lut_is_legacy(gamma_lut)) + return 0; + + return INTEL_INFO(i915)->display.color.gamma_lut_tests; +} + +static u32 intel_degamma_lut_tests(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + return INTEL_INFO(i915)->display.color.degamma_lut_tests; +} + +static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + + if (lut_is_legacy(gamma_lut)) + return LEGACY_LUT_LENGTH; + + return INTEL_INFO(i915)->display.color.gamma_lut_size; +} + +static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + return INTEL_INFO(i915)->display.color.degamma_lut_size; +} + static int check_lut_size(const struct drm_property_blob *lut, int expected) { int len; @@ -1299,29 +1573,23 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) return 0; } -static int check_luts(const struct intel_crtc_state *crtc_state) +static int _check_luts(const struct intel_crtc_state *crtc_state, + u32 degamma_tests, u32 gamma_tests) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; - - /* Always allow legacy gamma LUT with no further checking. */ - if (crtc_state_is_legacy_gamma(crtc_state)) - return 0; /* C8 relies on its palette being stored in the legacy LUT */ - if (crtc_state->c8_planes) { + if (crtc_state->c8_planes && !lut_is_legacy(crtc_state->hw.gamma_lut)) { drm_dbg_kms(&i915->drm, "C8 pixelformat requires the legacy LUT\n"); return -EINVAL; } - degamma_length = INTEL_INFO(i915)->display.color.degamma_lut_size; - gamma_length = INTEL_INFO(i915)->display.color.gamma_lut_size; - degamma_tests = INTEL_INFO(i915)->display.color.degamma_lut_tests; - gamma_tests = INTEL_INFO(i915)->display.color.gamma_lut_tests; + degamma_length = intel_degamma_lut_size(crtc_state); + gamma_length = intel_gamma_lut_size(crtc_state); if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) @@ -1334,13 +1602,44 @@ static int check_luts(const struct intel_crtc_state *crtc_state) return 0; } +static int check_luts(const struct intel_crtc_state *crtc_state) +{ + return _check_luts(crtc_state, + intel_degamma_lut_tests(crtc_state), + intel_gamma_lut_tests(crtc_state)); +} + static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else - return GAMMA_MODE_MODE_10BIT; /* i965+ only */ + return GAMMA_MODE_MODE_10BIT; +} + +static int i9xx_lut_10_diff(u16 a, u16 b) +{ + return drm_color_lut_extract(a, 10) - + drm_color_lut_extract(b, 10); +} + +static int i9xx_check_lut_10(struct drm_i915_private *dev_priv, + const struct drm_property_blob *blob) +{ + const struct drm_color_lut *lut = blob->data; + int lut_size = drm_color_lut_size(blob); + const struct drm_color_lut *a = &lut[lut_size - 2]; + const struct drm_color_lut *b = &lut[lut_size - 1]; + + if (i9xx_lut_10_diff(b->red, a->red) > 0x7f || + i9xx_lut_10_diff(b->green, a->green) > 0x7f || + i9xx_lut_10_diff(b->blue, a->blue) > 0x7f) { + drm_dbg_kms(&dev_priv->drm, "Last gamma LUT entry exceeds max slope\n"); + return -EINVAL; + } + + return 0; } void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) @@ -1355,15 +1654,19 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } else if (DISPLAY_VER(i915) == 10) { drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut == crtc_state->hw.gamma_lut && crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut); drm_WARN_ON(&i915->drm, + !ilk_lut_limited_range(crtc_state) && + crtc_state->post_csc_lut != NULL && crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { drm_WARN_ON(&i915->drm, crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut); drm_WARN_ON(&i915->drm, + !ilk_lut_limited_range(crtc_state) && crtc_state->post_csc_lut != crtc_state->hw.degamma_lut && crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } @@ -1379,6 +1682,7 @@ static void intel_assign_luts(struct intel_crtc_state *crtc_state) static int i9xx_color_check(struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; ret = check_luts(crtc_state); @@ -1391,6 +1695,13 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state); + if (DISPLAY_VER(i915) < 4 && + crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) { + ret = i9xx_check_lut_10(i915, crtc_state->hw.gamma_lut); + if (ret) + return ret; + } + ret = intel_color_add_affected_planes(crtc_state); if (ret) return ret; @@ -1406,14 +1717,12 @@ static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state) { u32 cgm_mode = 0; - if (crtc_state_is_legacy_gamma(crtc_state)) - return 0; - if (crtc_state->hw.degamma_lut) cgm_mode |= CGM_PIPE_MODE_DEGAMMA; if (crtc_state->hw.ctm) cgm_mode |= CGM_PIPE_MODE_CSC; - if (crtc_state->hw.gamma_lut) + if (crtc_state->hw.gamma_lut && + !lut_is_legacy(crtc_state->hw.gamma_lut)) cgm_mode |= CGM_PIPE_MODE_GAMMA; return cgm_mode; @@ -1440,7 +1749,7 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) * Otherwise we bypass it and use the CGM gamma instead. */ crtc_state->gamma_enable = - crtc_state_is_legacy_gamma(crtc_state) && + lut_is_legacy(crtc_state->hw.gamma_lut) && !crtc_state->c8_planes; crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT; @@ -1475,7 +1784,7 @@ static bool ilk_csc_enable(const struct intel_crtc_state *crtc_state) static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else return GAMMA_MODE_MODE_10BIT; @@ -1499,8 +1808,28 @@ static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state) CSC_POSITION_BEFORE_GAMMA; } -static void ilk_assign_luts(struct intel_crtc_state *crtc_state) +static int ilk_assign_luts(struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (ilk_lut_limited_range(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + drm_color_lut_size(crtc_state->hw.gamma_lut), + true); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut); + + drm_property_blob_put(gamma_lut); + + drm_property_replace_blob(&crtc_state->pre_csc_lut, crtc_state->hw.degamma_lut); + + return 0; + } + if (crtc_state->hw.degamma_lut || crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) { drm_property_replace_blob(&crtc_state->pre_csc_lut, @@ -1513,6 +1842,8 @@ static void ilk_assign_luts(struct intel_crtc_state *crtc_state) drm_property_replace_blob(&crtc_state->post_csc_lut, NULL); } + + return 0; } static int ilk_color_check(struct intel_crtc_state *crtc_state) @@ -1549,7 +1880,9 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - ilk_assign_luts(crtc_state); + ret = ilk_assign_luts(crtc_state); + if (ret) + return ret; crtc_state->preload_luts = intel_can_preload_luts(crtc_state); @@ -1585,19 +1918,19 @@ static int ivb_assign_luts(struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); struct drm_property_blob *degamma_lut, *gamma_lut; - if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { - ilk_assign_luts(crtc_state); - return 0; - } + if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) + return ilk_assign_luts(crtc_state); drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024); drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024); - degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512); + degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512, + false); if (IS_ERR(degamma_lut)) return PTR_ERR(degamma_lut); - gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512); + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512, + ilk_lut_limited_range(crtc_state)); if (IS_ERR(gamma_lut)) { drm_property_blob_put(degamma_lut); return PTR_ERR(gamma_lut); @@ -1621,6 +1954,12 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + if (crtc_state->c8_planes && crtc_state->hw.degamma_lut) { + drm_dbg_kms(&i915->drm, + "C8 pixelformat and degamma together are not possible\n"); + return -EINVAL; + } + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { drm_dbg_kms(&i915->drm, @@ -1659,17 +1998,57 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else return GAMMA_MODE_MODE_10BIT; } -static void glk_assign_luts(struct intel_crtc_state *crtc_state) +static bool glk_use_pre_csc_lut_for_gamma(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->hw.gamma_lut && + !crtc_state->c8_planes && + crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB; +} + +static int glk_assign_luts(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - intel_assign_luts(crtc_state); + if (glk_use_pre_csc_lut_for_gamma(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + INTEL_INFO(i915)->display.color.degamma_lut_size, + false); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->pre_csc_lut, gamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, NULL); + + drm_property_blob_put(gamma_lut); + + return 0; + } + + if (ilk_lut_limited_range(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + drm_color_lut_size(crtc_state->hw.gamma_lut), + true); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut); + + drm_property_blob_put(gamma_lut); + } else { + drm_property_replace_blob(&crtc_state->post_csc_lut, crtc_state->hw.gamma_lut); + } + + drm_property_replace_blob(&crtc_state->pre_csc_lut, crtc_state->hw.degamma_lut); /* * On GLK+ both pipe CSC and degamma LUT are controlled @@ -1680,6 +2059,19 @@ static void glk_assign_luts(struct intel_crtc_state *crtc_state) if (crtc_state->csc_enable && !crtc_state->pre_csc_lut) drm_property_replace_blob(&crtc_state->pre_csc_lut, i915->display.color.glk_linear_degamma_lut); + + return 0; +} + +static int glk_check_luts(const struct intel_crtc_state *crtc_state) +{ + u32 degamma_tests = intel_degamma_lut_tests(crtc_state); + u32 gamma_tests = intel_gamma_lut_tests(crtc_state); + + if (glk_use_pre_csc_lut_for_gamma(crtc_state)) + gamma_tests |= degamma_tests; + + return _check_luts(crtc_state, degamma_tests, gamma_tests); } static int glk_color_check(struct intel_crtc_state *crtc_state) @@ -1687,7 +2079,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; - ret = check_luts(crtc_state); + ret = glk_check_luts(crtc_state); if (ret) return ret; @@ -1706,14 +2098,16 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) } crtc_state->gamma_enable = + !glk_use_pre_csc_lut_for_gamma(crtc_state) && crtc_state->hw.gamma_lut && !crtc_state->c8_planes; /* On GLK+ degamma LUT is controlled by csc_enable */ crtc_state->csc_enable = + glk_use_pre_csc_lut_for_gamma(crtc_state) || crtc_state->hw.degamma_lut || crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || - crtc_state->hw.ctm || crtc_state->limited_color_range; + crtc_state->hw.ctm || ilk_csc_limited_range(crtc_state); crtc_state->gamma_mode = glk_gamma_mode(crtc_state); @@ -1723,7 +2117,9 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - glk_assign_luts(crtc_state); + ret = glk_assign_luts(crtc_state); + if (ret) + return ret; crtc_state->preload_luts = intel_can_preload_luts(crtc_state); @@ -1744,7 +2140,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) gamma_mode |= POST_CSC_GAMMA_ENABLE; if (!crtc_state->hw.gamma_lut || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) gamma_mode |= GAMMA_MODE_MODE_8BIT; /* * Enable 10bit gamma for D13 @@ -1754,7 +2150,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) else if (DISPLAY_VER(i915) >= 13) gamma_mode |= GAMMA_MODE_MODE_10BIT; else - gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED; + gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEG; return gamma_mode; } @@ -1792,68 +2188,153 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) return 0; } -static int i9xx_gamma_precision(const struct intel_crtc_state *crtc_state) +static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: return 8; case GAMMA_MODE_MODE_10BIT: - return 16; + return 10; default: MISSING_CASE(crtc_state->gamma_mode); return 0; } } -static int ilk_gamma_precision(const struct intel_crtc_state *crtc_state) +static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) - return 0; + return 0; +} - if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0) +static int i965_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: return 8; case GAMMA_MODE_MODE_10BIT: - return 10; + return 16; default: MISSING_CASE(crtc_state->gamma_mode); return 0; } } -static int chv_gamma_precision(const struct intel_crtc_state *crtc_state) +static int ilk_gamma_mode_precision(u32 gamma_mode) { - if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) + switch (gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + return 8; + case GAMMA_MODE_MODE_10BIT: return 10; - else - return i9xx_gamma_precision(crtc_state); + default: + MISSING_CASE(gamma_mode); + return 0; + } +} + +static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->c8_planes) + return true; + + return crtc_state->gamma_enable && + (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0; } -static int glk_gamma_precision(const struct intel_crtc_state *crtc_state) +static bool ilk_has_pre_csc_lut(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) + return crtc_state->gamma_enable && + (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0; +} + +static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_has_post_csc_lut(crtc_state)) return 0; - switch (crtc_state->gamma_mode) { - case GAMMA_MODE_MODE_8BIT: - return 8; - case GAMMA_MODE_MODE_10BIT: + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int ilk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_has_pre_csc_lut(crtc_state)) + return 0; + + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int ivb_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->gamma_enable && + crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) return 10; - default: - MISSING_CASE(crtc_state->gamma_mode); + + return ilk_post_csc_lut_precision(crtc_state); +} + +static int ivb_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->gamma_enable && + crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) + return 10; + + return ilk_pre_csc_lut_precision(crtc_state); +} + +static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) + return 10; + + return i965_post_csc_lut_precision(crtc_state); +} + +static int chv_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA) + return 14; + + return 0; +} + +static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; - } + + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int glk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->csc_enable) + return 0; + + return 16; +} + +static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->c8_planes) + return true; + + return crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE; +} + +static bool icl_has_pre_csc_lut(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->gamma_mode & PRE_CSC_GAMMA_ENABLE; } -static int icl_gamma_precision(const struct intel_crtc_state *crtc_state) +static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if ((crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE) == 0) + if (!icl_has_post_csc_lut(crtc_state)) return 0; switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { @@ -1861,7 +2342,7 @@ static int icl_gamma_precision(const struct intel_crtc_state *crtc_state) return 8; case GAMMA_MODE_MODE_10BIT: return 10; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: return 16; default: MISSING_CASE(crtc_state->gamma_mode); @@ -1869,26 +2350,12 @@ static int icl_gamma_precision(const struct intel_crtc_state *crtc_state) } } -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state) +static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - - if (HAS_GMCH(i915)) { - if (IS_CHERRYVIEW(i915)) - return chv_gamma_precision(crtc_state); - else - return i9xx_gamma_precision(crtc_state); - } else { - if (DISPLAY_VER(i915) >= 11) - return icl_gamma_precision(crtc_state); - else if (DISPLAY_VER(i915) == 10) - return glk_gamma_precision(crtc_state); - else if (IS_IRONLAKE(i915)) - return ilk_gamma_precision(crtc_state); - } + if (!icl_has_pre_csc_lut(crtc_state)) + return 0; - return 0; + return 16; } static bool err_check(struct drm_color_lut *lut1, @@ -1899,9 +2366,9 @@ static bool err_check(struct drm_color_lut *lut1, ((abs((long)lut2->green - lut1->green)) <= err); } -static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1, - struct drm_color_lut *lut2, - int lut_size, u32 err) +static bool intel_lut_entries_equal(struct drm_color_lut *lut1, + struct drm_color_lut *lut2, + int lut_size, u32 err) { int i; @@ -1913,9 +2380,9 @@ static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1, return true; } -bool intel_color_lut_equal(struct drm_property_blob *blob1, - struct drm_property_blob *blob2, - u32 gamma_mode, u32 bit_precision) +static bool intel_lut_equal(const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + int check_size, int precision) { struct drm_color_lut *lut1, *lut2; int lut_size1, lut_size2; @@ -1924,40 +2391,134 @@ bool intel_color_lut_equal(struct drm_property_blob *blob1, if (!blob1 != !blob2) return false; + if (!blob1 != !precision) + return false; + if (!blob1) return true; lut_size1 = drm_color_lut_size(blob1); lut_size2 = drm_color_lut_size(blob2); - /* check sw and hw lut size */ if (lut_size1 != lut_size2) return false; + if (check_size > lut_size1) + return false; + lut1 = blob1->data; lut2 = blob2->data; - err = 0xffff >> bit_precision; + err = 0xffff >> precision; - /* check sw and hw lut entry to be equal */ - switch (gamma_mode & GAMMA_MODE_MODE_MASK) { - case GAMMA_MODE_MODE_8BIT: - case GAMMA_MODE_MODE_10BIT: - if (!intel_color_lut_entries_equal(lut1, lut2, - lut_size2, err)) - return false; - break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: - if (!intel_color_lut_entries_equal(lut1, lut2, - 9, err)) - return false; - break; - default: - MISSING_CASE(gamma_mode); - return false; - } + if (!check_size) + check_size = lut_size1; - return true; + return intel_lut_entries_equal(lut1, lut2, check_size, err); +} + +static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + int check_size = 0; + + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + i9xx_pre_csc_lut_precision(crtc_state)); + + /* 10bit mode last entry is implicit, just skip it */ + if (crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) + check_size = 128; + + return intel_lut_equal(blob1, blob2, check_size, + i9xx_post_csc_lut_precision(crtc_state)); +} + +static bool i965_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + i9xx_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + i965_post_csc_lut_precision(crtc_state)); +} + +static bool chv_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + chv_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + chv_post_csc_lut_precision(crtc_state)); +} + +static bool ilk_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + ilk_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + ilk_post_csc_lut_precision(crtc_state)); +} + +static bool ivb_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + ivb_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + ivb_post_csc_lut_precision(crtc_state)); +} + +static bool glk_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + glk_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + glk_post_csc_lut_precision(crtc_state)); +} + +static bool icl_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + int check_size = 0; + + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + icl_pre_csc_lut_precision(crtc_state)); + + /* hw readout broken except for the super fine segment :( */ + if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) == + GAMMA_MODE_MODE_12BIT_MULTI_SEG) + check_size = 9; + + return intel_lut_equal(blob1, blob2, check_size, + icl_post_csc_lut_precision(crtc_state)); } static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) @@ -1985,14 +2546,53 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) return blob; } +static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + u32 ldw, udw; + int i; + + blob = drm_property_create_blob(&dev_priv->drm, + lut_size * sizeof(lut[0]), NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size - 1; i++) { + ldw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 0)); + udw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 1)); + + i9xx_lut_10_pack(&lut[i], ldw, udw); + } + + i9xx_lut_10_pack_slope(&lut[i], ldw, udw); + + return blob; +} + static void i9xx_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; - crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_10BIT: + crtc_state->post_csc_lut = i9xx_read_lut_10(crtc); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) @@ -2029,13 +2629,46 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; - if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); - else + break; + case GAMMA_MODE_MODE_10BIT: crtc_state->post_csc_lut = i965_read_lut_10p6(crtc); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } +} + +static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size; i++) { + u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0)); + u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1)); + + chv_cgm_degamma_pack(&lut[i], ldw, udw); + } + + return blob; } static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) @@ -2068,6 +2701,9 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA) + crtc_state->pre_csc_lut = chv_read_cgm_degamma(crtc); + if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) crtc_state->post_csc_lut = chv_read_cgm_gamma(crtc); else @@ -2127,19 +2763,88 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) static void ilk_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; - if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0) + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + *blob = ilk_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_10BIT: + *blob = ilk_read_lut_10(crtc); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } +} + +/* + * IVB/HSW Bspec / PAL_PREC_INDEX: + * "Restriction : Index auto increment mode is not + * supported and must not be enabled." + */ +static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc, + u32 prec_index) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = ivb_lut_10_size(prec_index); + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size; i++) { + u32 val; + + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + prec_index + i); + val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe)); + + ilk_lut_10_pack(&lut[i], val); + } + + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + + return blob; +} + +static void ivb_read_luts(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; + + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - crtc_state->post_csc_lut = ilk_read_lut_8(crtc); + *blob = ilk_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_SPLIT: + crtc_state->pre_csc_lut = + ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = + ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: - crtc_state->post_csc_lut = ilk_read_lut_10(crtc); + *blob = ivb_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -2152,14 +2857,11 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, u32 prec_index) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - int i, hw_lut_size = ivb_lut_10_size(prec_index); - int lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; + int i, lut_size = ivb_lut_10_size(prec_index); enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - drm_WARN_ON(&i915->drm, lut_size != hw_lut_size); - blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); @@ -2169,7 +2871,10 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, lut = blob->data; intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + prec_index); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + prec_index); for (i = 0; i < lut_size; i++) { u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe)); @@ -2177,7 +2882,80 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, ilk_lut_10_pack(&lut[i], val); } - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + + return blob; +} + +static void bdw_read_luts(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; + + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) + return; + + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + *blob = ilk_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_SPLIT: + crtc_state->pre_csc_lut = + bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = + bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(512)); + break; + case GAMMA_MODE_MODE_10BIT: + *blob = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } +} + +static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + /* + * When setting the auto-increment bit, the hardware seems to + * ignore the index bits, so we need to reset it to index 0 + * separately. + */ + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_INDEX_VALUE(0)); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT | + PRE_CSC_GAMC_INDEX_VALUE(0)); + + for (i = 0; i < lut_size; i++) { + u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe)); + + lut[i].red = val; + lut[i].green = val; + lut[i].blue = val; + } + + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_INDEX_VALUE(0)); return blob; } @@ -2186,7 +2964,10 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->gamma_enable) + if (crtc_state->csc_enable) + crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc); + + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { @@ -2220,7 +3001,10 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) lut = blob->data; intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_AUTO_INCREMENT | + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); for (i = 0; i < 9; i++) { u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); @@ -2229,7 +3013,8 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) ilk_lut_12p4_pack(&lut[i], ldw, udw); } - intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); /* * FIXME readouts from PAL_PREC_DATA register aren't giving @@ -2244,7 +3029,10 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if ((crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE) == 0) + if (icl_has_pre_csc_lut(crtc_state)) + crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc); + + if (!icl_has_post_csc_lut(crtc_state)) return; switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { @@ -2254,7 +3042,7 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) case GAMMA_MODE_MODE_10BIT: crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: crtc_state->post_csc_lut = icl_read_lut_multi_segment(crtc); break; default: @@ -2268,6 +3056,7 @@ static const struct intel_color_funcs chv_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = chv_load_luts, .read_luts = chv_read_luts, + .lut_equal = chv_lut_equal, }; static const struct intel_color_funcs i965_color_funcs = { @@ -2275,6 +3064,7 @@ static const struct intel_color_funcs i965_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = i965_load_luts, .read_luts = i965_read_luts, + .lut_equal = i965_lut_equal, }; static const struct intel_color_funcs i9xx_color_funcs = { @@ -2282,6 +3072,7 @@ static const struct intel_color_funcs i9xx_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = i9xx_load_luts, .read_luts = i9xx_read_luts, + .lut_equal = i9xx_lut_equal, }; static const struct intel_color_funcs icl_color_funcs = { @@ -2290,6 +3081,7 @@ static const struct intel_color_funcs icl_color_funcs = { .color_commit_arm = skl_color_commit_arm, .load_luts = icl_load_luts, .read_luts = icl_read_luts, + .lut_equal = icl_lut_equal, }; static const struct intel_color_funcs glk_color_funcs = { @@ -2298,6 +3090,7 @@ static const struct intel_color_funcs glk_color_funcs = { .color_commit_arm = skl_color_commit_arm, .load_luts = glk_load_luts, .read_luts = glk_read_luts, + .lut_equal = glk_lut_equal, }; static const struct intel_color_funcs skl_color_funcs = { @@ -2305,7 +3098,8 @@ static const struct intel_color_funcs skl_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = skl_color_commit_arm, .load_luts = bdw_load_luts, - .read_luts = NULL, + .read_luts = bdw_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs bdw_color_funcs = { @@ -2313,7 +3107,8 @@ static const struct intel_color_funcs bdw_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = bdw_load_luts, - .read_luts = NULL, + .read_luts = bdw_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs hsw_color_funcs = { @@ -2321,7 +3116,8 @@ static const struct intel_color_funcs hsw_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = ivb_load_luts, - .read_luts = NULL, + .read_luts = ivb_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs ivb_color_funcs = { @@ -2329,7 +3125,8 @@ static const struct intel_color_funcs ivb_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = ilk_color_commit_arm, .load_luts = ivb_load_luts, - .read_luts = NULL, + .read_luts = ivb_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs ilk_color_funcs = { @@ -2338,19 +3135,34 @@ static const struct intel_color_funcs ilk_color_funcs = { .color_commit_arm = ilk_color_commit_arm, .load_luts = ilk_load_luts, .read_luts = ilk_read_luts, + .lut_equal = ilk_lut_equal, }; void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - bool has_ctm = INTEL_INFO(i915)->display.color.degamma_lut_size != 0; + int degamma_lut_size, gamma_lut_size; + bool has_ctm; drm_mode_crtc_set_gamma_size(&crtc->base, 256); - drm_crtc_enable_color_mgmt(&crtc->base, - INTEL_INFO(i915)->display.color.degamma_lut_size, - has_ctm, - INTEL_INFO(i915)->display.color.gamma_lut_size); + gamma_lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; + degamma_lut_size = INTEL_INFO(i915)->display.color.degamma_lut_size; + has_ctm = degamma_lut_size != 0; + + /* + * "DPALETTE_A: NOTE: The 8-bit (non-10-bit) mode is the + * only mode supported by Alviso and Grantsdale." + * + * Actually looks like this affects all of gen3. + * Confirmed on alv,cst,pnv. Mobile gen2 parts (alm,mgm) + * are confirmed not to suffer from this restriction. + */ + if (DISPLAY_VER(i915) == 3 && crtc->pipe == PIPE_A) + gamma_lut_size = 256; + + drm_crtc_enable_color_mgmt(&crtc->base, degamma_lut_size, + has_ctm, gamma_lut_size); } int intel_color_init(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 2a5ada67774d..d620b5b1e2a6 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -17,14 +17,16 @@ void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); void intel_color_crtc_init(struct intel_crtc *crtc); int intel_color_check(struct intel_crtc_state *crtc_state); +void intel_color_prepare_commit(struct intel_crtc_state *crtc_state); +void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state); void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state); void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); void intel_color_load_luts(const struct intel_crtc_state *crtc_state); void intel_color_get_config(struct intel_crtc_state *crtc_state); -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state); -bool intel_color_lut_equal(struct drm_property_blob *blob1, - struct drm_property_blob *blob2, - u32 gamma_mode, u32 bit_precision); +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index 6205ddd3ded0..562da3b741e2 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -54,7 +54,7 @@ int intel_connector_init(struct intel_connector *connector) __drm_atomic_helper_connector_reset(&connector->base, &conn_state->base); - INIT_LIST_HEAD(&connector->panel.fixed_modes); + intel_panel_init_alloc(connector); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 797ad9489f7e..7267ffc7f539 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -682,30 +682,20 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) { struct drm_device *dev = crt->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_uncore *uncore = &dev_priv->uncore; u32 save_bclrpat; u32 save_vtotal; u32 vtotal, vactive; u32 vsample; u32 vblank, vblank_start, vblank_end; u32 dsl; - i915_reg_t bclrpat_reg, vtotal_reg, - vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg; u8 st00; enum drm_connector_status status; drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n"); - bclrpat_reg = BCLRPAT(pipe); - vtotal_reg = VTOTAL(pipe); - vblank_reg = VBLANK(pipe); - vsync_reg = VSYNC(pipe); - pipeconf_reg = PIPECONF(pipe); - pipe_dsl_reg = PIPEDSL(pipe); - - save_bclrpat = intel_uncore_read(uncore, bclrpat_reg); - save_vtotal = intel_uncore_read(uncore, vtotal_reg); - vblank = intel_uncore_read(uncore, vblank_reg); + save_bclrpat = intel_de_read(dev_priv, BCLRPAT(pipe)); + save_vtotal = intel_de_read(dev_priv, VTOTAL(pipe)); + vblank = intel_de_read(dev_priv, VBLANK(pipe)); vtotal = ((save_vtotal >> 16) & 0xfff) + 1; vactive = (save_vtotal & 0x7ff) + 1; @@ -714,23 +704,23 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) vblank_end = ((vblank >> 16) & 0xfff) + 1; /* Set the border color to purple. */ - intel_uncore_write(uncore, bclrpat_reg, 0x500050); + intel_de_write(dev_priv, BCLRPAT(pipe), 0x500050); if (DISPLAY_VER(dev_priv) != 2) { - u32 pipeconf = intel_uncore_read(uncore, pipeconf_reg); - intel_uncore_write(uncore, - pipeconf_reg, - pipeconf | PIPECONF_FORCE_BORDER); - intel_uncore_posting_read(uncore, pipeconf_reg); + u32 pipeconf = intel_de_read(dev_priv, PIPECONF(pipe)); + + intel_de_write(dev_priv, PIPECONF(pipe), + pipeconf | PIPECONF_FORCE_BORDER); + intel_de_posting_read(dev_priv, PIPECONF(pipe)); /* Wait for next Vblank to substitue * border color for Color info */ intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); - st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE); + st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? connector_status_connected : connector_status_disconnected; - intel_uncore_write(uncore, pipeconf_reg, pipeconf); + intel_de_write(dev_priv, PIPECONF(pipe), pipeconf); } else { bool restore_vblank = false; int count, detect; @@ -740,14 +730,12 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) * Yes, this will flicker */ if (vblank_start <= vactive && vblank_end >= vtotal) { - u32 vsync = intel_de_read(dev_priv, vsync_reg); + u32 vsync = intel_de_read(dev_priv, VSYNC(pipe)); u32 vsync_start = (vsync & 0xffff) + 1; vblank_start = vsync_start; - intel_uncore_write(uncore, - vblank_reg, - (vblank_start - 1) | - ((vblank_end - 1) << 16)); + intel_de_write(dev_priv, VBLANK(pipe), + (vblank_start - 1) | ((vblank_end - 1) << 16)); restore_vblank = true; } /* sample in the vertical border, selecting the larger one */ @@ -759,10 +747,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) /* * Wait for the border to be displayed */ - while (intel_uncore_read(uncore, pipe_dsl_reg) >= vactive) + while (intel_de_read(dev_priv, PIPEDSL(pipe)) >= vactive) ; - while ((dsl = intel_uncore_read(uncore, pipe_dsl_reg)) <= - vsample) + while ((dsl = intel_de_read(dev_priv, PIPEDSL(pipe))) <= vsample) ; /* * Watch ST00 for an entire scanline @@ -772,14 +759,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) do { count++; /* Read the ST00 VGA status register */ - st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE); + st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE); if (st00 & (1 << 4)) detect++; - } while ((intel_uncore_read(uncore, pipe_dsl_reg) == dsl)); + } while ((intel_de_read(dev_priv, PIPEDSL(pipe)) == dsl)); /* restore vblank if necessary */ if (restore_vblank) - intel_uncore_write(uncore, vblank_reg, vblank); + intel_de_write(dev_priv, VBLANK(pipe), vblank); /* * If more than 3/4 of the scanline detected a monitor, * then it is assumed to be present. This works even on i830, @@ -792,7 +779,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) } /* Restore previous settings */ - intel_uncore_write(uncore, bclrpat_reg, save_bclrpat); + intel_de_write(dev_priv, BCLRPAT(pipe), save_bclrpat); return status; } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0f1ec2a98cc8..1f5a471a0adf 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -185,6 +185,8 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, enum port port) { + enum phy phy = intel_port_to_phy(dev_priv, port); + int timeout_us; int ret; /* Wait > 518 usecs for DDI_BUF_CTL to be non idle */ @@ -193,8 +195,19 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, return; } + if (IS_DG2(dev_priv)) { + timeout_us = 1200; + } else if (DISPLAY_VER(dev_priv) >= 12) { + if (intel_phy_is_tc(dev_priv, phy)) + timeout_us = 3000; + else + timeout_us = 1000; + } else { + timeout_us = 500; + } + ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & - DDI_BUF_IS_IDLE), IS_DG2(dev_priv) ? 1200 : 500, 10, 10); + DDI_BUF_IS_IDLE), timeout_us, 10, 10); if (ret) drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n", @@ -2726,10 +2739,10 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) { intel_crtc_vblank_off(old_crtc_state); - intel_disable_transcoder(old_crtc_state); - intel_vrr_disable(old_crtc_state); + intel_disable_transcoder(old_crtc_state); + intel_ddi_disable_transcoder_func(old_crtc_state); intel_dsc_disable(old_crtc_state); @@ -2933,6 +2946,8 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, } intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl); + intel_wait_ddi_buf_active(dev_priv, port); + intel_audio_codec_enable(encoder, crtc_state, conn_state); } @@ -2946,10 +2961,13 @@ static void intel_enable_ddi(struct intel_atomic_state *state, if (!intel_crtc_is_bigjoiner_slave(crtc_state)) intel_ddi_enable_transcoder_func(encoder, crtc_state); - intel_vrr_enable(encoder, crtc_state); + /* Enable/Disable DP2.0 SDP split config before transcoder */ + intel_audio_sdp_split_update(encoder, crtc_state); intel_enable_transcoder(crtc_state); + intel_vrr_enable(encoder, crtc_state); + intel_crtc_vblank_on(crtc_state); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 9c104f65e4c8..3dbd76fdabd6 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -16,6 +16,12 @@ intel_de_read(struct drm_i915_private *i915, i915_reg_t reg) return intel_uncore_read(&i915->uncore, reg); } +static inline u8 +intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) +{ + return intel_uncore_read8(&i915->uncore, reg); +} + static inline void intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) { @@ -28,10 +34,10 @@ intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val) intel_uncore_write(&i915->uncore, reg, val); } -static inline void +static inline u32 intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set) { - intel_uncore_rmw(&i915->uncore, reg, clear, set); + return intel_uncore_rmw(&i915->uncore, reg, clear, set); } static inline int @@ -42,6 +48,23 @@ intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, } static inline int +intel_de_wait_for_register_fw(struct drm_i915_private *i915, i915_reg_t reg, + u32 mask, u32 value, unsigned int timeout) +{ + return intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout); +} + +static inline int +__intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, + u32 mask, u32 value, + unsigned int fast_timeout_us, + unsigned int slow_timeout_ms, u32 *out_value) +{ + return __intel_wait_for_register(&i915->uncore, reg, mask, value, + fast_timeout_us, slow_timeout_ms, out_value); +} + +static inline int intel_de_wait_for_set(struct drm_i915_private *i915, i915_reg_t reg, u32 mask, unsigned int timeout) { @@ -81,4 +104,16 @@ intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val) intel_uncore_write_fw(&i915->uncore, reg, val); } +static inline u32 +intel_de_read_notrace(struct drm_i915_private *i915, i915_reg_t reg) +{ + return intel_uncore_read_notrace(&i915->uncore, reg); +} + +static inline void +intel_de_write_notrace(struct drm_i915_private *i915, i915_reg_t reg, u32 val) +{ + intel_uncore_write_notrace(&i915->uncore, reg, val); +} + #endif /* __INTEL_DE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6c2686ecb62a..e75b9b2a0e01 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -70,8 +70,6 @@ #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" -#include "gt/gen8_ppgtt.h" - #include "g4x_dp.h" #include "g4x_hdmi.h" #include "hsw_ips.h" @@ -93,7 +91,6 @@ #include "intel_dp_link_training.h" #include "intel_dpio_phy.h" #include "intel_dpt.h" -#include "intel_dsb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" @@ -1246,7 +1243,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(dev_priv); - hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); if (needs_async_flip_vtd_wa(old_crtc_state) && @@ -5531,7 +5527,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); bool ret = true; - u32 bp_gamma = 0; bool fixup_inherited = fastset && current_config->inherited && !pipe_config->inherited; @@ -5682,21 +5677,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \ - if (current_config->name1 != pipe_config->name1) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name1), \ - "(expected %i, found %i, won't compare lut values)", \ - current_config->name1, \ - pipe_config->name1); \ - ret = false;\ - } else { \ - if (!intel_color_lut_equal(current_config->name2, \ - pipe_config->name2, pipe_config->name1, \ - bit_precision)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name2), \ - "hw_state doesn't match sw_state"); \ - ret = false; \ - } \ +#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \ + if (current_config->gamma_mode == pipe_config->gamma_mode && \ + !intel_color_lut_equal(current_config, \ + current_config->lut, pipe_config->lut, \ + is_pre_csc_lut)) { \ + pipe_config_mismatch(fastset, crtc, __stringify(lut), \ + "hw_state doesn't match sw_state"); \ + ret = false; \ } \ } while (0) @@ -5793,9 +5781,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(linetime); PIPE_CONF_CHECK_I(ips_linetime); - bp_gamma = intel_color_get_gamma_bit_precision(pipe_config); - if (bp_gamma) - PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma); + PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true); + PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false); if (current_config->active_planes) { PIPE_CONF_CHECK_BOOL(has_psr); @@ -6941,7 +6928,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { if (intel_crtc_needs_color_update(crtc_state)) - intel_dsb_prepare(crtc_state); + intel_color_prepare_commit(crtc_state); } return 0; @@ -7392,24 +7379,18 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat &wait_reset); } -static void intel_cleanup_dsbs(struct intel_atomic_state *state) -{ - struct intel_crtc_state *old_crtc_state, *new_crtc_state; - struct intel_crtc *crtc; - int i; - - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) - intel_dsb_cleanup(old_crtc_state); -} - static void intel_atomic_cleanup_work(struct work_struct *work) { struct intel_atomic_state *state = container_of(work, struct intel_atomic_state, base.commit_work); struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *old_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) + intel_color_cleanup_commit(old_crtc_state); - intel_cleanup_dsbs(state); drm_atomic_helper_cleanup_planes(&i915->drm, &state->base); drm_atomic_helper_commit_cleanup_done(&state->base); drm_atomic_state_put(&state->base); @@ -7587,6 +7568,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); + /* Must be done after gamma readout due to HSW split gamma vs. IPS w/a */ + hsw_ips_post_update(state, crtc); + /* * Activate DRRS after state readout to avoid * dp_m_n vs. dp_m2_n2 confusion on BDW+. @@ -7597,6 +7581,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * DSB cleanup is done in cleanup_work aligning with framebuffer * cleanup. So copy and reset the dsb structure to sync with * commit_done and later do dsb cleanup in cleanup_work. + * + * FIXME get rid of this funny new->old swapping */ old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb); } @@ -7747,7 +7733,7 @@ static int intel_atomic_commit(struct drm_device *dev, i915_sw_fence_commit(&state->commit_ready); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) - intel_dsb_cleanup(new_crtc_state); + intel_color_cleanup_commit(new_crtc_state); drm_atomic_helper_cleanup_planes(dev, &state->base); intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 714030136b7f..ef73730f32b0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -440,6 +440,14 @@ enum hpd_pin { (__i)++) \ for_each_if(plane) +#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->base.dev->mode_config.num_crtc && \ + ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ + (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \ + (__i)++) \ + for_each_if(crtc) + #define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 3adba64937de..1a23ecd4623a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1673,7 +1673,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) >= 12) { val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM | DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR; - intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val); + intel_de_rmw(dev_priv, GEN11_CHICKEN_DCPR_2, 0, val); } /* Wa_14011503030:xelpd */ diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f07395065a69..32e8b2fc3cc6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -291,7 +291,7 @@ struct intel_vbt_panel_data { struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ /* Feature bits */ - unsigned int panel_type:4; + int panel_type; unsigned int lvds_dither:1; unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ @@ -330,7 +330,7 @@ struct intel_vbt_panel_data { bool present; bool active_low_pwm; u8 min_brightness; /* min_brightness/255 of max */ - u8 controller; /* brightness controller number */ + s8 controller; /* brightness controller number */ enum intel_backlight_type type; } backlight; @@ -1295,6 +1295,8 @@ struct intel_crtc_state { /* Forward Error correction State */ bool fec_enable; + bool sdp_split_enable; + /* Pointer to master transcoder in case of tiled displays */ enum transcoder master_transcoder; @@ -1568,11 +1570,19 @@ struct intel_pps { ktime_t panel_power_off_time; intel_wakeref_t vdd_wakeref; - /* - * Pipe whose power sequencer is currently locked into - * this port. Only relevant on VLV/CHV. - */ - enum pipe pps_pipe; + union { + /* + * Pipe whose power sequencer is currently locked into + * this port. Only relevant on VLV/CHV. + */ + enum pipe pps_pipe; + + /* + * Power sequencer index. Only relevant on BXT+. + */ + int pps_idx; + }; + /* * Pipe currently driving the port. Used for preventing * the use of the PPS for any pipe currentrly driving @@ -1581,7 +1591,7 @@ struct intel_pps { enum pipe active_pipe; /* * Set if the sequencer may be reset due to a power transition, - * requiring a reinitialization. Only relevant on BXT. + * requiring a reinitialization. Only relevant on BXT+. */ bool pps_reset; struct edp_power_seq pps_delays; diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index eff3add70611..4124b3d37110 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -53,51 +53,40 @@ #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE #define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) -#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 8) MODULE_FIRMWARE(DG2_DMC_PATH); #define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) -#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); #define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) -#define ADLS_DMC_VERSION_REQUIRED DMC_VERSION(2, 1) MODULE_FIRMWARE(ADLS_DMC_PATH); #define DG1_DMC_PATH DMC_PATH(dg1, 2, 02) -#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2) MODULE_FIRMWARE(DG1_DMC_PATH); #define RKL_DMC_PATH DMC_PATH(rkl, 2, 03) -#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 3) MODULE_FIRMWARE(RKL_DMC_PATH); #define TGL_DMC_PATH DMC_PATH(tgl, 2, 12) -#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 12) MODULE_FIRMWARE(TGL_DMC_PATH); #define ICL_DMC_PATH DMC_PATH(icl, 1, 09) -#define ICL_DMC_VERSION_REQUIRED DMC_VERSION(1, 9) #define ICL_DMC_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(ICL_DMC_PATH); #define GLK_DMC_PATH DMC_PATH(glk, 1, 04) -#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4) #define GLK_DMC_MAX_FW_SIZE 0x4000 MODULE_FIRMWARE(GLK_DMC_PATH); #define KBL_DMC_PATH DMC_PATH(kbl, 1, 04) -#define KBL_DMC_VERSION_REQUIRED DMC_VERSION(1, 4) #define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(KBL_DMC_PATH); #define SKL_DMC_PATH DMC_PATH(skl, 1, 27) -#define SKL_DMC_VERSION_REQUIRED DMC_VERSION(1, 27) #define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(SKL_DMC_PATH); #define BXT_DMC_PATH DMC_PATH(bxt, 1, 07) -#define BXT_DMC_VERSION_REQUIRED DMC_VERSION(1, 7) #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); @@ -387,11 +376,11 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) { enum pipe pipe; - if (DISPLAY_VER(i915) != 13) + if (DISPLAY_VER(i915) < 13) return; /* - * Wa_16015201720:adl-p,dg2 + * Wa_16015201720:adl-p,dg2, mtl * The WA requires clock gating to be disabled all the time * for pipe A and B. * For pipe C and D clock gating needs to be disabled only @@ -433,9 +422,9 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv) for (id = 0; id < DMC_FW_MAX; id++) { for (i = 0; i < dmc->dmc_info[id].dmc_fw_size; i++) { - intel_uncore_write_fw(&dev_priv->uncore, - DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i), - dmc->dmc_info[id].payload[i]); + intel_de_write_fw(dev_priv, + DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i), + dmc->dmc_info[id].payload[i]); } } @@ -765,17 +754,6 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc, return 0; } - if (dmc->required_version && - css_header->version != dmc->required_version) { - drm_info(&i915->drm, "Refusing to load DMC firmware v%u.%u," - " please use v%u.%u\n", - DMC_VERSION_MAJOR(css_header->version), - DMC_VERSION_MINOR(css_header->version), - DMC_VERSION_MAJOR(dmc->required_version), - DMC_VERSION_MINOR(dmc->required_version)); - return 0; - } - dmc->version = css_header->version; return sizeof(struct intel_css_header); @@ -903,49 +881,38 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) if (IS_DG2(dev_priv)) { dmc->fw_path = DG2_DMC_PATH; - dmc->required_version = DG2_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; } else if (IS_ALDERLAKE_P(dev_priv)) { dmc->fw_path = ADLP_DMC_PATH; - dmc->required_version = ADLP_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; } else if (IS_ALDERLAKE_S(dev_priv)) { dmc->fw_path = ADLS_DMC_PATH; - dmc->required_version = ADLS_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_DG1(dev_priv)) { dmc->fw_path = DG1_DMC_PATH; - dmc->required_version = DG1_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_ROCKETLAKE(dev_priv)) { dmc->fw_path = RKL_DMC_PATH; - dmc->required_version = RKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_TIGERLAKE(dev_priv)) { dmc->fw_path = TGL_DMC_PATH; - dmc->required_version = TGL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (DISPLAY_VER(dev_priv) == 11) { dmc->fw_path = ICL_DMC_PATH; - dmc->required_version = ICL_DMC_VERSION_REQUIRED; dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE; } else if (IS_GEMINILAKE(dev_priv)) { dmc->fw_path = GLK_DMC_PATH; - dmc->required_version = GLK_DMC_VERSION_REQUIRED; dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE; } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv)) { dmc->fw_path = KBL_DMC_PATH; - dmc->required_version = KBL_DMC_VERSION_REQUIRED; dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE; } else if (IS_SKYLAKE(dev_priv)) { dmc->fw_path = SKL_DMC_PATH; - dmc->required_version = SKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE; } else if (IS_BROXTON(dev_priv)) { dmc->fw_path = BXT_DMC_PATH; - dmc->required_version = BXT_DMC_VERSION_REQUIRED; dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE; } @@ -958,8 +925,6 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) } dmc->fw_path = dev_priv->params.dmc_firmware_path; - /* Bypass version check for firmware override. */ - dmc->required_version = 0; } if (!dmc->fw_path) { diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 67e03315ef99..435eab9b016b 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -25,7 +25,6 @@ enum { struct intel_dmc { struct work_struct work; const char *fw_path; - u32 required_version; u32 max_fw_size; /* bytes */ u32 version; struct dmc_fw_info { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 75070eb07d4b..80d95cec8f9d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -117,7 +117,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) } static void intel_dp_unset_edid(struct intel_dp *intel_dp); -static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); /* Is link rate UHBR and thus 128b/132b? */ bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state) @@ -673,23 +672,59 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915) return 6144 * 8; } -static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, - u32 link_clock, u32 lane_count, - u32 mode_clock, u32 mode_hdisplay, - bool bigjoiner, - u32 pipe_bpp) +u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp) { - u32 bits_per_pixel, max_bpp_small_joiner_ram; + u32 bits_per_pixel = bpp; int i; + /* Error out if the max bpp is less than smallest allowed valid bpp */ + if (bits_per_pixel < valid_dsc_bpp[0]) { + drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n", + bits_per_pixel, valid_dsc_bpp[0]); + return 0; + } + + /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */ + if (DISPLAY_VER(i915) >= 13) { + bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1); + } else { + /* Find the nearest match in the array of known BPPs from VESA */ + for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { + if (bits_per_pixel < valid_dsc_bpp[i + 1]) + break; + } + drm_dbg_kms(&i915->drm, "Set dsc bpp from %d to VESA %d\n", + bits_per_pixel, valid_dsc_bpp[i]); + + bits_per_pixel = valid_dsc_bpp[i]; + } + + return bits_per_pixel; +} + +u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, + u32 link_clock, u32 lane_count, + u32 mode_clock, u32 mode_hdisplay, + bool bigjoiner, + u32 pipe_bpp, + u32 timeslots) +{ + u32 bits_per_pixel, max_bpp_small_joiner_ram; + /* * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* - * (LinkSymbolClock)* 8 * (TimeSlotsPerMTP) - * for SST -> TimeSlotsPerMTP is 1, - * for MST -> TimeSlotsPerMTP has to be calculated + * (LinkSymbolClock)* 8 * (TimeSlots / 64) + * for SST -> TimeSlots is 64(i.e all TimeSlots that are available) + * for MST -> TimeSlots has to be calculated, based on mode requirements */ - bits_per_pixel = (link_clock * lane_count * 8) / - intel_dp_mode_to_fec_clock(mode_clock); + bits_per_pixel = DIV_ROUND_UP((link_clock * lane_count) * timeslots, + intel_dp_mode_to_fec_clock(mode_clock) * 8); + + drm_dbg_kms(&i915->drm, "Max link bpp is %u for %u timeslots " + "total bw %u pixel clock %u\n", + bits_per_pixel, timeslots, + (link_clock * lane_count * 8), + intel_dp_mode_to_fec_clock(mode_clock)); /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / @@ -712,24 +747,7 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner); } - /* Error out if the max bpp is less than smallest allowed valid bpp */ - if (bits_per_pixel < valid_dsc_bpp[0]) { - drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n", - bits_per_pixel, valid_dsc_bpp[0]); - return 0; - } - - /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */ - if (DISPLAY_VER(i915) >= 13) { - bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1); - } else { - /* Find the nearest match in the array of known BPPs from VESA */ - for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { - if (bits_per_pixel < valid_dsc_bpp[i + 1]) - break; - } - bits_per_pixel = valid_dsc_bpp[i]; - } + bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp); /* * Compressed BPP in U6.4 format so multiply by 16, for Gen 11, @@ -738,9 +756,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, return bits_per_pixel << 4; } -static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, - int mode_clock, int mode_hdisplay, - bool bigjoiner) +u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, + int mode_clock, int mode_hdisplay, + bool bigjoiner) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 min_slice_count, i; @@ -947,8 +965,8 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_OK; } -static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, - int hdisplay, int clock) +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -974,9 +992,6 @@ intel_dp_mode_valid(struct drm_connector *_connector, enum drm_mode_status status; bool dsc = false, bigjoiner = false; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; @@ -1013,7 +1028,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, * Output bpp is stored in 6.4 format so right shift by 4 to get the * integer value since we support only integer values of bpp. */ - if (DISPLAY_VER(dev_priv) >= 10 && + if (HAS_DSC(dev_priv) && drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) { /* * TBD pass the connector BPC, @@ -1035,7 +1050,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock, mode->hdisplay, bigjoiner, - pipe_bpp) >> 4; + pipe_bpp, 64) >> 4; dsc_slice_count = intel_dp_dsc_get_slice_count(intel_dp, target_clock, @@ -1364,7 +1379,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, return -EINVAL; } -static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc) +int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); int i, num_bpc; @@ -1465,10 +1480,12 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, return drm_dsc_compute_rc_parameters(vdsc_cfg); } -static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state, - struct link_config_limits *limits) +int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, + struct link_config_limits *limits, + int timeslots, + bool compute_pipe_bpp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); @@ -1483,7 +1500,10 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, if (!intel_dp_supports_dsc(intel_dp, pipe_config)) return -EINVAL; - pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc); + if (compute_pipe_bpp) + pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc); + else + pipe_bpp = pipe_config->pipe_bpp; if (intel_dp->force_dsc_bpc) { pipe_bpp = intel_dp->force_dsc_bpc * 3; @@ -1514,33 +1534,52 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, true); } else { - u16 dsc_max_output_bpp; + u16 dsc_max_output_bpp = 0; u8 dsc_dp_slice_count; - dsc_max_output_bpp = - intel_dp_dsc_get_output_bpp(dev_priv, - pipe_config->port_clock, - pipe_config->lane_count, - adjusted_mode->crtc_clock, - adjusted_mode->crtc_hdisplay, - pipe_config->bigjoiner_pipes, - pipe_bpp); + if (compute_pipe_bpp) { + dsc_max_output_bpp = + intel_dp_dsc_get_output_bpp(dev_priv, + pipe_config->port_clock, + pipe_config->lane_count, + adjusted_mode->crtc_clock, + adjusted_mode->crtc_hdisplay, + pipe_config->bigjoiner_pipes, + pipe_bpp, + timeslots); + if (!dsc_max_output_bpp) { + drm_dbg_kms(&dev_priv->drm, + "Compressed BPP not supported\n"); + return -EINVAL; + } + } dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, pipe_config->bigjoiner_pipes); - if (!dsc_max_output_bpp || !dsc_dp_slice_count) { + if (!dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, - "Compressed BPP/Slice Count not supported\n"); + "Compressed Slice Count not supported\n"); return -EINVAL; } - pipe_config->dsc.compressed_bpp = min_t(u16, - dsc_max_output_bpp >> 4, - pipe_config->pipe_bpp); + + /* + * compute pipe bpp is set to false for DP MST DSC case + * and compressed_bpp is calculated same time once + * vpci timeslots are allocated, because overall bpp + * calculation procedure is bit different for MST case. + */ + if (compute_pipe_bpp) { + pipe_config->dsc.compressed_bpp = min_t(u16, + dsc_max_output_bpp >> 4, + pipe_config->pipe_bpp); + } pipe_config->dsc.slice_count = dsc_dp_slice_count; + drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n", + pipe_config->dsc.compressed_bpp, + pipe_config->dsc.slice_count); } - /* * VDSC engine operates at 1 Pixel per clock, so if peak pixel rate * is greater than the maximum Cdclock and if slice count is even @@ -1548,13 +1587,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, */ if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_cdclk_freq || pipe_config->bigjoiner_pipes) { - if (pipe_config->dsc.slice_count < 2) { + if (pipe_config->dsc.slice_count > 1) { + pipe_config->dsc.dsc_split = true; + } else { drm_dbg_kms(&dev_priv->drm, "Cannot split stream to use 2 VDSC instances\n"); return -EINVAL; } - - pipe_config->dsc.dsc_split = true; } ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config); @@ -1643,7 +1682,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, - conn_state, &limits); + conn_state, &limits, 64, true); if (ret < 0) return ret; } @@ -2009,6 +2048,23 @@ intel_dp_compute_output_format(struct intel_encoder *encoder, return ret; } +static void +intel_dp_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_connector *connector = conn_state->connector; + + pipe_config->sdp_split_enable = + intel_dp_has_audio(encoder, pipe_config, conn_state) && + intel_dp_is_uhbr(pipe_config); + + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDP split enable: %s\n", + connector->base.id, connector->name, + str_yes_no(pipe_config->sdp_split_enable)); +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2036,7 +2092,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (HAS_GMCH(dev_priv) && + if (!connector->base.interlace_allowed && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) return -EINVAL; @@ -2092,6 +2148,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, adjusted_mode->crtc_clock /= n; } + intel_dp_audio_compute_config(encoder, pipe_config, conn_state); + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, adjusted_mode->crtc_clock, @@ -2907,7 +2965,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_max_sink_lane_count(intel_dp); /* Read the eDP DSC DPCD registers */ - if (DISPLAY_VER(dev_priv) >= 10) + if (HAS_DSC(dev_priv)) intel_dp_get_dsc_sink_cap(intel_dp); /* @@ -4633,7 +4691,7 @@ intel_dp_detect(struct drm_connector *connector, } /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */ - if (DISPLAY_VER(dev_priv) >= 11) + if (HAS_DSC(dev_priv)) intel_dp_get_dsc_sink_cap(intel_dp); intel_dp_configure_mst(intel_dp); @@ -5202,7 +5260,20 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, return false; } - intel_pps_init(intel_dp); + intel_bios_init_panel_early(dev_priv, &intel_connector->panel, + encoder->devdata); + + if (!intel_pps_init(intel_dp)) { + drm_info(&dev_priv->drm, + "[ENCODER:%d:%s] unusable PPS, disabling eDP\n", + encoder->base.base.id, encoder->base.name); + /* + * The BIOS may have still enabled VDD on the PPS even + * though it's unusable. Make sure we turn it back off + * and to release the power domain references/etc. + */ + goto out_vdd_off; + } /* Cache DPCD and EDID for edp. */ has_dpcd = intel_edp_init_dpcd(intel_dp); @@ -5237,8 +5308,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; - intel_bios_init_panel(dev_priv, &intel_connector->panel, - encoder->devdata, IS_ERR(edid) ? NULL : edid); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, + encoder->devdata, IS_ERR(edid) ? NULL : edid); intel_panel_add_edid_fixed_modes(intel_connector, true); @@ -5364,7 +5435,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, drm_connector_init(dev, connector, &intel_dp_connector_funcs, type); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - if (!HAS_GMCH(dev_priv)) + if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12) connector->interlace_allowed = true; intel_connector->polled = DRM_CONNECTOR_POLL_HPD; diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index a54902c713a3..ef39e4f7a329 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -56,6 +56,12 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder); int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); +int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, + struct link_config_limits *limits, + int timeslots, + bool recompute_pipe_bpp); bool intel_dp_is_edp(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); @@ -96,6 +102,18 @@ void intel_read_dp_sdp(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, unsigned int type); bool intel_digital_port_connected(struct intel_encoder *encoder); +int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); +u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, + u32 link_clock, u32 lane_count, + u32 mode_clock, u32 mode_hdisplay, + bool bigjoiner, + u32 pipe_bpp, + u32 timeslots); +u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, + int mode_clock, int mode_hdisplay, + bool bigjoiner); +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + int hdisplay, int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) { @@ -103,6 +121,7 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) } u32 intel_dp_mode_to_fec_clock(u32 mode_clock); +u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp); void intel_ddi_update_pipe(struct intel_atomic_state *state, struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 664bebdecea7..5a176bfb10a2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -6,6 +6,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "i915_trace.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dp_aux.h" #include "intel_pps.h" @@ -40,20 +41,16 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp) i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); const unsigned int timeout_ms = 10; u32 status; - bool done; - -#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) - done = wait_event_timeout(i915->display.gmbus.wait_queue, C, - msecs_to_jiffies_timeout(timeout_ms)); + int ret; - /* just trace the final value */ - trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); + ret = __intel_de_wait_for_register(i915, ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY, 0, + 2, timeout_ms, &status); - if (!done) + if (ret == -ETIMEDOUT) drm_err(&i915->drm, "%s: did not complete or timeout within %ums (status 0x%08x)\n", intel_dp->aux.name, timeout_ms, status); -#undef C return status; } @@ -191,7 +188,6 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum phy phy = intel_port_to_phy(i915, dig_port->base.port); bool is_tc_port = intel_phy_is_tc(i915, phy); i915_reg_t ch_ctl, ch_data[5]; @@ -235,7 +231,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, /* Try to wait for any previous AUX channel activity */ for (try = 0; try < 3; try++) { - status = intel_uncore_read_notrace(uncore, ch_ctl); + status = intel_de_read_notrace(i915, ch_ctl); if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) break; msleep(1); @@ -244,7 +240,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); if (try == 3) { - const u32 status = intel_uncore_read(uncore, ch_ctl); + const u32 status = intel_de_read(i915, ch_ctl); if (status != intel_dp->aux_busy_last_status) { drm_WARN(&i915->drm, 1, @@ -274,23 +270,20 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ for (i = 0; i < send_bytes; i += 4) - intel_uncore_write(uncore, - ch_data[i >> 2], - intel_dp_aux_pack(send + i, - send_bytes - i)); + intel_de_write(i915, ch_data[i >> 2], + intel_dp_aux_pack(send + i, + send_bytes - i)); /* Send the command and wait for it to complete */ - intel_uncore_write(uncore, ch_ctl, send_ctl); + intel_de_write(i915, ch_ctl, send_ctl); status = intel_dp_aux_wait_done(intel_dp); /* Clear done status and any errors */ - intel_uncore_write(uncore, - ch_ctl, - status | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); + intel_de_write(i915, ch_ctl, + status | DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); /* * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 @@ -361,7 +354,7 @@ done: recv_bytes = recv_size; for (i = 0; i < recv_bytes; i += 4) - intel_dp_aux_unpack(intel_uncore_read(uncore, ch_data[i >> 2]), + intel_dp_aux_unpack(intel_de_read(i915, ch_data[i >> 2]), recv + i, recv_bytes - i); ret = recv_bytes; diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 4077a979a924..8b0e4defa3f1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -45,10 +45,14 @@ #include "intel_hotplug.h" #include "skl_scaler.h" -static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - struct link_config_limits *limits) +static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int max_bpp, + int min_bpp, + struct link_config_limits *limits, + struct drm_connector_state *conn_state, + int step, + bool dsc) { struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); @@ -60,6 +64,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int bpp, slots = -EINVAL; + int ret = 0; mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); if (IS_ERR(mst_state)) @@ -71,30 +76,68 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, // TODO: Handle pbn_div changes by adding a new MST helper if (!mst_state->pbn_div) { mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, - limits->max_rate, - limits->max_lane_count); + crtc_state->port_clock, + crtc_state->lane_count); } - for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { - crtc_state->pipe_bpp = bpp; - + for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, - crtc_state->pipe_bpp, - false); + dsc ? bpp << 4 : bpp, + dsc); + + drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); + slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, - connector->port, crtc_state->pbn); + connector->port, + crtc_state->pbn); if (slots == -EDEADLK) return slots; - if (slots >= 0) - break; + + if (slots >= 0) { + ret = drm_dp_mst_atomic_check(state); + /* + * If we got slots >= 0 and we can fit those based on check + * then we can exit the loop. Otherwise keep trying. + */ + if (!ret) + break; + } } + /* Despite slots are non-zero, we still failed the atomic check */ + if (ret && slots >= 0) + slots = ret; + if (slots < 0) { drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n", slots); - return slots; + } else { + if (!dsc) + crtc_state->pipe_bpp = bpp; + else + crtc_state->dsc.compressed_bpp = bpp; + drm_dbg_kms(&i915->drm, "Got %d slots for pipe bpp %d dsc %d\n", slots, bpp, dsc); } + return slots; +} + +static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + struct link_config_limits *limits) +{ + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int slots = -EINVAL; + + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp, + limits->min_bpp, limits, + conn_state, 2 * 3, false); + + if (slots < 0) + return slots; + intel_link_compute_m_n(crtc_state->pipe_bpp, crtc_state->lane_count, adjusted_mode->crtc_clock, @@ -106,6 +149,99 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, return 0; } +static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + struct link_config_limits *limits) +{ + struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); + struct intel_dp *intel_dp = &intel_mst->primary->dp; + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int slots = -EINVAL; + int i, num_bpc; + u8 dsc_bpc[3] = {0}; + int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp; + u8 dsc_max_bpc; + bool need_timeslot_recalc = false; + u32 last_compressed_bpp; + + /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */ + if (DISPLAY_VER(i915) >= 12) + dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc); + else + dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc); + + max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp); + min_bpp = limits->min_bpp; + + num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd, + dsc_bpc); + + drm_dbg_kms(&i915->drm, "DSC Source supported min bpp %d max bpp %d\n", + min_bpp, max_bpp); + + sink_max_bpp = dsc_bpc[0] * 3; + sink_min_bpp = sink_max_bpp; + + for (i = 1; i < num_bpc; i++) { + if (sink_min_bpp > dsc_bpc[i] * 3) + sink_min_bpp = dsc_bpc[i] * 3; + if (sink_max_bpp < dsc_bpc[i] * 3) + sink_max_bpp = dsc_bpc[i] * 3; + } + + drm_dbg_kms(&i915->drm, "DSC Sink supported min bpp %d max bpp %d\n", + sink_min_bpp, sink_max_bpp); + + if (min_bpp < sink_min_bpp) + min_bpp = sink_min_bpp; + + if (max_bpp > sink_max_bpp) + max_bpp = sink_max_bpp; + + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp, + min_bpp, limits, + conn_state, 2 * 3, true); + + if (slots < 0) + return slots; + + last_compressed_bpp = crtc_state->dsc.compressed_bpp; + + crtc_state->dsc.compressed_bpp = intel_dp_dsc_nearest_valid_bpp(i915, + last_compressed_bpp, + crtc_state->pipe_bpp); + + if (crtc_state->dsc.compressed_bpp != last_compressed_bpp) + need_timeslot_recalc = true; + + /* + * Apparently some MST hubs dislike if vcpi slots are not matching precisely + * the actual compressed bpp we use. + */ + if (need_timeslot_recalc) { + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, + crtc_state->dsc.compressed_bpp, + crtc_state->dsc.compressed_bpp, + limits, conn_state, 2 * 3, true); + if (slots < 0) + return slots; + } + + intel_link_compute_m_n(crtc_state->pipe_bpp, + crtc_state->lane_count, + adjusted_mode->crtc_clock, + crtc_state->port_clock, + &crtc_state->dp_m_n, + crtc_state->fec_enable); + crtc_state->dp_m_n.tu = slots; + + return 0; +} static int intel_dp_mst_update_slots(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -182,6 +318,29 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, ret = intel_dp_mst_compute_link_config(encoder, pipe_config, conn_state, &limits); + + if (ret == -EDEADLK) + return ret; + + /* enable compression if the mode doesn't fit available BW */ + drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en); + if (ret || intel_dp->force_dsc_en) { + /* + * Try to get at least some timeslots and then see, if + * we can fit there with DSC. + */ + drm_dbg_kms(&dev_priv->drm, "Trying to find VCPI slots in DSC mode\n"); + + ret = intel_dp_dsc_mst_compute_link_config(encoder, pipe_config, + conn_state, &limits); + if (ret < 0) + return ret; + + ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, + conn_state, &limits, + pipe_config->dp_m_n.tu, false); + } + if (ret) return ret; @@ -692,6 +851,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; int ret; + bool dsc = false, bigjoiner = false; + u16 dsc_max_output_bpp = 0; + u8 dsc_slice_count = 0; + int target_clock = mode->clock; if (drm_connector_is_unregistered(connector)) { *status = MODE_ERROR; @@ -729,6 +892,48 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } + if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) { + bigjoiner = true; + max_dotclk *= 2; + } + + if (DISPLAY_VER(dev_priv) >= 10 && + drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) { + /* + * TBD pass the connector BPC, + * for now U8_MAX so that max BPC on that platform would be picked + */ + int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX); + + if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) { + dsc_max_output_bpp = + intel_dp_dsc_get_output_bpp(dev_priv, + max_link_clock, + max_lanes, + target_clock, + mode->hdisplay, + bigjoiner, + pipe_bpp, 64) >> 4; + dsc_slice_count = + intel_dp_dsc_get_slice_count(intel_dp, + target_clock, + mode->hdisplay, + bigjoiner); + } + + dsc = dsc_max_output_bpp && dsc_slice_count; + } + + /* + * Big joiner configuration needs DSC for TGL which is not true for + * XE_LPD where uncompressed joiner is supported. + */ + if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc) + return MODE_CLOCK_HIGH; + + if (mode_rate > max_rate && !dsc) + return MODE_CLOCK_HIGH; + *status = intel_mode_valid_max_plane_size(dev_priv, mode, false); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 1e1c6107d51b..3d63c1bf1e4f 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -24,8 +24,10 @@ enum dsb_id { struct intel_dsb { enum dsb_id id; + u32 *cmd_buf; struct i915_vma *vma; + struct intel_crtc *crtc; /* * free_pos will point the first free entry position @@ -113,7 +115,7 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915, /** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. - * @crtc_state: intel_crtc_state structure + * @dsb: DSB context * @reg: register address. * @val: value. * @@ -123,20 +125,14 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915, * is done through mmio write. */ -void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_dsb *dsb = crtc_state->dsb; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *crtc = dsb->crtc; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf; + u32 *buf = dsb->cmd_buf; u32 reg_val; - if (!dsb) { - intel_de_write_fw(dev_priv, reg, val); - return; - } - buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; @@ -200,21 +196,13 @@ void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, * and rest all erroneous condition register programming is done * through mmio write. */ -void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *crtc = dsb->crtc; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_dsb *dsb; - u32 *buf; + u32 *buf = dsb->cmd_buf; - dsb = crtc_state->dsb; - if (!dsb) { - intel_de_write_fw(dev_priv, reg, val); - return; - } - - buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; @@ -229,17 +217,14 @@ void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, /** * intel_dsb_commit() - Trigger workload execution of DSB. - * @crtc_state: intel_crtc_state structure + * @dsb: DSB context * * This function is used to do actual write to hardware using DSB. - * On errors, fall back to MMIO. Also this function help to reset the context. */ -void intel_dsb_commit(const struct intel_crtc_state *crtc_state) +void intel_dsb_commit(struct intel_dsb *dsb) { - struct intel_dsb *dsb = crtc_state->dsb; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = dsb->crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 tail; @@ -286,14 +271,16 @@ reset: /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. - * @crtc_state: intel_crtc_state structure to prepare associated dsb instance. + * @crtc: the CRTC * * This function prepare the command buffer which is used to store dsb * instructions with data. + * + * Returns: + * DSB context, NULL on failure */ -void intel_dsb_prepare(struct intel_crtc_state *crtc_state) +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_dsb *dsb; struct drm_i915_gem_object *obj; @@ -302,63 +289,60 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state) intel_wakeref_t wakeref; if (!HAS_DSB(i915)) - return; + return NULL; dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); - if (!dsb) { - drm_err(&i915->drm, "DSB object creation failed\n"); - return; - } + if (!dsb) + goto out; wakeref = intel_runtime_pm_get(&i915->runtime_pm); obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); - if (IS_ERR(obj)) { - kfree(dsb); - goto out; - } + if (IS_ERR(obj)) + goto out_put_rpm; vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { i915_gem_object_put(obj); - kfree(dsb); - goto out; + goto out_put_rpm; } buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC); if (IS_ERR(buf)) { i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); - kfree(dsb); - goto out; + goto out_put_rpm; } + intel_runtime_pm_put(&i915->runtime_pm, wakeref); + dsb->id = DSB1; dsb->vma = vma; + dsb->crtc = crtc; dsb->cmd_buf = buf; dsb->free_pos = 0; dsb->ins_start_offset = 0; - crtc_state->dsb = dsb; -out: - if (!crtc_state->dsb) - drm_info(&i915->drm, - "DSB queue setup failed, will fallback to MMIO for display HW programming\n"); + return dsb; + +out_put_rpm: intel_runtime_pm_put(&i915->runtime_pm, wakeref); + kfree(dsb); +out: + drm_info_once(&i915->drm, + "DSB queue setup failed, will fallback to MMIO for display HW programming\n"); + + return NULL; } /** * intel_dsb_cleanup() - To cleanup DSB context. - * @crtc_state: intel_crtc_state structure to cleanup associated dsb instance. + * @dsb: DSB context * * This function cleanup the DSB context by unpinning and releasing * the VMA object associated with it. */ -void intel_dsb_cleanup(struct intel_crtc_state *crtc_state) +void intel_dsb_cleanup(struct intel_dsb *dsb) { - if (!crtc_state->dsb) - return; - - i915_vma_unpin_and_release(&crtc_state->dsb->vma, I915_VMA_RELEASE_MAP); - kfree(crtc_state->dsb); - crtc_state->dsb = NULL; + i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); + kfree(dsb); } diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 74dd2b3343bb..25f13c4d5389 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -10,14 +10,15 @@ #include "i915_reg_defs.h" -struct intel_crtc_state; +struct intel_crtc; +struct intel_dsb; -void intel_dsb_prepare(struct intel_crtc_state *crtc_state); -void intel_dsb_cleanup(struct intel_crtc_state *crtc_state); -void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); +void intel_dsb_cleanup(struct intel_dsb *dsb); +void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_commit(const struct intel_crtc_state *crtc_state); +void intel_dsb_commit(struct intel_dsb *dsb); #endif diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index c86f9890754d..4aeae0f3ac91 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -38,6 +38,7 @@ #include "intel_display_types.h" #include "intel_dvo.h" #include "intel_dvo_dev.h" +#include "intel_dvo_regs.h" #include "intel_gmbus.h" #include "intel_panel.h" @@ -56,48 +57,42 @@ static const struct intel_dvo_device intel_dvo_devices[] = { { .type = INTEL_DVO_CHIP_TMDS, .name = "sil164", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = SIL164_ADDR, .dev_ops = &sil164_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = CH7xxx_ADDR, .dev_ops = &ch7xxx_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = 0x75, /* For some ch7010 */ .dev_ops = &ch7xxx_ops, }, { .type = INTEL_DVO_CHIP_LVDS, .name = "ivch", - .dvo_reg = DVOA, - .dvo_srcdim_reg = DVOA_SRCDIM, + .port = PORT_A, .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ .dev_ops = &ivch_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "tfp410", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = TFP410_ADDR, .dev_ops = &tfp410_ops, }, { .type = INTEL_DVO_CHIP_LVDS, .name = "ch7017", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = 0x75, .gpio = GMBUS_PIN_DPB, .dev_ops = &ch7017_ops, @@ -105,8 +100,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { { .type = INTEL_DVO_CHIP_LVDS_NO_FIXED, .name = "ns2501", - .dvo_reg = DVOB, - .dvo_srcdim_reg = DVOB_SRCDIM, + .port = PORT_B, .slave_addr = NS2501_ADDR, .dev_ops = &ns2501_ops, }, @@ -118,8 +112,6 @@ struct intel_dvo { struct intel_dvo_device dev; struct intel_connector *attached_connector; - - bool panel_wants_dither; }; static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder) @@ -134,12 +126,13 @@ static struct intel_dvo *intel_attached_dvo(struct intel_connector *connector) static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_dvo *intel_dvo = intel_attached_dvo(connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_encoder *encoder = intel_attached_encoder(connector); + struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; u32 tmp; - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); if (!(tmp & DVO_ENABLE)) return false; @@ -150,13 +143,13 @@ static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; u32 tmp; - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); - *pipe = (tmp & DVO_PIPE_SEL_MASK) >> DVO_PIPE_SEL_SHIFT; + *pipe = REG_FIELD_GET(DVO_PIPE_SEL_MASK, tmp); return tmp & DVO_ENABLE; } @@ -164,13 +157,13 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, static void intel_dvo_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; u32 tmp, flags = 0; pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO); - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); if (tmp & DVO_HSYNC_ACTIVE_HIGH) flags |= DRM_MODE_FLAG_PHSYNC; else @@ -190,14 +183,14 @@ static void intel_disable_dvo(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(dev_priv, dvo_reg); + enum port port = encoder->port; intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); - intel_de_write(dev_priv, dvo_reg, temp & ~DVO_ENABLE); - intel_de_read(dev_priv, dvo_reg); + + intel_de_rmw(i915, DVO(port), DVO_ENABLE, 0); + intel_de_posting_read(i915, DVO(port)); } static void intel_enable_dvo(struct intel_atomic_state *state, @@ -205,30 +198,29 @@ static void intel_enable_dvo(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(dev_priv, dvo_reg); + enum port port = encoder->port; intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, &pipe_config->hw.mode, &pipe_config->hw.adjusted_mode); - intel_de_write(dev_priv, dvo_reg, temp | DVO_ENABLE); - intel_de_read(dev_priv, dvo_reg); + intel_de_rmw(i915, DVO(port), 0, DVO_ENABLE); + intel_de_posting_read(i915, DVO(port)); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } static enum drm_mode_status -intel_dvo_mode_valid(struct drm_connector *connector, +intel_dvo_mode_valid(struct drm_connector *_connector, struct drm_display_mode *mode) { - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_dvo *intel_dvo = intel_attached_dvo(connector); const struct drm_display_mode *fixed_mode = - intel_panel_fixed_mode(intel_connector, mode); - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + intel_panel_fixed_mode(connector, mode); + int max_dotclk = to_i915(connector->base.dev)->max_dotclk_freq; int target_clock = mode->clock; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -239,7 +231,7 @@ intel_dvo_mode_valid(struct drm_connector *connector, if (fixed_mode) { enum drm_mode_status status; - status = intel_panel_mode_valid(intel_connector, mode); + status = intel_panel_mode_valid(connector, mode); if (status != MODE_OK) return status; @@ -289,18 +281,17 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; enum pipe pipe = crtc->pipe; u32 dvo_val; - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg; - /* Save the data order, since I don't know what it should be set to. */ - dvo_val = intel_de_read(dev_priv, dvo_reg) & - (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + /* Save the active data order, since I don't know what it should be set to. */ + dvo_val = intel_de_read(i915, DVO(port)) & + (DVO_DEDICATED_INT_ENABLE | + DVO_PRESERVE_MASK | DVO_ACT_DATA_ORDER_MASK); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; @@ -311,19 +302,21 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) dvo_val |= DVO_VSYNC_ACTIVE_HIGH; - intel_de_write(dev_priv, dvo_srcdim_reg, - (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); - intel_de_write(dev_priv, dvo_reg, dvo_val); + intel_de_write(i915, DVO_SRCDIM(port), + DVO_SRCDIM_HORIZONTAL(adjusted_mode->crtc_hdisplay) | + DVO_SRCDIM_VERTICAL(adjusted_mode->crtc_vdisplay)); + intel_de_write(i915, DVO(port), dvo_val); } static enum drm_connector_status -intel_dvo_detect(struct drm_connector *connector, bool force) +intel_dvo_detect(struct drm_connector *_connector, bool force) { - struct drm_i915_private *i915 = to_i915(connector->dev); - struct intel_dvo *intel_dvo = intel_attached_dvo(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", + connector->base.base.id, connector->base.name); if (!INTEL_DISPLAY_ENABLED(i915)) return connector_status_disconnected; @@ -331,9 +324,10 @@ intel_dvo_detect(struct drm_connector *connector, bool force) return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); } -static int intel_dvo_get_modes(struct drm_connector *connector) +static int intel_dvo_get_modes(struct drm_connector *_connector) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int num_modes; /* @@ -342,12 +336,12 @@ static int intel_dvo_get_modes(struct drm_connector *connector) * (TV-out, for example), but for now with just TMDS and LVDS, * that's not the case. */ - num_modes = intel_ddc_get_modes(connector, - intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); + num_modes = intel_ddc_get_modes(&connector->base, + intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC)); if (num_modes) return num_modes; - return intel_panel_get_modes(to_intel_connector(connector)); + return intel_panel_get_modes(connector); } static const struct drm_connector_funcs intel_dvo_connector_funcs = { @@ -379,165 +373,187 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { .destroy = intel_dvo_enc_destroy, }; -static enum port intel_dvo_port(i915_reg_t dvo_reg) +static int intel_dvo_encoder_type(const struct intel_dvo_device *dvo) +{ + switch (dvo->type) { + case INTEL_DVO_CHIP_TMDS: + return DRM_MODE_ENCODER_TMDS; + case INTEL_DVO_CHIP_LVDS_NO_FIXED: + case INTEL_DVO_CHIP_LVDS: + return DRM_MODE_ENCODER_LVDS; + default: + MISSING_CASE(dvo->type); + return DRM_MODE_ENCODER_NONE; + } +} + +static int intel_dvo_connector_type(const struct intel_dvo_device *dvo) +{ + switch (dvo->type) { + case INTEL_DVO_CHIP_TMDS: + return DRM_MODE_CONNECTOR_DVII; + case INTEL_DVO_CHIP_LVDS_NO_FIXED: + case INTEL_DVO_CHIP_LVDS: + return DRM_MODE_CONNECTOR_LVDS; + default: + MISSING_CASE(dvo->type); + return DRM_MODE_CONNECTOR_Unknown; + } +} + +static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv, + struct intel_dvo *intel_dvo, + const struct intel_dvo_device *dvo) { - if (i915_mmio_reg_equal(dvo_reg, DVOA)) - return PORT_A; - else if (i915_mmio_reg_equal(dvo_reg, DVOB)) - return PORT_B; + struct i2c_adapter *i2c; + u32 dpll[I915_MAX_PIPES]; + enum pipe pipe; + int gpio; + bool ret; + + /* + * Allow the I2C driver info to specify the GPIO to be used in + * special cases, but otherwise default to what's defined + * in the spec. + */ + if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) + gpio = dvo->gpio; + else if (dvo->type == INTEL_DVO_CHIP_LVDS) + gpio = GMBUS_PIN_SSC; else - return PORT_C; + gpio = GMBUS_PIN_DPB; + + /* + * Set up the I2C bus necessary for the chip we're probing. + * It appears that everything is on GPIOE except for panels + * on i830 laptops, which are on GPIOB (DVOA). + */ + i2c = intel_gmbus_get_adapter(dev_priv, gpio); + + intel_dvo->dev = *dvo; + + /* + * GMBUS NAK handling seems to be unstable, hence let the + * transmitter detection run in bit banging mode for now. + */ + intel_gmbus_force_bit(i2c, true); + + /* + * ns2501 requires the DVO 2x clock before it will + * respond to i2c accesses, so make sure we have + * the clock enabled before we attempt to initialize + * the device. + */ + for_each_pipe(dev_priv, pipe) { + dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(pipe), + dpll[pipe] | DPLL_DVO_2X_MODE); + } + + ret = dvo->dev_ops->init(&intel_dvo->dev, i2c); + + /* restore the DVO 2x clock state to original */ + for_each_pipe(dev_priv, pipe) { + intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); + } + + intel_gmbus_force_bit(i2c, false); + + return ret; } -void intel_dvo_init(struct drm_i915_private *dev_priv) +static bool intel_dvo_probe(struct drm_i915_private *i915, + struct intel_dvo *intel_dvo) { - struct intel_encoder *intel_encoder; - struct intel_dvo *intel_dvo; - struct intel_connector *intel_connector; int i; - int encoder_type = DRM_MODE_ENCODER_NONE; + + /* Now, try to find a controller */ + for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { + if (intel_dvo_init_dev(i915, intel_dvo, + &intel_dvo_devices[i])) + return true; + } + + return false; +} + +void intel_dvo_init(struct drm_i915_private *i915) +{ + struct intel_connector *connector; + struct intel_encoder *encoder; + struct intel_dvo *intel_dvo; intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) return; - intel_connector = intel_connector_alloc(); - if (!intel_connector) { + connector = intel_connector_alloc(); + if (!connector) { kfree(intel_dvo); return; } - intel_dvo->attached_connector = intel_connector; + intel_dvo->attached_connector = connector; - intel_encoder = &intel_dvo->base; + encoder = &intel_dvo->base; - intel_encoder->disable = intel_disable_dvo; - intel_encoder->enable = intel_enable_dvo; - intel_encoder->get_hw_state = intel_dvo_get_hw_state; - intel_encoder->get_config = intel_dvo_get_config; - intel_encoder->compute_config = intel_dvo_compute_config; - intel_encoder->pre_enable = intel_dvo_pre_enable; - intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; + encoder->disable = intel_disable_dvo; + encoder->enable = intel_enable_dvo; + encoder->get_hw_state = intel_dvo_get_hw_state; + encoder->get_config = intel_dvo_get_config; + encoder->compute_config = intel_dvo_compute_config; + encoder->pre_enable = intel_dvo_pre_enable; + connector->get_hw_state = intel_dvo_connector_get_hw_state; - /* Now, try to find a controller */ - for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { - struct drm_connector *connector = &intel_connector->base; - const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; - struct i2c_adapter *i2c; - int gpio; - bool dvoinit; - enum pipe pipe; - u32 dpll[I915_MAX_PIPES]; - enum port port; + if (!intel_dvo_probe(i915, intel_dvo)) { + kfree(intel_dvo); + intel_connector_free(connector); + return; + } - /* - * Allow the I2C driver info to specify the GPIO to be used in - * special cases, but otherwise default to what's defined - * in the spec. - */ - if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) - gpio = dvo->gpio; - else if (dvo->type == INTEL_DVO_CHIP_LVDS) - gpio = GMBUS_PIN_SSC; - else - gpio = GMBUS_PIN_DPB; + encoder->type = INTEL_OUTPUT_DVO; + encoder->power_domain = POWER_DOMAIN_PORT_OTHER; + encoder->port = intel_dvo->dev.port; + encoder->pipe_mask = ~0; - /* - * Set up the I2C bus necessary for the chip we're probing. - * It appears that everything is on GPIOE except for panels - * on i830 laptops, which are on GPIOB (DVOA). - */ - i2c = intel_gmbus_get_adapter(dev_priv, gpio); + if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS) + encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | + BIT(INTEL_OUTPUT_DVO); - intel_dvo->dev = *dvo; + drm_encoder_init(&i915->drm, &encoder->base, + &intel_dvo_enc_funcs, + intel_dvo_encoder_type(&intel_dvo->dev), + "DVO %c", port_name(encoder->port)); - /* - * GMBUS NAK handling seems to be unstable, hence let the - * transmitter detection run in bit banging mode for now. - */ - intel_gmbus_force_bit(i2c, true); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] detected %s\n", + encoder->base.base.id, encoder->base.name, + intel_dvo->dev.name); + + if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS) + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_init(&i915->drm, &connector->base, + &intel_dvo_connector_funcs, + intel_dvo_connector_type(&intel_dvo->dev)); + + drm_connector_helper_add(&connector->base, + &intel_dvo_connector_helper_funcs); + connector->base.display_info.subpixel_order = SubPixelHorizontalRGB; + intel_connector_attach_encoder(connector, encoder); + + if (intel_dvo->dev.type == INTEL_DVO_CHIP_LVDS) { /* - * ns2501 requires the DVO 2x clock before it will - * respond to i2c accesses, so make sure we have - * have the clock enabled before we attempt to - * initialize the device. + * For our LVDS chipsets, we should hopefully be able + * to dig the fixed panel mode out of the BIOS data. + * However, it's in a different format from the BIOS + * data on chipsets with integrated LVDS (stored in AIM + * headers, likely), so for now, just get the current + * mode being output through DVO. */ - for_each_pipe(dev_priv, pipe) { - dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); - intel_de_write(dev_priv, DPLL(pipe), - dpll[pipe] | DPLL_DVO_2X_MODE); - } - - dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); - - /* restore the DVO 2x clock state to original */ - for_each_pipe(dev_priv, pipe) { - intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); - } - - intel_gmbus_force_bit(i2c, false); - - if (!dvoinit) - continue; - - port = intel_dvo_port(dvo->dvo_reg); - drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dvo_enc_funcs, encoder_type, - "DVO %c", port_name(port)); - - intel_encoder->type = INTEL_OUTPUT_DVO; - intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - intel_encoder->port = port; - intel_encoder->pipe_mask = ~0; - - if (dvo->type != INTEL_DVO_CHIP_LVDS) - intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | - BIT(INTEL_OUTPUT_DVO); - - switch (dvo->type) { - case INTEL_DVO_CHIP_TMDS: - intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - DRM_MODE_CONNECTOR_DVII); - encoder_type = DRM_MODE_ENCODER_TMDS; - break; - case INTEL_DVO_CHIP_LVDS_NO_FIXED: - case INTEL_DVO_CHIP_LVDS: - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - encoder_type = DRM_MODE_ENCODER_LVDS; - break; - } - - drm_connector_helper_add(connector, - &intel_dvo_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - - intel_connector_attach_encoder(intel_connector, intel_encoder); - if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* - * For our LVDS chipsets, we should hopefully be able - * to dig the fixed panel mode out of the BIOS data. - * However, it's in a different format from the BIOS - * data on chipsets with integrated LVDS (stored in AIM - * headers, likely), so for now, just get the current - * mode being output through DVO. - */ - intel_panel_add_encoder_fixed_mode(intel_connector, - intel_encoder); - - intel_panel_init(intel_connector); - - intel_dvo->panel_wants_dither = true; - } + intel_panel_add_encoder_fixed_mode(connector, encoder); - return; + intel_panel_init(connector); } - - kfree(intel_dvo); - kfree(intel_connector); } diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index ecff7b190856..ea8eb7dcee38 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -25,6 +25,8 @@ #include "i915_reg_defs.h" +#include "intel_display.h" + enum drm_connector_status; struct drm_display_mode; struct i2c_adapter; @@ -32,9 +34,8 @@ struct i2c_adapter; struct intel_dvo_device { const char *name; int type; - /* DVOA/B/C output register */ - i915_reg_t dvo_reg; - i915_reg_t dvo_srcdim_reg; + /* DVOA/B/C */ + enum port port; /* GPIO register used for i2c bus to control this device */ u32 gpio; int slave_addr; diff --git a/drivers/gpu/drm/i915/display/intel_dvo_regs.h b/drivers/gpu/drm/i915/display/intel_dvo_regs.h new file mode 100644 index 000000000000..6f9058462850 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dvo_regs.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DVO_REGS_H__ +#define __INTEL_DVO_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _DVOA 0x61120 +#define _DVOB 0x61140 +#define _DVOC 0x61160 +#define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB) +#define DVO_ENABLE REG_BIT(31) +#define DVO_PIPE_SEL_MASK REG_BIT(30) +#define DVO_PIPE_SEL(pipe) REG_FIELD_PREP(DVO_PIPE_SEL_MASK, (pipe)) +#define DVO_PIPE_STALL_MASK REG_GENMASK(29, 28) +#define DVO_PIPE_STALL_UNUSED REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 0) +#define DVO_PIPE_STALL REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 1) +#define DVO_PIPE_STALL_TV REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 2) +#define DVO_INTERRUPT_SELECT REG_BIT(27) +#define DVO_DEDICATED_INT_ENABLE REG_BIT(26) +#define DVO_PRESERVE_MASK REG_GENMASK(25, 24) +#define DVO_USE_VGA_SYNC REG_BIT(15) +#define DVO_DATA_ORDER_MASK REG_BIT(14) +#define DVO_DATA_ORDER_I740 REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 0) +#define DVO_DATA_ORDER_FP REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_DISABLE REG_BIT(11) +#define DVO_HSYNC_DISABLE REG_BIT(10) +#define DVO_VSYNC_TRISTATE REG_BIT(9) +#define DVO_HSYNC_TRISTATE REG_BIT(8) +#define DVO_BORDER_ENABLE REG_BIT(7) +#define DVO_ACT_DATA_ORDER_MASK REG_BIT(6) +#define DVO_ACT_DATA_ORDER_RGGB REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_GBRG REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_ACT_DATA_ORDER_GBRG_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_RGGB_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_ACTIVE_HIGH REG_BIT(4) +#define DVO_HSYNC_ACTIVE_HIGH REG_BIT(3) +#define DVO_BLANK_ACTIVE_HIGH REG_BIT(2) +#define DVO_OUTPUT_CSTATE_PIXELS REG_BIT(1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS REG_BIT(0) /* SDG only */ + +#define _DVOA_SRCDIM 0x61124 +#define _DVOB_SRCDIM 0x61144 +#define _DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM) +#define DVO_SRCDIM_HORIZONTAL_MASK REG_GENMASK(22, 12) +#define DVO_SRCDIM_HORIZONTAL(x) REG_FIELD_PREP(DVO_SRCDIM_HORIZONTAL_MASK, (x)) +#define DVO_SRCDIM_VERTICAL_MASK REG_GENMASK(10, 0) +#define DVO_SRCDIM_VERTICAL(x) REG_FIELD_PREP(DVO_SRCDIM_VERTICAL_MASK, (x)) + +#endif /* __INTEL_DVO_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 63137ae5ab21..93d0e46e5481 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -174,7 +174,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC, }, { .modifier = I915_FORMAT_MOD_4_TILED, - .display_ver = { 13, 13 }, + .display_ver = { 13, -1 }, .plane_caps = INTEL_PLANE_CAP_TILING_4, }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index b5ee5ea0d010..5e69d3c11d21 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -323,10 +323,8 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); } static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) @@ -359,10 +357,8 @@ static void i965_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); } static const struct intel_fbc_funcs i965_fbc_funcs = { @@ -815,7 +811,7 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc) static void intel_fbc_program_workarounds(struct intel_fbc *fbc) { - /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp */ + /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915)) intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); @@ -1095,7 +1091,9 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, } /* Wa_14016291713 */ - if (IS_DISPLAY_VER(i915, 12, 13) && crtc_state->has_psr) { + if ((IS_DISPLAY_VER(i915, 12, 13) || + IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0)) && + crtc_state->has_psr) { plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)"; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index a5840a28a69d..0bc4f6b48e80 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -255,14 +255,12 @@ static void bxt_gmbus_clock_gating(struct drm_i915_private *i915, static u32 get_reserved(struct intel_gmbus *bus) { struct drm_i915_private *i915 = bus->i915; - struct intel_uncore *uncore = &i915->uncore; u32 reserved = 0; /* On most chips, these bits must be preserved in software. */ if (!IS_I830(i915) && !IS_I845G(i915)) - reserved = intel_uncore_read_notrace(uncore, bus->gpio_reg) & - (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); + reserved = intel_de_read_notrace(i915, bus->gpio_reg) & + (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); return reserved; } @@ -270,37 +268,31 @@ static u32 get_reserved(struct intel_gmbus *bus) static int get_clock(void *data) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | GPIO_CLOCK_DIR_MASK); - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK); + intel_de_write_notrace(i915, bus->gpio_reg, reserved); - return (intel_uncore_read_notrace(uncore, bus->gpio_reg) & - GPIO_CLOCK_VAL_IN) != 0; + return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0; } static int get_data(void *data) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | GPIO_DATA_DIR_MASK); - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK); + intel_de_write_notrace(i915, bus->gpio_reg, reserved); - return (intel_uncore_read_notrace(uncore, bus->gpio_reg) & - GPIO_DATA_VAL_IN) != 0; + return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0; } static void set_clock(void *data, int state_high) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); u32 clock_bits; @@ -310,16 +302,14 @@ static void set_clock(void *data, int state_high) clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | clock_bits); - intel_uncore_posting_read(uncore, bus->gpio_reg); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | clock_bits); + intel_de_posting_read(i915, bus->gpio_reg); } static void set_data(void *data, int state_high) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); u32 data_bits; @@ -329,8 +319,8 @@ static void set_data(void *data, int state_high) data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK; - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved | data_bits); - intel_uncore_posting_read(uncore, bus->gpio_reg); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | data_bits); + intel_de_posting_read(i915, bus->gpio_reg); } static int @@ -439,9 +429,7 @@ gmbus_wait_idle(struct drm_i915_private *i915) add_wait_queue(&i915->display.gmbus.wait_queue, &wait); intel_de_write_fw(i915, GMBUS4(i915), irq_enable); - ret = intel_wait_for_register_fw(&i915->uncore, - GMBUS2(i915), GMBUS_ACTIVE, 0, - 10); + ret = intel_de_wait_for_register_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10); intel_de_write_fw(i915, GMBUS4(i915), 0); remove_wait_queue(&i915->display.gmbus.wait_queue, &wait); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index bac85d88054f..6a2ee342eab5 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -537,7 +537,8 @@ void hsw_write_infoframe(struct intel_encoder *encoder, 0); /* Wa_14013475917 */ - if (DISPLAY_VER(dev_priv) == 13 && crtc_state->has_psr && + if ((DISPLAY_VER(dev_priv) == 13 || + IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) && crtc_state->has_psr && type == DP_SDP_VSC) return; @@ -767,6 +768,7 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd; int ret; @@ -776,7 +778,11 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD); - ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); + if (IS_DGFX(i915)) + ret = hdmi_spd_infoframe_init(frame, "Intel", "Discrete gfx"); + else + ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); + if (drm_WARN_ON(encoder->base.dev, ret)) return false; @@ -1988,9 +1994,6 @@ intel_hdmi_mode_valid(struct drm_connector *connector, 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; - if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) clock *= 2; @@ -2252,6 +2255,10 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; + if (!connector->interlace_allowed && + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + return -EINVAL; + pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_hdmi, conn_state) && @@ -2953,7 +2960,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, ddc); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); - connector->interlace_allowed = true; + if (DISPLAY_VER(dev_priv) < 12) + connector->interlace_allowed = true; + connector->stereo_allowed = true; if (DISPLAY_VER(dev_priv) >= 10) diff --git a/drivers/gpu/drm/i915/display/intel_hti.c b/drivers/gpu/drm/i915/display/intel_hti.c index 12a1f4ce1a77..c518efebdf77 100644 --- a/drivers/gpu/drm/i915/display/intel_hti.c +++ b/drivers/gpu/drm/i915/display/intel_hti.c @@ -21,6 +21,9 @@ void intel_hti_init(struct drm_i915_private *i915) bool intel_hti_uses_phy(struct drm_i915_private *i915, enum phy phy) { + if (drm_WARN_ON(&i915->drm, phy == PHY_NONE)) + return false; + return i915->display.hti.state & HDPORT_ENABLED && i915->display.hti.state & HDPORT_DDI_USED(phy); } diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 7bf1bdfd03ec..aecec992cd0d 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -964,8 +964,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) } intel_connector->edid = edid; - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, - IS_ERR(edid) ? NULL : edid); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, + IS_ERR(edid) ? NULL : edid); /* Try EDID first */ intel_panel_add_edid_fixed_modes(intel_connector, true); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 1640726bfbf6..3b1004b019a8 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -661,6 +661,15 @@ intel_panel_mode_valid(struct intel_connector *connector, return MODE_OK; } +void intel_panel_init_alloc(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + + connector->panel.vbt.panel_type = -1; + connector->panel.vbt.backlight.controller = -1; + INIT_LIST_HEAD(&panel->fixed_modes); +} + int intel_panel_init(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 5c5b5b7f95b6..4b51e1c51da6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -18,6 +18,7 @@ struct intel_connector; struct intel_crtc_state; struct intel_encoder; +void intel_panel_init_alloc(struct intel_connector *connector); int intel_panel_init(struct intel_connector *connector); void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 9bbf41a076f7..7b21438edd9b 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -22,6 +22,40 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, static void pps_init_delays(struct intel_dp *intel_dp); static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd); +static const char *pps_name(struct drm_i915_private *i915, + struct intel_pps *pps) +{ + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + switch (pps->pps_pipe) { + case INVALID_PIPE: + /* + * FIXME would be nice if we can guarantee + * to always have a valid PPS when calling this. + */ + return "PPS <none>"; + case PIPE_A: + return "PPS A"; + case PIPE_B: + return "PPS B"; + default: + MISSING_CASE(pps->pps_pipe); + break; + } + } else { + switch (pps->pps_idx) { + case 0: + return "PPS 0"; + case 1: + return "PPS 1"; + default: + MISSING_CASE(pps->pps_idx); + break; + } + } + + return "PPS <invalid>"; +} + intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -60,15 +94,15 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) if (drm_WARN(&dev_priv->drm, intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN, - "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name)) + "skipping %s kick due to [ENCODER:%d:%s] being active\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name)) return; drm_dbg_kms(&dev_priv->drm, - "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name); + "kicking %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); /* Preserve the BIOS-computed detected bit. This is * supposed to be read-only. @@ -95,7 +129,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) { drm_err(&dev_priv->drm, - "Failed to force on pll for pipe %c!\n", + "Failed to force on PLL for pipe %c!\n", pipe_name(pipe)); return; } @@ -190,10 +224,9 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) intel_dp->pps.pps_pipe = pipe; drm_dbg_kms(&dev_priv->drm, - "picked pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(intel_dp->pps.pps_pipe), - dig_port->base.base.base.id, - dig_port->base.base.name); + "picked %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); /* init power sequencer on this pipe and port */ pps_init_delays(intel_dp); @@ -212,8 +245,7 @@ static int bxt_power_sequencer_idx(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_connector *connector = intel_dp->attached_connector; - int backlight_controller = connector->panel.vbt.backlight.controller; + int pps_idx = intel_dp->pps.pps_idx; lockdep_assert_held(&dev_priv->display.pps.mutex); @@ -221,7 +253,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp)); if (!intel_dp->pps.pps_reset) - return backlight_controller; + return pps_idx; intel_dp->pps.pps_reset = false; @@ -231,34 +263,29 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) */ pps_init_registers(intel_dp, false); - return backlight_controller; + return pps_idx; } -typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv, - enum pipe pipe); +typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx); -static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_has_pp_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON; + return intel_de_read(dev_priv, PP_STATUS(pps_idx)) & PP_ON; } -static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_has_vdd_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD; + return intel_de_read(dev_priv, PP_CONTROL(pps_idx)) & EDP_FORCE_VDD; } -static bool vlv_pipe_any(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_any(struct drm_i915_private *dev_priv, int pps_idx) { return true; } static enum pipe vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, - enum port port, - vlv_pipe_check pipe_check) + enum port port, pps_check check) { enum pipe pipe; @@ -269,7 +296,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, if (port_sel != PANEL_PORT_SELECT_VLV(port)) continue; - if (!pipe_check(dev_priv, pipe)) + if (!check(dev_priv, pipe)) continue; return pipe; @@ -290,30 +317,117 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) /* try to find a pipe with this port selected */ /* first pick one where the panel is on */ intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_has_pp_on); + pps_has_pp_on); /* didn't find one? pick one where vdd is on */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_has_vdd_on); + pps_has_vdd_on); /* didn't find one? pick one with just the correct port */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_any); + pps_any); /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) { drm_dbg_kms(&dev_priv->drm, - "no initial power sequencer for [ENCODER:%d:%s]\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + "[ENCODER:%d:%s] no initial power sequencer\n", + dig_port->base.base.base.id, dig_port->base.base.name); return; } drm_dbg_kms(&dev_priv->drm, - "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n", - dig_port->base.base.base.id, - dig_port->base.base.name, - pipe_name(intel_dp->pps.pps_pipe)); + "[ENCODER:%d:%s] initial power sequencer: %s\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); +} + +static int intel_num_pps(struct drm_i915_private *i915) +{ + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return 2; + + if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) + return 2; + + if (INTEL_PCH_TYPE(i915) >= PCH_DG1) + return 1; + + if (INTEL_PCH_TYPE(i915) >= PCH_ICP) + return 2; + + return 1; +} + +static bool intel_pps_is_valid(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (intel_dp->pps.pps_idx == 1 && + INTEL_PCH_TYPE(i915) >= PCH_ICP && + INTEL_PCH_TYPE(i915) < PCH_MTP) + return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT; + + return true; +} + +static int +bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) +{ + int pps_idx, pps_num = intel_num_pps(i915); + + for (pps_idx = 0; pps_idx < pps_num; pps_idx++) { + if (check(i915, pps_idx)) + return pps_idx; + } + + return -1; +} + +static bool +pps_initial_setup(struct intel_dp *intel_dp) +{ + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct intel_connector *connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + lockdep_assert_held(&i915->display.pps.mutex); + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + vlv_initial_power_sequencer_setup(intel_dp); + return true; + } + + /* first ask the VBT */ + if (intel_num_pps(i915) > 1) + intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; + else + intel_dp->pps.pps_idx = 0; + + if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= intel_num_pps(i915))) + intel_dp->pps.pps_idx = -1; + + /* VBT wasn't parsed yet? pick one where the panel is on */ + if (intel_dp->pps.pps_idx < 0) + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_pp_on); + /* didn't find one? pick one where vdd is on */ + if (intel_dp->pps.pps_idx < 0) + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_vdd_on); + /* didn't find one? pick any */ + if (intel_dp->pps.pps_idx < 0) { + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_any); + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] no initial power sequencer, assuming %s\n", + encoder->base.base.id, encoder->base.name, + pps_name(i915, &intel_dp->pps)); + } else { + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] initial power sequencer: %s\n", + encoder->base.base.id, encoder->base.name, + pps_name(i915, &intel_dp->pps)); + } + + return intel_pps_is_valid(intel_dp); } void intel_pps_reset_all(struct drm_i915_private *dev_priv) @@ -364,14 +478,16 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, struct pps_registers *regs) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - int pps_idx = 0; + int pps_idx; memset(regs, 0, sizeof(*regs)); - if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - pps_idx = bxt_power_sequencer_idx(intel_dp); - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) pps_idx = vlv_power_sequencer_pipe(intel_dp); + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) + pps_idx = bxt_power_sequencer_idx(intel_dp); + else + pps_idx = intel_dp->pps.pps_idx; regs->pp_ctrl = PP_CONTROL(pps_idx); regs->pp_stat = PP_STATUS(pps_idx); @@ -435,21 +551,27 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); if (!intel_dp_is_edp(intel_dp)) return; if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) { drm_WARN(&dev_priv->drm, 1, - "eDP powered off while attempting aux channel communication.\n"); - drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n", + "[ENCODER:%d:%s] %s powered off while attempting AUX CH communication.\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); + drm_dbg_kms(&dev_priv->drm, + "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, _pp_stat_reg(intel_dp)), intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp))); } } #define IDLE_ON_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) -#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) +#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) #define IDLE_OFF_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | 0) #define IDLE_OFF_VALUE (0 | PP_SEQUENCE_NONE | 0 | 0) @@ -460,10 +582,10 @@ void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) static void intel_pps_verify_state(struct intel_dp *intel_dp); static void wait_panel_status(struct intel_dp *intel_dp, - u32 mask, - u32 value) + u32 mask, u32 value) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); i915_reg_t pp_stat_reg, pp_ctrl_reg; lockdep_assert_held(&dev_priv->display.pps.mutex); @@ -474,7 +596,9 @@ static void wait_panel_status(struct intel_dp *intel_dp, pp_ctrl_reg = _pp_ctrl_reg(intel_dp); drm_dbg_kms(&dev_priv->drm, - "mask %08x value %08x status %08x control %08x\n", + "[ENCODER:%d:%s] %s mask: 0x%08x value: 0x%08x PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), mask, value, intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -482,7 +606,9 @@ static void wait_panel_status(struct intel_dp *intel_dp, if (intel_de_wait_for_register(dev_priv, pp_stat_reg, mask, value, 5000)) drm_err(&dev_priv->drm, - "Panel status timeout: status %08x control %08x\n", + "[ENCODER:%d:%s] %s panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -492,26 +618,35 @@ static void wait_panel_status(struct intel_dp *intel_dp, static void wait_panel_on(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - drm_dbg_kms(&i915->drm, "Wait for panel power on\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power on\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE); } static void wait_panel_off(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - drm_dbg_kms(&i915->drm, "Wait for panel power off time\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power off time\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE); } static void wait_panel_power_cycle(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); ktime_t panel_power_on_time; s64 panel_power_off_duration; - drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power cycle\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); /* take the difference of current time and panel power off time * and then make panel wait for t11_t12 if needed. */ @@ -598,9 +733,12 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port)); - drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + pp_stat_reg = _pp_stat_reg(intel_dp); + pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD on\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); if (!edp_have_panel_power(intel_dp)) wait_panel_power_cycle(intel_dp); @@ -608,12 +746,11 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) pp = ilk_get_pp_control(intel_dp); pp |= EDP_FORCE_VDD; - pp_stat_reg = _pp_stat_reg(intel_dp); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); - intel_de_write(dev_priv, pp_ctrl_reg, pp); intel_de_posting_read(dev_priv, pp_ctrl_reg); - drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); /* @@ -621,9 +758,9 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) */ if (!edp_have_panel_power(intel_dp)) { drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] panel power wasn't enabled\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + "[ENCODER:%d:%s] %s panel power wasn't enabled\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); msleep(intel_dp->pps.panel_power_up_delay); } @@ -638,6 +775,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) */ void intel_pps_vdd_on(struct intel_dp *intel_dp) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); intel_wakeref_t wakeref; bool vdd; @@ -647,9 +785,10 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp) vdd = false; with_intel_pps_lock(intel_dp, wakeref) vdd = intel_pps_vdd_on_unlocked(intel_dp); - I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n", + I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] %s VDD already requested on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(i915, &intel_dp->pps)); } static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) @@ -667,9 +806,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) if (!edp_have_panel_vdd(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD off\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); pp = ilk_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; @@ -681,7 +820,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) intel_de_posting_read(dev_priv, pp_ctrl_reg); /* Make sure sequencer is idle before allowing subsequent activity */ - drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -756,9 +897,10 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync) if (!intel_dp_is_edp(intel_dp)) return; - I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on", + I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] %s VDD not forced on", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); intel_dp->pps.want_panel_vdd = false; @@ -779,14 +921,16 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) if (!intel_dp_is_edp(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp), - "[ENCODER:%d:%s] panel power already on\n", + "[ENCODER:%d:%s] %s panel power already on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name)) + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps))) return; wait_panel_power_cycle(intel_dp); @@ -840,12 +984,14 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp) if (!intel_dp_is_edp(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n", - dig_port->base.base.base.id, dig_port->base.base.name); + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power off\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); drm_WARN(&dev_priv->drm, !intel_dp->pps.want_panel_vdd, - "Need [ENCODER:%d:%s] VDD to turn off panel\n", - dig_port->base.base.base.id, dig_port->base.base.name); + "[ENCODER:%d:%s] %s need VDD to turn off panel\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); pp = ilk_get_pp_control(intel_dp); /* We need to switch off panel power _and_ force vdd, for otherwise some @@ -980,9 +1126,9 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) * from a port. */ drm_dbg_kms(&dev_priv->drm, - "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name); + "detaching %s from [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); intel_de_write(dev_priv, pp_on_reg, 0); intel_de_posting_read(dev_priv, pp_on_reg); @@ -1000,7 +1146,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); drm_WARN(&dev_priv->drm, intel_dp->pps.active_pipe == pipe, - "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n", + "stealing PPS %c from active [ENCODER:%d:%s]\n", pipe_name(pipe), encoder->base.base.id, encoder->base.name); @@ -1008,7 +1154,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, continue; drm_dbg_kms(&dev_priv->drm, - "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n", + "stealing PPS %c from [ENCODER:%d:%s]\n", pipe_name(pipe), encoder->base.base.id, encoder->base.name); @@ -1053,9 +1199,9 @@ void vlv_pps_init(struct intel_encoder *encoder, intel_dp->pps.pps_pipe = crtc->pipe; drm_dbg_kms(&dev_priv->drm, - "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(intel_dp->pps.pps_pipe), encoder->base.base.id, - encoder->base.name); + "initializing %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + encoder->base.base.id, encoder->base.name); /* init power sequencer on this pipe and port */ pps_init_delays(intel_dp); @@ -1079,7 +1225,9 @@ static void pps_vdd_init(struct intel_dp *intel_dp) * indefinitely. */ drm_dbg_kms(&dev_priv->drm, - "VDD left on by BIOS, adjusting state tracking\n"); + "[ENCODER:%d:%s] %s VDD left on by BIOS, adjusting state tracking\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref); intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port)); @@ -1432,10 +1580,10 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp) } } -void intel_pps_init(struct intel_dp *intel_dp) +bool intel_pps_init(struct intel_dp *intel_dp) { - struct drm_i915_private *i915 = dp_to_i915(intel_dp); intel_wakeref_t wakeref; + bool ret; intel_dp->pps.initializing = true; INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work); @@ -1443,13 +1591,36 @@ void intel_pps_init(struct intel_dp *intel_dp) pps_init_timestamps(intel_dp); with_intel_pps_lock(intel_dp, wakeref) { - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - vlv_initial_power_sequencer_setup(intel_dp); + ret = pps_initial_setup(intel_dp); pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); pps_vdd_init(intel_dp); } + + return ret; +} + +static void pps_init_late(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct intel_connector *connector = intel_dp->attached_connector; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return; + + if (intel_num_pps(i915) < 2) + return; + + drm_WARN(&i915->drm, connector->panel.vbt.backlight.controller >= 0 && + intel_dp->pps.pps_idx != connector->panel.vbt.backlight.controller, + "[ENCODER:%d:%s] power sequencer mismatch: %d (initial) vs. %d (VBT)\n", + encoder->base.base.id, encoder->base.name, + intel_dp->pps.pps_idx, connector->panel.vbt.backlight.controller); + + if (connector->panel.vbt.backlight.controller >= 0) + intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; } void intel_pps_init_late(struct intel_dp *intel_dp) @@ -1458,6 +1629,8 @@ void intel_pps_init_late(struct intel_dp *intel_dp) with_intel_pps_lock(intel_dp, wakeref) { /* Reinit delays after per-panel info has been parsed from VBT */ + pps_init_late(intel_dp); + memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp->pps.pps_delays)); pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); @@ -1480,10 +1653,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) * This w/a is needed at least on CPT/PPT, but to be sure apply it * everywhere where registers can be write protected. */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - pps_num = 2; - else - pps_num = 1; + pps_num = intel_num_pps(dev_priv); for (pps_idx = 0; pps_idx < pps_num; pps_idx++) { u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx)); diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h index a3a56f903f26..a2c2467e3c22 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.h +++ b/drivers/gpu/drm/i915/display/intel_pps.h @@ -40,7 +40,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp); bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp); void intel_pps_wait_power_cycle(struct intel_dp *intel_dp); -void intel_pps_init(struct intel_dp *intel_dp); +bool intel_pps_init(struct intel_dp *intel_dp); void intel_pps_init_late(struct intel_dp *intel_dp); void intel_pps_encoder_reset(struct intel_dp *intel_dp); void intel_pps_reset_all(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 5b678916e6db..d0d774219cc5 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -797,7 +797,7 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp, return intel_dp->psr.su_y_granularity == 4; /* - * adl_p and display 14+ platforms has 1 line granularity. + * adl_p and mtl platforms have 1 line granularity. * For other platforms with SW tracking we can adjust the y coordinates * to match sink requirement if multiple of 4. */ @@ -1170,11 +1170,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, PSR2_ADD_VERTICAL_LINE_COUNT); /* - * Wa_16014451276:adlp + * Wa_16014451276:adlp,mtl[a0,b0] * All supported adlp panels have 1-based X granularity, this may * cause issues if non-supported panels are used. */ - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), 0, + ADLP_1_BASED_X_GRANULARITY); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, ADLP_1_BASED_X_GRANULARITY); @@ -1185,8 +1188,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, TRANS_SET_CONTEXT_LATENCY_MASK, TRANS_SET_CONTEXT_LATENCY_VALUE(1)); - /* Wa_16012604467:adlp */ - if (IS_ALDERLAKE_P(dev_priv)) + /* Wa_16012604467:adlp,mtl[a0,b0] */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, + MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0, + MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, CLKGATE_DIS_MISC_DMASC_GATING_DIS); @@ -1362,8 +1369,12 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) TRANS_SET_CONTEXT_LATENCY(intel_dp->psr.transcoder), TRANS_SET_CONTEXT_LATENCY_MASK, 0); - /* Wa_16012604467:adlp */ - if (IS_ALDERLAKE_P(dev_priv)) + /* Wa_16012604467:adlp,mtl[a0,b0] */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, + MTL_CLKGATE_DIS_TRANS(intel_dp->psr.transcoder), + MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); @@ -1510,7 +1521,8 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | - man_trk_ctl_single_full_frame_bit_get(dev_priv)); + man_trk_ctl_single_full_frame_bit_get(dev_priv) | + man_trk_ctl_continuos_full_frame(dev_priv)); /* * Display WA #0884: skl+ @@ -1624,11 +1636,8 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, val |= man_trk_ctl_partial_frame_bit_get(dev_priv); if (full_update) { - /* - * Not applying Wa_14014971508:adlp as we do not support the - * feature that requires this workaround. - */ val |= man_trk_ctl_single_full_frame_bit_get(dev_priv); + val |= man_trk_ctl_continuos_full_frame(dev_priv); goto exit; } @@ -2307,12 +2316,15 @@ static void _psr_flush_handle(struct intel_dp *intel_dp) /* can we turn CFF off? */ if (intel_dp->psr.busy_frontbuffer_bits == 0) { u32 val = man_trk_ctl_enable_bit_get(dev_priv) | - man_trk_ctl_partial_frame_bit_get(dev_priv) | - man_trk_ctl_single_full_frame_bit_get(dev_priv); + man_trk_ctl_partial_frame_bit_get(dev_priv) | + man_trk_ctl_single_full_frame_bit_get(dev_priv) | + man_trk_ctl_continuos_full_frame(dev_priv); /* - * turn continuous full frame off and do a single - * full frame + * Set psr2_sel_fetch_cff_enabled as false to allow selective + * updates. Still keep cff bit enabled as we don't have proper + * SU configuration in case update is sent for any reason after + * sff bit gets cleared by the HW on next vblank. */ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), val); diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 329b9d9af667..21805c15d5eb 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2886,7 +2886,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type) if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; - intel_bios_init_panel(i915, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(i915, &intel_connector->panel, NULL, NULL); /* * Fetch modes from VBT. For SDVO prefer the VBT mode since some diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index c799e891f8b5..9494cfd45519 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -44,18 +44,18 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) } } -void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv, +void intel_snps_phy_update_psr_power_state(struct drm_i915_private *i915, enum phy phy, bool enable) { u32 val; - if (!intel_phy_is_snps(dev_priv, phy)) + if (!intel_phy_is_snps(i915, phy)) return; val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, enable ? 2 : 3); - intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_TX_REQ(phy), - SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val); + intel_de_rmw(i915, SNPS_PHY_TX_REQ(phy), + SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val); } void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, @@ -1785,7 +1785,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder, */ /* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */ - intel_uncore_rmw(&dev_priv->uncore, enable_reg, 0, PLL_ENABLE); + intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE); /* * 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This @@ -1830,14 +1830,13 @@ void intel_mpllb_disable(struct intel_encoder *encoder) */ /* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */ - intel_uncore_rmw(&i915->uncore, enable_reg, PLL_ENABLE, 0); + intel_de_rmw(i915, enable_reg, PLL_ENABLE, 0); /* * 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0". * This will allow the PLL to stop running. */ - intel_uncore_rmw(&i915->uncore, SNPS_PHY_MPLLB_DIV(phy), - SNPS_PHY_MPLLB_FORCE_EN, 0); + intel_de_rmw(i915, SNPS_PHY_MPLLB_DIV(phy), SNPS_PHY_MPLLB_FORCE_EN, 0); /* * 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 70624b4b2d38..f45328712bff 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -5,6 +5,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_de.h" #include "intel_display.h" #include "intel_display_power_map.h" #include "intel_display_types.h" @@ -120,11 +121,9 @@ assert_tc_cold_blocked(struct intel_digital_port *dig_port) u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 lane_mask; - lane_mask = intel_uncore_read(uncore, - PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); assert_tc_cold_blocked(dig_port); @@ -136,11 +135,9 @@ u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 pin_mask; - pin_mask = intel_uncore_read(uncore, - PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); + pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); assert_tc_cold_blocked(dig_port); @@ -186,7 +183,6 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; - struct intel_uncore *uncore = &i915->uncore; u32 val; drm_WARN_ON(&i915->drm, @@ -194,8 +190,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, assert_tc_cold_blocked(dig_port); - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx); switch (required_lanes) { @@ -216,8 +211,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, MISSING_CASE(required_lanes); } - intel_uncore_write(uncore, - PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); + intel_de_write(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); } static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, @@ -246,13 +240,11 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; u32 mask = 0; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, @@ -266,7 +258,7 @@ static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx)) mask |= BIT(TC_PORT_DP_ALT); - if (intel_uncore_read(uncore, SDEISR) & isr_bit) + if (intel_de_read(i915, SDEISR) & isr_bit) mask |= BIT(TC_PORT_LEGACY); /* The sink can be connected only in a single mode. */ @@ -281,7 +273,6 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; - struct intel_uncore *uncore = &i915->uncore; u32 val, mask = 0; /* @@ -289,13 +280,13 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) * registers in IOM. Note that this doesn't apply to PHY and FIA * registers. */ - val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); + val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port)); if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT) mask |= BIT(TC_PORT_DP_ALT); if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT) mask |= BIT(TC_PORT_TBT_ALT); - if (intel_uncore_read(uncore, SDEISR) & isr_bit) + if (intel_de_read(i915, SDEISR) & isr_bit) mask |= BIT(TC_PORT_LEGACY); /* The sink can be connected only in a single mode. */ @@ -326,11 +317,9 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port) static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assuming not complete\n", @@ -352,10 +341,9 @@ static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); + val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assuming not complete\n", @@ -380,11 +368,9 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, can't %s ownership\n", @@ -397,8 +383,7 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, if (take) val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); - intel_uncore_write(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); + intel_de_write(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); return true; } @@ -407,11 +392,10 @@ static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum port port = dig_port->base.port; - intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, - take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); + intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, + take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); return true; } @@ -429,11 +413,9 @@ static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assume safe mode\n", @@ -447,11 +429,10 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port) static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum port port = dig_port->base.port; u32 val; - val = intel_uncore_read(uncore, DDI_BUF_CTL(port)); + val = intel_de_read(i915, DDI_BUF_CTL(port)); return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP; } @@ -907,7 +888,7 @@ tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig mutex_lock(&dig_port->tc_lock); wakeref = tc_cold_block(dig_port, &domain); - val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1)); + val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1)); tc_cold_unblock(dig_port, domain, wakeref); mutex_unlock(&dig_port->tc_lock); diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 9d3b77b41b5c..207b2a648d32 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -345,16 +345,13 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - if (!RUNTIME_INFO(i915)->has_dsc) + if (!HAS_DSC(i915)) return false; - if (DISPLAY_VER(i915) >= 12) - return true; - - if (DISPLAY_VER(i915) >= 11 && cpu_transcoder != TRANSCODER_A) - return true; + if (DISPLAY_VER(i915) == 11 && cpu_transcoder == TRANSCODER_A) + return false; - return false; + return true; } static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 7b1357e82b69..5ff6aed9575e 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -78,10 +78,10 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - /* The hw imposes the extra scanline before frame start */ if (DISPLAY_VER(i915) >= 13) - return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1; + return crtc_state->vrr.guardband; else + /* The hw imposes the extra scanline before frame start */ return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; } @@ -151,50 +151,46 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, * number of scan lines. Assuming 0 for no DSB. */ crtc_state->vrr.guardband = - crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay; + crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vdisplay; } else { - /* - * FIXME: s/4/framestart_delay/ to get consistent - * earliest/latest points for register latching regardless - * of the framestart_delay used? - * - * FIXME: this really needs the extra scanline to provide consistent - * behaviour for all framestart_delay values. Otherwise with - * framestart_delay==4 we will end up extending the min vblank by - * one extra line. - */ crtc_state->vrr.pipeline_full = - min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); + min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - + crtc_state->framestart_delay - 1); } crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } +static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (DISPLAY_VER(i915) >= 13) + return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | + XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband); + else + return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | + VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) | + VRR_CTL_PIPELINE_FULL_OVERRIDE; +} + void intel_vrr_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 trans_vrr_ctl; if (!crtc_state->vrr.enable) return; - if (DISPLAY_VER(dev_priv) >= 13) - trans_vrr_ctl = VRR_CTL_VRR_ENABLE | - VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | - XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband); - else - trans_vrr_ctl = VRR_CTL_VRR_ENABLE | - VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | - VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) | - VRR_CTL_PIPELINE_FULL_OVERRIDE; - intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1); intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1); - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state)); intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1); intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN); + + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), + VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); } void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) @@ -231,8 +227,13 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->vrr.enable) return; - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), + trans_vrr_ctl(old_crtc_state)); + intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder), + VRR_STATUS_VRR_EN_LIVE, 1000); + intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); } void intel_vrr_get_config(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index d7390067b7d4..01e881293612 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 +#define MTL_MAX_SRC_W 4096 +#define MTL_MAX_SRC_H 8192 +#define MTL_MAX_DST_W 8192 +#define MTL_MAX_DST_H 8192 #define SKL_MIN_YUV_420_SRC_W 16 #define SKL_MIN_YUV_420_SRC_H 16 @@ -103,6 +107,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int min_src_w, min_src_h, min_dst_w, min_dst_h; + int max_src_w, max_src_h, max_dst_w, max_dst_h; /* * Src coordinates are already rotated by 270 degrees for @@ -157,15 +163,33 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, return -EINVAL; } + min_src_w = SKL_MIN_SRC_W; + min_src_h = SKL_MIN_SRC_H; + min_dst_w = SKL_MIN_DST_W; + min_dst_h = SKL_MIN_DST_H; + + if (DISPLAY_VER(dev_priv) < 11) { + max_src_w = SKL_MAX_SRC_W; + max_src_h = SKL_MAX_SRC_H; + max_dst_w = SKL_MAX_DST_W; + max_dst_h = SKL_MAX_DST_H; + } else if (DISPLAY_VER(dev_priv) < 14) { + max_src_w = ICL_MAX_SRC_W; + max_src_h = ICL_MAX_SRC_H; + max_dst_w = ICL_MAX_DST_W; + max_dst_h = ICL_MAX_DST_H; + } else { + max_src_w = MTL_MAX_SRC_W; + max_src_h = MTL_MAX_SRC_H; + max_dst_w = MTL_MAX_DST_W; + max_dst_h = MTL_MAX_DST_H; + } + /* range checks */ - if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H || - dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || - (DISPLAY_VER(dev_priv) >= 11 && - (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H || - dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) || - (DISPLAY_VER(dev_priv) < 11 && - (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || - dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) { + if (src_w < min_src_w || src_h < min_src_h || + dst_w < min_dst_w || dst_h < min_dst_h || + src_w > max_src_w || src_h > max_src_h || + dst_w > max_dst_w || dst_h > max_dst_h) { drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: src %ux%u dst %ux%u " "size is out of scaler range\n", diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index e0766d1be966..ae4e9e680c2e 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -45,8 +45,7 @@ u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *i915) enum dbuf_slice slice; for_each_dbuf_slice(i915, slice) { - if (intel_uncore_read(&i915->uncore, - DBUF_CTL_S(slice)) & DBUF_POWER_STATE) + if (intel_de_read(i915, DBUF_CTL_S(slice)) & DBUF_POWER_STATE) enabled_slices |= BIT(slice); } @@ -75,7 +74,7 @@ intel_sagv_block_time(struct drm_i915_private *i915) if (DISPLAY_VER(i915) >= 14) { u32 val; - val = intel_uncore_read(&i915->uncore, MTL_LATENCY_SAGV); + val = intel_de_read(i915, MTL_LATENCY_SAGV); return REG_FIELD_GET(MTL_LATENCY_QCLK_SAGV, val); } else if (DISPLAY_VER(i915) >= 12) { @@ -756,18 +755,18 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *i915, /* Cursor doesn't support NV12/planar, so no extra calculation needed */ if (plane_id == PLANE_CURSOR) { - val = intel_uncore_read(&i915->uncore, CUR_BUF_CFG(pipe)); + val = intel_de_read(i915, CUR_BUF_CFG(pipe)); skl_ddb_entry_init_from_hw(ddb, val); return; } - val = intel_uncore_read(&i915->uncore, PLANE_BUF_CFG(pipe, plane_id)); + val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id)); skl_ddb_entry_init_from_hw(ddb, val); if (DISPLAY_VER(i915) >= 11) return; - val = intel_uncore_read(&i915->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id)); + val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id)); skl_ddb_entry_init_from_hw(ddb_y, val); } @@ -2821,36 +2820,32 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, for (level = 0; level <= max_level; level++) { if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, PLANE_WM(pipe, plane_id, level)); + val = intel_de_read(i915, PLANE_WM(pipe, plane_id, level)); else - val = intel_uncore_read(&i915->uncore, CUR_WM(pipe, level)); + val = intel_de_read(i915, CUR_WM(pipe, level)); skl_wm_level_from_reg_val(val, &wm->wm[level]); } if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, PLANE_WM_TRANS(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_TRANS(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, CUR_WM_TRANS(pipe)); + val = intel_de_read(i915, CUR_WM_TRANS(pipe)); skl_wm_level_from_reg_val(val, &wm->trans_wm); if (HAS_HW_SAGV_WM(i915)) { if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, - PLANE_WM_SAGV(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, - CUR_WM_SAGV(pipe)); + val = intel_de_read(i915, CUR_WM_SAGV(pipe)); skl_wm_level_from_reg_val(val, &wm->sagv.wm0); if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, - PLANE_WM_SAGV_TRANS(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, - CUR_WM_SAGV_TRANS(pipe)); + val = intel_de_read(i915, CUR_WM_SAGV_TRANS(pipe)); skl_wm_level_from_reg_val(val, &wm->sagv.trans_wm); } else if (DISPLAY_VER(i915) >= 12) { @@ -3126,8 +3121,8 @@ void skl_watermark_ipc_update(struct drm_i915_private *i915) if (!HAS_IPC(i915)) return; - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL2, DISP_IPC_ENABLE, - skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); + intel_de_rmw(i915, DISP_ARB_CTL2, DISP_IPC_ENABLE, + skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); } static bool skl_watermark_ipc_can_enable(struct drm_i915_private *i915) @@ -3201,19 +3196,18 @@ adjust_wm_latency(struct drm_i915_private *i915, static void mtl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) { - struct intel_uncore *uncore = &i915->uncore; int max_level = ilk_wm_max_level(i915); u32 val; - val = intel_uncore_read(uncore, MTL_LATENCY_LP0_LP1); + val = intel_de_read(i915, MTL_LATENCY_LP0_LP1); wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); - val = intel_uncore_read(uncore, MTL_LATENCY_LP2_LP3); + val = intel_de_read(i915, MTL_LATENCY_LP2_LP3); wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); - val = intel_uncore_read(uncore, MTL_LATENCY_LP4_LP5); + val = intel_de_read(i915, MTL_LATENCY_LP4_LP5); wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 84481030883a..662bdb656aa3 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1916,7 +1916,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_dsi->panel_power_off_time = ktime_get_boottime(); - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL); if (intel_connector->panel.vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 69103ae37779..ef94baebb337 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -75,6 +75,8 @@ #include "pxp/intel_pxp_pm.h" +#include "soc/intel_dram.h" + #include "i915_file_private.h" #include "i915_debugfs.h" #include "i915_driver.h" @@ -93,7 +95,6 @@ #include "i915_sysfs.h" #include "i915_utils.h" #include "i915_vgpu.h" -#include "intel_dram.h" #include "intel_gvt.h" #include "intel_memory_region.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a380db36d52c..360743a8a163 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -49,6 +49,8 @@ #include "gt/intel_workarounds.h" #include "gt/uc/intel_uc.h" +#include "soc/intel_pch.h" + #include "i915_drm_client.h" #include "i915_gem.h" #include "i915_gpu_error.h" @@ -58,7 +60,6 @@ #include "i915_utils.h" #include "intel_device_info.h" #include "intel_memory_region.h" -#include "intel_pch.h" #include "intel_runtime_pm.h" #include "intel_step.h" #include "intel_uncore.h" @@ -466,6 +467,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision) #define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) +#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step) #define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step) @@ -726,6 +728,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, (IS_SUBPLATFORM(__i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_##variant) && \ IS_GRAPHICS_STEP(__i915, since, until)) +#define IS_MTL_DISPLAY_STEP(__i915, since, until) \ + (IS_METEORLAKE(__i915) && \ + IS_DISPLAY_STEP(__i915, since, until)) + /* * DG2 hardware steppings are a bit unusual. The hardware design was forked to * create three variants (G10, G11, and G12) which each have distinct diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 91c533986041..54ea28cf8a1a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2451,8 +2451,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) ret = IRQ_HANDLED; gen8_de_misc_irq_handler(dev_priv, iir); } else { - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE MISC)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE MISC)!\n"); } } @@ -2463,8 +2463,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) ret = IRQ_HANDLED; gen11_hpd_irq_handler(dev_priv, iir); } else { - drm_err(&dev_priv->drm, - "The master control interrupt lied, (DE HPD)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied, (DE HPD)!\n"); } } @@ -2513,12 +2513,12 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (!found) - drm_err(&dev_priv->drm, - "Unexpected DE Port interrupt\n"); + drm_err_ratelimited(&dev_priv->drm, + "Unexpected DE Port interrupt\n"); } else - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE PORT)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE PORT)!\n"); } for_each_pipe(dev_priv, pipe) { @@ -2529,8 +2529,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); if (!iir) { - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE PIPE)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE PIPE)!\n"); continue; } @@ -2551,10 +2551,10 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); if (fault_errors) - drm_err(&dev_priv->drm, - "Fault errors on pipe %c: 0x%08x\n", - pipe_name(pipe), - fault_errors); + drm_err_ratelimited(&dev_priv->drm, + "Fault errors on pipe %c: 0x%08x\n", + pipe_name(pipe), + fault_errors); } if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index d1e4d528cb17..5b24dd50fb6a 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -122,7 +122,7 @@ i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, "Default: 0"); i915_param_named_unsafe(force_probe, charp, 0400, - "Force probe the driver for specified devices. " + "Force probe options for specified supported devices. " "See CONFIG_DRM_I915_FORCE_PROBE for details."); i915_param_named_unsafe(disable_power_well, int, 0400, diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index ccd1f864aa19..0f3e0ce416f8 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -132,9 +132,9 @@ [PIPE_D] = TGL_CURSOR_D_OFFSET, \ } -#define I9XX_COLORS \ +#define I845_COLORS \ .display.color = { .gamma_lut_size = 256 } -#define I965_COLORS \ +#define I9XX_COLORS \ .display.color = { .gamma_lut_size = 129, \ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ } @@ -210,7 +210,7 @@ .dma_mask_size = 32, \ I845_PIPE_OFFSETS, \ I845_CURSOR_OFFSETS, \ - I9XX_COLORS, \ + I845_COLORS, \ GEN_DEFAULT_PAGE_SIZES, \ GEN_DEFAULT_REGIONS @@ -341,7 +341,7 @@ static const struct intel_device_info pnv_m_info = { .dma_mask_size = 36, \ I9XX_PIPE_OFFSETS, \ I9XX_CURSOR_OFFSETS, \ - I965_COLORS, \ + I9XX_COLORS, \ GEN_DEFAULT_PAGE_SIZES, \ GEN_DEFAULT_REGIONS @@ -547,7 +547,7 @@ static const struct intel_device_info vlv_info = { .display.mmio_offset = VLV_DISPLAY_BASE, I9XX_PIPE_OFFSETS, I9XX_CURSOR_OFFSETS, - I965_COLORS, + I9XX_COLORS, GEN_DEFAULT_PAGE_SIZES, GEN_DEFAULT_REGIONS, }; @@ -889,7 +889,7 @@ static const struct intel_device_info jsl_info = { TGL_CURSOR_OFFSETS, \ .has_global_mocs = 1, \ .has_pxp = 1, \ - .display.has_dsb = 0 /* FIXME: LUT load is broken with DSB */ + .display.has_dsb = 1 static const struct intel_device_info tgl_info = { GEN12_FEATURES, @@ -948,7 +948,7 @@ static const struct intel_device_info adl_s_info = { #define XE_LPD_FEATURES \ .display.abox_mask = GENMASK(1, 0), \ .display.color = { \ - .degamma_lut_size = 128, .gamma_lut_size = 1024, \ + .degamma_lut_size = 129, .gamma_lut_size = 1024, \ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ DRM_COLOR_LUT_EQUAL_CHANNELS, \ }, \ @@ -1017,6 +1017,7 @@ static const struct intel_device_info adl_p_info = { .has_3d_pipeline = 1, \ .has_64bit_reloc = 1, \ .has_flat_ccs = 1, \ + .has_4tile = 1, \ .has_global_mocs = 1, \ .has_gt_uc = 1, \ .has_llc = 1, \ @@ -1061,7 +1062,6 @@ static const struct intel_device_info xehpsdv_info = { .__runtime.graphics.ip.rel = 55, \ .__runtime.media.ip.rel = 55, \ PLATFORM(INTEL_DG2), \ - .has_4tile = 1, \ .has_64k_pages = 1, \ .has_guc_deprivilege = 1, \ .has_heci_pxp = 1, \ @@ -1117,6 +1117,7 @@ static const struct intel_device_info pvc_info = { XE_LPD_FEATURES, \ .__runtime.display.ip.ver = 14, \ .display.has_cdclk_crawl = 1, \ + .display.has_cdclk_squash = 1, \ .__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) static const struct intel_gt_definition xelpmp_extra_gt[] = { @@ -1252,7 +1253,7 @@ static void i915_pci_remove(struct pci_dev *pdev) } /* is device_id present in comma separated list of ids */ -static bool force_probe(u16 device_id, const char *devices) +static bool device_id_in_list(u16 device_id, const char *devices, bool negative) { char *s, *p, *tok; bool ret; @@ -1261,7 +1262,9 @@ static bool force_probe(u16 device_id, const char *devices) return false; /* match everything */ - if (strcmp(devices, "*") == 0) + if (negative && strcmp(devices, "!*") == 0) + return true; + if (!negative && strcmp(devices, "*") == 0) return true; s = kstrdup(devices, GFP_KERNEL); @@ -1271,6 +1274,12 @@ static bool force_probe(u16 device_id, const char *devices) for (p = s, ret = false; (tok = strsep(&p, ",")) != NULL; ) { u16 val; + if (negative && tok[0] == '!') + tok++; + else if ((negative && tok[0] != '!') || + (!negative && tok[0] == '!')) + continue; + if (kstrtou16(tok, 16, &val) == 0 && val == device_id) { ret = true; break; @@ -1282,6 +1291,16 @@ static bool force_probe(u16 device_id, const char *devices) return ret; } +static bool id_forced(u16 device_id) +{ + return device_id_in_list(device_id, i915_modparams.force_probe, false); +} + +static bool id_blocked(u16 device_id) +{ + return device_id_in_list(device_id, i915_modparams.force_probe, true); +} + bool i915_pci_resource_valid(struct pci_dev *pdev, int bar) { if (!pci_resource_flags(pdev, bar)) @@ -1307,10 +1326,9 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (struct intel_device_info *) ent->driver_data; int err; - if (intel_info->require_force_probe && - !force_probe(pdev->device, i915_modparams.force_probe)) { + if (intel_info->require_force_probe && !id_forced(pdev->device)) { dev_info(&pdev->dev, - "Your graphics device %04x is not properly supported by the driver in this\n" + "Your graphics device %04x is not properly supported by i915 in this\n" "kernel version. To force driver probe anyway, use i915.force_probe=%04x\n" "module parameter or CONFIG_DRM_I915_FORCE_PROBE=%04x configuration option,\n" "or (recommended) check for kernel updates.\n", @@ -1318,6 +1336,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (id_blocked(pdev->device)) { + dev_info(&pdev->dev, "I915 probe blocked for Device ID %04x.\n", + pdev->device); + return -ENODEV; + } + /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 916176872544..c76a02c6d22c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1713,6 +1713,20 @@ #define PALETTE_RED_MASK REG_GENMASK(23, 16) #define PALETTE_GREEN_MASK REG_GENMASK(15, 8) #define PALETTE_BLUE_MASK REG_GENMASK(7, 0) +/* pre-i965 10bit interpolated mode ldw */ +#define PALETTE_10BIT_RED_LDW_MASK REG_GENMASK(23, 16) +#define PALETTE_10BIT_GREEN_LDW_MASK REG_GENMASK(15, 8) +#define PALETTE_10BIT_BLUE_LDW_MASK REG_GENMASK(7, 0) +/* pre-i965 10bit interpolated mode udw */ +#define PALETTE_10BIT_RED_EXP_MASK REG_GENMASK(23, 22) +#define PALETTE_10BIT_RED_MANT_MASK REG_GENMASK(21, 18) +#define PALETTE_10BIT_RED_UDW_MASK REG_GENMASK(17, 16) +#define PALETTE_10BIT_GREEN_EXP_MASK REG_GENMASK(15, 14) +#define PALETTE_10BIT_GREEN_MANT_MASK REG_GENMASK(13, 10) +#define PALETTE_10BIT_GREEN_UDW_MASK REG_GENMASK(9, 8) +#define PALETTE_10BIT_BLUE_EXP_MASK REG_GENMASK(7, 6) +#define PALETTE_10BIT_BLUE_MANT_MASK REG_GENMASK(5, 2) +#define PALETTE_10BIT_BLUE_UDW_MASK REG_GENMASK(1, 0) #define PALETTE(pipe, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + \ _PICK((pipe), _PALETTE_A, \ _PALETTE_B, _CHV_PALETTE_C) + \ @@ -2575,46 +2589,6 @@ #define SDVO_PIPE_SEL_MASK_CHV (3 << 24) #define SDVO_PIPE_SEL_CHV(pipe) ((pipe) << 24) - -/* DVO port control */ -#define _DVOA 0x61120 -#define DVOA _MMIO(_DVOA) -#define _DVOB 0x61140 -#define DVOB _MMIO(_DVOB) -#define _DVOC 0x61160 -#define DVOC _MMIO(_DVOC) -#define DVO_ENABLE (1 << 31) -#define DVO_PIPE_SEL_SHIFT 30 -#define DVO_PIPE_SEL_MASK (1 << 30) -#define DVO_PIPE_SEL(pipe) ((pipe) << 30) -#define DVO_PIPE_STALL_UNUSED (0 << 28) -#define DVO_PIPE_STALL (1 << 28) -#define DVO_PIPE_STALL_TV (2 << 28) -#define DVO_PIPE_STALL_MASK (3 << 28) -#define DVO_USE_VGA_SYNC (1 << 15) -#define DVO_DATA_ORDER_I740 (0 << 14) -#define DVO_DATA_ORDER_FP (1 << 14) -#define DVO_VSYNC_DISABLE (1 << 11) -#define DVO_HSYNC_DISABLE (1 << 10) -#define DVO_VSYNC_TRISTATE (1 << 9) -#define DVO_HSYNC_TRISTATE (1 << 8) -#define DVO_BORDER_ENABLE (1 << 7) -#define DVO_DATA_ORDER_GBRG (1 << 6) -#define DVO_DATA_ORDER_RGGB (0 << 6) -#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) -#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) -#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) -#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) -#define DVO_BLANK_ACTIVE_HIGH (1 << 2) -#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ -#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ -#define DVO_PRESERVE_MASK (0x7 << 24) -#define DVOA_SRCDIM _MMIO(0x61124) -#define DVOB_SRCDIM _MMIO(0x61144) -#define DVOC_SRCDIM _MMIO(0x61164) -#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 -#define DVO_SRCDIM_VERTICAL_SHIFT 0 - /* LVDS port control */ #define LVDS _MMIO(0x61180) /* @@ -3646,7 +3620,7 @@ #define _PIPEAGCMAX 0x70010 #define _PIPEBGCMAX 0x71010 -#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4) +#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4) /* u1.16 */ #define _PIPE_ARB_CTL_A 0x70028 /* icl+ */ #define PIPE_ARB_CTL(pipe) _MMIO_PIPE2(pipe, _PIPE_ARB_CTL_A) @@ -5330,19 +5304,20 @@ #define _PREC_PIPEAGCMAX 0x4d000 #define _PREC_PIPEBGCMAX 0x4d010 -#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) +#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) /* u1.16 */ #define _GAMMA_MODE_A 0x4a480 #define _GAMMA_MODE_B 0x4ac80 #define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) -#define PRE_CSC_GAMMA_ENABLE (1 << 31) -#define POST_CSC_GAMMA_ENABLE (1 << 30) -#define GAMMA_MODE_MODE_MASK (3 << 0) -#define GAMMA_MODE_MODE_8BIT (0 << 0) -#define GAMMA_MODE_MODE_10BIT (1 << 0) -#define GAMMA_MODE_MODE_12BIT (2 << 0) -#define GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */ -#define GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */ +#define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */ +#define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */ +#define PALETTE_ANTICOL_DISABLE REG_BIT(15) /* skl+ */ +#define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0) +#define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0) +#define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1) +#define GAMMA_MODE_MODE_12BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 2) +#define GAMMA_MODE_MODE_SPLIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* ivb-bdw */ +#define GAMMA_MODE_MODE_12BIT_MULTI_SEG REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* icl-tgl */ /* Display Internal Timeout Register */ #define RM_TIMEOUT _MMIO(0x42060) @@ -6269,6 +6244,7 @@ #define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8) #define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8) #define SBCLK_RUN_REFCLK_DIS (1 << 7) +#define ICP_SECOND_PPS_IO_SELECT REG_BIT(2) #define SPT_PWM_GRANULARITY (1 << 0) #define SOUTH_CHICKEN2 _MMIO(0xc2004) #define FDI_MPHY_IOSFSB_RESET_STATUS (1 << 13) @@ -7557,11 +7533,10 @@ enum skl_power_gate { #define _PAL_PREC_INDEX_A 0x4A400 #define _PAL_PREC_INDEX_B 0x4AC00 #define _PAL_PREC_INDEX_C 0x4B400 -#define PAL_PREC_10_12_BIT (0 << 31) -#define PAL_PREC_SPLIT_MODE (1 << 31) -#define PAL_PREC_AUTO_INCREMENT (1 << 15) -#define PAL_PREC_INDEX_VALUE_MASK (0x3ff << 0) -#define PAL_PREC_INDEX_VALUE(x) ((x) << 0) +#define PAL_PREC_SPLIT_MODE REG_BIT(31) +#define PAL_PREC_AUTO_INCREMENT REG_BIT(15) +#define PAL_PREC_INDEX_VALUE_MASK REG_GENMASK(9, 0) +#define PAL_PREC_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_INDEX_VALUE_MASK, (x)) #define _PAL_PREC_DATA_A 0x4A404 #define _PAL_PREC_DATA_B 0x4AC04 #define _PAL_PREC_DATA_C 0x4B404 @@ -7578,14 +7553,16 @@ enum skl_power_gate { #define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B) #define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B) -#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) -#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) -#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) +#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) /* u1.16 */ +#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) /* u3.16 */ +#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) /* glk+, u3.16 */ #define _PRE_CSC_GAMC_INDEX_A 0x4A484 #define _PRE_CSC_GAMC_INDEX_B 0x4AC84 #define _PRE_CSC_GAMC_INDEX_C 0x4B484 -#define PRE_CSC_GAMC_AUTO_INCREMENT (1 << 10) +#define PRE_CSC_GAMC_AUTO_INCREMENT REG_BIT(10) +#define PRE_CSC_GAMC_INDEX_VALUE_MASK REG_GENMASK(7, 0) +#define PRE_CSC_GAMC_INDEX_VALUE(x) REG_FIELD_PREP(PRE_CSC_GAMC_INDEX_VALUE_MASK, (x)) #define _PRE_CSC_GAMC_DATA_A 0x4A488 #define _PRE_CSC_GAMC_DATA_B 0x4AC88 #define _PRE_CSC_GAMC_DATA_C 0x4B488 @@ -7596,8 +7573,9 @@ enum skl_power_gate { /* ICL Multi segmented gamma */ #define _PAL_PREC_MULTI_SEG_INDEX_A 0x4A408 #define _PAL_PREC_MULTI_SEG_INDEX_B 0x4AC08 -#define PAL_PREC_MULTI_SEGMENT_AUTO_INCREMENT REG_BIT(15) -#define PAL_PREC_MULTI_SEGMENT_INDEX_VALUE_MASK REG_GENMASK(4, 0) +#define PAL_PREC_MULTI_SEG_AUTO_INCREMENT REG_BIT(15) +#define PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK REG_GENMASK(4, 0) +#define PAL_PREC_MULTI_SEG_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK, (x)) #define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C #define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 4f4c2e15e736..71b8a63f6f10 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -68,11 +68,12 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); * @wf: the wakeref * * Acquire a hold on the wakeref. The first user to do so, will acquire - * the runtime pm wakeref and then call the @fn underneath the wakeref - * mutex. + * the runtime pm wakeref and then call the intel_wakeref_ops->get() + * underneath the wakeref mutex. * - * Note that @fn is allowed to fail, in which case the runtime-pm wakeref - * will be released and the acquisition unwound, and an error reported. + * Note that intel_wakeref_ops->get() is allowed to fail, in which case + * the runtime-pm wakeref will be released and the acquisition unwound, + * and an error reported. * * Returns: 0 if the wakeref was acquired successfully, or a negative error * code otherwise. @@ -130,19 +131,17 @@ intel_wakeref_might_get(struct intel_wakeref *wf) } /** - * intel_wakeref_put_flags: Release the wakeref + * __intel_wakeref_put: Release the wakeref * @wf: the wakeref * @flags: control flags * * Release our hold on the wakeref. When there are no more users, - * the runtime pm wakeref will be released after the @fn callback is called - * underneath the wakeref mutex. + * the runtime pm wakeref will be released after the intel_wakeref_ops->put() + * callback is called underneath the wakeref mutex. * - * Note that @fn is allowed to fail, in which case the runtime-pm wakeref - * is retained and an error reported. + * Note that intel_wakeref_ops->put() is allowed to fail, in which case the + * runtime-pm wakeref is retained. * - * Returns: 0 if the wakeref was released successfully, or a negative error - * code otherwise. */ static inline void __intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) diff --git a/drivers/gpu/drm/i915/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index bba8cb6e8ae4..bba8cb6e8ae4 100644 --- a/drivers/gpu/drm/i915/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c diff --git a/drivers/gpu/drm/i915/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 4ba13c13162c..4ba13c13162c 100644 --- a/drivers/gpu/drm/i915/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c index ba9843cb1b13..ba9843cb1b13 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/soc/intel_pch.c diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/soc/intel_pch.h index 32aff5a70d04..32aff5a70d04 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/soc/intel_pch.h diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index ed10e6b6f99d..632376c291db 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -240,6 +240,8 @@ #define DP_DSC_SUPPORT 0x060 /* DP 1.4 */ # define DP_DSC_DECOMPRESSION_IS_SUPPORTED (1 << 0) # define DP_DSC_PASSTHROUGH_IS_SUPPORTED (1 << 1) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_COMP_TO_COMP (1 << 2) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_UNCOMP_TO_COMP (1 << 3) #define DP_DSC_REV 0x061 # define DP_DSC_MAJOR_MASK (0xf << 0) @@ -278,12 +280,15 @@ #define DP_DSC_BLK_PREDICTION_SUPPORT 0x066 # define DP_DSC_BLK_PREDICTION_IS_SUPPORTED (1 << 0) +# define DP_DSC_RGB_COLOR_CONV_BYPASS_SUPPORT (1 << 1) #define DP_DSC_MAX_BITS_PER_PIXEL_LOW 0x067 /* eDP 1.4 */ #define DP_DSC_MAX_BITS_PER_PIXEL_HI 0x068 /* eDP 1.4 */ # define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK (0x3 << 0) # define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8 +# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK 0x06 +# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY 0x08 #define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069 # define DP_DSC_RGB (1 << 0) @@ -345,11 +350,13 @@ # define DP_DSC_24_PER_DP_DSC_SINK (1 << 2) #define DP_DSC_BITS_PER_PIXEL_INC 0x06F +# define DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK 0x1f +# define DP_DSC_RGB_YCbCr420_MAX_BPP_DELTA_MASK 0xe0 # define DP_DSC_BITS_PER_PIXEL_1_16 0x0 # define DP_DSC_BITS_PER_PIXEL_1_8 0x1 # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 -# define DP_DSC_BITS_PER_PIXEL_1 0x4 +# define DP_DSC_BITS_PER_PIXEL_1_1 0x4 #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ # define DP_PSR_IS_SUPPORTED 1 |