diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-04-06 17:31:32 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-04-06 17:31:33 +0300 |
commit | 4d877b1a6e855d1c8685fa0e27ad7a521b31b6ca (patch) | |
tree | 24c7e6084e77ed638f8134d49564e7c5cca84431 /drivers/gpu | |
parent | 8904a1e20ba8ee82c1d24d6f8091ba464b878a54 (diff) | |
parent | b358793c3bf231c455c55e0173256a86483997a8 (diff) | |
download | linux-4d877b1a6e855d1c8685fa0e27ad7a521b31b6ca.tar.xz |
Merge tag 'drm-intel-next-2023-04-06' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
- Fix DPT+shmem combo and add i915.enable_dpt modparam (Ville)
- i915.enable_sagv module parameter (Ville)
- Correction to QGV related register addresses (Vinod)
- IPS debugfs per-crtc and new file for false_color (Ville)
- More clean-up and reorganization of Display code (Jani)
- DP DSC related fixes and improvements (Stanislav, Ankit, Suraj, Swati)
- Make utility pin asserts more accurate (Ville)
- Meteor Lake enabling (Daniele)
- High refresh rate PSR fixes (Jouni)
- Cursor and Plane chicken register fixes (Ville)
- Align the ADL-P TypeC sequences with hardware specification (Imre)
- Documentation build fixes and improvements to catch bugs earlier (Lee, Jani)
- PL1 power limit hwmon entry changed to use 0 as disabled state (Ashutosh)
- DP aux sync fix and improvements (Ville)
- DP MST fixes and w/a (Stanislav)
- Limit PXP drm-errors or warning on firmware API failures (Alan)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ZC7RR3Laet8ywHRo@intel.com
Diffstat (limited to 'drivers/gpu')
74 files changed, 3949 insertions, 2887 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 98f4e44976e0..06a0ca157e89 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -164,11 +164,5 @@ menu "drm/i915 Profile Guided Optimisation" source "drivers/gpu/drm/i915/Kconfig.profile" endmenu -menu "drm/i915 Unstable Evolution" - visible if EXPERT && STAGING && BROKEN - depends on DRM_I915 - source "drivers/gpu/drm/i915/Kconfig.unstable" -endmenu - config DRM_I915_GVT bool diff --git a/drivers/gpu/drm/i915/Kconfig.unstable b/drivers/gpu/drm/i915/Kconfig.unstable deleted file mode 100644 index cf151a297ed7..000000000000 --- a/drivers/gpu/drm/i915/Kconfig.unstable +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config DRM_I915_UNSTABLE - bool "Enable unstable API for early prototype development" - depends on EXPERT - depends on STAGING - depends on BROKEN # should never be enabled by distros! - # We use the dependency on !COMPILE_TEST to not be enabled in - # allmodconfig or allyesconfig configurations - depends on !COMPILE_TEST - default n - help - Enable prototype uAPI under general discussion before they are - finalized. Such prototypes may be withdrawn or substantially - changed before release. They are only enabled here so that a wide - number of interested parties (userspace driver developers) can - verify that the uAPI meet their expectations. These uAPI should - never be used in production. - - Recommended for driver developers _only_. - - If in the slightest bit of doubt, say "N". diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 057ef22fa9c6..97b0d4ae221a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -47,10 +47,10 @@ i915-y += i915_driver.o \ i915_switcheroo.o \ i915_sysfs.o \ i915_utils.o \ + intel_clock_gating.o \ intel_device_info.o \ intel_memory_region.o \ intel_pcode.o \ - intel_pm.o \ intel_region_ttm.o \ intel_runtime_pm.o \ intel_sbi.o \ @@ -369,6 +369,13 @@ include $(src)/gvt/Makefile obj-$(CONFIG_DRM_I915) += i915.o obj-$(CONFIG_DRM_I915_GVT_KVMGT) += kvmgt.o +# kernel-doc test +# +# Enable locally for CONFIG_DRM_I915_WERROR=y. See also scripts/Makefile.build +ifdef CONFIG_DRM_I915_WERROR + cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $< +endif + # header test # exclude some broken headers from the test coverage @@ -380,7 +387,8 @@ always-$(CONFIG_DRM_I915_WERROR) += \ $(shell cd $(srctree)/$(src) && find * -name '*.h'))) quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) - cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@ + cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; \ + $(srctree)/scripts/kernel-doc -none $<; touch $@ $(obj)/%.hdrtest: $(src)/%.h FORCE $(call if_changed_dep,hdrtest) diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c index 2910f5d0f3e2..8eca0de065b6 100644 --- a/drivers/gpu/drm/i915/display/hsw_ips.c +++ b/drivers/gpu/drm/i915/display/hsw_ips.c @@ -14,6 +14,7 @@ static void hsw_ips_enable(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); + u32 val; if (!crtc_state->ips_enabled) return; @@ -26,10 +27,15 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state) drm_WARN_ON(&i915->drm, !(crtc_state->active_planes & ~BIT(PLANE_CURSOR))); + val = IPS_ENABLE; + + if (i915->display.ips.false_color) + val |= IPS_FALSE_COLOR; + if (IS_BROADWELL(i915)) { drm_WARN_ON(&i915->drm, snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL, - IPS_ENABLE | IPS_PCODE_CONTROL)); + val | IPS_PCODE_CONTROL)); /* * Quoting Art Runyan: "its not safe to expect any particular * value in IPS_CTL bit 31 after enabling IPS through the @@ -37,7 +43,7 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state) * so we need to just enable it and continue on. */ } else { - intel_de_write(i915, IPS_CTL, IPS_ENABLE); + intel_de_write(i915, IPS_CTL, val); /* * The bit only becomes 1 in the next vblank, so this wait here * is essentially intel_wait_for_vblank. If we don't have this @@ -268,14 +274,57 @@ void hsw_ips_get_config(struct intel_crtc_state *crtc_state) } } +static int hsw_ips_debugfs_false_color_get(void *data, u64 *val) +{ + struct intel_crtc *crtc = data; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + *val = i915->display.ips.false_color; + + return 0; +} + +static int hsw_ips_debugfs_false_color_set(void *data, u64 val) +{ + struct intel_crtc *crtc = data; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state; + int ret; + + ret = drm_modeset_lock(&crtc->base.mutex, NULL); + if (ret) + return ret; + + i915->display.ips.false_color = val; + + crtc_state = to_intel_crtc_state(crtc->base.state); + + if (!crtc_state->hw.active) + goto unlock; + + if (crtc_state->uapi.commit && + !try_wait_for_completion(&crtc_state->uapi.commit->hw_done)) + goto unlock; + + hsw_ips_enable(crtc_state); + + unlock: + drm_modeset_unlock(&crtc->base.mutex); + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(hsw_ips_debugfs_false_color_fops, + hsw_ips_debugfs_false_color_get, + hsw_ips_debugfs_false_color_set, + "%llu\n"); + static int hsw_ips_debugfs_status_show(struct seq_file *m, void *unused) { - struct drm_i915_private *i915 = m->private; + struct intel_crtc *crtc = m->private; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); intel_wakeref_t wakeref; - if (!HAS_IPS(i915)) - return -ENODEV; - wakeref = intel_runtime_pm_get(&i915->runtime_pm); seq_printf(m, "Enabled by kernel parameter: %s\n", @@ -297,10 +346,14 @@ static int hsw_ips_debugfs_status_show(struct seq_file *m, void *unused) DEFINE_SHOW_ATTRIBUTE(hsw_ips_debugfs_status); -void hsw_ips_debugfs_register(struct drm_i915_private *i915) +void hsw_ips_crtc_debugfs_add(struct intel_crtc *crtc) { - struct drm_minor *minor = i915->drm.primary; + if (!hsw_crtc_supports_ips(crtc)) + return; + + debugfs_create_file("i915_ips_false_color", 0644, crtc->base.debugfs_entry, + crtc, &hsw_ips_debugfs_false_color_fops); - debugfs_create_file("i915_ips_status", 0444, minor->debugfs_root, - i915, &hsw_ips_debugfs_status_fops); + debugfs_create_file("i915_ips_status", 0444, crtc->base.debugfs_entry, + crtc, &hsw_ips_debugfs_status_fops); } diff --git a/drivers/gpu/drm/i915/display/hsw_ips.h b/drivers/gpu/drm/i915/display/hsw_ips.h index 7ed6061874f7..4eb83b350791 100644 --- a/drivers/gpu/drm/i915/display/hsw_ips.h +++ b/drivers/gpu/drm/i915/display/hsw_ips.h @@ -8,7 +8,6 @@ #include <linux/types.h> -struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -23,6 +22,6 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state); int hsw_ips_compute_config(struct intel_atomic_state *state, struct intel_crtc *crtc); void hsw_ips_get_config(struct intel_crtc_state *crtc_state); -void hsw_ips_debugfs_register(struct drm_i915_private *i915); +void hsw_ips_crtc_debugfs_add(struct intel_crtc *crtc); #endif /* __HSW_IPS_H__ */ diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 4ff10b00ffbd..ad78148e0788 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1552,8 +1552,6 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder, if (crtc_state->dsc.slice_count > 1) crtc_state->dsc.dsc_split = true; - vdsc_cfg->convert_rgb = true; - /* FIXME: initialize from VBT */ vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST; diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 8f2ebead0826..38e9c61c2344 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -44,6 +44,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_fdi.h" +#include "intel_fdi_regs.h" #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug.h" diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 766633566fd6..54c8adc0702e 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -123,7 +123,7 @@ static const char * const output_format_str[] = { [INTEL_OUTPUT_FORMAT_YCBCR444] = "YCBCR4:4:4", }; -static const char *output_formats(enum intel_output_format format) +const char *intel_output_format_name(enum intel_output_format format) { if (format >= ARRAY_SIZE(output_format_str)) return "invalid"; @@ -181,7 +181,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, "active: %s, output_types: %s (0x%x), output format: %s\n", str_yes_no(pipe_config->hw.active), buf, pipe_config->output_types, - output_formats(pipe_config->output_format)); + intel_output_format_name(pipe_config->output_format)); drm_dbg_kms(&i915->drm, "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h index 9399c35b7e5e..780f3f1190d7 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.h @@ -8,9 +8,11 @@ struct intel_crtc_state; struct intel_atomic_state; +enum intel_output_format; void intel_crtc_state_dump(const struct intel_crtc_state *crtc_state, struct intel_atomic_state *state, const char *context); +const char *intel_output_format_name(enum intel_output_format format); #endif /* __INTEL_CRTC_STATE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index d8a9790f9d36..d0bb3a52ae5c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2720,9 +2720,6 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - bool is_tc_port = intel_phy_is_tc(dev_priv, phy); struct intel_crtc *slave_crtc; if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) { @@ -2772,6 +2769,17 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, else intel_ddi_post_disable_dp(state, encoder, old_crtc_state, old_conn_state); +} + +static void intel_ddi_post_pll_disable(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + enum phy phy = intel_port_to_phy(i915, encoder->port); + bool is_tc_port = intel_phy_is_tc(i915, phy); main_link_aux_power_domain_put(dig_port, old_crtc_state); @@ -3053,39 +3061,6 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state, } static void -intel_ddi_update_prepare(struct intel_atomic_state *state, - struct intel_encoder *encoder, - struct intel_crtc *crtc) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - struct intel_crtc_state *crtc_state = - crtc ? intel_atomic_get_new_crtc_state(state, crtc) : NULL; - int required_lanes = crtc_state ? crtc_state->lane_count : 1; - - drm_WARN_ON(state->base.dev, crtc && crtc->active); - - intel_tc_port_get_link(enc_to_dig_port(encoder), - required_lanes); - if (crtc_state && crtc_state->hw.active) { - struct intel_crtc *slave_crtc; - - intel_update_active_dpll(state, crtc, encoder); - - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(crtc_state)) - intel_update_active_dpll(state, slave_crtc, encoder); - } -} - -static void -intel_ddi_update_complete(struct intel_atomic_state *state, - struct intel_encoder *encoder, - struct intel_crtc *crtc) -{ - intel_tc_port_put_link(enc_to_dig_port(encoder)); -} - -static void intel_ddi_pre_pll_enable(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, @@ -3096,9 +3071,20 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, enum phy phy = intel_port_to_phy(dev_priv, encoder->port); bool is_tc_port = intel_phy_is_tc(dev_priv, phy); - if (is_tc_port) + if (is_tc_port) { + struct intel_crtc *master_crtc = + to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *slave_crtc; + intel_tc_port_get_link(dig_port, crtc_state->lane_count); + intel_update_active_dpll(state, master_crtc, encoder); + + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(crtc_state)) + intel_update_active_dpll(state, slave_crtc, encoder); + } + main_link_aux_power_domain_get(dig_port, crtc_state); if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port)) @@ -3843,7 +3829,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) intel_dp_encoder_flush_work(encoder); if (intel_phy_is_tc(i915, phy)) - intel_tc_port_flush_work(dig_port); + intel_tc_port_cleanup(dig_port); intel_display_power_flush_work(i915); drm_encoder_cleanup(encoder); @@ -4284,7 +4270,7 @@ static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) if (!intel_phy_is_tc(i915, phy)) return; - intel_tc_port_flush_work(dig_port); + intel_tc_port_cleanup(dig_port); } #define port_tc_name(port) ((port) - PORT_TC1 + '1') @@ -4398,6 +4384,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->pre_pll_enable = intel_ddi_pre_pll_enable; encoder->pre_enable = intel_ddi_pre_enable; encoder->disable = intel_disable_ddi; + encoder->post_pll_disable = intel_ddi_post_pll_disable; encoder->post_disable = intel_ddi_post_disable; encoder->update_pipe = intel_ddi_update_pipe; encoder->get_hw_state = intel_ddi_get_hw_state; @@ -4541,10 +4528,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) is_legacy ? "legacy" : "non-legacy"); } - intel_tc_port_init(dig_port, is_legacy); - - encoder->update_prepare = intel_ddi_update_prepare; - encoder->update_complete = intel_ddi_update_complete; + if (intel_tc_port_init(dig_port, is_legacy) < 0) + goto err; } drm_WARN_ON(&dev_priv->drm, port > PORT_I); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5a386c7c0bc9..010ee793e1ff 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -63,6 +63,7 @@ #include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" +#include "intel_clock_gating.h" #include "intel_color.h" #include "intel_crt.h" #include "intel_crtc.h" @@ -105,7 +106,6 @@ #include "intel_pcode.h" #include "intel_pipe_crc.h" #include "intel_plane_initial.h" -#include "intel_pm.h" #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" @@ -850,7 +850,7 @@ void intel_display_finish_reset(struct drm_i915_private *i915) */ intel_pps_unlock_regs_wa(i915); intel_modeset_init_hw(i915); - intel_init_clock_gating(i915); + intel_clock_gating_init(i915); intel_hpd_init(i915); ret = __intel_display_resume(i915, state, ctx); @@ -1320,36 +1320,11 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state, intel_frontbuffer_flip(dev_priv, fb_bits); } -/* - * intel_connector_primary_encoder - get the primary encoder for a connector - * @connector: connector for which to return the encoder - * - * Returns the primary encoder for a connector. There is a 1:1 mapping from - * all connectors to their encoder, except for DP-MST connectors which have - * both a virtual and a primary encoder. These DP-MST primary encoders can be - * pointed to by as many DP-MST connectors as there are pipes. - */ -static struct intel_encoder * -intel_connector_primary_encoder(struct intel_connector *connector) -{ - struct intel_encoder *encoder; - - if (connector->mst_port) - return &dp_to_dig_port(connector->mst_port)->base; - - encoder = intel_attached_encoder(connector); - drm_WARN_ON(connector->base.dev, !encoder); - - return encoder; -} - static void intel_encoders_update_prepare(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - struct drm_connector_state *new_conn_state; - struct drm_connector *connector; int i; /* @@ -1365,57 +1340,6 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state) new_crtc_state->dpll_hw_state = old_crtc_state->dpll_hw_state; } } - - if (!state->modeset) - return; - - for_each_new_connector_in_state(&state->base, connector, new_conn_state, - i) { - struct intel_connector *intel_connector; - struct intel_encoder *encoder; - struct intel_crtc *crtc; - - if (!intel_connector_needs_modeset(state, connector)) - continue; - - intel_connector = to_intel_connector(connector); - encoder = intel_connector_primary_encoder(intel_connector); - if (!encoder->update_prepare) - continue; - - crtc = new_conn_state->crtc ? - to_intel_crtc(new_conn_state->crtc) : NULL; - encoder->update_prepare(state, encoder, crtc); - } -} - -static void intel_encoders_update_complete(struct intel_atomic_state *state) -{ - struct drm_connector_state *new_conn_state; - struct drm_connector *connector; - int i; - - if (!state->modeset) - return; - - for_each_new_connector_in_state(&state->base, connector, new_conn_state, - i) { - struct intel_connector *intel_connector; - struct intel_encoder *encoder; - struct intel_crtc *crtc; - - if (!intel_connector_needs_modeset(state, connector)) - continue; - - intel_connector = to_intel_connector(connector); - encoder = intel_connector_primary_encoder(intel_connector); - if (!encoder->update_complete) - continue; - - crtc = new_conn_state->crtc ? - to_intel_crtc(new_conn_state->crtc) : NULL; - encoder->update_complete(state, encoder, crtc); - } } static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state, @@ -1905,6 +1829,8 @@ static void ilk_crtc_disable(struct intel_atomic_state *state, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); + + intel_disable_shared_dpll(old_crtc_state); } static void hsw_crtc_disable(struct intel_atomic_state *state, @@ -1923,6 +1849,10 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_post_disable(state, crtc); } + intel_disable_shared_dpll(old_crtc_state); + + intel_encoders_post_pll_disable(state, crtc); + intel_dmc_disable_pipe(i915, crtc->pipe); } @@ -6972,6 +6902,12 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); bool modeset = intel_crtc_needs_modeset(new_crtc_state); + if (old_crtc_state->inherited || + intel_crtc_needs_modeset(new_crtc_state)) { + if (HAS_DPT(i915)) + intel_dpt_configure(crtc); + } + if (!modeset) { if (new_crtc_state->preload_luts && intel_crtc_needs_color_update(new_crtc_state)) @@ -7035,7 +6971,6 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, dev_priv->display.funcs.display->crtc_disable(state, crtc); crtc->active = false; intel_fbc_disable(crtc); - intel_disable_shared_dpll(old_crtc_state); if (!new_crtc_state->hw.active) intel_initial_watermarks(state, crtc); @@ -7434,8 +7369,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) /* Now enable the clocks, plane, pipe, and connectors that we set up. */ dev_priv->display.funcs.display->commit_modeset_enables(state); - intel_encoders_update_complete(state); - if (state->modeset) intel_set_cdclk_post_plane_update(state); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 596fd3ec1983..287159bdeb0d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -164,13 +164,6 @@ enum tc_port { I915_MAX_TC_PORTS }; -enum tc_port_mode { - TC_PORT_DISCONNECTED, - TC_PORT_TBT_ALT, - TC_PORT_DP_ALT, - TC_PORT_LEGACY, -}; - enum aux_ch { AUX_CH_NONE = -1, diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 0b5509f268a7..e36f88a39b86 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -419,6 +419,10 @@ struct intel_display { } hti; struct { + bool false_color; + } ips; + + struct { struct i915_power_domains domains; /* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */ diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index cc5026272558..45113ae107ba 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -13,6 +13,7 @@ #include "i915_irq.h" #include "i915_reg.h" #include "intel_de.h" +#include "intel_crtc_state_dump.h" #include "intel_display_debugfs.h" #include "intel_display_power.h" #include "intel_display_power_well.h" @@ -28,6 +29,7 @@ #include "intel_hotplug.h" #include "intel_panel.h" #include "intel_psr.h" +#include "intel_psr_regs.h" #include "intel_sprite.h" #include "intel_wm.h" @@ -1092,7 +1094,6 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) ARRAY_SIZE(intel_display_debugfs_list), minor->debugfs_root, minor); - hsw_ips_debugfs_register(i915); intel_dmc_debugfs_register(i915); intel_fbc_debugfs_register(i915); intel_hpd_debugfs_register(i915); @@ -1235,6 +1236,13 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data) str_yes_no(crtc_state->dsc.compression_enable)); seq_printf(m, "DSC_Sink_Support: %s\n", str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd))); + seq_printf(m, "DSC_Output_Format_Sink_Support: RGB: %s YCBCR420: %s YCBCR444: %s\n", + str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, + DP_DSC_RGB)), + str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, + DP_DSC_YCbCr420_Native)), + str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, + DP_DSC_YCbCr444))); seq_printf(m, "Force_DSC_Enable: %s\n", str_yes_no(intel_dp->force_dsc_en)); if (!intel_dp_is_edp(intel_dp)) @@ -1360,6 +1368,73 @@ static const struct file_operations i915_dsc_bpc_fops = { .write = i915_dsc_bpc_write }; +static int i915_dsc_output_format_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct drm_device *dev = connector->dev; + struct drm_crtc *crtc; + struct intel_crtc_state *crtc_state; + struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); + int ret; + + if (!encoder) + return -ENODEV; + + ret = drm_modeset_lock_single_interruptible(&dev->mode_config.connection_mutex); + if (ret) + return ret; + + crtc = connector->state->crtc; + if (connector->status != connector_status_connected || !crtc) { + ret = -ENODEV; + goto out; + } + + crtc_state = to_intel_crtc_state(crtc->state); + seq_printf(m, "DSC_Output_Format: %s\n", + intel_output_format_name(crtc_state->output_format)); + +out: drm_modeset_unlock(&dev->mode_config.connection_mutex); + + return ret; +} + +static ssize_t i915_dsc_output_format_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct drm_connector *connector = + ((struct seq_file *)file->private_data)->private; + struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + int dsc_output_format = 0; + int ret; + + ret = kstrtoint_from_user(ubuf, len, 0, &dsc_output_format); + if (ret < 0) + return ret; + + intel_dp->force_dsc_output_format = dsc_output_format; + *offp += len; + + return len; +} + +static int i915_dsc_output_format_open(struct inode *inode, + struct file *file) +{ + return single_open(file, i915_dsc_output_format_show, inode->i_private); +} + +static const struct file_operations i915_dsc_output_format_fops = { + .owner = THIS_MODULE, + .open = i915_dsc_output_format_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_dsc_output_format_write +}; + /* * Returns the Current CRTC's bpc. * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc @@ -1396,7 +1471,7 @@ DEFINE_SHOW_ATTRIBUTE(intel_crtc_pipe); /** * intel_connector_debugfs_add - add i915 specific connector debugfs files - * @connector: pointer to a registered drm_connector + * @intel_connector: pointer to a registered drm_connector * * Cleanup will be done by drm_connector_unregister() through a call to * drm_debugfs_connector_remove(). @@ -1434,6 +1509,9 @@ void intel_connector_debugfs_add(struct intel_connector *intel_connector) debugfs_create_file("i915_dsc_bpc", 0644, root, connector, &i915_dsc_bpc_fops); + + debugfs_create_file("i915_dsc_output_format", 0644, root, + connector, &i915_dsc_output_format_fops); } if (connector->connector_type == DRM_MODE_CONNECTOR_DSI || @@ -1461,6 +1539,7 @@ void intel_crtc_debugfs_add(struct intel_crtc *crtc) crtc_updates_add(crtc); intel_drrs_crtc_debugfs_add(crtc); intel_fbc_crtc_debugfs_add(crtc); + hsw_ips_crtc_debugfs_add(crtc); debugfs_create_file("i915_current_bpc", 0444, root, crtc, &i915_current_bpc_fops); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index f86060195987..7c9f4288329e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -19,8 +19,10 @@ #include "intel_mchbar_regs.h" #include "intel_pch_refclk.h" #include "intel_pcode.h" +#include "intel_pps_regs.h" #include "intel_snps_phy.h" #include "skl_watermark.h" +#include "skl_watermark_regs.h" #include "vlv_sideband.h" #define for_each_power_domain_well(__dev_priv, __power_well, __domain) \ @@ -697,7 +699,7 @@ out_verify: } /** - * intel_display_power_put_async - release a power domain reference asynchronously + * __intel_display_power_put_async - release a power domain reference asynchronously * @i915: i915 device instance * @domain: power domain to reference * @wakeref: wakeref acquired for the reference that is being released @@ -1182,8 +1184,10 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) "CPU PWM2 enabled\n"); I915_STATE_WARN(intel_de_read(dev_priv, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, "PCH PWM1 enabled\n"); - I915_STATE_WARN(intel_de_read(dev_priv, UTIL_PIN_CTL) & UTIL_PIN_ENABLE, - "Utility pin enabled\n"); + I915_STATE_WARN((intel_de_read(dev_priv, UTIL_PIN_CTL) & + (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == + (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM), + "Utility pin enabled in PWM mode\n"); I915_STATE_WARN(intel_de_read(dev_priv, PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n"); diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 1676df1dc066..62bafcbc7937 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -15,6 +15,7 @@ #include "intel_dkl_phy.h" #include "intel_dkl_phy_regs.h" #include "intel_dmc.h" +#include "intel_dp_aux_regs.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_hotplug.h" @@ -818,8 +819,10 @@ void gen9_enable_dc5(struct drm_i915_private *dev_priv) static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) { drm_WARN_ONCE(&dev_priv->drm, - intel_de_read(dev_priv, UTIL_PIN_CTL) & UTIL_PIN_ENABLE, - "Backlight is not disabled.\n"); + (intel_de_read(dev_priv, UTIL_PIN_CTL) & + (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == + (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM), + "Utility pin enabled in PWM mode\n"); drm_WARN_ONCE(&dev_priv->drm, (intel_de_read(dev_priv, DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ab146b5b68bd..47395b39c8f4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -60,6 +60,7 @@ struct __intel_global_objs_state; struct intel_ddi_buf_trans; struct intel_fbc; struct intel_connector; +struct intel_tc_port; /* * Display related stuff @@ -169,9 +170,6 @@ struct intel_encoder { int (*compute_config_late)(struct intel_encoder *, struct intel_crtc_state *, struct drm_connector_state *); - void (*update_prepare)(struct intel_atomic_state *, - struct intel_encoder *, - struct intel_crtc *); void (*pre_pll_enable)(struct intel_atomic_state *, struct intel_encoder *, const struct intel_crtc_state *, @@ -184,9 +182,6 @@ struct intel_encoder { struct intel_encoder *, const struct intel_crtc_state *, const struct drm_connector_state *); - void (*update_complete)(struct intel_atomic_state *, - struct intel_encoder *, - struct intel_crtc *); void (*disable)(struct intel_atomic_state *, struct intel_encoder *, const struct intel_crtc_state *, @@ -1157,6 +1152,7 @@ struct intel_crtc_state { bool has_psr2; bool enable_psr2_sel_fetch; bool req_psr2_sdp_prior_scanline; + bool wm_level_disabled; u32 dc3co_exitline; u16 su_y_granularity; struct drm_dp_vsc_sdp psr_vsc; @@ -1740,6 +1736,7 @@ struct intel_dp { /* Display stream compression testing */ bool force_dsc_en; + int force_dsc_output_format; int force_dsc_bpc; bool hobl_failed; @@ -1780,17 +1777,7 @@ struct intel_digital_port { intel_wakeref_t ddi_io_wakeref; intel_wakeref_t aux_wakeref; - struct mutex tc_lock; /* protects the TypeC port mode */ - intel_wakeref_t tc_lock_wakeref; - enum intel_display_power_domain tc_lock_power_domain; - struct delayed_work tc_disconnect_phy_work; - int tc_link_refcount; - bool tc_legacy_port:1; - char tc_port_name[8]; - enum tc_port_mode tc_mode; - enum tc_port_mode tc_init_mode; - enum phy_fia tc_phy_fia; - u8 tc_phy_fia_idx; + struct intel_tc_port *tc; /* protects num_hdcp_streams reference count, hdcp_port_data and hdcp_auth_status */ struct mutex hdcp_mutex; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index da1c00ee92fb..f0bace9d98a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -76,6 +76,7 @@ #include "intel_tc.h" #include "intel_vdsc.h" #include "intel_vrr.h" +#include "intel_crtc_state_dump.h" /* DP DSC throughput values used for slice count calculations KPixels/s */ #define DP_DSC_PEAK_PIXEL_RATE 2720000 @@ -833,6 +834,9 @@ intel_dp_output_format(struct intel_connector *connector, { struct intel_dp *intel_dp = intel_attached_dp(connector); + if (intel_dp->force_dsc_output_format) + return intel_dp->force_dsc_output_format; + if (!connector->base.ycbcr_420_allowed || !ycbcr_420_output) return INTEL_OUTPUT_FORMAT_RGB; @@ -1490,9 +1494,10 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, vdsc_cfg->dsc_version_minor = min(intel_dp_source_dsc_version_minor(intel_dp), intel_dp_sink_dsc_version_minor(intel_dp)); - - vdsc_cfg->convert_rgb = intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & - DP_DSC_RGB; + if (vdsc_cfg->convert_rgb) + vdsc_cfg->convert_rgb = + intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & + DP_DSC_RGB; line_buf_depth = drm_dp_dsc_sink_line_buf_depth(intel_dp->dsc_dpcd); if (!line_buf_depth) { @@ -1515,6 +1520,31 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, return drm_dsc_compute_rc_parameters(vdsc_cfg); } +static bool intel_dp_dsc_supports_format(struct intel_dp *intel_dp, + enum intel_output_format output_format) +{ + u8 sink_dsc_format; + + switch (output_format) { + case INTEL_OUTPUT_FORMAT_RGB: + sink_dsc_format = DP_DSC_RGB; + break; + case INTEL_OUTPUT_FORMAT_YCBCR444: + sink_dsc_format = DP_DSC_YCbCr444; + break; + case INTEL_OUTPUT_FORMAT_YCBCR420: + if (min(intel_dp_source_dsc_version_minor(intel_dp), + intel_dp_sink_dsc_version_minor(intel_dp)) < 2) + return false; + sink_dsc_format = DP_DSC_YCbCr420_Native; + break; + default: + return false; + } + + return drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, sink_dsc_format); +} + int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, @@ -1535,6 +1565,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, if (!intel_dp_supports_dsc(intel_dp, pipe_config)) return -EINVAL; + if (!intel_dp_dsc_supports_format(intel_dp, pipe_config->output_format)) + return -EINVAL; + if (compute_pipe_bpp) pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc); else @@ -1582,6 +1615,15 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, pipe_config->bigjoiner_pipes, pipe_bpp, timeslots); + /* + * According to DSC 1.2a Section 4.1.1 Table 4.1 the maximum + * supported PPS value can be 63.9375 and with the further + * mention that bpp should be programmed double the target bpp + * restricting our target bpp to be 31.9375 at max + */ + if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) + dsc_max_output_bpp = min_t(u16, dsc_max_output_bpp, 31 << 4); + if (!dsc_max_output_bpp) { drm_dbg_kms(&dev_priv->drm, "Compressed BPP not supported\n"); diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index eb07dc5d8709..705915d50565 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -10,6 +10,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dp_aux.h" +#include "intel_dp_aux_regs.h" #include "intel_pps.h" #include "intel_tc.h" @@ -118,6 +119,32 @@ static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) return index ? 0 : 1; } +static int intel_dp_aux_sync_len(void) +{ + int precharge = 16; /* 10-16 */ + int preamble = 16; + + return precharge + preamble; +} + +static int intel_dp_aux_fw_sync_len(void) +{ + int precharge = 16; /* 10-16 */ + int preamble = 8; + + return precharge + preamble; +} + +static int g4x_dp_aux_precharge_len(void) +{ + int precharge_min = 10; + int preamble = 16; + + /* HW wants the length of the extra precharge in 2us units */ + return (intel_dp_aux_sync_len() - + precharge_min - preamble) / 2; +} + static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp, int send_bytes, u32 aux_clock_divider) @@ -140,7 +167,7 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp, timeout | DP_AUX_CH_CTL_RECEIVE_ERROR | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - (3 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (g4x_dp_aux_precharge_len() << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT); } @@ -164,8 +191,8 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, DP_AUX_CH_CTL_TIME_OUT_MAX | DP_AUX_CH_CTL_RECEIVE_ERROR | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) | - DP_AUX_CH_CTL_SYNC_PULSE_SKL(32); + DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) | + DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len()); if (intel_tc_port_in_tbt_alt_mode(dig_port)) ret |= DP_AUX_CH_CTL_TBT_IO; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h new file mode 100644 index 000000000000..5702f318d537 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_DP_AUX_REGS_H__ +#define __INTEL_DP_AUX_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* + * The aux channel provides a way to talk to the signal sink for DDC etc. Max + * packet size supported is 20 bytes in each direction, hence the 5 fixed data + * registers + */ +#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010) +#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014) + +#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110) +#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114) + +#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL) +#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ + +#define _XELPDP_USBC1_AUX_CH_CTL 0x16F210 +#define _XELPDP_USBC2_AUX_CH_CTL 0x16F410 +#define _XELPDP_USBC3_AUX_CH_CTL 0x16F610 +#define _XELPDP_USBC4_AUX_CH_CTL 0x16F810 + +#define XELPDP_DP_AUX_CH_CTL(aux_ch) _MMIO(_PICK(aux_ch, \ + _DPA_AUX_CH_CTL, \ + _DPB_AUX_CH_CTL, \ + 0, /* port/aux_ch C is non-existent */ \ + _XELPDP_USBC1_AUX_CH_CTL, \ + _XELPDP_USBC2_AUX_CH_CTL, \ + _XELPDP_USBC3_AUX_CH_CTL, \ + _XELPDP_USBC4_AUX_CH_CTL)) + +#define _XELPDP_USBC1_AUX_CH_DATA1 0x16F214 +#define _XELPDP_USBC2_AUX_CH_DATA1 0x16F414 +#define _XELPDP_USBC3_AUX_CH_DATA1 0x16F614 +#define _XELPDP_USBC4_AUX_CH_DATA1 0x16F814 + +#define XELPDP_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PICK(aux_ch, \ + _DPA_AUX_CH_DATA1, \ + _DPB_AUX_CH_DATA1, \ + 0, /* port/aux_ch C is non-existent */ \ + _XELPDP_USBC1_AUX_CH_DATA1, \ + _XELPDP_USBC2_AUX_CH_DATA1, \ + _XELPDP_USBC3_AUX_CH_DATA1, \ + _XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4) + +#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) +#define DP_AUX_CH_CTL_DONE (1 << 30) +#define DP_AUX_CH_CTL_INTERRUPT (1 << 29) +#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28) +#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_MAX (3 << 26) /* Varies per platform */ +#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) +#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20 +#define XELPDP_DP_AUX_CH_CTL_POWER_REQUEST REG_BIT(19) +#define XELPDP_DP_AUX_CH_CTL_POWER_STATUS REG_BIT(18) +#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16) +#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16 +#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15) +#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14) +#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13) +#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12) +#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0 +#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL (1 << 14) +#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL (1 << 13) +#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL (1 << 12) +#define DP_AUX_CH_CTL_TBT_IO (1 << 11) +#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (0x1f << 5) +#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5) +#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) ((c) - 1) + +#endif /* __INTEL_DP_AUX_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index a860cbc5dbea..a88b852c437c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -45,6 +45,27 @@ #include "intel_hotplug.h" #include "skl_scaler.h" +static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int bpp, + const struct drm_display_mode *adjusted_mode, + struct intel_crtc_state *crtc_state, + bool dsc) +{ + if (intel_dp_is_uhbr(crtc_state) && DISPLAY_VER(i915) <= 13 && dsc) { + int output_bpp = bpp; + /* DisplayPort 2 128b/132b, bits per lane is always 32 */ + int symbol_clock = crtc_state->port_clock / 32; + + if (output_bpp * adjusted_mode->crtc_clock >= + symbol_clock * 72) { + drm_dbg_kms(&i915->drm, "UHBR check failed(required bw %d available %d)\n", + output_bpp * adjusted_mode->crtc_clock, symbol_clock * 72); + return -EINVAL; + } + } + + return 0; +} + static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, int max_bpp, @@ -81,12 +102,16 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, } for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { + drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); + + ret = intel_dp_mst_check_constraints(i915, bpp, adjusted_mode, crtc_state, dsc); + if (ret) + continue; + crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, 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); @@ -104,8 +129,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, } } - /* Despite slots are non-zero, we still failed the atomic check */ - if (ret && slots >= 0) + /* We failed to find a proper bpp/timeslots, return error */ + if (ret) slots = ret; if (slots < 0) { @@ -232,7 +257,7 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, return slots; } - intel_link_compute_m_n(crtc_state->pipe_bpp, + intel_link_compute_m_n(crtc_state->dsc.compressed_bpp, crtc_state->lane_count, adjusted_mode->crtc_clock, crtc_state->port_clock, @@ -623,6 +648,20 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_dp->active_mst_links); } +static void intel_mst_post_pll_disable_dp(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); + struct intel_digital_port *dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &dig_port->dp; + + if (intel_dp->active_mst_links == 0 && + dig_port->base.post_pll_disable) + dig_port->base.post_pll_disable(state, encoder, old_crtc_state, old_conn_state); +} + static void intel_mst_pre_pll_enable_dp(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, @@ -1146,6 +1185,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe intel_encoder->compute_config_late = intel_dp_mst_compute_config_late; intel_encoder->disable = intel_mst_disable_dp; intel_encoder->post_disable = intel_mst_post_disable_dp; + intel_encoder->post_pll_disable = intel_mst_post_pll_disable_dp; intel_encoder->update_pipe = intel_ddi_update_pipe; intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; intel_encoder->pre_enable = intel_mst_pre_enable_dp; diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index ad1a37b515fb..b8027392144d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -9,6 +9,8 @@ #include "gt/gen8_ppgtt.h" #include "i915_drv.h" +#include "i915_reg.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" @@ -301,6 +303,7 @@ intel_dpt_create(struct intel_framebuffer *fb) vm->pte_encode = gen8_ggtt_pte_encode; dpt->obj = dpt_obj; + dpt->obj->is_dpt = true; return &dpt->vm; } @@ -309,5 +312,29 @@ void intel_dpt_destroy(struct i915_address_space *vm) { struct i915_dpt *dpt = i915_vm_to_dpt(vm); + dpt->obj->is_dpt = false; i915_vm_put(&dpt->vm); } + +void intel_dpt_configure(struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (DISPLAY_VER(i915) == 14) { + enum pipe pipe = crtc->pipe; + enum plane_id plane_id; + + for_each_plane_id_on_crtc(crtc, plane_id) { + if (plane_id == PLANE_CURSOR) + continue; + + intel_de_rmw(i915, PLANE_CHICKEN(pipe, plane_id), + PLANE_CHICKEN_DISABLE_DPT, + i915->params.enable_dpt ? 0 : PLANE_CHICKEN_DISABLE_DPT); + } + } else if (DISPLAY_VER(i915) == 13) { + intel_de_rmw(i915, CHICKEN_MISC_2, + CHICKEN_MISC_DISABLE_DPT, + i915->params.enable_dpt ? 0 : CHICKEN_MISC_DISABLE_DPT); + } +} diff --git a/drivers/gpu/drm/i915/display/intel_dpt.h b/drivers/gpu/drm/i915/display/intel_dpt.h index e18a9f767b11..d9a166550185 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.h +++ b/drivers/gpu/drm/i915/display/intel_dpt.h @@ -10,6 +10,7 @@ struct drm_i915_private; struct i915_address_space; struct i915_vma; +struct intel_crtc; struct intel_framebuffer; void intel_dpt_destroy(struct i915_address_space *vm); @@ -19,5 +20,6 @@ void intel_dpt_suspend(struct drm_i915_private *i915); void intel_dpt_resume(struct drm_i915_private *i915); struct i915_address_space * intel_dpt_create(struct intel_framebuffer *fb); +void intel_dpt_configure(struct intel_crtc *crtc); #endif /* __INTEL_DPT_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 19e422da57dc..bed058d2c3ac 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -11,6 +11,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsb.h" +#include "intel_dsb_regs.h" struct i915_vma; diff --git a/drivers/gpu/drm/i915/display/intel_dsb_regs.h b/drivers/gpu/drm/i915/display/intel_dsb_regs.h new file mode 100644 index 000000000000..12535d478775 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dsb_regs.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_DSB_REGS_H__ +#define __INTEL_DSB_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* This register controls the Display State Buffer (DSB) engines. */ +#define _DSBSL_INSTANCE_BASE 0x70B00 +#define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \ + (pipe) * 0x1000 + (id) * 0x100) +#define DSB_HEAD(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x0) +#define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) +#define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) +#define DSB_ENABLE REG_BIT(31) +#define DSB_BUF_REITERATE REG_BIT(29) +#define DSB_WAIT_FOR_VBLANK REG_BIT(28) +#define DSB_WAIT_FOR_LINE_IN REG_BIT(27) +#define DSB_HALT REG_BIT(16) +#define DSB_NON_POSTED REG_BIT(8) +#define DSB_STATUS_BUSY REG_BIT(0) +#define DSB_MMIOCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xc) +#define DSB_MMIO_DEAD_CLOCKS_ENABLE REG_BIT(31) +#define DSB_MMIO_DEAD_CLOCKS_COUNT_MASK REG_GENMASK(15, 8) +#define DSB_MMIO_DEAD_CLOCKS_COUNT(x) REG_FIELD_PREP(DSB_MMIO_DEAD_CLOCK_COUNT_MASK, (x)) +#define DSB_MMIO_CYCLES_MASK REG_GENMASK(7, 0) +#define DSB_MMIO_CYCLES(x) REG_FIELD_PREP(DSB_MMIO_CYCLES_MASK, (x)) +#define DSB_POLLFUNC(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x10) +#define DSB_POLL_ENABLE REG_BIT(31) +#define DSB_POLL_WAIT_MASK REG_GENMASK(30, 23) +#define DSB_POLL_WAIT(x) REG_FIELD_PREP(DSB_POLL_WAIT_MASK, (x)) /* usec */ +#define DSB_POLL_COUNT_MASK REG_GENMASK(22, 15) +#define DSB_POLL_COUNT(x) REG_FIELD_PREP(DSB_POLL_COUNT_MASK, (x)) +#define DSB_DEBUG(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x14) +#define DSB_POLLMASK(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x1c) +#define DSB_STATUS(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x24) +#define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28) +#define DSB_ATS_FAULT_INT_EN REG_BIT(20) +#define DSB_GTT_FAULT_INT_EN REG_BIT(19) +#define DSB_RSPTIMEOUT_INT_EN REG_BIT(18) +#define DSB_POLL_ERR_INT_EN REG_BIT(17) +#define DSB_PROG_INT_EN REG_BIT(16) +#define DSB_ATS_FAULT_INT_STATUS REG_BIT(4) +#define DSB_GTT_FAULT_INT_STATUS REG_BIT(3) +#define DSB_RSPTIMEOUT_INT_STATUS REG_BIT(2) +#define DSB_POLL_ERR_INT_STATUS REG_BIT(1) +#define DSB_PROG_INT_STATUS REG_BIT(0) +#define DSB_CURRENT_HEAD(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x2c) +#define DSB_RM_TIMEOUT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x30) +#define DSB_RM_CLAIM_TIMEOUT REG_BIT(31) +#define DSB_RM_READY_TIMEOUT REG_BIT(30) +#define DSB_RM_CLAIM_TIMEOUT_COUNT_MASK REG_GENMASK(23, 16) +#define DSB_RM_CLAIM_TIMEOUT_COUNT(x) REG_FIELD_PREP(DSB_RM_CLAIM_TIMEOUT_COUNT_MASK, (x)) /* clocks */ +#define DSB_RM_READY_TIMEOUT_VALUE_MASK REG_GENMASK(15, 0) +#define DSB_RM_READY_TIMEOUT_VALUE(x) REG_FIELD_PREP(DSB_RM_READY_TIMEOUT_VALUE, (x)) /* usec */ +#define DSB_RMTIMEOUTREG_CAPTURE(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x34) +#define DSB_PMCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x38) +#define DSB_PMCTRL_2(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x3c) +#define DSB_PF_LN_LOWER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x40) +#define DSB_PF_LN_UPPER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x44) +#define DSB_BUFRPT_CNT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x48) +#define DSB_CHICKEN(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xf0) + +#endif /* __INTEL_DSB_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 2cbc1292ab38..695b0d69a4cb 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -46,6 +46,7 @@ #include "intel_dsi.h" #include "intel_dsi_vbt.h" #include "intel_gmbus_regs.h" +#include "intel_pps_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 799bdc81a6a9..e5f637897b5e 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -716,14 +716,15 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) } } -static bool intel_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier) +bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier) { - return DISPLAY_VER(i915) >= 13 && modifier != DRM_FORMAT_MOD_LINEAR; + return HAS_DPT(i915) && modifier != DRM_FORMAT_MOD_LINEAR; } bool intel_fb_uses_dpt(const struct drm_framebuffer *fb) { - return fb && intel_modifier_uses_dpt(to_i915(fb->dev), fb->modifier); + return fb && to_i915(fb->dev)->params.enable_dpt && + intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier); } unsigned int intel_cursor_alignment(const struct drm_i915_private *i915) @@ -1189,7 +1190,7 @@ bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb) { struct drm_i915_private *i915 = to_i915(fb->base.dev); - return IS_ALDERLAKE_P(i915) && fb->base.modifier != DRM_FORMAT_MOD_LINEAR; + return IS_ALDERLAKE_P(i915) && intel_fb_uses_dpt(&fb->base); } static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) @@ -1705,7 +1706,7 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv, * The new CCS hash mode makes remapping impossible */ if (DISPLAY_VER(dev_priv) < 4 || intel_fb_is_ccs_modifier(modifier) || - intel_modifier_uses_dpt(dev_priv, modifier)) + intel_fb_modifier_uses_dpt(dev_priv, modifier)) return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier); else if (DISPLAY_VER(dev_priv) >= 7) return 256 * 1024; diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 4662b812b934..e85167d6bc34 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -92,6 +92,7 @@ intel_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, const struct drm_mode_fb_cmd2 *user_mode_cmd); +bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier); bool intel_fb_uses_dpt(const struct drm_framebuffer *fb); #endif /* __INTEL_FB_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index c08c26a321b3..55283677c45a 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -12,6 +12,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_fdi.h" +#include "intel_fdi_regs.h" struct intel_fdi_funcs { void (*fdi_link_train)(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_fdi_regs.h b/drivers/gpu/drm/i915/display/intel_fdi_regs.h new file mode 100644 index 000000000000..853b834c35a9 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_fdi_regs.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_FDI_REGS_H__ +#define __INTEL_FDI_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define FDI_PLL_BIOS_0 _MMIO(0x46000) +#define FDI_PLL_FB_CLOCK_MASK 0xff +#define FDI_PLL_BIOS_1 _MMIO(0x46004) +#define FDI_PLL_BIOS_2 _MMIO(0x46008) +#define DISPLAY_PORT_PLL_BIOS_0 _MMIO(0x4600c) +#define DISPLAY_PORT_PLL_BIOS_1 _MMIO(0x46010) +#define DISPLAY_PORT_PLL_BIOS_2 _MMIO(0x46014) + +#define FDI_PLL_FREQ_CTL _MMIO(0x46030) +#define FDI_PLL_FREQ_CHANGE_REQUEST (1 << 24) +#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 +#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff + +#define _FDI_RXA_CHICKEN 0xc200c +#define _FDI_RXB_CHICKEN 0xc2010 +#define FDI_RX_PHASE_SYNC_POINTER_OVR (1 << 1) +#define FDI_RX_PHASE_SYNC_POINTER_EN (1 << 0) +#define FDI_RX_CHICKEN(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) + +/* CPU: FDI_TX */ +#define _FDI_TXA_CTL 0x60100 +#define _FDI_TXB_CTL 0x61100 +#define FDI_TX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL) +#define FDI_TX_DISABLE (0 << 31) +#define FDI_TX_ENABLE (1 << 31) +#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28) +#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28) +#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28) +#define FDI_LINK_TRAIN_NONE (3 << 28) +#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) +/* ILK always use 400mV 0dB for voltage swing and pre-emphasis level. + SNB has different settings. */ +/* SNB A-stepping */ +#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x0 << 22) +/* SNB B-stepping */ +#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x0 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22) +#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22) +#define FDI_DP_PORT_WIDTH_SHIFT 19 +#define FDI_DP_PORT_WIDTH_MASK (7 << FDI_DP_PORT_WIDTH_SHIFT) +#define FDI_DP_PORT_WIDTH(width) (((width) - 1) << FDI_DP_PORT_WIDTH_SHIFT) +#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18) +/* Ironlake: hardwired to 1 */ +#define FDI_TX_PLL_ENABLE (1 << 14) + +/* Ivybridge has different bits for lolz */ +#define FDI_LINK_TRAIN_PATTERN_1_IVB (0 << 8) +#define FDI_LINK_TRAIN_PATTERN_2_IVB (1 << 8) +#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2 << 8) +#define FDI_LINK_TRAIN_NONE_IVB (3 << 8) + +/* both Tx and Rx */ +#define FDI_COMPOSITE_SYNC (1 << 11) +#define FDI_LINK_TRAIN_AUTO (1 << 10) +#define FDI_SCRAMBLING_ENABLE (0 << 7) +#define FDI_SCRAMBLING_DISABLE (1 << 7) + +/* FDI_RX, FDI_X is hard-wired to Transcoder_X */ +#define _FDI_RXA_CTL 0xf000c +#define _FDI_RXB_CTL 0xf100c +#define FDI_RX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) +#define FDI_RX_ENABLE (1 << 31) +/* train, dp width same as FDI_TX */ +#define FDI_FS_ERRC_ENABLE (1 << 27) +#define FDI_FE_ERRC_ENABLE (1 << 26) +#define FDI_RX_POLARITY_REVERSED_LPT (1 << 16) +#define FDI_8BPC (0 << 16) +#define FDI_10BPC (1 << 16) +#define FDI_6BPC (2 << 16) +#define FDI_12BPC (3 << 16) +#define FDI_RX_LINK_REVERSAL_OVERRIDE (1 << 15) +#define FDI_DMI_LINK_REVERSE_MASK (1 << 14) +#define FDI_RX_PLL_ENABLE (1 << 13) +#define FDI_FS_ERR_CORRECT_ENABLE (1 << 11) +#define FDI_FE_ERR_CORRECT_ENABLE (1 << 10) +#define FDI_FS_ERR_REPORT_ENABLE (1 << 9) +#define FDI_FE_ERR_REPORT_ENABLE (1 << 8) +#define FDI_RX_ENHANCE_FRAME_ENABLE (1 << 6) +#define FDI_PCDCLK (1 << 4) +/* CPT */ +#define FDI_AUTO_TRAINING (1 << 10) +#define FDI_LINK_TRAIN_PATTERN_1_CPT (0 << 8) +#define FDI_LINK_TRAIN_PATTERN_2_CPT (1 << 8) +#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2 << 8) +#define FDI_LINK_TRAIN_NORMAL_CPT (3 << 8) +#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3 << 8) + +#define _FDI_RXA_MISC 0xf0010 +#define _FDI_RXB_MISC 0xf1010 +#define FDI_RX_PWRDN_LANE1_MASK (3 << 26) +#define FDI_RX_PWRDN_LANE1_VAL(x) ((x) << 26) +#define FDI_RX_PWRDN_LANE0_MASK (3 << 24) +#define FDI_RX_PWRDN_LANE0_VAL(x) ((x) << 24) +#define FDI_RX_TP1_TO_TP2_48 (2 << 20) +#define FDI_RX_TP1_TO_TP2_64 (3 << 20) +#define FDI_RX_FDI_DELAY_90 (0x90 << 0) +#define FDI_RX_MISC(pipe) _MMIO_PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) + +#define _FDI_RXA_TUSIZE1 0xf0030 +#define _FDI_RXA_TUSIZE2 0xf0038 +#define _FDI_RXB_TUSIZE1 0xf1030 +#define _FDI_RXB_TUSIZE2 0xf1038 +#define FDI_RX_TUSIZE1(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) +#define FDI_RX_TUSIZE2(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) + +/* FDI_RX interrupt register format */ +#define FDI_RX_INTER_LANE_ALIGN (1 << 10) +#define FDI_RX_SYMBOL_LOCK (1 << 9) /* train 2 */ +#define FDI_RX_BIT_LOCK (1 << 8) /* train 1 */ +#define FDI_RX_TRAIN_PATTERN_2_FAIL (1 << 7) +#define FDI_RX_FS_CODE_ERR (1 << 6) +#define FDI_RX_FE_CODE_ERR (1 << 5) +#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1 << 4) +#define FDI_RX_HDCP_LINK_FAIL (1 << 3) +#define FDI_RX_PIXEL_FIFO_OVERFLOW (1 << 2) +#define FDI_RX_CROSS_CLOCK_OVERFLOW (1 << 1) +#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1 << 0) + +#define _FDI_RXA_IIR 0xf0014 +#define _FDI_RXA_IMR 0xf0018 +#define _FDI_RXB_IIR 0xf1014 +#define _FDI_RXB_IMR 0xf1018 +#define FDI_RX_IIR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR) +#define FDI_RX_IMR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR) + +#define FDI_PLL_CTL_1 _MMIO(0xfe000) +#define FDI_PLL_CTL_2 _MMIO(0xfe004) + +#endif /* __INTEL_FDI_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index a504b3a7fbd5..0de44b3631cd 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -51,6 +51,7 @@ #include "intel_lvds.h" #include "intel_lvds_regs.h" #include "intel_panel.h" +#include "intel_pps_regs.h" /* Private structure for the integrated LVDS support */ struct intel_lvds_pps { diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 4558d02641fe..134b943f1953 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -100,7 +100,6 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, intel_fbc_disable(crtc); intel_update_watermarks(i915); - intel_disable_shared_dpll(crtc_state); intel_display_power_put_all_in_set(i915, &crtc->enabled_power_domains); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 22507da0b5f0..2411fe4dee8b 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -9,6 +9,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_fdi.h" +#include "intel_fdi_regs.h" #include "intel_lvds.h" #include "intel_lvds_regs.h" #include "intel_pch_display.h" diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 24b5b12f7732..7f9926672a6a 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -15,6 +15,7 @@ #include "intel_lvds.h" #include "intel_lvds_regs.h" #include "intel_pps.h" +#include "intel_pps_regs.h" #include "intel_quirks.h" static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_pps_regs.h b/drivers/gpu/drm/i915/display/intel_pps_regs.h new file mode 100644 index 000000000000..60edd2a27100 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_pps_regs.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_PPS_REGS_H__ +#define __INTEL_PPS_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* Panel power sequencing */ +#define PPS_BASE 0x61200 +#define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) +#define PCH_PPS_BASE 0xC7200 + +#define _MMIO_PPS(pps_idx, reg) _MMIO(dev_priv->display.pps.mmio_base - \ + PPS_BASE + (reg) + \ + (pps_idx) * 0x100) + +#define _PP_STATUS 0x61200 +#define PP_STATUS(pps_idx) _MMIO_PPS(pps_idx, _PP_STATUS) +#define PP_ON REG_BIT(31) +/* + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +#define PP_READY REG_BIT(30) +#define PP_SEQUENCE_MASK REG_GENMASK(29, 28) +#define PP_SEQUENCE_NONE REG_FIELD_PREP(PP_SEQUENCE_MASK, 0) +#define PP_SEQUENCE_POWER_UP REG_FIELD_PREP(PP_SEQUENCE_MASK, 1) +#define PP_SEQUENCE_POWER_DOWN REG_FIELD_PREP(PP_SEQUENCE_MASK, 2) +#define PP_CYCLE_DELAY_ACTIVE REG_BIT(27) +#define PP_SEQUENCE_STATE_MASK REG_GENMASK(3, 0) +#define PP_SEQUENCE_STATE_OFF_IDLE REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x0) +#define PP_SEQUENCE_STATE_OFF_S0_1 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x1) +#define PP_SEQUENCE_STATE_OFF_S0_2 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x2) +#define PP_SEQUENCE_STATE_OFF_S0_3 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x3) +#define PP_SEQUENCE_STATE_ON_IDLE REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x8) +#define PP_SEQUENCE_STATE_ON_S1_1 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x9) +#define PP_SEQUENCE_STATE_ON_S1_2 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xa) +#define PP_SEQUENCE_STATE_ON_S1_3 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xb) +#define PP_SEQUENCE_STATE_RESET REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xf) + +#define _PP_CONTROL 0x61204 +#define PP_CONTROL(pps_idx) _MMIO_PPS(pps_idx, _PP_CONTROL) +#define PANEL_UNLOCK_MASK REG_GENMASK(31, 16) +#define PANEL_UNLOCK_REGS REG_FIELD_PREP(PANEL_UNLOCK_MASK, 0xabcd) +#define BXT_POWER_CYCLE_DELAY_MASK REG_GENMASK(8, 4) +#define EDP_FORCE_VDD REG_BIT(3) +#define EDP_BLC_ENABLE REG_BIT(2) +#define PANEL_POWER_RESET REG_BIT(1) +#define PANEL_POWER_ON REG_BIT(0) + +#define _PP_ON_DELAYS 0x61208 +#define PP_ON_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_ON_DELAYS) +#define PANEL_PORT_SELECT_MASK REG_GENMASK(31, 30) +#define PANEL_PORT_SELECT_LVDS REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 0) +#define PANEL_PORT_SELECT_DPA REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 1) +#define PANEL_PORT_SELECT_DPC REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 2) +#define PANEL_PORT_SELECT_DPD REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 3) +#define PANEL_PORT_SELECT_VLV(port) REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, port) +#define PANEL_POWER_UP_DELAY_MASK REG_GENMASK(28, 16) +#define PANEL_LIGHT_ON_DELAY_MASK REG_GENMASK(12, 0) + +#define _PP_OFF_DELAYS 0x6120C +#define PP_OFF_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_OFF_DELAYS) +#define PANEL_POWER_DOWN_DELAY_MASK REG_GENMASK(28, 16) +#define PANEL_LIGHT_OFF_DELAY_MASK REG_GENMASK(12, 0) + +#define _PP_DIVISOR 0x61210 +#define PP_DIVISOR(pps_idx) _MMIO_PPS(pps_idx, _PP_DIVISOR) +#define PP_REFERENCE_DIVIDER_MASK REG_GENMASK(31, 8) +#define PANEL_POWER_CYCLE_DELAY_MASK REG_GENMASK(4, 0) + +#endif /* __INTEL_PPS_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 31084d95711d..6badfff2b4a2 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -34,6 +34,7 @@ #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" +#include "intel_psr_regs.h" #include "intel_snps_phy.h" #include "skl_universal_plane.h" @@ -519,6 +520,17 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) return val; } +static int psr2_block_count_lines(struct intel_dp *intel_dp) +{ + return intel_dp->psr.io_wake_lines < 9 && + intel_dp->psr.fast_wake_lines < 9 ? 8 : 12; +} + +static int psr2_block_count(struct intel_dp *intel_dp) +{ + return psr2_block_count_lines(intel_dp) / 4; +} + static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -536,11 +548,10 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= intel_psr2_get_tp_time(intel_dp); if (DISPLAY_VER(dev_priv) >= 12) { - if (intel_dp->psr.io_wake_lines < 9 && - intel_dp->psr.fast_wake_lines < 9) - val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; - else + if (psr2_block_count(intel_dp) > 2) val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3; + else + val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; } /* Wa_22012278275:adl-p */ @@ -958,6 +969,15 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + /* Vblank >= PSR2_CTL Block Count Number maximum line count */ + if (crtc_state->hw.adjusted_mode.crtc_vblank_end - + crtc_state->hw.adjusted_mode.crtc_vblank_start < + psr2_block_count_lines(intel_dp)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, too short vblank time\n"); + return false; + } + if (HAS_PSR2_SEL_FETCH(dev_priv)) { if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && !HAS_PSR_HW_TRACKING(dev_priv)) { @@ -1134,6 +1154,34 @@ static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp) } } +/* + * Wa_16013835468 + * Wa_14015648006 + */ +static void wm_optimization_wa(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + bool set_wa_bit = false; + + /* Wa_14015648006 */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 11, 13)) + set_wa_bit |= crtc_state->wm_level_disabled; + + /* Wa_16013835468 */ + if (DISPLAY_VER(dev_priv) == 12) + set_wa_bit |= crtc_state->hw.adjusted_mode.crtc_vblank_start != + crtc_state->hw.adjusted_mode.crtc_vdisplay; + + if (set_wa_bit) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + 0, wa_16013835468_bit_get(intel_dp)); + else + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + wa_16013835468_bit_get(intel_dp), 0); +} + static void intel_psr_enable_source(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -1177,13 +1225,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, * Wa_16013835468 * Wa_14015648006 */ - if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || - IS_DISPLAY_VER(dev_priv, 12, 13)) { - if (crtc_state->hw.adjusted_mode.crtc_vblank_start != - crtc_state->hw.adjusted_mode.crtc_vdisplay) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, - wa_16013835468_bit_get(intel_dp)); - } + wm_optimization_wa(intel_dp, crtc_state); if (intel_dp->psr.psr2_enabled) { if (DISPLAY_VER(dev_priv) == 9) @@ -1361,8 +1403,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) * Wa_16013835468 * Wa_14015648006 */ - if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || - IS_DISPLAY_VER(dev_priv, 12, 13)) + if (DISPLAY_VER(dev_priv) >= 11) intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, wa_16013835468_bit_get(intel_dp), 0); @@ -1928,14 +1969,20 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, * - PSR disabled in new state * - All planes will go inactive * - Changing between PSR versions + * - Display WA #1136: skl, bxt */ needs_to_disable |= intel_crtc_needs_modeset(new_crtc_state); needs_to_disable |= !new_crtc_state->has_psr; needs_to_disable |= !new_crtc_state->active_planes; needs_to_disable |= new_crtc_state->has_psr2 != psr->psr2_enabled; + needs_to_disable |= DISPLAY_VER(i915) < 11 && + new_crtc_state->wm_level_disabled; if (psr->enabled && needs_to_disable) intel_psr_disable_locked(intel_dp); + else if (psr->enabled && new_crtc_state->wm_level_disabled) + /* Wa_14015648006 */ + wm_optimization_wa(intel_dp, new_crtc_state); mutex_unlock(&psr->lock); } @@ -1954,23 +2001,29 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state, crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_psr *psr = &intel_dp->psr; + bool keep_disabled = false; mutex_lock(&psr->lock); - if (psr->sink_not_reliable) - goto exit; - drm_WARN_ON(&dev_priv->drm, psr->enabled && !crtc_state->active_planes); - /* Only enable if there is active planes */ - if (!psr->enabled && crtc_state->active_planes) + keep_disabled |= psr->sink_not_reliable; + keep_disabled |= !crtc_state->active_planes; + + /* Display WA #1136: skl, bxt */ + keep_disabled |= DISPLAY_VER(dev_priv) < 11 && + crtc_state->wm_level_disabled; + + if (!psr->enabled && !keep_disabled) intel_psr_enable_locked(intel_dp, crtc_state); + else if (psr->enabled && !crtc_state->wm_level_disabled) + /* Wa_14015648006 */ + wm_optimization_wa(intel_dp, crtc_state); /* Force a PSR exit when enabling CRC to avoid CRC timeouts */ if (crtc_state->crc_enabled && psr->enabled) psr_force_hw_tracking_exit(intel_dp); -exit: mutex_unlock(&psr->lock); } } diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h new file mode 100644 index 000000000000..958d8cabc44b --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_PSR_REGS_H__ +#define __INTEL_PSR_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define TRANS_EXITLINE(trans) _MMIO_TRANS2((trans), _TRANS_EXITLINE_A) +#define EXITLINE_ENABLE REG_BIT(31) +#define EXITLINE_MASK REG_GENMASK(12, 0) +#define EXITLINE_SHIFT 0 + +/* + * HSW+ eDP PSR registers + * + * HSW PSR registers are relative to DDIA(_DDI_BUF_CTL_A + 0x800) with just one + * instance of it + */ +#define _SRD_CTL_A 0x60800 +#define _SRD_CTL_EDP 0x6f800 +#define EDP_PSR_CTL(tran) _MMIO_TRANS2(tran, _SRD_CTL_A) +#define EDP_PSR_ENABLE (1 << 31) +#define BDW_PSR_SINGLE_FRAME (1 << 30) +#define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK (1 << 29) /* SW can't modify */ +#define EDP_PSR_LINK_STANDBY (1 << 27) +#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3 << 25) +#define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES (0 << 25) +#define EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES (1 << 25) +#define EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES (2 << 25) +#define EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES (3 << 25) +#define EDP_PSR_MAX_SLEEP_TIME_SHIFT 20 +#define EDP_PSR_SKIP_AUX_EXIT (1 << 12) +#define EDP_PSR_TP1_TP2_SEL (0 << 11) +#define EDP_PSR_TP1_TP3_SEL (1 << 11) +#define EDP_PSR_CRC_ENABLE (1 << 10) /* BDW+ */ +#define EDP_PSR_TP2_TP3_TIME_500us (0 << 8) +#define EDP_PSR_TP2_TP3_TIME_100us (1 << 8) +#define EDP_PSR_TP2_TP3_TIME_2500us (2 << 8) +#define EDP_PSR_TP2_TP3_TIME_0us (3 << 8) +#define EDP_PSR_TP4_TIME_0US (3 << 6) /* ICL+ */ +#define EDP_PSR_TP1_TIME_500us (0 << 4) +#define EDP_PSR_TP1_TIME_100us (1 << 4) +#define EDP_PSR_TP1_TIME_2500us (2 << 4) +#define EDP_PSR_TP1_TIME_0us (3 << 4) +#define EDP_PSR_IDLE_FRAME_SHIFT 0 + +/* + * Until TGL, IMR/IIR are fixed at 0x648xx. On TGL+ those registers are relative + * to transcoder and bits defined for each one as if using no shift (i.e. as if + * it was for TRANSCODER_EDP) + */ +#define EDP_PSR_IMR _MMIO(0x64834) +#define EDP_PSR_IIR _MMIO(0x64838) +#define _PSR_IMR_A 0x60814 +#define _PSR_IIR_A 0x60818 +#define TRANS_PSR_IMR(tran) _MMIO_TRANS2(tran, _PSR_IMR_A) +#define TRANS_PSR_IIR(tran) _MMIO_TRANS2(tran, _PSR_IIR_A) +#define _EDP_PSR_TRANS_SHIFT(trans) ((trans) == TRANSCODER_EDP ? \ + 0 : ((trans) - TRANSCODER_A + 1) * 8) +#define TGL_PSR_MASK REG_GENMASK(2, 0) +#define TGL_PSR_ERROR REG_BIT(2) +#define TGL_PSR_POST_EXIT REG_BIT(1) +#define TGL_PSR_PRE_ENTRY REG_BIT(0) +#define EDP_PSR_MASK(trans) (TGL_PSR_MASK << \ + _EDP_PSR_TRANS_SHIFT(trans)) +#define EDP_PSR_ERROR(trans) (TGL_PSR_ERROR << \ + _EDP_PSR_TRANS_SHIFT(trans)) +#define EDP_PSR_POST_EXIT(trans) (TGL_PSR_POST_EXIT << \ + _EDP_PSR_TRANS_SHIFT(trans)) +#define EDP_PSR_PRE_ENTRY(trans) (TGL_PSR_PRE_ENTRY << \ + _EDP_PSR_TRANS_SHIFT(trans)) + +#define _SRD_AUX_DATA_A 0x60814 +#define _SRD_AUX_DATA_EDP 0x6f814 +#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) + 4) /* 5 registers */ + +#define _SRD_STATUS_A 0x60840 +#define _SRD_STATUS_EDP 0x6f840 +#define EDP_PSR_STATUS(tran) _MMIO_TRANS2(tran, _SRD_STATUS_A) +#define EDP_PSR_STATUS_STATE_MASK (7 << 29) +#define EDP_PSR_STATUS_STATE_SHIFT 29 +#define EDP_PSR_STATUS_STATE_IDLE (0 << 29) +#define EDP_PSR_STATUS_STATE_SRDONACK (1 << 29) +#define EDP_PSR_STATUS_STATE_SRDENT (2 << 29) +#define EDP_PSR_STATUS_STATE_BUFOFF (3 << 29) +#define EDP_PSR_STATUS_STATE_BUFON (4 << 29) +#define EDP_PSR_STATUS_STATE_AUXACK (5 << 29) +#define EDP_PSR_STATUS_STATE_SRDOFFACK (6 << 29) +#define EDP_PSR_STATUS_LINK_MASK (3 << 26) +#define EDP_PSR_STATUS_LINK_FULL_OFF (0 << 26) +#define EDP_PSR_STATUS_LINK_FULL_ON (1 << 26) +#define EDP_PSR_STATUS_LINK_STANDBY (2 << 26) +#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 20 +#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK 0x1f +#define EDP_PSR_STATUS_COUNT_SHIFT 16 +#define EDP_PSR_STATUS_COUNT_MASK 0xf +#define EDP_PSR_STATUS_AUX_ERROR (1 << 15) +#define EDP_PSR_STATUS_AUX_SENDING (1 << 12) +#define EDP_PSR_STATUS_SENDING_IDLE (1 << 9) +#define EDP_PSR_STATUS_SENDING_TP2_TP3 (1 << 8) +#define EDP_PSR_STATUS_SENDING_TP1 (1 << 4) +#define EDP_PSR_STATUS_IDLE_MASK 0xf + +#define _SRD_PERF_CNT_A 0x60844 +#define _SRD_PERF_CNT_EDP 0x6f844 +#define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(tran, _SRD_PERF_CNT_A) +#define EDP_PSR_PERF_CNT_MASK 0xffffff + +/* PSR_MASK on SKL+ */ +#define _SRD_DEBUG_A 0x60860 +#define _SRD_DEBUG_EDP 0x6f860 +#define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(tran, _SRD_DEBUG_A) +#define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1 << 28) +#define EDP_PSR_DEBUG_MASK_LPSP (1 << 27) +#define EDP_PSR_DEBUG_MASK_MEMUP (1 << 26) +#define EDP_PSR_DEBUG_MASK_HPD (1 << 25) +#define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (1 << 16) /* Reserved in ICL+ */ +#define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1 << 15) /* SKL+ */ + +#define _PSR2_CTL_A 0x60900 +#define _PSR2_CTL_EDP 0x6f900 +#define EDP_PSR2_CTL(tran) _MMIO_TRANS2(tran, _PSR2_CTL_A) +#define EDP_PSR2_ENABLE (1 << 31) +#define EDP_SU_TRACK_ENABLE (1 << 30) /* up to adl-p */ +#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 (0 << 28) +#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 (1 << 28) +#define EDP_Y_COORDINATE_ENABLE REG_BIT(25) /* display 10, 11 and 12 */ +#define EDP_PSR2_SU_SDP_SCANLINE REG_BIT(25) /* display 13+ */ +#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << 20) +#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f << 20) +#define EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES 8 +#define EDP_PSR2_IO_BUFFER_WAKE(lines) ((EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES - (lines)) << 13) +#define EDP_PSR2_IO_BUFFER_WAKE_MASK (3 << 13) +#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5 +#define TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT 13 +#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) (((lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT) +#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK (7 << 13) +#define EDP_PSR2_FAST_WAKE_MAX_LINES 8 +#define EDP_PSR2_FAST_WAKE(lines) ((EDP_PSR2_FAST_WAKE_MAX_LINES - (lines)) << 11) +#define EDP_PSR2_FAST_WAKE_MASK (3 << 11) +#define TGL_EDP_PSR2_FAST_WAKE_MIN_LINES 5 +#define TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT 10 +#define TGL_EDP_PSR2_FAST_WAKE(lines) (((lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES) << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT) +#define TGL_EDP_PSR2_FAST_WAKE_MASK (7 << 10) +#define EDP_PSR2_TP2_TIME_500us (0 << 8) +#define EDP_PSR2_TP2_TIME_100us (1 << 8) +#define EDP_PSR2_TP2_TIME_2500us (2 << 8) +#define EDP_PSR2_TP2_TIME_50us (3 << 8) +#define EDP_PSR2_TP2_TIME_MASK (3 << 8) +#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 +#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf << 4) +#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a) << 4) +#define EDP_PSR2_IDLE_FRAME_MASK 0xf +#define EDP_PSR2_IDLE_FRAME_SHIFT 0 + +#define _PSR_EVENT_TRANS_A 0x60848 +#define _PSR_EVENT_TRANS_B 0x61848 +#define _PSR_EVENT_TRANS_C 0x62848 +#define _PSR_EVENT_TRANS_D 0x63848 +#define _PSR_EVENT_TRANS_EDP 0x6f848 +#define PSR_EVENT(tran) _MMIO_TRANS2(tran, _PSR_EVENT_TRANS_A) +#define PSR_EVENT_PSR2_WD_TIMER_EXPIRE (1 << 17) +#define PSR_EVENT_PSR2_DISABLED (1 << 16) +#define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN (1 << 15) +#define PSR_EVENT_SU_CRC_FIFO_UNDERRUN (1 << 14) +#define PSR_EVENT_GRAPHICS_RESET (1 << 12) +#define PSR_EVENT_PCH_INTERRUPT (1 << 11) +#define PSR_EVENT_MEMORY_UP (1 << 10) +#define PSR_EVENT_FRONT_BUFFER_MODIFY (1 << 9) +#define PSR_EVENT_WD_TIMER_EXPIRE (1 << 8) +#define PSR_EVENT_PIPE_REGISTERS_UPDATE (1 << 6) +#define PSR_EVENT_REGISTER_UPDATE (1 << 5) /* Reserved in ICL+ */ +#define PSR_EVENT_HDCP_ENABLE (1 << 4) +#define PSR_EVENT_KVMR_SESSION_ENABLE (1 << 3) +#define PSR_EVENT_VBI_ENABLE (1 << 2) +#define PSR_EVENT_LPSP_MODE_EXIT (1 << 1) +#define PSR_EVENT_PSR_DISABLE (1 << 0) + +#define _PSR2_STATUS_A 0x60940 +#define _PSR2_STATUS_EDP 0x6f940 +#define EDP_PSR2_STATUS(tran) _MMIO_TRANS2(tran, _PSR2_STATUS_A) +#define EDP_PSR2_STATUS_STATE_MASK REG_GENMASK(31, 28) +#define EDP_PSR2_STATUS_STATE_DEEP_SLEEP REG_FIELD_PREP(EDP_PSR2_STATUS_STATE_MASK, 0x8) + +#define _PSR2_SU_STATUS_A 0x60914 +#define _PSR2_SU_STATUS_EDP 0x6f914 +#define _PSR2_SU_STATUS(tran, index) _MMIO_TRANS2(tran, _PSR2_SU_STATUS_A + (index) * 4) +#define PSR2_SU_STATUS(tran, frame) (_PSR2_SU_STATUS(tran, (frame) / 3)) +#define PSR2_SU_STATUS_SHIFT(frame) (((frame) % 3) * 10) +#define PSR2_SU_STATUS_MASK(frame) (0x3ff << PSR2_SU_STATUS_SHIFT(frame)) +#define PSR2_SU_STATUS_FRAMES 8 + +#define _PSR2_MAN_TRK_CTL_A 0x60910 +#define _PSR2_MAN_TRK_CTL_EDP 0x6f910 +#define PSR2_MAN_TRK_CTL(tran) _MMIO_TRANS2(tran, _PSR2_MAN_TRK_CTL_A) +#define PSR2_MAN_TRK_CTL_ENABLE REG_BIT(31) +#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(30, 21) +#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) +#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(20, 11) +#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) +#define PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(3) +#define PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(2) +#define PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(1) +#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(28, 16) +#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) +#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0) +#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) +#define ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31) +#define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14) +#define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13) + +#define _SEL_FETCH_PLANE_BASE_1_A 0x70890 +#define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 +#define _SEL_FETCH_PLANE_BASE_3_A 0x708D0 +#define _SEL_FETCH_PLANE_BASE_4_A 0x708F0 +#define _SEL_FETCH_PLANE_BASE_5_A 0x70920 +#define _SEL_FETCH_PLANE_BASE_6_A 0x70940 +#define _SEL_FETCH_PLANE_BASE_7_A 0x70960 +#define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880 +#define _SEL_FETCH_PLANE_BASE_1_B 0x71890 + +#define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \ + _SEL_FETCH_PLANE_BASE_1_A, \ + _SEL_FETCH_PLANE_BASE_2_A, \ + _SEL_FETCH_PLANE_BASE_3_A, \ + _SEL_FETCH_PLANE_BASE_4_A, \ + _SEL_FETCH_PLANE_BASE_5_A, \ + _SEL_FETCH_PLANE_BASE_6_A, \ + _SEL_FETCH_PLANE_BASE_7_A, \ + _SEL_FETCH_PLANE_BASE_CUR_A) +#define _SEL_FETCH_PLANE_BASE_1(pipe) _PIPE(pipe, _SEL_FETCH_PLANE_BASE_1_A, _SEL_FETCH_PLANE_BASE_1_B) +#define _SEL_FETCH_PLANE_BASE(pipe, plane) (_SEL_FETCH_PLANE_BASE_1(pipe) - \ + _SEL_FETCH_PLANE_BASE_1_A + \ + _SEL_FETCH_PLANE_BASE_A(plane)) + +#define _SEL_FETCH_PLANE_CTL_1_A 0x70890 +#define PLANE_SEL_FETCH_CTL(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ + _SEL_FETCH_PLANE_CTL_1_A - \ + _SEL_FETCH_PLANE_BASE_1_A) +#define PLANE_SEL_FETCH_CTL_ENABLE REG_BIT(31) + +#define _SEL_FETCH_PLANE_POS_1_A 0x70894 +#define PLANE_SEL_FETCH_POS(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ + _SEL_FETCH_PLANE_POS_1_A - \ + _SEL_FETCH_PLANE_BASE_1_A) + +#define _SEL_FETCH_PLANE_SIZE_1_A 0x70898 +#define PLANE_SEL_FETCH_SIZE(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ + _SEL_FETCH_PLANE_SIZE_1_A - \ + _SEL_FETCH_PLANE_BASE_1_A) + +#define _SEL_FETCH_PLANE_OFFSET_1_A 0x7089C +#define PLANE_SEL_FETCH_OFFSET(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ + _SEL_FETCH_PLANE_OFFSET_1_A - \ + _SEL_FETCH_PLANE_BASE_1_A) + +#endif /* __INTEL_PSR_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.c b/drivers/gpu/drm/i915/display/intel_qp_tables.c index 6f8e4ec5c0fb..6e86c0971d24 100644 --- a/drivers/gpu/drm/i915/display/intel_qp_tables.c +++ b/drivers/gpu/drm/i915/display/intel_qp_tables.c @@ -17,6 +17,15 @@ /* from BPP 6 to 36 in steps of 0.5 */ #define RC_RANGE_QP444_12BPC_MAX_NUM_BPP 61 +/* from BPP 6 to 24 in steps of 0.5 */ +#define RC_RANGE_QP420_8BPC_MAX_NUM_BPP 17 + +/* from BPP 6 to 30 in steps of 0.5 */ +#define RC_RANGE_QP420_10BPC_MAX_NUM_BPP 23 + +/* from BPP 6 to 36 in steps of 0.5 */ +#define RC_RANGE_QP420_12BPC_MAX_NUM_BPP 29 + /* * These qp tables are as per the C model * and it has the rows pointing to bpps which increment @@ -283,26 +292,182 @@ static const u8 rc_range_maxqp444_12bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_12BPC 11, 11, 10, 10, 10, 10, 10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 4 } }; -#define PARAM_TABLE(_minmax, _bpc, _row, _col) do { \ - if (bpc == (_bpc)) \ - return rc_range_##_minmax##qp444_##_bpc##bpc[_row][_col]; \ +static const u8 rc_range_minqp420_8bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_8BPC_MAX_NUM_BPP] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, + { 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, + { 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, + { 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0 }, + { 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0 }, + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1 }, + { 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 1, 1 }, + { 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 2, 2, 1 }, + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 3, 3, 2, 1 }, + { 9, 8, 8, 7, 7, 7, 7, 7, 7, 6, 5, 5, 4, 3, 3, 3, 2 }, + { 13, 12, 12, 11, 10, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3 } +}; + +static const u8 rc_range_maxqp420_8bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_8BPC_MAX_NUM_BPP] = { + { 4, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 4, 4, 4, 4, 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, + { 5, 5, 5, 5, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, + { 6, 6, 6, 6, 6, 5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0 }, + { 7, 7, 7, 7, 7, 5, 4, 3, 2, 2, 2, 2, 2, 1, 1, 1, 0 }, + { 7, 7, 7, 7, 7, 6, 5, 4, 3, 3, 3, 2, 2, 2, 1, 1, 0 }, + { 7, 7, 7, 7, 7, 6, 5, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1 }, + { 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 3, 3, 2, 2, 2, 1 }, + { 9, 9, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1 }, + { 10, 10, 9, 9, 9, 8, 7, 6, 5, 5, 5, 4, 4, 3, 3, 2, 2 }, + { 10, 10, 10, 9, 9, 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 2, 2 }, + { 11, 11, 10, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4, 3, 3, 2 }, + { 11, 11, 11, 10, 9, 9, 9, 8, 7, 7, 6, 5, 5, 4, 4, 3, 2 }, + { 13, 12, 12, 11, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 4, 3 }, + { 14, 13, 13, 12, 11, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 4 } +}; + +static const u8 rc_range_minqp420_10bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_10BPC_MAX_NUM_BPP] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 4, 4, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 }, + { 7, 7, 7, 7, 7, 6, 5, 5, 5, 5, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0 }, + { 7, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3, 2, 2, 2, 2, 1, 1, 1, 0 }, + { 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 4, 4, 4, 3, 2, 2, 2, 1, 1, 1, 0 }, + { 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 1, 1 }, + { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1 }, + { 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1 }, + { 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 4, 4, 3, 3, 2, 1 }, + { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, 3, 2, 1 }, + { 13, 12, 12, 11, 11, 11, 11, 11, 11, 10, 9, 9, 8, 7, 7, 6, 5, 5, 4, 3, 3, + 2, 2 }, + { 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, 10, 9, 8, 8, 7, 6, 6, 5, + 5, 4, 4 } +}; + +static const u8 rc_range_maxqp420_10bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_10BPC_MAX_NUM_BPP] = { + { 8, 8, 7, 6, 4, 4, 3, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 8, 8, 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 9, 9, 9, 8, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0 }, + { 10, 10, 10, 9, 9, 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 0, + 0 }, + { 11, 11, 11, 10, 10, 8, 7, 6, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, + 0 }, + { 11, 11, 11, 10, 10, 9, 8, 7, 6, 6, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 1, + 1 }, + { 11, 11, 11, 11, 11, 10, 9, 8, 7, 7, 7, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, + 1 }, + { 12, 12, 12, 12, 12, 11, 10, 9, 8, 8, 8, 7, 6, 5, 5, 4, 3, 3, 3, 2, 2, + 2, 1 }, + { 13, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, 3, 3, + 2, 2 }, + { 14, 14, 13, 13, 13, 12, 11, 10, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, 3, + 2, 2 }, + { 14, 14, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, + 3, 3, 2 }, + { 15, 15, 14, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8, 7, 7, 6, 5, 5, 4, + 4, 3, 2 }, + { 15, 15, 15, 14, 13, 13, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, + 4, 3, 2 }, + { 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, + 4, 3, 3 }, + { 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 11, 10, 9, 9, 8, 7, 7, + 6, 6, 5, 5 } +}; + +static const u8 rc_range_minqp420_12bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_12BPC_MAX_NUM_BPP] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }, + { 4, 4, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }, + { 9, 8, 8, 7, 7, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }, + { 10, 9, 9, 8, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0 }, + { 11, 10, 10, 10, 10, 9, 9, 8, 7, 6, 6, 6, 6, 5, 5, 4, 3, 3, 3, 2, 2, 1, + 0, 0, 0, 0, 0, 0, 0 }, + { 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 9, 8, 7, 6, 5, 5, 4, 4, 3, 3, 3, 2, + 1, 1, 0, 0, 0, 0, 0 }, + { 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7, 6, 5, 5, 5, 5, 4, 3, 3, + 2, 1, 1, 1, 1, 1, 0 }, + { 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 8, 8, 8, 7, 6, 6, 5, 4, 4, + 3, 2, 2, 1, 1, 1, 1, 1 }, + { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 5, + 5, 4, 4, 2, 2, 1, 1, 1, 1 }, + { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, + 5, 4, 4, 3, 2, 2, 1, 1, 1 }, + { 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, + 6, 5, 4, 3, 3, 2, 2, 1, 1 }, + { 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 10, 10, 9, 8, 8, + 7, 7, 6, 5, 4, 3, 3, 2, 2, 1 }, + { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 9, 8, 8, + 7, 7, 6, 5, 4, 4, 3, 2, 2, 1 }, + { 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 13, 13, 12, 11, 11, 10, 9, 9, 8, + 8, 7, 6, 6, 5, 4, 4, 3, 3, 2 }, + { 21, 20, 20, 19, 18, 18, 17, 16, 16, 15, 14, 14, 14, 13, 12, 12, 11, 10, + 10, 10, 9, 8, 8, 7, 6, 6, 5, 5, 4 } +}; + +static const u8 rc_range_maxqp420_12bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP420_12BPC_MAX_NUM_BPP] = { + { 11, 10, 9, 8, 6, 6, 5, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0 }, + { 12, 11, 11, 10, 9, 8, 7, 7, 6, 6, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0 }, + { 13, 12, 12, 11, 11, 10, 9, 8, 7, 6, 6, 6, 5, 5, 4, 3, 3, 2, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0 }, + { 14, 13, 13, 12, 12, 11, 10, 9, 8, 7, 7, 6, 6, 5, 5, 4, 3, 3, 2, 2, 2, 1, + 1, 1, 0, 0, 0, 0, 0 }, + { 15, 14, 14, 13, 13, 11, 10, 9, 8, 7, 7, 7, 7, 6, 6, 5, 4, 4, 4, 3, 3, 2, + 1, 1, 1, 0, 0, 0, 0 }, + { 15, 15, 15, 14, 14, 13, 12, 11, 10, 10, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, + 4, 3, 2, 2, 1, 1, 0, 0, 0 }, + { 15, 15, 15, 15, 15, 14, 13, 12, 11, 11, 11, 10, 9, 8, 7, 6, 6, 6, 6, 5, + 4, 4, 3, 2, 2, 2, 1, 1, 0 }, + { 16, 16, 16, 16, 16, 15, 14, 13, 12, 12, 12, 11, 10, 9, 9, 8, 7, 7, 6, 5, + 5, 4, 3, 3, 2, 2, 2, 1, 1 }, + { 17, 17, 17, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 9, 8, 8, 7, + 6, 6, 5, 5, 3, 3, 2, 2, 1, 1 }, + { 18, 18, 17, 17, 17, 16, 15, 14, 13, 13, 13, 12, 12, 11, 11, 10, 9, 8, 8, + 7, 6, 5, 5, 4, 3, 3, 2, 2, 1 }, + { 18, 18, 18, 17, 17, 16, 16, 15, 14, 14, 13, 13, 12, 12, 11, 10, 9, 9, 8, + 8, 7, 6, 5, 4, 4, 3, 3, 2, 2 }, + { 19, 19, 18, 18, 17, 17, 16, 15, 15, 14, 14, 13, 13, 12, 11, 11, 10, 9, + 9, 8, 8, 7, 6, 5, 4, 4, 3, 3, 2 }, + { 19, 19, 19, 18, 17, 17, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 9, + 9, 8, 8, 7, 6, 5, 5, 4, 3, 3, 2 }, + { 21, 20, 20, 19, 18, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, + 9, 9, 8, 7, 7, 6, 5, 5, 4, 4, 3 }, + { 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 15, 14, 13, 13, 12, 11, + 11, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5 } +}; + +#define PARAM_TABLE(_minmax, _bpc, _row, _col, _is_420) do { \ + if (bpc == (_bpc)) { \ + if (_is_420) \ + return rc_range_##_minmax##qp420_##_bpc##bpc[_row][_col]; \ + else \ + return rc_range_##_minmax##qp444_##_bpc##bpc[_row][_col]; \ + } \ } while (0) -u8 intel_lookup_range_min_qp(int bpc, int buf_i, int bpp_i) +u8 intel_lookup_range_min_qp(int bpc, int buf_i, int bpp_i, bool is_420) { - PARAM_TABLE(min, 8, buf_i, bpp_i); - PARAM_TABLE(min, 10, buf_i, bpp_i); - PARAM_TABLE(min, 12, buf_i, bpp_i); + PARAM_TABLE(min, 8, buf_i, bpp_i, is_420); + PARAM_TABLE(min, 10, buf_i, bpp_i, is_420); + PARAM_TABLE(min, 12, buf_i, bpp_i, is_420); MISSING_CASE(bpc); return 0; } -u8 intel_lookup_range_max_qp(int bpc, int buf_i, int bpp_i) +u8 intel_lookup_range_max_qp(int bpc, int buf_i, int bpp_i, bool is_420) { - PARAM_TABLE(max, 8, buf_i, bpp_i); - PARAM_TABLE(max, 10, buf_i, bpp_i); - PARAM_TABLE(max, 12, buf_i, bpp_i); + PARAM_TABLE(max, 8, buf_i, bpp_i, is_420); + PARAM_TABLE(max, 10, buf_i, bpp_i, is_420); + PARAM_TABLE(max, 12, buf_i, bpp_i, is_420); MISSING_CASE(bpc); return 0; diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.h b/drivers/gpu/drm/i915/display/intel_qp_tables.h index 9fb3c36bd7c6..a9ff9ca29938 100644 --- a/drivers/gpu/drm/i915/display/intel_qp_tables.h +++ b/drivers/gpu/drm/i915/display/intel_qp_tables.h @@ -8,7 +8,7 @@ #include <linux/types.h> -u8 intel_lookup_range_min_qp(int bpc, int buf_i, int bpp_i); -u8 intel_lookup_range_max_qp(int bpc, int buf_i, int bpp_i); +u8 intel_lookup_range_min_qp(int bpc, int buf_i, int bpp_i, bool is_420); +u8 intel_lookup_range_max_qp(int bpc, int buf_i, int bpp_i, bool is_420); #endif diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index bd8c9df5f98f..3b60995e9dfb 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -15,6 +15,52 @@ #include "intel_mg_phy_regs.h" #include "intel_tc.h" +enum tc_port_mode { + TC_PORT_DISCONNECTED, + TC_PORT_TBT_ALT, + TC_PORT_DP_ALT, + TC_PORT_LEGACY, +}; + +struct intel_tc_port; + +struct intel_tc_phy_ops { + enum intel_display_power_domain (*cold_off_domain)(struct intel_tc_port *tc); + u32 (*hpd_live_status)(struct intel_tc_port *tc); + bool (*is_ready)(struct intel_tc_port *tc); + bool (*is_owned)(struct intel_tc_port *tc); + void (*get_hw_state)(struct intel_tc_port *tc); + bool (*connect)(struct intel_tc_port *tc, int required_lanes); + void (*disconnect)(struct intel_tc_port *tc); + void (*init)(struct intel_tc_port *tc); +}; + +struct intel_tc_port { + struct intel_digital_port *dig_port; + + const struct intel_tc_phy_ops *phy_ops; + + struct mutex lock; /* protects the TypeC port mode */ + intel_wakeref_t lock_wakeref; +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) + enum intel_display_power_domain lock_power_domain; +#endif + struct delayed_work disconnect_phy_work; + int link_refcount; + bool legacy_port:1; + char port_name[8]; + enum tc_port_mode mode; + enum tc_port_mode init_mode; + enum phy_fia phy_fia; + u8 phy_fia_idx; +}; + +static enum intel_display_power_domain +tc_phy_cold_off_domain(struct intel_tc_port *); +static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc); +static bool tc_phy_is_ready(struct intel_tc_port *tc); +static enum tc_port_mode tc_phy_get_current_mode(struct intel_tc_port *tc); + static const char *tc_port_mode_name(enum tc_port_mode mode) { static const char * const names[] = { @@ -30,13 +76,24 @@ static const char *tc_port_mode_name(enum tc_port_mode mode) return names[mode]; } +static struct intel_tc_port *to_tc_port(struct intel_digital_port *dig_port) +{ + return dig_port->tc; +} + +static struct drm_i915_private *tc_to_i915(struct intel_tc_port *tc) +{ + return to_i915(tc->dig_port->base.base.dev); +} + static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port, enum tc_port_mode mode) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + struct intel_tc_port *tc = to_tc_port(dig_port); - return intel_phy_is_tc(i915, phy) && dig_port->tc_mode == mode; + return intel_phy_is_tc(i915, phy) && tc->mode == mode; } bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port) @@ -54,127 +111,178 @@ bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port) return intel_tc_port_in_mode(dig_port, TC_PORT_LEGACY); } +/* + * The display power domains used for TC ports depending on the + * platform and TC mode (legacy, DP-alt, TBT): + * + * POWER_DOMAIN_DISPLAY_CORE: + * -------------------------- + * ADLP/all modes: + * - TCSS/IOM access for PHY ready state. + * ADLP+/all modes: + * - DE/north-,south-HPD ISR access for HPD live state. + * + * POWER_DOMAIN_PORT_DDI_LANES_<port>: + * ----------------------------------- + * ICL+/all modes: + * - DE/DDI_BUF access for port enabled state. + * ADLP/all modes: + * - DE/DDI_BUF access for PHY owned state. + * + * POWER_DOMAIN_AUX_USBC<TC port index>: + * ------------------------------------- + * ICL/legacy mode: + * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state + * - TCSS/PHY: block TC-cold power state for using the PHY AUX and + * main lanes. + * ADLP/legacy, DP-alt modes: + * - TCSS/PHY: block TC-cold power state for using the PHY AUX and + * main lanes. + * + * POWER_DOMAIN_TC_COLD_OFF: + * ------------------------- + * TGL/legacy, DP-alt modes: + * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state + * - TCSS/PHY: block TC-cold power state for using the PHY AUX and + * main lanes. + * + * ICL, TGL, ADLP/TBT mode: + * - TCSS/IOM,FIA access for HPD live state + * - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN) + * AUX and main lanes. + */ bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc = to_tc_port(dig_port); - return (DISPLAY_VER(i915) == 11 && dig_port->tc_legacy_port) || - IS_ALDERLAKE_P(i915); + return tc_phy_cold_off_domain(tc) == + intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); } -static enum intel_display_power_domain -tc_cold_get_power_domain(struct intel_digital_port *dig_port, enum tc_port_mode mode) +static intel_wakeref_t +__tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domain) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); - if (mode == TC_PORT_TBT_ALT || !intel_tc_cold_requires_aux_pw(dig_port)) - return POWER_DOMAIN_TC_COLD_OFF; + *domain = tc_phy_cold_off_domain(tc); - return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); + return intel_display_power_get(i915, *domain); } static intel_wakeref_t -tc_cold_block_in_mode(struct intel_digital_port *dig_port, enum tc_port_mode mode, - enum intel_display_power_domain *domain) +tc_cold_block(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - - *domain = tc_cold_get_power_domain(dig_port, mode); + enum intel_display_power_domain domain; + intel_wakeref_t wakeref; - return intel_display_power_get(i915, *domain); + wakeref = __tc_cold_block(tc, &domain); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) + tc->lock_power_domain = domain; +#endif + return wakeref; } -static intel_wakeref_t -tc_cold_block(struct intel_digital_port *dig_port, enum intel_display_power_domain *domain) +static void +__tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain domain, + intel_wakeref_t wakeref) { - return tc_cold_block_in_mode(dig_port, dig_port->tc_mode, domain); + struct drm_i915_private *i915 = tc_to_i915(tc); + + intel_display_power_put(i915, domain, wakeref); } static void -tc_cold_unblock(struct intel_digital_port *dig_port, enum intel_display_power_domain domain, - intel_wakeref_t wakeref) +tc_cold_unblock(struct intel_tc_port *tc, intel_wakeref_t wakeref) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum intel_display_power_domain domain = tc_phy_cold_off_domain(tc); - /* - * wakeref == -1, means some error happened saving save_depot_stack but - * power should still be put down and 0 is a invalid save_depot_stack - * id so can be used to skip it for non TC legacy ports. - */ - if (wakeref == 0) - return; +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) + drm_WARN_ON(&tc_to_i915(tc)->drm, tc->lock_power_domain != domain); +#endif + __tc_cold_unblock(tc, domain, wakeref); +} - intel_display_power_put(i915, domain, wakeref); +static void +assert_display_core_power_enabled(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + + drm_WARN_ON(&i915->drm, + !intel_display_power_is_enabled(i915, POWER_DOMAIN_DISPLAY_CORE)); } static void -assert_tc_cold_blocked(struct intel_digital_port *dig_port) +assert_tc_cold_blocked(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); bool enabled; enabled = intel_display_power_is_enabled(i915, - tc_cold_get_power_domain(dig_port, - dig_port->tc_mode)); + tc_phy_cold_off_domain(tc)); drm_WARN_ON(&i915->drm, !enabled); } static enum intel_display_power_domain -tc_port_power_domain(struct intel_digital_port *dig_port) +tc_port_power_domain(struct intel_tc_port *tc) { - 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 drm_i915_private *i915 = tc_to_i915(tc); + enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; } static void -assert_tc_port_power_enabled(struct intel_digital_port *dig_port) +assert_tc_port_power_enabled(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); drm_WARN_ON(&i915->drm, - !intel_display_power_is_enabled(i915, tc_port_power_domain(dig_port))); + !intel_display_power_is_enabled(i915, tc_port_power_domain(tc))); } 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_tc_port *tc = to_tc_port(dig_port); u32 lane_mask; - lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); - assert_tc_cold_blocked(dig_port); + assert_tc_cold_blocked(tc); - lane_mask &= DP_LANE_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx); - return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx); + lane_mask &= DP_LANE_ASSIGNMENT_MASK(tc->phy_fia_idx); + return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(tc->phy_fia_idx); } 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_tc_port *tc = to_tc_port(dig_port); u32 pin_mask; - pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); + pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(tc->phy_fia)); drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); - assert_tc_cold_blocked(dig_port); + assert_tc_cold_blocked(tc); - return (pin_mask & DP_PIN_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx)) >> - DP_PIN_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx); + return (pin_mask & DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx)) >> + DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx); } int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc = to_tc_port(dig_port); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); intel_wakeref_t wakeref; u32 lane_mask; - if (dig_port->tc_mode != TC_PORT_DP_ALT) + if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT) return 4; - assert_tc_cold_blocked(dig_port); + assert_tc_cold_blocked(tc); lane_mask = 0; with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) @@ -201,45 +309,51 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, int required_lanes) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc = to_tc_port(dig_port); bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; u32 val; drm_WARN_ON(&i915->drm, - lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY); + lane_reversal && tc->mode != TC_PORT_LEGACY); - assert_tc_cold_blocked(dig_port); + assert_tc_cold_blocked(tc); - val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); - val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx); + val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia)); + val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx); switch (required_lanes) { case 1: val |= lane_reversal ? - DFLEXDPMLE1_DPMLETC_ML3(dig_port->tc_phy_fia_idx) : - DFLEXDPMLE1_DPMLETC_ML0(dig_port->tc_phy_fia_idx); + DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) : + DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx); break; case 2: val |= lane_reversal ? - DFLEXDPMLE1_DPMLETC_ML3_2(dig_port->tc_phy_fia_idx) : - DFLEXDPMLE1_DPMLETC_ML1_0(dig_port->tc_phy_fia_idx); + DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) : + DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx); break; case 4: - val |= DFLEXDPMLE1_DPMLETC_ML3_0(dig_port->tc_phy_fia_idx); + val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx); break; default: MISSING_CASE(required_lanes); } - intel_de_write(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); + intel_de_write(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val); } -static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, +static void tc_port_fixup_legacy_flag(struct intel_tc_port *tc, u32 live_status_mask) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); u32 valid_hpd_mask; - if (dig_port->tc_legacy_port) + drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); + + if (hweight32(live_status_mask) != 1) + return; + + if (tc->legacy_port) valid_hpd_mask = BIT(TC_PORT_LEGACY); else valid_hpd_mask = BIT(TC_PORT_DP_ALT) | @@ -251,80 +365,79 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, /* If live status mismatches the VBT flag, trust the live status. */ drm_dbg_kms(&i915->drm, "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n", - dig_port->tc_port_name, live_status_mask, valid_hpd_mask); + tc->port_name, live_status_mask, valid_hpd_mask); - dig_port->tc_legacy_port = !dig_port->tc_legacy_port; + tc->legacy_port = !tc->legacy_port; } -static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) +static void tc_phy_load_fia_params(struct intel_tc_port *tc, bool modular_fia) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; - u32 mask = 0; - u32 val; - - val = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + struct drm_i915_private *i915 = tc_to_i915(tc); + enum port port = tc->dig_port->base.port; + enum tc_port tc_port = intel_port_to_tc(i915, port); - if (val == 0xffffffff) { - drm_dbg_kms(&i915->drm, - "Port %s: PHY in TCCOLD, nothing connected\n", - dig_port->tc_port_name); - return mask; + /* + * Each Modular FIA instance houses 2 TC ports. In SOC that has more + * than two TC ports, there are multiple instances of Modular FIA. + */ + if (modular_fia) { + tc->phy_fia = tc_port / 2; + tc->phy_fia_idx = tc_port % 2; + } else { + tc->phy_fia = FIA1; + tc->phy_fia_idx = tc_port; } +} - if (val & TC_LIVE_STATE_TBT(dig_port->tc_phy_fia_idx)) - mask |= BIT(TC_PORT_TBT_ALT); - if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx)) - mask |= BIT(TC_PORT_DP_ALT); - - if (intel_de_read(i915, SDEISR) & isr_bit) - mask |= BIT(TC_PORT_LEGACY); +/* + * ICL TC PHY handlers + * ------------------- + */ +static enum intel_display_power_domain +icl_tc_phy_cold_off_domain(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; - /* The sink can be connected only in a single mode. */ - if (!drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1)) - tc_port_fixup_legacy_flag(dig_port, mask); + if (tc->legacy_port) + return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); - return mask; + return POWER_DOMAIN_TC_COLD_OFF; } -static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) +static u32 icl_tc_phy_hpd_live_status(struct intel_tc_port *tc) { - 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 drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; - u32 val, mask = 0; + intel_wakeref_t wakeref; + u32 fia_isr; + u32 pch_isr; + u32 mask = 0; - /* - * On ADL-P HW/FW will wake from TCCOLD to complete the read access of - * registers in IOM. Note that this doesn't apply to PHY and FIA - * registers. - */ - 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) + with_intel_display_power(i915, tc_phy_cold_off_domain(tc), wakeref) { + fia_isr = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); + pch_isr = intel_de_read(i915, SDEISR); + } + + if (fia_isr == 0xffffffff) { + drm_dbg_kms(&i915->drm, + "Port %s: PHY in TCCOLD, nothing connected\n", + tc->port_name); + return mask; + } + + if (fia_isr & TC_LIVE_STATE_TBT(tc->phy_fia_idx)) mask |= BIT(TC_PORT_TBT_ALT); + if (fia_isr & TC_LIVE_STATE_TC(tc->phy_fia_idx)) + mask |= BIT(TC_PORT_DP_ALT); - if (intel_de_read(i915, SDEISR) & isr_bit) + if (pch_isr & isr_bit) mask |= BIT(TC_PORT_LEGACY); - /* The sink can be connected only in a single mode. */ - if (!drm_WARN_ON(&i915->drm, hweight32(mask) > 1)) - tc_port_fixup_legacy_flag(dig_port, mask); - return mask; } -static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - - if (IS_ALDERLAKE_P(i915)) - return adl_tc_port_live_status_mask(dig_port); - - return icl_tc_port_live_status_mask(dig_port); -} - /* * Return the PHY status complete flag indicating that display can acquire the * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink @@ -333,136 +446,80 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port) * owned by the TBT subsystem and so switching the ownership to display is not * required. */ -static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) +static bool icl_tc_phy_is_ready(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); u32 val; - 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", - dig_port->tc_port_name); - return false; - } - - return val & DP_PHY_MODE_STATUS_COMPLETED(dig_port->tc_phy_fia_idx); -} - -/* - * Return the PHY status complete flag indicating that display can acquire the - * PHY ownership. The IOM firmware sets this flag when it's ready to switch - * the ownership to display, regardless of what sink is connected (TBT-alt, - * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT - * subsystem and so switching the ownership to display is not required. - */ -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); - u32 val; + assert_tc_cold_blocked(tc); - val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port)); + val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(tc->phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, - "Port %s: PHY in TCCOLD, assuming not complete\n", - dig_port->tc_port_name); + "Port %s: PHY in TCCOLD, assuming not ready\n", + tc->port_name); return false; } - return val & TCSS_DDI_STATUS_READY; -} - -static bool tc_phy_status_complete(struct intel_digital_port *dig_port) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - - if (IS_ALDERLAKE_P(i915)) - return adl_tc_phy_status_complete(dig_port); - - return icl_tc_phy_status_complete(dig_port); + return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx); } -static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, +static bool icl_tc_phy_take_ownership(struct intel_tc_port *tc, bool take) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); u32 val; - val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + assert_tc_cold_blocked(tc); + + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, can't %s ownership\n", - dig_port->tc_port_name, take ? "take" : "release"); + tc->port_name, take ? "take" : "release"); return false; } - val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); + val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); if (take) - val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); - - intel_de_write(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); - - return true; -} - -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); - enum port port = dig_port->base.port; + val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); - intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, - take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); + intel_de_write(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val); return true; } -static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) +static bool icl_tc_phy_is_owned(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - - if (IS_ALDERLAKE_P(i915)) - return adl_tc_phy_take_ownership(dig_port, take); - - return icl_tc_phy_take_ownership(dig_port, 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 drm_i915_private *i915 = tc_to_i915(tc); u32 val; - val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + assert_tc_cold_blocked(tc); + + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assume not owned\n", - dig_port->tc_port_name); + tc->port_name); return false; } - return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); + return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); } -static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port) +static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum port port = dig_port->base.port; - u32 val; - - val = intel_de_read(i915, DDI_BUF_CTL(port)); - return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP; -} + enum intel_display_power_domain domain; + intel_wakeref_t tc_cold_wref; -static bool tc_phy_is_owned(struct intel_digital_port *dig_port) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + tc_cold_wref = __tc_cold_block(tc, &domain); - if (IS_ALDERLAKE_P(i915)) - return adl_tc_phy_is_owned(dig_port); + tc->mode = tc_phy_get_current_mode(tc); + if (tc->mode != TC_PORT_DISCONNECTED) + tc->lock_wakeref = tc_cold_block(tc); - return icl_tc_phy_is_owned(dig_port); + __tc_cold_unblock(tc, domain, tc_cold_wref); } /* @@ -476,116 +533,410 @@ static bool tc_phy_is_owned(struct intel_digital_port *dig_port) * connect and disconnect to cleanly transfer ownership with the controller and * set the type-C power state. */ -static void icl_tc_phy_connect(struct intel_digital_port *dig_port, - int required_lanes) +static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc, + int required_lanes) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - u32 live_status_mask; + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; int max_lanes; - if (!tc_phy_status_complete(dig_port) && - !drm_WARN_ON(&i915->drm, dig_port->tc_legacy_port)) { - drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", - dig_port->tc_port_name); - goto out_set_tbt_alt_mode; - } - - live_status_mask = tc_port_live_status_mask(dig_port); - if (!(live_status_mask & (BIT(TC_PORT_DP_ALT) | BIT(TC_PORT_LEGACY))) && - !dig_port->tc_legacy_port) { - drm_dbg_kms(&i915->drm, "Port %s: PHY ownership not required (live status %02x)\n", - dig_port->tc_port_name, live_status_mask); - goto out_set_tbt_alt_mode; - } - - if (!tc_phy_take_ownership(dig_port, true) && - !drm_WARN_ON(&i915->drm, dig_port->tc_legacy_port)) - goto out_set_tbt_alt_mode; - max_lanes = intel_tc_port_fia_max_lane_count(dig_port); - if (dig_port->tc_legacy_port) { + if (tc->mode == TC_PORT_LEGACY) { drm_WARN_ON(&i915->drm, max_lanes != 4); - dig_port->tc_mode = TC_PORT_LEGACY; - - return; + return true; } + drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DP_ALT); + /* * Now we have to re-check the live state, in case the port recently * became disconnected. Not necessary for legacy mode. */ - if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) { + if (!(tc_phy_hpd_live_status(tc) & BIT(TC_PORT_DP_ALT))) { drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n", - dig_port->tc_port_name); - goto out_release_phy; + tc->port_name); + return false; } if (max_lanes < required_lanes) { drm_dbg_kms(&i915->drm, "Port %s: PHY max lanes %d < required lanes %d\n", - dig_port->tc_port_name, + tc->port_name, max_lanes, required_lanes); - goto out_release_phy; + return false; } - dig_port->tc_mode = TC_PORT_DP_ALT; + return true; +} + +static bool icl_tc_phy_connect(struct intel_tc_port *tc, + int required_lanes) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + + tc->lock_wakeref = tc_cold_block(tc); + + if (tc->mode == TC_PORT_TBT_ALT) + return true; + + if ((!tc_phy_is_ready(tc) || + !icl_tc_phy_take_ownership(tc, true)) && + !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { + drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership (ready %s)\n", + tc->port_name, + str_yes_no(tc_phy_is_ready(tc))); + goto out_unblock_tc_cold; + } + + + if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) + goto out_release_phy; - return; + return true; out_release_phy: - tc_phy_take_ownership(dig_port, false); -out_set_tbt_alt_mode: - dig_port->tc_mode = TC_PORT_TBT_ALT; + icl_tc_phy_take_ownership(tc, false); +out_unblock_tc_cold: + tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); + + return false; } /* * See the comment at the connect function. This implements the Disconnect * Flow. */ -static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port) +static void icl_tc_phy_disconnect(struct intel_tc_port *tc) { - switch (dig_port->tc_mode) { + switch (tc->mode) { case TC_PORT_LEGACY: case TC_PORT_DP_ALT: - tc_phy_take_ownership(dig_port, false); + icl_tc_phy_take_ownership(tc, false); fallthrough; case TC_PORT_TBT_ALT: - dig_port->tc_mode = TC_PORT_DISCONNECTED; + tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); + break; + default: + MISSING_CASE(tc->mode); + } +} + +static void icl_tc_phy_init(struct intel_tc_port *tc) +{ + tc_phy_load_fia_params(tc, false); +} + +static const struct intel_tc_phy_ops icl_tc_phy_ops = { + .cold_off_domain = icl_tc_phy_cold_off_domain, + .hpd_live_status = icl_tc_phy_hpd_live_status, + .is_ready = icl_tc_phy_is_ready, + .is_owned = icl_tc_phy_is_owned, + .get_hw_state = icl_tc_phy_get_hw_state, + .connect = icl_tc_phy_connect, + .disconnect = icl_tc_phy_disconnect, + .init = icl_tc_phy_init, +}; + +/* + * TGL TC PHY handlers + * ------------------- + */ +static enum intel_display_power_domain +tgl_tc_phy_cold_off_domain(struct intel_tc_port *tc) +{ + return POWER_DOMAIN_TC_COLD_OFF; +} + +static void tgl_tc_phy_init(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + intel_wakeref_t wakeref; + u32 val; + + with_intel_display_power(i915, tc_phy_cold_off_domain(tc), wakeref) + val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1)); + + drm_WARN_ON(&i915->drm, val == 0xffffffff); + + tc_phy_load_fia_params(tc, val & MODULAR_FIA_MASK); +} + +static const struct intel_tc_phy_ops tgl_tc_phy_ops = { + .cold_off_domain = tgl_tc_phy_cold_off_domain, + .hpd_live_status = icl_tc_phy_hpd_live_status, + .is_ready = icl_tc_phy_is_ready, + .is_owned = icl_tc_phy_is_owned, + .get_hw_state = icl_tc_phy_get_hw_state, + .connect = icl_tc_phy_connect, + .disconnect = icl_tc_phy_disconnect, + .init = tgl_tc_phy_init, +}; + +/* + * ADLP TC PHY handlers + * -------------------- + */ +static enum intel_display_power_domain +adlp_tc_phy_cold_off_domain(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; + + if (tc->mode != TC_PORT_TBT_ALT) + return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); + + return POWER_DOMAIN_TC_COLD_OFF; +} + +static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; + enum hpd_pin hpd_pin = dig_port->base.hpd_pin; + u32 cpu_isr_bits = i915->display.hotplug.hpd[hpd_pin]; + u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; + intel_wakeref_t wakeref; + u32 cpu_isr; + u32 pch_isr; + u32 mask = 0; + + with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) { + cpu_isr = intel_de_read(i915, GEN11_DE_HPD_ISR); + pch_isr = intel_de_read(i915, SDEISR); + } + + if (cpu_isr & (cpu_isr_bits & GEN11_DE_TC_HOTPLUG_MASK)) + mask |= BIT(TC_PORT_DP_ALT); + if (cpu_isr & (cpu_isr_bits & GEN11_DE_TBT_HOTPLUG_MASK)) + mask |= BIT(TC_PORT_TBT_ALT); + + if (pch_isr & pch_isr_bit) + mask |= BIT(TC_PORT_LEGACY); + + return mask; +} + +/* + * Return the PHY status complete flag indicating that display can acquire the + * PHY ownership. The IOM firmware sets this flag when it's ready to switch + * the ownership to display, regardless of what sink is connected (TBT-alt, + * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT + * subsystem and so switching the ownership to display is not required. + */ +static bool adlp_tc_phy_is_ready(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); + u32 val; + + assert_display_core_power_enabled(tc); + + 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 ready\n", + tc->port_name); + return false; + } + + return val & TCSS_DDI_STATUS_READY; +} + +static bool adlp_tc_phy_take_ownership(struct intel_tc_port *tc, + bool take) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum port port = tc->dig_port->base.port; + + assert_tc_port_power_enabled(tc); + + intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, + take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); + + return true; +} + +static bool adlp_tc_phy_is_owned(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum port port = tc->dig_port->base.port; + u32 val; + + assert_tc_port_power_enabled(tc); + + val = intel_de_read(i915, DDI_BUF_CTL(port)); + return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP; +} + +static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum intel_display_power_domain port_power_domain = + tc_port_power_domain(tc); + intel_wakeref_t port_wakeref; + + port_wakeref = intel_display_power_get(i915, port_power_domain); + + tc->mode = tc_phy_get_current_mode(tc); + if (tc->mode != TC_PORT_DISCONNECTED) + tc->lock_wakeref = tc_cold_block(tc); + + intel_display_power_put(i915, port_power_domain, port_wakeref); +} + +static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum intel_display_power_domain port_power_domain = + tc_port_power_domain(tc); + intel_wakeref_t port_wakeref; + + if (tc->mode == TC_PORT_TBT_ALT) { + tc->lock_wakeref = tc_cold_block(tc); + return true; + } + + port_wakeref = intel_display_power_get(i915, port_power_domain); + + if (!adlp_tc_phy_take_ownership(tc, true) && + !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { + drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership\n", + tc->port_name); + goto out_put_port_power; + } + + if (!tc_phy_is_ready(tc) && + !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { + drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", + tc->port_name); + goto out_release_phy; + } + + tc->lock_wakeref = tc_cold_block(tc); + + if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) + goto out_unblock_tc_cold; + + intel_display_power_put(i915, port_power_domain, port_wakeref); + + return true; + +out_unblock_tc_cold: + tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); +out_release_phy: + adlp_tc_phy_take_ownership(tc, false); +out_put_port_power: + intel_display_power_put(i915, port_power_domain, port_wakeref); + + return false; +} + +static void adlp_tc_phy_disconnect(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + enum intel_display_power_domain port_power_domain = + tc_port_power_domain(tc); + intel_wakeref_t port_wakeref; + + port_wakeref = intel_display_power_get(i915, port_power_domain); + + tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); + + switch (tc->mode) { + case TC_PORT_LEGACY: + case TC_PORT_DP_ALT: + adlp_tc_phy_take_ownership(tc, false); fallthrough; - case TC_PORT_DISCONNECTED: + case TC_PORT_TBT_ALT: break; default: - MISSING_CASE(dig_port->tc_mode); + MISSING_CASE(tc->mode); } + + intel_display_power_put(i915, port_power_domain, port_wakeref); +} + +static void adlp_tc_phy_init(struct intel_tc_port *tc) +{ + tc_phy_load_fia_params(tc, true); } -static bool tc_phy_is_ready_and_owned(struct intel_digital_port *dig_port, +static const struct intel_tc_phy_ops adlp_tc_phy_ops = { + .cold_off_domain = adlp_tc_phy_cold_off_domain, + .hpd_live_status = adlp_tc_phy_hpd_live_status, + .is_ready = adlp_tc_phy_is_ready, + .is_owned = adlp_tc_phy_is_owned, + .get_hw_state = adlp_tc_phy_get_hw_state, + .connect = adlp_tc_phy_connect, + .disconnect = adlp_tc_phy_disconnect, + .init = adlp_tc_phy_init, +}; + +/* + * Generic TC PHY handlers + * ----------------------- + */ +static enum intel_display_power_domain +tc_phy_cold_off_domain(struct intel_tc_port *tc) +{ + return tc->phy_ops->cold_off_domain(tc); +} + +static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + u32 mask; + + mask = tc->phy_ops->hpd_live_status(tc); + + /* The sink can be connected only in a single mode. */ + drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1); + + return mask; +} + +static bool tc_phy_is_ready(struct intel_tc_port *tc) +{ + return tc->phy_ops->is_ready(tc); +} + +static bool tc_phy_is_owned(struct intel_tc_port *tc) +{ + return tc->phy_ops->is_owned(tc); +} + +static void tc_phy_get_hw_state(struct intel_tc_port *tc) +{ + tc->phy_ops->get_hw_state(tc); +} + +static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc, bool phy_is_ready, bool phy_is_owned) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); drm_WARN_ON(&i915->drm, phy_is_owned && !phy_is_ready); return phy_is_ready && phy_is_owned; } -static bool tc_phy_is_connected(struct intel_digital_port *dig_port, +static bool tc_phy_is_connected(struct intel_tc_port *tc, enum icl_port_dpll_id port_pll_type) { - struct intel_encoder *encoder = &dig_port->base; + struct intel_encoder *encoder = &tc->dig_port->base; struct drm_i915_private *i915 = to_i915(encoder->base.dev); - bool phy_is_ready = tc_phy_status_complete(dig_port); - bool phy_is_owned = tc_phy_is_owned(dig_port); + bool phy_is_ready = tc_phy_is_ready(tc); + bool phy_is_owned = tc_phy_is_owned(tc); bool is_connected; - if (tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned)) + if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY; else is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT; drm_dbg_kms(&i915->drm, "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n", - dig_port->tc_port_name, + tc->port_name, str_yes_no(is_connected), str_yes_no(phy_is_ready), str_yes_no(phy_is_owned), @@ -594,13 +945,13 @@ static bool tc_phy_is_connected(struct intel_digital_port *dig_port, return is_connected; } -static void tc_phy_wait_for_ready(struct intel_digital_port *dig_port) +static void tc_phy_wait_for_ready(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); - if (wait_for(tc_phy_status_complete(dig_port), 100)) + if (wait_for(tc_phy_is_ready(tc), 100)) drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n", - dig_port->tc_port_name); + tc->port_name); } static enum tc_port_mode @@ -613,15 +964,15 @@ hpd_mask_to_tc_mode(u32 live_status_mask) } static enum tc_port_mode -tc_phy_hpd_live_mode(struct intel_digital_port *dig_port) +tc_phy_hpd_live_mode(struct intel_tc_port *tc) { - u32 live_status_mask = tc_port_live_status_mask(dig_port); + u32 live_status_mask = tc_phy_hpd_live_status(tc); return hpd_mask_to_tc_mode(live_status_mask); } static enum tc_port_mode -get_tc_mode_in_phy_owned_state(struct intel_digital_port *dig_port, +get_tc_mode_in_phy_owned_state(struct intel_tc_port *tc, enum tc_port_mode live_mode) { switch (live_mode) { @@ -633,7 +984,7 @@ get_tc_mode_in_phy_owned_state(struct intel_digital_port *dig_port, fallthrough; case TC_PORT_TBT_ALT: case TC_PORT_DISCONNECTED: - if (dig_port->tc_legacy_port) + if (tc->legacy_port) return TC_PORT_LEGACY; else return TC_PORT_DP_ALT; @@ -641,7 +992,7 @@ get_tc_mode_in_phy_owned_state(struct intel_digital_port *dig_port, } static enum tc_port_mode -get_tc_mode_in_phy_not_owned_state(struct intel_digital_port *dig_port, +get_tc_mode_in_phy_not_owned_state(struct intel_tc_port *tc, enum tc_port_mode live_mode) { switch (live_mode) { @@ -654,7 +1005,7 @@ get_tc_mode_in_phy_not_owned_state(struct intel_digital_port *dig_port, MISSING_CASE(live_mode); fallthrough; case TC_PORT_DISCONNECTED: - if (dig_port->tc_legacy_port) + if (tc->legacy_port) return TC_PORT_DISCONNECTED; else return TC_PORT_TBT_ALT; @@ -662,10 +1013,10 @@ get_tc_mode_in_phy_not_owned_state(struct intel_digital_port *dig_port, } static enum tc_port_mode -intel_tc_port_get_current_mode(struct intel_digital_port *dig_port) +tc_phy_get_current_mode(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum tc_port_mode live_mode = tc_phy_hpd_live_mode(dig_port); + struct drm_i915_private *i915 = tc_to_i915(tc); + enum tc_port_mode live_mode = tc_phy_hpd_live_mode(tc); bool phy_is_ready; bool phy_is_owned; enum tc_port_mode mode; @@ -675,22 +1026,22 @@ intel_tc_port_get_current_mode(struct intel_digital_port *dig_port) * and system resume whether or not a sink is connected. Wait here for * the initialization to get ready. */ - if (dig_port->tc_legacy_port) - tc_phy_wait_for_ready(dig_port); + if (tc->legacy_port) + tc_phy_wait_for_ready(tc); - phy_is_ready = tc_phy_status_complete(dig_port); - phy_is_owned = tc_phy_is_owned(dig_port); + phy_is_ready = tc_phy_is_ready(tc); + phy_is_owned = tc_phy_is_owned(tc); - if (!tc_phy_is_ready_and_owned(dig_port, phy_is_ready, phy_is_owned)) { - mode = get_tc_mode_in_phy_not_owned_state(dig_port, live_mode); + if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) { + mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); } else { drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT); - mode = get_tc_mode_in_phy_owned_state(dig_port, live_mode); + mode = get_tc_mode_in_phy_owned_state(tc, live_mode); } drm_dbg_kms(&i915->drm, "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n", - dig_port->tc_port_name, + tc->port_name, tc_port_mode_name(mode), str_yes_no(phy_is_ready), str_yes_no(phy_is_owned), @@ -699,38 +1050,73 @@ intel_tc_port_get_current_mode(struct intel_digital_port *dig_port) return mode; } -static enum tc_port_mode default_tc_mode(struct intel_digital_port *dig_port) +static enum tc_port_mode default_tc_mode(struct intel_tc_port *tc) { - if (dig_port->tc_legacy_port) + if (tc->legacy_port) return TC_PORT_LEGACY; return TC_PORT_TBT_ALT; } static enum tc_port_mode -hpd_mask_to_target_mode(struct intel_digital_port *dig_port, u32 live_status_mask) +hpd_mask_to_target_mode(struct intel_tc_port *tc, u32 live_status_mask) { enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask); if (mode != TC_PORT_DISCONNECTED) return mode; - return default_tc_mode(dig_port); + return default_tc_mode(tc); } static enum tc_port_mode -intel_tc_port_get_target_mode(struct intel_digital_port *dig_port) +tc_phy_get_target_mode(struct intel_tc_port *tc) +{ + u32 live_status_mask = tc_phy_hpd_live_status(tc); + + return hpd_mask_to_target_mode(tc, live_status_mask); +} + +static void tc_phy_connect(struct intel_tc_port *tc, int required_lanes) +{ + struct drm_i915_private *i915 = tc_to_i915(tc); + u32 live_status_mask = tc_phy_hpd_live_status(tc); + bool connected; + + tc_port_fixup_legacy_flag(tc, live_status_mask); + + tc->mode = hpd_mask_to_target_mode(tc, live_status_mask); + + connected = tc->phy_ops->connect(tc, required_lanes); + if (!connected && tc->mode != default_tc_mode(tc)) { + tc->mode = default_tc_mode(tc); + connected = tc->phy_ops->connect(tc, required_lanes); + } + + drm_WARN_ON(&i915->drm, !connected); +} + +static void tc_phy_disconnect(struct intel_tc_port *tc) { - u32 live_status_mask = tc_port_live_status_mask(dig_port); + if (tc->mode != TC_PORT_DISCONNECTED) { + tc->phy_ops->disconnect(tc); + tc->mode = TC_PORT_DISCONNECTED; + } +} - return hpd_mask_to_target_mode(dig_port, live_status_mask); +static void tc_phy_init(struct intel_tc_port *tc) +{ + mutex_lock(&tc->lock); + tc->phy_ops->init(tc); + mutex_unlock(&tc->lock); } -static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port, +static void intel_tc_port_reset_mode(struct intel_tc_port *tc, int required_lanes, bool force_disconnect) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum tc_port_mode old_tc_mode = dig_port->tc_mode; + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; + enum tc_port_mode old_tc_mode = tc->mode; intel_display_power_flush_work(i915); if (!intel_tc_cold_requires_aux_pw(dig_port)) { @@ -742,68 +1128,45 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port, drm_WARN_ON(&i915->drm, aux_powered); } - icl_tc_phy_disconnect(dig_port); + tc_phy_disconnect(tc); if (!force_disconnect) - icl_tc_phy_connect(dig_port, required_lanes); + tc_phy_connect(tc, required_lanes); drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n", - dig_port->tc_port_name, + tc->port_name, tc_port_mode_name(old_tc_mode), - tc_port_mode_name(dig_port->tc_mode)); + tc_port_mode_name(tc->mode)); } -static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port) +static bool intel_tc_port_needs_reset(struct intel_tc_port *tc) { - return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode; + return tc_phy_get_target_mode(tc) != tc->mode; } -static void intel_tc_port_update_mode(struct intel_digital_port *dig_port, +static void intel_tc_port_update_mode(struct intel_tc_port *tc, int required_lanes, bool force_disconnect) { - enum intel_display_power_domain domain; - intel_wakeref_t wref; - bool needs_reset = force_disconnect; - - if (!needs_reset) { - /* Get power domain required to check the hotplug live status. */ - wref = tc_cold_block(dig_port, &domain); - needs_reset = intel_tc_port_needs_reset(dig_port); - tc_cold_unblock(dig_port, domain, wref); - } - - if (!needs_reset) - return; - - /* Get power domain required for resetting the mode. */ - wref = tc_cold_block_in_mode(dig_port, TC_PORT_DISCONNECTED, &domain); - - intel_tc_port_reset_mode(dig_port, required_lanes, force_disconnect); - - /* Get power domain matching the new mode after reset. */ - tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, - fetch_and_zero(&dig_port->tc_lock_wakeref)); - if (dig_port->tc_mode != TC_PORT_DISCONNECTED) - dig_port->tc_lock_wakeref = tc_cold_block(dig_port, - &dig_port->tc_lock_power_domain); - - tc_cold_unblock(dig_port, domain, wref); + if (force_disconnect || + intel_tc_port_needs_reset(tc)) + intel_tc_port_reset_mode(tc, required_lanes, force_disconnect); } -static void __intel_tc_port_get_link(struct intel_digital_port *dig_port) +static void __intel_tc_port_get_link(struct intel_tc_port *tc) { - dig_port->tc_link_refcount++; + tc->link_refcount++; } -static void __intel_tc_port_put_link(struct intel_digital_port *dig_port) +static void __intel_tc_port_put_link(struct intel_tc_port *tc) { - dig_port->tc_link_refcount--; + tc->link_refcount--; } -static bool tc_port_is_enabled(struct intel_digital_port *dig_port) +static bool tc_port_is_enabled(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; - assert_tc_port_power_enabled(dig_port); + assert_tc_port_power_enabled(tc); return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & DDI_BUF_CTL_ENABLE; @@ -819,27 +1182,21 @@ static bool tc_port_is_enabled(struct intel_digital_port *dig_port) void intel_tc_port_init_mode(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - intel_wakeref_t tc_cold_wref; - enum intel_display_power_domain domain; + struct intel_tc_port *tc = to_tc_port(dig_port); bool update_mode = false; - mutex_lock(&dig_port->tc_lock); - - drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); - drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); - drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount); + mutex_lock(&tc->lock); - tc_cold_wref = tc_cold_block(dig_port, &domain); + drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); + drm_WARN_ON(&i915->drm, tc->lock_wakeref); + drm_WARN_ON(&i915->drm, tc->link_refcount); - dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); + tc_phy_get_hw_state(tc); /* * Save the initial mode for the state check in * intel_tc_port_sanitize_mode(). */ - dig_port->tc_init_mode = dig_port->tc_mode; - if (dig_port->tc_mode != TC_PORT_DISCONNECTED) - dig_port->tc_lock_wakeref = - tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); + tc->init_mode = tc->mode; /* * The PHY needs to be connected for AUX to work during HW readout and @@ -852,31 +1209,30 @@ void intel_tc_port_init_mode(struct intel_digital_port *dig_port) * cause a problem as the PHY ownership state is ignored by the * IOM/TCSS firmware (only display can own the PHY in that case). */ - if (!tc_port_is_enabled(dig_port)) { + if (!tc_port_is_enabled(tc)) { update_mode = true; - } else if (dig_port->tc_mode == TC_PORT_DISCONNECTED) { - drm_WARN_ON(&i915->drm, !dig_port->tc_legacy_port); + } else if (tc->mode == TC_PORT_DISCONNECTED) { + drm_WARN_ON(&i915->drm, !tc->legacy_port); drm_err(&i915->drm, "Port %s: PHY disconnected on enabled port, connecting it\n", - dig_port->tc_port_name); + tc->port_name); update_mode = true; } if (update_mode) - intel_tc_port_update_mode(dig_port, 1, false); + intel_tc_port_update_mode(tc, 1, false); - /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ - __intel_tc_port_get_link(dig_port); + /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */ + __intel_tc_port_get_link(tc); - tc_cold_unblock(dig_port, domain, tc_cold_wref); - - mutex_unlock(&dig_port->tc_lock); + mutex_unlock(&tc->lock); } -static bool tc_port_has_active_links(struct intel_digital_port *dig_port, +static bool tc_port_has_active_links(struct intel_tc_port *tc, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); + struct intel_digital_port *dig_port = tc->dig_port; enum icl_port_dpll_id pll_type = ICL_PORT_DPLL_DEFAULT; int active_links = 0; @@ -888,10 +1244,10 @@ static bool tc_port_has_active_links(struct intel_digital_port *dig_port, active_links = 1; } - if (active_links && !tc_phy_is_connected(dig_port, pll_type)) + if (active_links && !tc_phy_is_connected(tc, pll_type)) drm_err(&i915->drm, "Port %s: PHY disconnected with %d active link(s)\n", - dig_port->tc_port_name, active_links); + tc->port_name, active_links); return active_links; } @@ -912,35 +1268,33 @@ void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc = to_tc_port(dig_port); - mutex_lock(&dig_port->tc_lock); + mutex_lock(&tc->lock); - drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1); - if (!tc_port_has_active_links(dig_port, crtc_state)) { + drm_WARN_ON(&i915->drm, tc->link_refcount != 1); + if (!tc_port_has_active_links(tc, crtc_state)) { /* * TBT-alt is the default mode in any case the PHY ownership is not * held (regardless of the sink's connected live state), so * we'll just switch to disconnected mode from it here without * a note. */ - if (dig_port->tc_init_mode != TC_PORT_TBT_ALT && - dig_port->tc_init_mode != TC_PORT_DISCONNECTED) + if (tc->init_mode != TC_PORT_TBT_ALT && + tc->init_mode != TC_PORT_DISCONNECTED) drm_dbg_kms(&i915->drm, "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", - dig_port->tc_port_name, - tc_port_mode_name(dig_port->tc_init_mode)); - icl_tc_phy_disconnect(dig_port); - __intel_tc_port_put_link(dig_port); - - tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, - fetch_and_zero(&dig_port->tc_lock_wakeref)); + tc->port_name, + tc_port_mode_name(tc->init_mode)); + tc_phy_disconnect(tc); + __intel_tc_port_put_link(tc); } drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", - dig_port->tc_port_name, - tc_port_mode_name(dig_port->tc_mode)); + tc->port_name, + tc_port_mode_name(tc->mode)); - mutex_unlock(&dig_port->tc_lock); + mutex_unlock(&tc->lock); } /* @@ -957,66 +1311,69 @@ bool intel_tc_port_connected_locked(struct intel_encoder *encoder) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc = to_tc_port(dig_port); + u32 mask = ~0; drm_WARN_ON(&i915->drm, !intel_tc_port_ref_held(dig_port)); - return tc_port_live_status_mask(dig_port) & BIT(dig_port->tc_mode); + if (tc->mode != TC_PORT_DISCONNECTED) + mask = BIT(tc->mode); + + return tc_phy_hpd_live_status(tc) & mask; } bool intel_tc_port_connected(struct intel_encoder *encoder) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct intel_tc_port *tc = to_tc_port(dig_port); bool is_connected; - intel_tc_port_lock(dig_port); + mutex_lock(&tc->lock); is_connected = intel_tc_port_connected_locked(encoder); - intel_tc_port_unlock(dig_port); + mutex_unlock(&tc->lock); return is_connected; } -static void __intel_tc_port_lock(struct intel_digital_port *dig_port, +static void __intel_tc_port_lock(struct intel_tc_port *tc, int required_lanes) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct drm_i915_private *i915 = tc_to_i915(tc); - mutex_lock(&dig_port->tc_lock); + mutex_lock(&tc->lock); - cancel_delayed_work(&dig_port->tc_disconnect_phy_work); + cancel_delayed_work(&tc->disconnect_phy_work); - if (!dig_port->tc_link_refcount) - intel_tc_port_update_mode(dig_port, required_lanes, + if (!tc->link_refcount) + intel_tc_port_update_mode(tc, required_lanes, false); - drm_WARN_ON(&i915->drm, dig_port->tc_mode == TC_PORT_DISCONNECTED); - drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_TBT_ALT && - !tc_phy_is_owned(dig_port)); + drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_DISCONNECTED); + drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_TBT_ALT && + !tc_phy_is_owned(tc)); } void intel_tc_port_lock(struct intel_digital_port *dig_port) { - __intel_tc_port_lock(dig_port, 1); + __intel_tc_port_lock(to_tc_port(dig_port), 1); } -/** - * intel_tc_port_disconnect_phy_work: disconnect TypeC PHY from display port - * @dig_port: digital port - * +/* * Disconnect the given digital port from its TypeC PHY (handing back the * control of the PHY to the TypeC subsystem). This will happen in a delayed * manner after each aux transactions and modeset disables. */ static void intel_tc_port_disconnect_phy_work(struct work_struct *work) { - struct intel_digital_port *dig_port = - container_of(work, struct intel_digital_port, tc_disconnect_phy_work.work); + struct intel_tc_port *tc = + container_of(work, struct intel_tc_port, disconnect_phy_work.work); - mutex_lock(&dig_port->tc_lock); + mutex_lock(&tc->lock); - if (!dig_port->tc_link_refcount) - intel_tc_port_update_mode(dig_port, 1, true); + if (!tc->link_refcount) + intel_tc_port_update_mode(tc, 1, true); - mutex_unlock(&dig_port->tc_lock); + mutex_unlock(&tc->lock); } /** @@ -1027,105 +1384,91 @@ static void intel_tc_port_disconnect_phy_work(struct work_struct *work) */ void intel_tc_port_flush_work(struct intel_digital_port *dig_port) { - flush_delayed_work(&dig_port->tc_disconnect_phy_work); + flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work); } void intel_tc_port_unlock(struct intel_digital_port *dig_port) { - if (!dig_port->tc_link_refcount && dig_port->tc_mode != TC_PORT_DISCONNECTED) - queue_delayed_work(system_unbound_wq, &dig_port->tc_disconnect_phy_work, + struct intel_tc_port *tc = to_tc_port(dig_port); + + if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED) + queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work, msecs_to_jiffies(1000)); - mutex_unlock(&dig_port->tc_lock); + mutex_unlock(&tc->lock); } bool intel_tc_port_ref_held(struct intel_digital_port *dig_port) { - return mutex_is_locked(&dig_port->tc_lock) || - dig_port->tc_link_refcount; + struct intel_tc_port *tc = to_tc_port(dig_port); + + return mutex_is_locked(&tc->lock) || + tc->link_refcount; } void intel_tc_port_get_link(struct intel_digital_port *dig_port, int required_lanes) { - __intel_tc_port_lock(dig_port, required_lanes); - __intel_tc_port_get_link(dig_port); + struct intel_tc_port *tc = to_tc_port(dig_port); + + __intel_tc_port_lock(tc, required_lanes); + __intel_tc_port_get_link(tc); intel_tc_port_unlock(dig_port); } void intel_tc_port_put_link(struct intel_digital_port *dig_port) { + struct intel_tc_port *tc = to_tc_port(dig_port); + intel_tc_port_lock(dig_port); - __intel_tc_port_put_link(dig_port); + __intel_tc_port_put_link(tc); intel_tc_port_unlock(dig_port); - - /* - * Disconnecting the PHY after the PHY's PLL gets disabled may - * hang the system on ADL-P, so disconnect the PHY here synchronously. - * TODO: remove this once the root cause of the ordering requirement - * is found/fixed. - */ - intel_tc_port_flush_work(dig_port); } -static bool -tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig_port) +int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) { - enum intel_display_power_domain domain; - intel_wakeref_t wakeref; - u32 val; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_tc_port *tc; + enum port port = dig_port->base.port; + enum tc_port tc_port = intel_port_to_tc(i915, port); - if (!INTEL_INFO(i915)->display.has_modular_fia) - return false; + if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) + return -EINVAL; - mutex_lock(&dig_port->tc_lock); - wakeref = tc_cold_block(dig_port, &domain); - val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1)); - tc_cold_unblock(dig_port, domain, wakeref); - mutex_unlock(&dig_port->tc_lock); + tc = kzalloc(sizeof(*tc), GFP_KERNEL); + if (!tc) + return -ENOMEM; - drm_WARN_ON(&i915->drm, val == 0xffffffff); + dig_port->tc = tc; + tc->dig_port = dig_port; - return val & MODULAR_FIA_MASK; -} + if (DISPLAY_VER(i915) >= 13) + tc->phy_ops = &adlp_tc_phy_ops; + else if (DISPLAY_VER(i915) >= 12) + tc->phy_ops = &tgl_tc_phy_ops; + else + tc->phy_ops = &icl_tc_phy_ops; -static void -tc_port_load_fia_params(struct drm_i915_private *i915, struct intel_digital_port *dig_port) -{ - enum port port = dig_port->base.port; - enum tc_port tc_port = intel_port_to_tc(i915, port); + snprintf(tc->port_name, sizeof(tc->port_name), + "%c/TC#%d", port_name(port), tc_port + 1); - /* - * Each Modular FIA instance houses 2 TC ports. In SOC that has more - * than two TC ports, there are multiple instances of Modular FIA. - */ - if (tc_has_modular_fia(i915, dig_port)) { - dig_port->tc_phy_fia = tc_port / 2; - dig_port->tc_phy_fia_idx = tc_port % 2; - } else { - dig_port->tc_phy_fia = FIA1; - dig_port->tc_phy_fia_idx = tc_port; - } -} + mutex_init(&tc->lock); + INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work); + tc->legacy_port = is_legacy; + tc->mode = TC_PORT_DISCONNECTED; + tc->link_refcount = 0; -void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum port port = dig_port->base.port; - enum tc_port tc_port = intel_port_to_tc(i915, port); + tc_phy_init(tc); - if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) - return; + intel_tc_port_init_mode(dig_port); - snprintf(dig_port->tc_port_name, sizeof(dig_port->tc_port_name), - "%c/TC#%d", port_name(port), tc_port + 1); + return 0; +} - mutex_init(&dig_port->tc_lock); - INIT_DELAYED_WORK(&dig_port->tc_disconnect_phy_work, intel_tc_port_disconnect_phy_work); - dig_port->tc_legacy_port = is_legacy; - dig_port->tc_mode = TC_PORT_DISCONNECTED; - dig_port->tc_link_refcount = 0; - tc_port_load_fia_params(i915, dig_port); +void intel_tc_port_cleanup(struct intel_digital_port *dig_port) +{ + intel_tc_port_flush_work(dig_port); - intel_tc_port_init_mode(dig_port); + kfree(dig_port->tc); + dig_port->tc = NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h index 79667d977508..dd0810f9ea95 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.h +++ b/drivers/gpu/drm/i915/display/intel_tc.h @@ -6,7 +6,6 @@ #ifndef __INTEL_TC_H__ #define __INTEL_TC_H__ -#include <linux/mutex.h> #include <linux/types.h> struct intel_crtc_state; @@ -37,7 +36,8 @@ void intel_tc_port_get_link(struct intel_digital_port *dig_port, void intel_tc_port_put_link(struct intel_digital_port *dig_port); bool intel_tc_port_ref_held(struct intel_digital_port *dig_port); -void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy); +int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy); +void intel_tc_port_cleanup(struct intel_digital_port *dig_port); bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port); diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 3b5ff84dc615..557ec5b62afa 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -35,8 +35,8 @@ #include <drm/drm_edid.h> #include "i915_drv.h" -#include "i915_reg.h" #include "i915_irq.h" +#include "i915_reg.h" #include "intel_connector.h" #include "intel_crtc.h" #include "intel_de.h" @@ -44,6 +44,7 @@ #include "intel_dpll.h" #include "intel_hotplug.h" #include "intel_tv.h" +#include "intel_tv_regs.h" enum tv_margin { TV_MARGIN_LEFT, TV_MARGIN_TOP, diff --git a/drivers/gpu/drm/i915/display/intel_tv_regs.h b/drivers/gpu/drm/i915/display/intel_tv_regs.h new file mode 100644 index 000000000000..ab25aeb3c423 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_tv_regs.h @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_TV_REGS_H__ +#define __INTEL_TV_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* TV port control */ +#define TV_CTL _MMIO(0x68000) +/* Enables the TV encoder */ +# define TV_ENC_ENABLE (1 << 31) +/* Sources the TV encoder input from pipe B instead of A. */ +# define TV_ENC_PIPE_SEL_SHIFT 30 +# define TV_ENC_PIPE_SEL_MASK (1 << 30) +# define TV_ENC_PIPE_SEL(pipe) ((pipe) << 30) +/* Outputs composite video (DAC A only) */ +# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) +/* Outputs SVideo video (DAC B/C) */ +# define TV_ENC_OUTPUT_SVIDEO (1 << 28) +/* Outputs Component video (DAC A/B/C) */ +# define TV_ENC_OUTPUT_COMPONENT (2 << 28) +/* Outputs Composite and SVideo (DAC A/B/C) */ +# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28) +# define TV_TRILEVEL_SYNC (1 << 21) +/* Enables slow sync generation (945GM only) */ +# define TV_SLOW_SYNC (1 << 20) +/* Selects 4x oversampling for 480i and 576p */ +# define TV_OVERSAMPLE_4X (0 << 18) +/* Selects 2x oversampling for 720p and 1080i */ +# define TV_OVERSAMPLE_2X (1 << 18) +/* Selects no oversampling for 1080p */ +# define TV_OVERSAMPLE_NONE (2 << 18) +/* Selects 8x oversampling */ +# define TV_OVERSAMPLE_8X (3 << 18) +# define TV_OVERSAMPLE_MASK (3 << 18) +/* Selects progressive mode rather than interlaced */ +# define TV_PROGRESSIVE (1 << 17) +/* Sets the colorburst to PAL mode. Required for non-M PAL modes. */ +# define TV_PAL_BURST (1 << 16) +/* Field for setting delay of Y compared to C */ +# define TV_YC_SKEW_MASK (7 << 12) +/* Enables a fix for 480p/576p standard definition modes on the 915GM only */ +# define TV_ENC_SDP_FIX (1 << 11) +/* + * Enables a fix for the 915GM only. + * + * Not sure what it does. + */ +# define TV_ENC_C0_FIX (1 << 10) +/* Bits that must be preserved by software */ +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) +# define TV_FUSE_STATE_MASK (3 << 4) +/* Read-only state that reports all features enabled */ +# define TV_FUSE_STATE_ENABLED (0 << 4) +/* Read-only state that reports that Macrovision is disabled in hardware*/ +# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) +/* Read-only state that reports that TV-out is disabled in hardware. */ +# define TV_FUSE_STATE_DISABLED (2 << 4) +/* Normal operation */ +# define TV_TEST_MODE_NORMAL (0 << 0) +/* Encoder test pattern 1 - combo pattern */ +# define TV_TEST_MODE_PATTERN_1 (1 << 0) +/* Encoder test pattern 2 - full screen vertical 75% color bars */ +# define TV_TEST_MODE_PATTERN_2 (2 << 0) +/* Encoder test pattern 3 - full screen horizontal 75% color bars */ +# define TV_TEST_MODE_PATTERN_3 (3 << 0) +/* Encoder test pattern 4 - random noise */ +# define TV_TEST_MODE_PATTERN_4 (4 << 0) +/* Encoder test pattern 5 - linear color ramps */ +# define TV_TEST_MODE_PATTERN_5 (5 << 0) +/* + * This test mode forces the DACs to 50% of full output. + * + * This is used for load detection in combination with TVDAC_SENSE_MASK + */ +# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) +# define TV_TEST_MODE_MASK (7 << 0) + +#define TV_DAC _MMIO(0x68004) +# define TV_DAC_SAVE 0x00ffff00 +/* + * Reports that DAC state change logic has reported change (RO). + * + * This gets cleared when TV_DAC_STATE_EN is cleared +*/ +# define TVDAC_STATE_CHG (1 << 31) +# define TVDAC_SENSE_MASK (7 << 28) +/* Reports that DAC A voltage is above the detect threshold */ +# define TVDAC_A_SENSE (1 << 30) +/* Reports that DAC B voltage is above the detect threshold */ +# define TVDAC_B_SENSE (1 << 29) +/* Reports that DAC C voltage is above the detect threshold */ +# define TVDAC_C_SENSE (1 << 28) +/* + * Enables DAC state detection logic, for load-based TV detection. + * + * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set + * to off, for load detection to work. + */ +# define TVDAC_STATE_CHG_EN (1 << 27) +/* Sets the DAC A sense value to high */ +# define TVDAC_A_SENSE_CTL (1 << 26) +/* Sets the DAC B sense value to high */ +# define TVDAC_B_SENSE_CTL (1 << 25) +/* Sets the DAC C sense value to high */ +# define TVDAC_C_SENSE_CTL (1 << 24) +/* Overrides the ENC_ENABLE and DAC voltage levels */ +# define DAC_CTL_OVERRIDE (1 << 7) +/* Sets the slew rate. Must be preserved in software */ +# define ENC_TVDAC_SLEW_FAST (1 << 6) +# define DAC_A_1_3_V (0 << 4) +# define DAC_A_1_1_V (1 << 4) +# define DAC_A_0_7_V (2 << 4) +# define DAC_A_MASK (3 << 4) +# define DAC_B_1_3_V (0 << 2) +# define DAC_B_1_1_V (1 << 2) +# define DAC_B_0_7_V (2 << 2) +# define DAC_B_MASK (3 << 2) +# define DAC_C_1_3_V (0 << 0) +# define DAC_C_1_1_V (1 << 0) +# define DAC_C_0_7_V (2 << 0) +# define DAC_C_MASK (3 << 0) + +/* + * CSC coefficients are stored in a floating point format with 9 bits of + * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, + * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with + * -1 (0x3) being the only legal negative value. + */ +#define TV_CSC_Y _MMIO(0x68010) +# define TV_RY_MASK 0x07ff0000 +# define TV_RY_SHIFT 16 +# define TV_GY_MASK 0x00000fff +# define TV_GY_SHIFT 0 + +#define TV_CSC_Y2 _MMIO(0x68014) +# define TV_BY_MASK 0x07ff0000 +# define TV_BY_SHIFT 16 +/* + * Y attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AY_MASK 0x000003ff +# define TV_AY_SHIFT 0 + +#define TV_CSC_U _MMIO(0x68018) +# define TV_RU_MASK 0x07ff0000 +# define TV_RU_SHIFT 16 +# define TV_GU_MASK 0x000007ff +# define TV_GU_SHIFT 0 + +#define TV_CSC_U2 _MMIO(0x6801c) +# define TV_BU_MASK 0x07ff0000 +# define TV_BU_SHIFT 16 +/* + * U attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AU_MASK 0x000003ff +# define TV_AU_SHIFT 0 + +#define TV_CSC_V _MMIO(0x68020) +# define TV_RV_MASK 0x0fff0000 +# define TV_RV_SHIFT 16 +# define TV_GV_MASK 0x000007ff +# define TV_GV_SHIFT 0 + +#define TV_CSC_V2 _MMIO(0x68024) +# define TV_BV_MASK 0x07ff0000 +# define TV_BV_SHIFT 16 +/* + * V attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AV_MASK 0x000007ff +# define TV_AV_SHIFT 0 + +#define TV_CLR_KNOBS _MMIO(0x68028) +/* 2s-complement brightness adjustment */ +# define TV_BRIGHTNESS_MASK 0xff000000 +# define TV_BRIGHTNESS_SHIFT 24 +/* Contrast adjustment, as a 2.6 unsigned floating point number */ +# define TV_CONTRAST_MASK 0x00ff0000 +# define TV_CONTRAST_SHIFT 16 +/* Saturation adjustment, as a 2.6 unsigned floating point number */ +# define TV_SATURATION_MASK 0x0000ff00 +# define TV_SATURATION_SHIFT 8 +/* Hue adjustment, as an integer phase angle in degrees */ +# define TV_HUE_MASK 0x000000ff +# define TV_HUE_SHIFT 0 + +#define TV_CLR_LEVEL _MMIO(0x6802c) +/* Controls the DAC level for black */ +# define TV_BLACK_LEVEL_MASK 0x01ff0000 +# define TV_BLACK_LEVEL_SHIFT 16 +/* Controls the DAC level for blanking */ +# define TV_BLANK_LEVEL_MASK 0x000001ff +# define TV_BLANK_LEVEL_SHIFT 0 + +#define TV_H_CTL_1 _MMIO(0x68030) +/* Number of pixels in the hsync. */ +# define TV_HSYNC_END_MASK 0x1fff0000 +# define TV_HSYNC_END_SHIFT 16 +/* Total number of pixels minus one in the line (display and blanking). */ +# define TV_HTOTAL_MASK 0x00001fff +# define TV_HTOTAL_SHIFT 0 + +#define TV_H_CTL_2 _MMIO(0x68034) +/* Enables the colorburst (needed for non-component color) */ +# define TV_BURST_ENA (1 << 31) +/* Offset of the colorburst from the start of hsync, in pixels minus one. */ +# define TV_HBURST_START_SHIFT 16 +# define TV_HBURST_START_MASK 0x1fff0000 +/* Length of the colorburst */ +# define TV_HBURST_LEN_SHIFT 0 +# define TV_HBURST_LEN_MASK 0x0001fff + +#define TV_H_CTL_3 _MMIO(0x68038) +/* End of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_END_SHIFT 16 +# define TV_HBLANK_END_MASK 0x1fff0000 +/* Start of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_START_SHIFT 0 +# define TV_HBLANK_START_MASK 0x0001fff + +#define TV_V_CTL_1 _MMIO(0x6803c) +/* XXX */ +# define TV_NBR_END_SHIFT 16 +# define TV_NBR_END_MASK 0x07ff0000 +/* XXX */ +# define TV_VI_END_F1_SHIFT 8 +# define TV_VI_END_F1_MASK 0x00003f00 +/* XXX */ +# define TV_VI_END_F2_SHIFT 0 +# define TV_VI_END_F2_MASK 0x0000003f + +#define TV_V_CTL_2 _MMIO(0x68040) +/* Length of vsync, in half lines */ +# define TV_VSYNC_LEN_MASK 0x07ff0000 +# define TV_VSYNC_LEN_SHIFT 16 +/* Offset of the start of vsync in field 1, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F1_MASK 0x00007f00 +# define TV_VSYNC_START_F1_SHIFT 8 +/* + * Offset of the start of vsync in field 2, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F2_MASK 0x0000007f +# define TV_VSYNC_START_F2_SHIFT 0 + +#define TV_V_CTL_3 _MMIO(0x68044) +/* Enables generation of the equalization signal */ +# define TV_EQUAL_ENA (1 << 31) +/* Length of vsync, in half lines */ +# define TV_VEQ_LEN_MASK 0x007f0000 +# define TV_VEQ_LEN_SHIFT 16 +/* Offset of the start of equalization in field 1, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F1_MASK 0x0007f00 +# define TV_VEQ_START_F1_SHIFT 8 +/* + * Offset of the start of equalization in field 2, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F2_MASK 0x000007f +# define TV_VEQ_START_F2_SHIFT 0 + +#define TV_V_CTL_4 _MMIO(0x68048) +/* + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F1_MASK 0x003f0000 +# define TV_VBURST_START_F1_SHIFT 16 +/* + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F1_MASK 0x000000ff +# define TV_VBURST_END_F1_SHIFT 0 + +#define TV_V_CTL_5 _MMIO(0x6804c) +/* + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F2_MASK 0x003f0000 +# define TV_VBURST_START_F2_SHIFT 16 +/* + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F2_MASK 0x000000ff +# define TV_VBURST_END_F2_SHIFT 0 + +#define TV_V_CTL_6 _MMIO(0x68050) +/* + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F3_MASK 0x003f0000 +# define TV_VBURST_START_F3_SHIFT 16 +/* + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F3_MASK 0x000000ff +# define TV_VBURST_END_F3_SHIFT 0 + +#define TV_V_CTL_7 _MMIO(0x68054) +/* + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F4_MASK 0x003f0000 +# define TV_VBURST_START_F4_SHIFT 16 +/* + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F4_MASK 0x000000ff +# define TV_VBURST_END_F4_SHIFT 0 + +#define TV_SC_CTL_1 _MMIO(0x68060) +/* Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA1_EN (1 << 31) +/* Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA2_EN (1 << 30) +/* Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA3_EN (1 << 29) +/* Sets the subcarrier DDA to reset frequency every other field */ +# define TV_SC_RESET_EVERY_2 (0 << 24) +/* Sets the subcarrier DDA to reset frequency every fourth field */ +# define TV_SC_RESET_EVERY_4 (1 << 24) +/* Sets the subcarrier DDA to reset frequency every eighth field */ +# define TV_SC_RESET_EVERY_8 (2 << 24) +/* Sets the subcarrier DDA to never reset the frequency */ +# define TV_SC_RESET_NEVER (3 << 24) +/* Sets the peak amplitude of the colorburst.*/ +# define TV_BURST_LEVEL_MASK 0x00ff0000 +# define TV_BURST_LEVEL_SHIFT 16 +/* Sets the increment of the first subcarrier phase generation DDA */ +# define TV_SCDDA1_INC_MASK 0x00000fff +# define TV_SCDDA1_INC_SHIFT 0 + +#define TV_SC_CTL_2 _MMIO(0x68064) +/* Sets the rollover for the second subcarrier phase generation DDA */ +# define TV_SCDDA2_SIZE_MASK 0x7fff0000 +# define TV_SCDDA2_SIZE_SHIFT 16 +/* Sets the increent of the second subcarrier phase generation DDA */ +# define TV_SCDDA2_INC_MASK 0x00007fff +# define TV_SCDDA2_INC_SHIFT 0 + +#define TV_SC_CTL_3 _MMIO(0x68068) +/* Sets the rollover for the third subcarrier phase generation DDA */ +# define TV_SCDDA3_SIZE_MASK 0x7fff0000 +# define TV_SCDDA3_SIZE_SHIFT 16 +/* Sets the increent of the third subcarrier phase generation DDA */ +# define TV_SCDDA3_INC_MASK 0x00007fff +# define TV_SCDDA3_INC_SHIFT 0 + +#define TV_WIN_POS _MMIO(0x68070) +/* X coordinate of the display from the start of horizontal active */ +# define TV_XPOS_MASK 0x1fff0000 +# define TV_XPOS_SHIFT 16 +/* Y coordinate of the display from the start of vertical active (NBR) */ +# define TV_YPOS_MASK 0x00000fff +# define TV_YPOS_SHIFT 0 + +#define TV_WIN_SIZE _MMIO(0x68074) +/* Horizontal size of the display window, measured in pixels*/ +# define TV_XSIZE_MASK 0x1fff0000 +# define TV_XSIZE_SHIFT 16 +/* + * Vertical size of the display window, measured in pixels. + * + * Must be even for interlaced modes. + */ +# define TV_YSIZE_MASK 0x00000fff +# define TV_YSIZE_SHIFT 0 + +#define TV_FILTER_CTL_1 _MMIO(0x68080) +/* + * Enables automatic scaling calculation. + * + * If set, the rest of the registers are ignored, and the calculated values can + * be read back from the register. + */ +# define TV_AUTO_SCALE (1 << 31) +/* + * Disables the vertical filter. + * + * This is required on modes more than 1024 pixels wide */ +# define TV_V_FILTER_BYPASS (1 << 29) +/* Enables adaptive vertical filtering */ +# define TV_VADAPT (1 << 28) +# define TV_VADAPT_MODE_MASK (3 << 26) +/* Selects the least adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_LEAST (0 << 26) +/* Selects the moderately adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MODERATE (1 << 26) +/* Selects the most adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MOST (3 << 26) +/* + * Sets the horizontal scaling factor. + * + * This should be the fractional part of the horizontal scaling factor divided + * by the oversampling rate. TV_HSCALE should be less than 1, and set to: + * + * (src width - 1) / ((oversample * dest width) - 1) + */ +# define TV_HSCALE_FRAC_MASK 0x00003fff +# define TV_HSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_2 _MMIO(0x68084) +/* + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) + */ +# define TV_VSCALE_INT_MASK 0x00038000 +# define TV_VSCALE_INT_SHIFT 15 +/* + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * \sa TV_VSCALE_INT_MASK + */ +# define TV_VSCALE_FRAC_MASK 0x00007fff +# define TV_VSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_3 _MMIO(0x68088) +/* + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + */ +# define TV_VSCALE_IP_INT_MASK 0x00038000 +# define TV_VSCALE_IP_INT_SHIFT 15 +/* + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + * + * \sa TV_VSCALE_IP_INT_MASK + */ +# define TV_VSCALE_IP_FRAC_MASK 0x00007fff +# define TV_VSCALE_IP_FRAC_SHIFT 0 + +#define TV_CC_CONTROL _MMIO(0x68090) +# define TV_CC_ENABLE (1 << 31) +/* + * Specifies which field to send the CC data in. + * + * CC data is usually sent in field 0. + */ +# define TV_CC_FID_MASK (1 << 27) +# define TV_CC_FID_SHIFT 27 +/* Sets the horizontal position of the CC data. Usually 135. */ +# define TV_CC_HOFF_MASK 0x03ff0000 +# define TV_CC_HOFF_SHIFT 16 +/* Sets the vertical position of the CC data. Usually 21 */ +# define TV_CC_LINE_MASK 0x0000003f +# define TV_CC_LINE_SHIFT 0 + +#define TV_CC_DATA _MMIO(0x68094) +# define TV_CC_RDY (1 << 31) +/* Second word of CC data to be transmitted. */ +# define TV_CC_DATA_2_MASK 0x007f0000 +# define TV_CC_DATA_2_SHIFT 16 +/* First word of CC data to be transmitted. */ +# define TV_CC_DATA_1_MASK 0x0000007f +# define TV_CC_DATA_1_SHIFT 0 + +#define TV_H_LUMA(i) _MMIO(0x68100 + (i) * 4) /* 60 registers */ +#define TV_H_CHROMA(i) _MMIO(0x68200 + (i) * 4) /* 60 registers */ +#define TV_V_LUMA(i) _MMIO(0x68300 + (i) * 4) /* 43 registers */ +#define TV_V_CHROMA(i) _MMIO(0x68400 + (i) * 4) /* 43 registers */ + +#endif /* __INTEL_TV_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 09b32ffdc552..8e787c13d26d 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -423,9 +423,9 @@ calculate_rc_params(struct rc_parameters *rc, for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) { /* Read range_minqp and range_max_qp from qp tables */ rc->rc_range_params[buf_i].range_min_qp = - intel_lookup_range_min_qp(bpc, buf_i, bpp_i); + intel_lookup_range_min_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420); rc->rc_range_params[buf_i].range_max_qp = - intel_lookup_range_max_qp(bpc, buf_i, bpp_i); + intel_lookup_range_max_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420); /* Calculate range_bgp_offset */ if (bpp <= 6) { @@ -448,6 +448,29 @@ calculate_rc_params(struct rc_parameters *rc, } } +static int intel_dsc_slice_dimensions_valid(struct intel_crtc_state *pipe_config, + struct drm_dsc_config *vdsc_cfg) +{ + if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_RGB || + pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) { + if (vdsc_cfg->slice_height > 4095) + return -EINVAL; + if (vdsc_cfg->slice_height * vdsc_cfg->slice_width < 15000) + return -EINVAL; + } else if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { + if (vdsc_cfg->slice_width % 2) + return -EINVAL; + if (vdsc_cfg->slice_height % 2) + return -EINVAL; + if (vdsc_cfg->slice_height > 4094) + return -EINVAL; + if (vdsc_cfg->slice_height * vdsc_cfg->slice_width < 30000) + return -EINVAL; + } + + return 0; +} + int intel_dsc_compute_params(struct intel_crtc_state *pipe_config) { struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); @@ -456,19 +479,64 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config) u16 compressed_bpp = pipe_config->dsc.compressed_bpp; const struct rc_parameters *rc_params; struct rc_parameters *rc = NULL; + int err; u8 i = 0; vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width, pipe_config->dsc.slice_count); - /* Gen 11 does not support YCbCr */ + err = intel_dsc_slice_dimensions_valid(pipe_config, vdsc_cfg); + + if (err) { + drm_dbg_kms(&dev_priv->drm, "Slice dimension requirements not met\n"); + return err; + } + + /* + * According to DSC 1.2 specs if colorspace is YCbCr then convert_rgb is 0 + * else 1 + */ + vdsc_cfg->convert_rgb = pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 && + pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR444; + + if (DISPLAY_VER(dev_priv) >= 14 && + pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) + vdsc_cfg->native_420 = true; + /* We do not support YcBCr422 as of now */ + vdsc_cfg->native_422 = false; vdsc_cfg->simple_422 = false; /* Gen 11 does not support VBR */ vdsc_cfg->vbr_enable = false; /* Gen 11 only supports integral values of bpp */ vdsc_cfg->bits_per_pixel = compressed_bpp << 4; + + /* + * According to DSC 1.2 specs in Section 4.1 if native_420 is set: + * -We need to double the current bpp. + * -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice + * height < 8. + * -second_line_offset_adj is 512 as shown by emperical values to yeild best chroma + * preservation in second line. + * -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded + * up to 16 fractional bits, we left shift second line offset by 11 to preserve 11 + * fractional bits. + */ + if (vdsc_cfg->native_420) { + vdsc_cfg->bits_per_pixel <<= 1; + + if (vdsc_cfg->slice_height >= 8) + vdsc_cfg->second_line_bpg_offset = 12; + else + vdsc_cfg->second_line_bpg_offset = + 2 * (vdsc_cfg->slice_height - 1); + + vdsc_cfg->second_line_offset_adj = 512; + vdsc_cfg->nsl_bpg_offset = DIV_ROUND_UP(vdsc_cfg->second_line_bpg_offset << 11, + vdsc_cfg->slice_height - 1); + } + vdsc_cfg->bits_per_component = pipe_config->pipe_bpp / 3; for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) { @@ -595,8 +663,13 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) DSC_VER_MIN_SHIFT | vdsc_cfg->bits_per_component << DSC_BPC_SHIFT | vdsc_cfg->line_buf_depth << DSC_LINE_BUF_DEPTH_SHIFT; - if (vdsc_cfg->dsc_version_minor == 2) + if (vdsc_cfg->dsc_version_minor == 2) { pps_val |= DSC_ALT_ICH_SEL; + if (vdsc_cfg->native_420) + pps_val |= DSC_NATIVE_420_ENABLE; + if (vdsc_cfg->native_422) + pps_val |= DSC_NATIVE_422_ENABLE; + } if (vdsc_cfg->block_pred_enable) pps_val |= DSC_BLOCK_PREDICTION; if (vdsc_cfg->convert_rgb) @@ -907,6 +980,33 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) pps_val); } + if (DISPLAY_VER(dev_priv) >= 14) { + /* Populate PICTURE_PARAMETER_SET_17 registers */ + pps_val = 0; + pps_val |= DSC_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset); + drm_dbg_kms(&dev_priv->drm, "PPS17 = 0x%08x\n", pps_val); + intel_de_write(dev_priv, + MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe), + pps_val); + if (crtc_state->dsc.dsc_split) + intel_de_write(dev_priv, + MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe), + pps_val); + + /* Populate PICTURE_PARAMETER_SET_18 registers */ + pps_val = 0; + pps_val |= DSC_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) | + DSC_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj); + drm_dbg_kms(&dev_priv->drm, "PPS18 = 0x%08x\n", pps_val); + intel_de_write(dev_priv, + MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe), + pps_val); + if (crtc_state->dsc.dsc_split) + intel_de_write(dev_priv, + MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe), + pps_val); + } + /* Populate the RC_BUF_THRESH registers */ memset(rc_buf_thresh_dword, 0, sizeof(rc_buf_thresh_dword)); for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) { @@ -1181,7 +1281,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; - u32 dss_ctl1, dss_ctl2, val; + u32 dss_ctl1, dss_ctl2, pps0 = 0, pps1 = 0; if (!intel_dsc_source_support(crtc_state)) return; @@ -1204,13 +1304,21 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) /* FIXME: add more state readout as needed */ - /* PPS1 */ - if (!is_pipe_dsc(crtc, cpu_transcoder)) - val = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1); - else - val = intel_de_read(dev_priv, - ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); - vdsc_cfg->bits_per_pixel = val; + /* PPS0 & PPS1 */ + if (!is_pipe_dsc(crtc, cpu_transcoder)) { + pps1 = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1); + } else { + pps0 = intel_de_read(dev_priv, + ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe)); + pps1 = intel_de_read(dev_priv, + ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); + } + + vdsc_cfg->bits_per_pixel = pps1; + + if (pps0 & DSC_NATIVE_420_ENABLE) + vdsc_cfg->bits_per_pixel >>= 1; + crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4; out: intel_display_power_put(dev_priv, power_domain, wakeref); diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index 4fd883463752..b71f00b5c761 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -46,6 +46,32 @@ _ICL_PIPE_DSS_CTL2_PB, \ _ICL_PIPE_DSS_CTL2_PC) +/* MTL Display Stream Compression registers */ +#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PB 0x782B4 +#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PB 0x783B4 +#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PC 0x784B4 +#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PC 0x785B4 +#define MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ + _MTL_DSC0_PICTURE_PARAMETER_SET_17_PB, \ + _MTL_DSC0_PICTURE_PARAMETER_SET_17_PC) +#define MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ + _MTL_DSC1_PICTURE_PARAMETER_SET_17_PB, \ + _MTL_DSC1_PICTURE_PARAMETER_SET_17_PC) +#define DSC_SL_BPG_OFFSET(offset) ((offset) << 27) + +#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PB 0x782B8 +#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PB 0x783B8 +#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PC 0x784B8 +#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PC 0x785B8 +#define MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ + _MTL_DSC0_PICTURE_PARAMETER_SET_18_PB, \ + _MTL_DSC0_PICTURE_PARAMETER_SET_18_PC) +#define MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ + _MTL_DSC1_PICTURE_PARAMETER_SET_18_PB, \ + _MTL_DSC1_PICTURE_PARAMETER_SET_18_PC) +#define DSC_NSL_BPG_OFFSET(offset) ((offset) << 16) +#define DSC_SL_OFFSET_ADJ(offset) ((offset) << 0) + /* Icelake Display Stream Compression Registers */ #define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200) #define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00) @@ -59,6 +85,8 @@ #define ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PC) +#define DSC_NATIVE_422_ENABLE BIT(23) +#define DSC_NATIVE_420_ENABLE BIT(22) #define DSC_ALT_ICH_SEL (1 << 20) #define DSC_VBR_ENABLE (1 << 19) #define DSC_422_ENABLE (1 << 18) diff --git a/drivers/gpu/drm/i915/display/intel_wm.c b/drivers/gpu/drm/i915/display/intel_wm.c index bb99179cd5fd..b615449e70b4 100644 --- a/drivers/gpu/drm/i915/display/intel_wm.c +++ b/drivers/gpu/drm/i915/display/intel_wm.c @@ -11,7 +11,7 @@ /** * intel_update_watermarks - update FIFO watermark values based on current modes - * @dev_priv: i915 device + * @i915: i915 device * * Calculate watermark values for the various WM regs based on current mode * and plane configuration. diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index fd0065a46ec5..8ea0598a5a07 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2475,6 +2475,12 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, goto error; } + if (!dev_priv->params.enable_dpt && + intel_fb_modifier_uses_dpt(dev_priv, fb->modifier)) { + drm_dbg_kms(&dev_priv->drm, "DPT disabled, skipping initial FB\n"); + goto error; + } + /* * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr * while i915 HW rotation is clockwise, thats why this swapping. diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 50a9a6adbe32..1c7e6468f3e3 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -21,6 +21,7 @@ #include "intel_pcode.h" #include "intel_wm.h" #include "skl_watermark.h" +#include "skl_watermark_regs.h" static void skl_sagv_disable(struct drm_i915_private *i915); @@ -411,6 +412,9 @@ static bool intel_crtc_can_enable_sagv(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 (!i915->params.enable_sagv) + return false; + if (DISPLAY_VER(i915) >= 12) return tgl_crtc_can_enable_sagv(crtc_state); else @@ -2273,12 +2277,10 @@ static int skl_wm_check_vblank(struct intel_crtc_state *crtc_state) return level; /* - * FIXME PSR needs to toggle LATENCY_REPORTING_REMOVED_PIPE_* + * PSR needs to toggle LATENCY_REPORTING_REMOVED_PIPE_* * based on whether we're limited by the vblank duration. - * - * FIXME also related to skl+ w/a 1136 (also unimplemented as of - * now) perhaps? */ + crtc_state->wm_level_disabled = level < i915->display.wm.num_levels - 1; for (level++; level < i915->display.wm.num_levels; level++) { enum plane_id plane_id; @@ -3696,6 +3698,7 @@ static int intel_sagv_status_show(struct seq_file *m, void *unused) }; seq_printf(m, "SAGV available: %s\n", str_yes_no(intel_has_sagv(i915))); + seq_printf(m, "SAGV modparam: %s\n", str_enabled_disabled(i915->params.enable_sagv)); seq_printf(m, "SAGV status: %s\n", sagv_status[i915->display.sagv.status]); seq_printf(m, "SAGV block time: %d usec\n", i915->display.sagv.block_time_us); diff --git a/drivers/gpu/drm/i915/display/skl_watermark_regs.h b/drivers/gpu/drm/i915/display/skl_watermark_regs.h new file mode 100644 index 000000000000..628c5920ad49 --- /dev/null +++ b/drivers/gpu/drm/i915/display/skl_watermark_regs.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __SKL_WATERMARK_REGS_H__ +#define __SKL_WATERMARK_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _PIPEA_MBUS_DBOX_CTL 0x7003C +#define _PIPEB_MBUS_DBOX_CTL 0x7103C +#define PIPE_MBUS_DBOX_CTL(pipe) _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \ + _PIPEB_MBUS_DBOX_CTL) +#define MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK REG_GENMASK(24, 20) /* tgl+ */ +#define MBUS_DBOX_B2B_TRANSACTIONS_MAX(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK, x) +#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK REG_GENMASK(19, 17) /* tgl+ */ +#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK, x) +#define MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN REG_BIT(16) /* tgl+ */ +#define MBUS_DBOX_BW_CREDIT_MASK REG_GENMASK(15, 14) +#define MBUS_DBOX_BW_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, x) +#define MBUS_DBOX_BW_4CREDITS_MTL REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x2) +#define MBUS_DBOX_BW_8CREDITS_MTL REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x3) +#define MBUS_DBOX_B_CREDIT_MASK REG_GENMASK(12, 8) +#define MBUS_DBOX_B_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_B_CREDIT_MASK, x) +#define MBUS_DBOX_I_CREDIT_MASK REG_GENMASK(7, 5) +#define MBUS_DBOX_I_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_I_CREDIT_MASK, x) +#define MBUS_DBOX_A_CREDIT_MASK REG_GENMASK(3, 0) +#define MBUS_DBOX_A_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_A_CREDIT_MASK, x) + +#define MBUS_UBOX_CTL _MMIO(0x4503C) +#define MBUS_BBOX_CTL_S1 _MMIO(0x45040) +#define MBUS_BBOX_CTL_S2 _MMIO(0x45044) + +#define MBUS_CTL _MMIO(0x4438C) +#define MBUS_JOIN REG_BIT(31) +#define MBUS_HASHING_MODE_MASK REG_BIT(30) +#define MBUS_HASHING_MODE_2x2 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 0) +#define MBUS_HASHING_MODE_1x4 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 1) +#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26) +#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe) +#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7) + +/* Watermark register definitions for SKL */ +#define _CUR_WM_A_0 0x70140 +#define _CUR_WM_B_0 0x71140 +#define _CUR_WM_SAGV_A 0x70158 +#define _CUR_WM_SAGV_B 0x71158 +#define _CUR_WM_SAGV_TRANS_A 0x7015C +#define _CUR_WM_SAGV_TRANS_B 0x7115C +#define _CUR_WM_TRANS_A 0x70168 +#define _CUR_WM_TRANS_B 0x71168 +#define _PLANE_WM_1_A_0 0x70240 +#define _PLANE_WM_1_B_0 0x71240 +#define _PLANE_WM_2_A_0 0x70340 +#define _PLANE_WM_2_B_0 0x71340 +#define _PLANE_WM_SAGV_1_A 0x70258 +#define _PLANE_WM_SAGV_1_B 0x71258 +#define _PLANE_WM_SAGV_2_A 0x70358 +#define _PLANE_WM_SAGV_2_B 0x71358 +#define _PLANE_WM_SAGV_TRANS_1_A 0x7025C +#define _PLANE_WM_SAGV_TRANS_1_B 0x7125C +#define _PLANE_WM_SAGV_TRANS_2_A 0x7035C +#define _PLANE_WM_SAGV_TRANS_2_B 0x7135C +#define _PLANE_WM_TRANS_1_A 0x70268 +#define _PLANE_WM_TRANS_1_B 0x71268 +#define _PLANE_WM_TRANS_2_A 0x70368 +#define _PLANE_WM_TRANS_2_B 0x71368 +#define PLANE_WM_EN (1 << 31) +#define PLANE_WM_IGNORE_LINES (1 << 30) +#define PLANE_WM_LINES_MASK REG_GENMASK(26, 14) +#define PLANE_WM_BLOCKS_MASK REG_GENMASK(11, 0) + +#define _CUR_WM_0(pipe) _PIPE(pipe, _CUR_WM_A_0, _CUR_WM_B_0) +#define CUR_WM(pipe, level) _MMIO(_CUR_WM_0(pipe) + ((4) * (level))) +#define CUR_WM_SAGV(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_A, _CUR_WM_SAGV_B) +#define CUR_WM_SAGV_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_TRANS_A, _CUR_WM_SAGV_TRANS_B) +#define CUR_WM_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_TRANS_A, _CUR_WM_TRANS_B) +#define _PLANE_WM_1(pipe) _PIPE(pipe, _PLANE_WM_1_A_0, _PLANE_WM_1_B_0) +#define _PLANE_WM_2(pipe) _PIPE(pipe, _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) +#define _PLANE_WM_BASE(pipe, plane) \ + _PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe)) +#define PLANE_WM(pipe, plane, level) \ + _MMIO(_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) +#define _PLANE_WM_SAGV_1(pipe) \ + _PIPE(pipe, _PLANE_WM_SAGV_1_A, _PLANE_WM_SAGV_1_B) +#define _PLANE_WM_SAGV_2(pipe) \ + _PIPE(pipe, _PLANE_WM_SAGV_2_A, _PLANE_WM_SAGV_2_B) +#define PLANE_WM_SAGV(pipe, plane) \ + _MMIO(_PLANE(plane, _PLANE_WM_SAGV_1(pipe), _PLANE_WM_SAGV_2(pipe))) +#define _PLANE_WM_SAGV_TRANS_1(pipe) \ + _PIPE(pipe, _PLANE_WM_SAGV_TRANS_1_A, _PLANE_WM_SAGV_TRANS_1_B) +#define _PLANE_WM_SAGV_TRANS_2(pipe) \ + _PIPE(pipe, _PLANE_WM_SAGV_TRANS_2_A, _PLANE_WM_SAGV_TRANS_2_B) +#define PLANE_WM_SAGV_TRANS(pipe, plane) \ + _MMIO(_PLANE(plane, _PLANE_WM_SAGV_TRANS_1(pipe), _PLANE_WM_SAGV_TRANS_2(pipe))) +#define _PLANE_WM_TRANS_1(pipe) \ + _PIPE(pipe, _PLANE_WM_TRANS_1_A, _PLANE_WM_TRANS_1_B) +#define _PLANE_WM_TRANS_2(pipe) \ + _PIPE(pipe, _PLANE_WM_TRANS_2_A, _PLANE_WM_TRANS_2_B) +#define PLANE_WM_TRANS(pipe, plane) \ + _MMIO(_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))) + +#define _PLANE_BUF_CFG_1_B 0x7127c +#define _PLANE_BUF_CFG_2_B 0x7137c +#define _PLANE_BUF_CFG_1(pipe) \ + _PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) +#define _PLANE_BUF_CFG_2(pipe) \ + _PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) +#define PLANE_BUF_CFG(pipe, plane) \ + _MMIO_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) + +#define _PLANE_NV12_BUF_CFG_1_B 0x71278 +#define _PLANE_NV12_BUF_CFG_2_B 0x71378 +#define _PLANE_NV12_BUF_CFG_1(pipe) \ + _PIPE(pipe, _PLANE_NV12_BUF_CFG_1_A, _PLANE_NV12_BUF_CFG_1_B) +#define _PLANE_NV12_BUF_CFG_2(pipe) \ + _PIPE(pipe, _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B) +#define PLANE_NV12_BUF_CFG(pipe, plane) \ + _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) + +/* SKL new cursor registers */ +#define _CUR_BUF_CFG_A 0x7017c +#define _CUR_BUF_CFG_B 0x7117c +#define CUR_BUF_CFG(pipe) _MMIO_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) + +/* + * The below are numbered starting from "S1" on gen11/gen12, but starting + * with display 13, the bspec switches to a 0-based numbering scheme + * (although the addresses stay the same so new S0 = old S1, new S1 = old S2). + * We'll just use the 0-based numbering here for all platforms since it's the + * way things will be named by the hardware team going forward, plus it's more + * consistent with how most of the rest of our registers are named. + */ +#define _DBUF_CTL_S0 0x45008 +#define _DBUF_CTL_S1 0x44FE8 +#define _DBUF_CTL_S2 0x44300 +#define _DBUF_CTL_S3 0x44304 +#define DBUF_CTL_S(slice) _MMIO(_PICK(slice, \ + _DBUF_CTL_S0, \ + _DBUF_CTL_S1, \ + _DBUF_CTL_S2, \ + _DBUF_CTL_S3)) +#define DBUF_POWER_REQUEST REG_BIT(31) +#define DBUF_POWER_STATE REG_BIT(30) +#define DBUF_TRACKER_STATE_SERVICE_MASK REG_GENMASK(23, 19) +#define DBUF_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_TRACKER_STATE_SERVICE_MASK, x) +#define DBUF_MIN_TRACKER_STATE_SERVICE_MASK REG_GENMASK(18, 16) /* ADL-P+ */ +#define DBUF_MIN_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_MIN_TRACKER_STATE_SERVICE_MASK, x) /* ADL-P+ */ + +#define MTL_LATENCY_LP0_LP1 _MMIO(0x45780) +#define MTL_LATENCY_LP2_LP3 _MMIO(0x45784) +#define MTL_LATENCY_LP4_LP5 _MMIO(0x45788) +#define MTL_LATENCY_LEVEL_EVEN_MASK REG_GENMASK(12, 0) +#define MTL_LATENCY_LEVEL_ODD_MASK REG_GENMASK(28, 16) + +#define MTL_LATENCY_SAGV _MMIO(0x4578c) +#define MTL_LATENCY_QCLK_SAGV REG_GENMASK(12, 0) + +#endif /* __SKL_WATERMARK_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index f9a8acbba715..885ccde9dc3c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -303,7 +303,7 @@ i915_gem_object_never_mmap(const struct drm_i915_gem_object *obj) static inline bool i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj) { - return READ_ONCE(obj->frontbuffer); + return READ_ONCE(obj->frontbuffer) || obj->is_dpt; } static inline unsigned int diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 19c9bdd8f905..5dcbbef31d44 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -491,6 +491,9 @@ struct drm_i915_gem_object { */ unsigned int cache_dirty:1; + /* @is_dpt: Object houses a display page table (DPT) */ + unsigned int is_dpt:1; + /** * @read_domains: Read memory domains. * diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index d8e06e783e30..8ac376c24aa2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -890,8 +890,9 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, if (HAS_LMEMBAR_SMEM_STOLEN(i915)) { /* * MTL dsm size is in GGC register. - * Also MTL uses offset to DSMBASE in ptes, so i915 - * uses dsm_base = 0 to setup stolen region. + * Also MTL uses offset to GSMBASE in ptes, so i915 + * uses dsm_base = 8MBs to setup stolen region, since + * DSMBASE = GSMBASE + 8MB. */ ret = mtl_get_gms_size(uncore); if (ret < 0) { @@ -899,11 +900,11 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, return ERR_PTR(ret); } - dsm_base = 0; + dsm_base = SZ_8M; dsm_size = (resource_size_t)(ret * SZ_1M); GEM_BUG_ON(pci_resource_len(pdev, GEN12_LMEM_BAR) != SZ_256M); - GEM_BUG_ON((dsm_size + SZ_8M) > lmem_size); + GEM_BUG_ON((dsm_base + dsm_size) > lmem_size); } else { /* Use DSM base address instead for stolen memory */ dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE) & GEN12_BDSM_MASK; @@ -912,14 +913,12 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, dsm_size = ALIGN_DOWN(lmem_size - dsm_base, SZ_1M); } - io_size = dsm_size; - if (HAS_LMEMBAR_SMEM_STOLEN(i915)) { - io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + SZ_8M; - } else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) { + if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) { io_start = 0; io_size = 0; } else { io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base; + io_size = dsm_size; } min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index 1b509c1a1e33..7c49a3d673a5 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -32,6 +32,7 @@ * */ +#include "display/intel_dp_aux_regs.h" #include "display/intel_gmbus_regs.h" #include "gvt.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 3c8e0d198c4f..4b45a041ac5c 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -43,8 +43,13 @@ #include "intel_mchbar_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" +#include "display/intel_dp_aux_regs.h" #include "display/intel_dpio_phy.h" #include "display/intel_fbc.h" +#include "display/intel_fdi_regs.h" +#include "display/intel_pps_regs.h" +#include "display/intel_psr_regs.h" +#include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 8dde3512d2d1..93fdc40d724f 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -79,11 +79,11 @@ #include "soc/intel_dram.h" #include "soc/intel_gmch.h" -#include "i915_file_private.h" #include "i915_debugfs.h" #include "i915_driver.h" #include "i915_drm_client.h" #include "i915_drv.h" +#include "i915_file_private.h" #include "i915_getparam.h" #include "i915_hwmon.h" #include "i915_ioc32.h" @@ -97,11 +97,11 @@ #include "i915_sysfs.h" #include "i915_utils.h" #include "i915_vgpu.h" +#include "intel_clock_gating.h" #include "intel_gvt.h" #include "intel_memory_region.h" #include "intel_pci_config.h" #include "intel_pcode.h" -#include "intel_pm.h" #include "intel_region_ttm.h" #include "vlv_suspend.h" @@ -252,7 +252,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) intel_irq_init(dev_priv); intel_init_display_hooks(dev_priv); - intel_init_clock_gating_hooks(dev_priv); + intel_clock_gating_hooks_init(dev_priv); intel_detect_preproduction_hw(dev_priv); @@ -1244,7 +1244,7 @@ static int i915_drm_resume(struct drm_device *dev) i915_gem_resume(dev_priv); intel_modeset_init_hw(dev_priv); - intel_init_clock_gating(dev_priv); + intel_clock_gating_init(dev_priv); intel_hpd_init(dev_priv); /* MST sideband requires HPD interrupts enabled */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d81c35407d25..e771fdc3099c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -813,6 +813,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_FBC(dev_priv) (RUNTIME_INFO(dev_priv)->fbc_mask != 0) #define HAS_CUR_FBC(dev_priv) (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) >= 7) +#define HAS_DPT(dev_priv) (DISPLAY_VER(dev_priv) >= 13) + #define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) #define HAS_DP_MST(dev_priv) (INTEL_INFO(dev_priv)->display.has_dp_mst) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ecb47f834217..0a78bdbd36b1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -58,7 +58,7 @@ #include "i915_file_private.h" #include "i915_trace.h" #include "i915_vgpu.h" -#include "intel_pm.h" +#include "intel_clock_gating.h" static int insert_mappable_node(struct i915_ggtt *ggtt, struct drm_mm_node *node, u32 size) @@ -1164,7 +1164,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) } /* - * Despite its name intel_init_clock_gating applies both display + * Despite its name intel_clock_gating_init applies both display * clock gating workarounds; GT mmio workarounds and the occasional * GT power context workaround. Worse, sometimes it includes a context * register workaround which we need to apply before we record the @@ -1172,7 +1172,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) * * FIXME: break up the workarounds and apply them at the right time! */ - intel_init_clock_gating(dev_priv); + intel_clock_gating_init(dev_priv); for_each_gt(gt, dev_priv, i) { ret = intel_gt_init(gt); @@ -1216,7 +1216,7 @@ err_unlock: /* Minimal basic recovery for KMS */ ret = i915_ggtt_enable_hw(dev_priv); i915_ggtt_resume(to_gt(dev_priv)->ggtt); - intel_init_clock_gating(dev_priv); + intel_clock_gating_init(dev_priv); } i915_gem_drain_freed_objects(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c index 596dd2c07010..8e7dccc8d3a0 100644 --- a/drivers/gpu/drm/i915/i915_hwmon.c +++ b/drivers/gpu/drm/i915/i915_hwmon.c @@ -349,6 +349,8 @@ hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan) } } +#define PL1_DISABLE 0 + /* * HW allows arbitrary PL1 limits to be set but silently clamps these values to * "typical but not guaranteed" min/max values in rg.pkg_power_sku. Follow the @@ -362,6 +364,14 @@ hwm_power_max_read(struct hwm_drvdata *ddat, long *val) intel_wakeref_t wakeref; u64 r, min, max; + /* Check if PL1 limit is disabled */ + with_intel_runtime_pm(ddat->uncore->rpm, wakeref) + r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); + if (!(r & PKG_PWR_LIM_1_EN)) { + *val = PL1_DISABLE; + return 0; + } + *val = hwm_field_read_and_scale(ddat, hwmon->rg.pkg_rapl_limit, PKG_PWR_LIM_1, @@ -385,8 +395,24 @@ static int hwm_power_max_write(struct hwm_drvdata *ddat, long val) { struct i915_hwmon *hwmon = ddat->hwmon; + intel_wakeref_t wakeref; u32 nval; + /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */ + if (val == PL1_DISABLE) { + mutex_lock(&hwmon->hwmon_lock); + with_intel_runtime_pm(ddat->uncore->rpm, wakeref) { + intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, + PKG_PWR_LIM_1_EN, 0); + nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); + } + mutex_unlock(&hwmon->hwmon_lock); + + if (nval & PKG_PWR_LIM_1_EN) + return -ENODEV; + return 0; + } + /* Computation in 64-bits to avoid overflow. Round to nearest. */ nval = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_power, SF_POWER); nval = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, nval); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 31271c30a8cf..d24bdea65a3d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -37,10 +37,12 @@ #include "display/intel_de.h" #include "display/intel_display_trace.h" #include "display/intel_display_types.h" +#include "display/intel_fdi_regs.h" #include "display/intel_fifo_underrun.h" #include "display/intel_hotplug.h" #include "display/intel_lpe_audio.h" #include "display/intel_psr.h" +#include "display/intel_psr_regs.h" #include "gt/intel_breadcrumbs.h" #include "gt/intel_gt.h" diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index ade744cccfea..0a171b57fd8f 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -121,6 +121,9 @@ i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, "(0=disabled, 1=enabled) " "Default: 0"); +i915_param_named_unsafe(enable_sagv, bool, 0600, + "Enable system agent voltage/frequency scaling (SAGV) (default: true)"); + i915_param_named_unsafe(force_probe, charp, 0400, "Force probe options for specified supported devices. " "See CONFIG_DRM_I915_FORCE_PROBE for details."); @@ -131,6 +134,9 @@ i915_param_named_unsafe(disable_power_well, int, 0400, i915_param_named_unsafe(enable_ips, int, 0400, "Enable IPS (default: true)"); +i915_param_named_unsafe(enable_dpt, bool, 0400, + "Enable display page table (DPT) (default: true)"); + i915_param_named(fastboot, int, 0400, "Try to skip unnecessary mode sets at boot time " "(0=disabled, 1=enabled) " diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 3f51f90145b6..68abf0ad6c00 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -54,8 +54,10 @@ struct drm_printer; param(int, enable_dc, -1, 0400) \ param(int, enable_fbc, -1, 0600) \ param(int, enable_psr, -1, 0600) \ + param(bool, enable_dpt, true, 0400) \ param(bool, psr_safest_params, false, 0400) \ param(bool, enable_psr2_sel_fetch, true, 0400) \ + param(bool, enable_sagv, true, 0600) \ param(int, disable_power_well, -1, 0400) \ param(int, enable_ips, 1, 0600) \ param(int, invert_brightness, 0, 0600) \ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 621730b6551c..cddb6e197972 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -896,7 +896,6 @@ static const struct intel_device_info jsl_info = { static const struct intel_device_info tgl_info = { GEN12_FEATURES, PLATFORM(INTEL_TIGERLAKE), - .display.has_modular_fia = 1, .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), }; @@ -996,7 +995,6 @@ static const struct intel_device_info adl_p_info = { BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), .display.has_cdclk_crawl = 1, - .display.has_modular_fia = 1, .display.has_psr_hw_tracking = 0, .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), @@ -1144,7 +1142,6 @@ static const struct intel_device_info mtl_info = { .__runtime.graphics.ip.rel = 70, .__runtime.media.ip.ver = 13, PLATFORM(INTEL_METEORLAKE), - .display.has_modular_fia = 1, .extra_gt_list = xelpmp_extra_gt, .has_flat_ccs = 0, .has_gmd_id = 1, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8dac20b0e7a7..736a8dcf777b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1067,39 +1067,6 @@ #define MBUS_ABOX_BT_CREDIT_POOL1_MASK (0x1F << 0) #define MBUS_ABOX_BT_CREDIT_POOL1(x) ((x) << 0) -#define _PIPEA_MBUS_DBOX_CTL 0x7003C -#define _PIPEB_MBUS_DBOX_CTL 0x7103C -#define PIPE_MBUS_DBOX_CTL(pipe) _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \ - _PIPEB_MBUS_DBOX_CTL) -#define MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK REG_GENMASK(24, 20) /* tgl+ */ -#define MBUS_DBOX_B2B_TRANSACTIONS_MAX(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK, x) -#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK REG_GENMASK(19, 17) /* tgl+ */ -#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK, x) -#define MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN REG_BIT(16) /* tgl+ */ -#define MBUS_DBOX_BW_CREDIT_MASK REG_GENMASK(15, 14) -#define MBUS_DBOX_BW_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, x) -#define MBUS_DBOX_BW_4CREDITS_MTL REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x2) -#define MBUS_DBOX_BW_8CREDITS_MTL REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, 0x3) -#define MBUS_DBOX_B_CREDIT_MASK REG_GENMASK(12, 8) -#define MBUS_DBOX_B_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_B_CREDIT_MASK, x) -#define MBUS_DBOX_I_CREDIT_MASK REG_GENMASK(7, 5) -#define MBUS_DBOX_I_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_I_CREDIT_MASK, x) -#define MBUS_DBOX_A_CREDIT_MASK REG_GENMASK(3, 0) -#define MBUS_DBOX_A_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_A_CREDIT_MASK, x) - -#define MBUS_UBOX_CTL _MMIO(0x4503C) -#define MBUS_BBOX_CTL_S1 _MMIO(0x45040) -#define MBUS_BBOX_CTL_S2 _MMIO(0x45044) - -#define MBUS_CTL _MMIO(0x4438C) -#define MBUS_JOIN REG_BIT(31) -#define MBUS_HASHING_MODE_MASK REG_BIT(30) -#define MBUS_HASHING_MODE_2x2 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 0) -#define MBUS_HASHING_MODE_1x4 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 1) -#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26) -#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe) -#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7) - /* Make render/texture TLB fetches lower priorty than associated data * fetches. This is not turned on by default */ @@ -1407,7 +1374,8 @@ #define IVB_FBC_RT_BASE_UPPER _MMIO(0x7024) #define IPS_CTL _MMIO(0x43408) -#define IPS_ENABLE (1 << 31) +#define IPS_ENABLE REG_BIT(31) +#define IPS_FALSE_COLOR REG_BIT(4) #define MSG_FBC_REND_STATE(fbc_id) _MMIO_PIPE((fbc_id), 0x50380, 0x50384) #define FBC_REND_NUKE REG_BIT(2) @@ -2013,11 +1981,6 @@ #define PIPESRC(pipe) _MMIO_TRANS2((pipe), _PIPEASRC) #define TRANS_MULT(trans) _MMIO_TRANS2((trans), _TRANS_MULT_A) -#define TRANS_EXITLINE(trans) _MMIO_TRANS2((trans), _TRANS_EXITLINE_A) -#define EXITLINE_ENABLE REG_BIT(31) -#define EXITLINE_MASK REG_GENMASK(12, 0) -#define EXITLINE_SHIFT 0 - /* VRR registers */ #define _TRANS_VRR_CTL_A 0x60420 #define _TRANS_VRR_CTL_B 0x61420 @@ -2111,205 +2074,6 @@ #define TRANS_PUSH_EN REG_BIT(31) #define TRANS_PUSH_SEND REG_BIT(30) -/* - * HSW+ eDP PSR registers - * - * HSW PSR registers are relative to DDIA(_DDI_BUF_CTL_A + 0x800) with just one - * instance of it - */ -#define _SRD_CTL_A 0x60800 -#define _SRD_CTL_EDP 0x6f800 -#define EDP_PSR_CTL(tran) _MMIO_TRANS2(tran, _SRD_CTL_A) -#define EDP_PSR_ENABLE (1 << 31) -#define BDW_PSR_SINGLE_FRAME (1 << 30) -#define EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK (1 << 29) /* SW can't modify */ -#define EDP_PSR_LINK_STANDBY (1 << 27) -#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3 << 25) -#define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES (0 << 25) -#define EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES (1 << 25) -#define EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES (2 << 25) -#define EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES (3 << 25) -#define EDP_PSR_MAX_SLEEP_TIME_SHIFT 20 -#define EDP_PSR_SKIP_AUX_EXIT (1 << 12) -#define EDP_PSR_TP1_TP2_SEL (0 << 11) -#define EDP_PSR_TP1_TP3_SEL (1 << 11) -#define EDP_PSR_CRC_ENABLE (1 << 10) /* BDW+ */ -#define EDP_PSR_TP2_TP3_TIME_500us (0 << 8) -#define EDP_PSR_TP2_TP3_TIME_100us (1 << 8) -#define EDP_PSR_TP2_TP3_TIME_2500us (2 << 8) -#define EDP_PSR_TP2_TP3_TIME_0us (3 << 8) -#define EDP_PSR_TP4_TIME_0US (3 << 6) /* ICL+ */ -#define EDP_PSR_TP1_TIME_500us (0 << 4) -#define EDP_PSR_TP1_TIME_100us (1 << 4) -#define EDP_PSR_TP1_TIME_2500us (2 << 4) -#define EDP_PSR_TP1_TIME_0us (3 << 4) -#define EDP_PSR_IDLE_FRAME_SHIFT 0 - -/* - * Until TGL, IMR/IIR are fixed at 0x648xx. On TGL+ those registers are relative - * to transcoder and bits defined for each one as if using no shift (i.e. as if - * it was for TRANSCODER_EDP) - */ -#define EDP_PSR_IMR _MMIO(0x64834) -#define EDP_PSR_IIR _MMIO(0x64838) -#define _PSR_IMR_A 0x60814 -#define _PSR_IIR_A 0x60818 -#define TRANS_PSR_IMR(tran) _MMIO_TRANS2(tran, _PSR_IMR_A) -#define TRANS_PSR_IIR(tran) _MMIO_TRANS2(tran, _PSR_IIR_A) -#define _EDP_PSR_TRANS_SHIFT(trans) ((trans) == TRANSCODER_EDP ? \ - 0 : ((trans) - TRANSCODER_A + 1) * 8) -#define TGL_PSR_MASK REG_GENMASK(2, 0) -#define TGL_PSR_ERROR REG_BIT(2) -#define TGL_PSR_POST_EXIT REG_BIT(1) -#define TGL_PSR_PRE_ENTRY REG_BIT(0) -#define EDP_PSR_MASK(trans) (TGL_PSR_MASK << \ - _EDP_PSR_TRANS_SHIFT(trans)) -#define EDP_PSR_ERROR(trans) (TGL_PSR_ERROR << \ - _EDP_PSR_TRANS_SHIFT(trans)) -#define EDP_PSR_POST_EXIT(trans) (TGL_PSR_POST_EXIT << \ - _EDP_PSR_TRANS_SHIFT(trans)) -#define EDP_PSR_PRE_ENTRY(trans) (TGL_PSR_PRE_ENTRY << \ - _EDP_PSR_TRANS_SHIFT(trans)) - -#define _SRD_AUX_DATA_A 0x60814 -#define _SRD_AUX_DATA_EDP 0x6f814 -#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) + 4) /* 5 registers */ - -#define _SRD_STATUS_A 0x60840 -#define _SRD_STATUS_EDP 0x6f840 -#define EDP_PSR_STATUS(tran) _MMIO_TRANS2(tran, _SRD_STATUS_A) -#define EDP_PSR_STATUS_STATE_MASK (7 << 29) -#define EDP_PSR_STATUS_STATE_SHIFT 29 -#define EDP_PSR_STATUS_STATE_IDLE (0 << 29) -#define EDP_PSR_STATUS_STATE_SRDONACK (1 << 29) -#define EDP_PSR_STATUS_STATE_SRDENT (2 << 29) -#define EDP_PSR_STATUS_STATE_BUFOFF (3 << 29) -#define EDP_PSR_STATUS_STATE_BUFON (4 << 29) -#define EDP_PSR_STATUS_STATE_AUXACK (5 << 29) -#define EDP_PSR_STATUS_STATE_SRDOFFACK (6 << 29) -#define EDP_PSR_STATUS_LINK_MASK (3 << 26) -#define EDP_PSR_STATUS_LINK_FULL_OFF (0 << 26) -#define EDP_PSR_STATUS_LINK_FULL_ON (1 << 26) -#define EDP_PSR_STATUS_LINK_STANDBY (2 << 26) -#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 20 -#define EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK 0x1f -#define EDP_PSR_STATUS_COUNT_SHIFT 16 -#define EDP_PSR_STATUS_COUNT_MASK 0xf -#define EDP_PSR_STATUS_AUX_ERROR (1 << 15) -#define EDP_PSR_STATUS_AUX_SENDING (1 << 12) -#define EDP_PSR_STATUS_SENDING_IDLE (1 << 9) -#define EDP_PSR_STATUS_SENDING_TP2_TP3 (1 << 8) -#define EDP_PSR_STATUS_SENDING_TP1 (1 << 4) -#define EDP_PSR_STATUS_IDLE_MASK 0xf - -#define _SRD_PERF_CNT_A 0x60844 -#define _SRD_PERF_CNT_EDP 0x6f844 -#define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(tran, _SRD_PERF_CNT_A) -#define EDP_PSR_PERF_CNT_MASK 0xffffff - -/* PSR_MASK on SKL+ */ -#define _SRD_DEBUG_A 0x60860 -#define _SRD_DEBUG_EDP 0x6f860 -#define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(tran, _SRD_DEBUG_A) -#define EDP_PSR_DEBUG_MASK_MAX_SLEEP (1 << 28) -#define EDP_PSR_DEBUG_MASK_LPSP (1 << 27) -#define EDP_PSR_DEBUG_MASK_MEMUP (1 << 26) -#define EDP_PSR_DEBUG_MASK_HPD (1 << 25) -#define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE (1 << 16) /* Reserved in ICL+ */ -#define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1 << 15) /* SKL+ */ - -#define _PSR2_CTL_A 0x60900 -#define _PSR2_CTL_EDP 0x6f900 -#define EDP_PSR2_CTL(tran) _MMIO_TRANS2(tran, _PSR2_CTL_A) -#define EDP_PSR2_ENABLE (1 << 31) -#define EDP_SU_TRACK_ENABLE (1 << 30) /* up to adl-p */ -#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_2 (0 << 28) -#define TGL_EDP_PSR2_BLOCK_COUNT_NUM_3 (1 << 28) -#define EDP_Y_COORDINATE_ENABLE REG_BIT(25) /* display 10, 11 and 12 */ -#define EDP_PSR2_SU_SDP_SCANLINE REG_BIT(25) /* display 13+ */ -#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << 20) -#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f << 20) -#define EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES 8 -#define EDP_PSR2_IO_BUFFER_WAKE(lines) ((EDP_PSR2_IO_BUFFER_WAKE_MAX_LINES - (lines)) << 13) -#define EDP_PSR2_IO_BUFFER_WAKE_MASK (3 << 13) -#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES 5 -#define TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT 13 -#define TGL_EDP_PSR2_IO_BUFFER_WAKE(lines) (((lines) - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES) << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT) -#define TGL_EDP_PSR2_IO_BUFFER_WAKE_MASK (7 << 13) -#define EDP_PSR2_FAST_WAKE_MAX_LINES 8 -#define EDP_PSR2_FAST_WAKE(lines) ((EDP_PSR2_FAST_WAKE_MAX_LINES - (lines)) << 11) -#define EDP_PSR2_FAST_WAKE_MASK (3 << 11) -#define TGL_EDP_PSR2_FAST_WAKE_MIN_LINES 5 -#define TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT 10 -#define TGL_EDP_PSR2_FAST_WAKE(lines) (((lines) - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES) << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT) -#define TGL_EDP_PSR2_FAST_WAKE_MASK (7 << 10) -#define EDP_PSR2_TP2_TIME_500us (0 << 8) -#define EDP_PSR2_TP2_TIME_100us (1 << 8) -#define EDP_PSR2_TP2_TIME_2500us (2 << 8) -#define EDP_PSR2_TP2_TIME_50us (3 << 8) -#define EDP_PSR2_TP2_TIME_MASK (3 << 8) -#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 -#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf << 4) -#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a) << 4) -#define EDP_PSR2_IDLE_FRAME_MASK 0xf -#define EDP_PSR2_IDLE_FRAME_SHIFT 0 - -#define _PSR_EVENT_TRANS_A 0x60848 -#define _PSR_EVENT_TRANS_B 0x61848 -#define _PSR_EVENT_TRANS_C 0x62848 -#define _PSR_EVENT_TRANS_D 0x63848 -#define _PSR_EVENT_TRANS_EDP 0x6f848 -#define PSR_EVENT(tran) _MMIO_TRANS2(tran, _PSR_EVENT_TRANS_A) -#define PSR_EVENT_PSR2_WD_TIMER_EXPIRE (1 << 17) -#define PSR_EVENT_PSR2_DISABLED (1 << 16) -#define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN (1 << 15) -#define PSR_EVENT_SU_CRC_FIFO_UNDERRUN (1 << 14) -#define PSR_EVENT_GRAPHICS_RESET (1 << 12) -#define PSR_EVENT_PCH_INTERRUPT (1 << 11) -#define PSR_EVENT_MEMORY_UP (1 << 10) -#define PSR_EVENT_FRONT_BUFFER_MODIFY (1 << 9) -#define PSR_EVENT_WD_TIMER_EXPIRE (1 << 8) -#define PSR_EVENT_PIPE_REGISTERS_UPDATE (1 << 6) -#define PSR_EVENT_REGISTER_UPDATE (1 << 5) /* Reserved in ICL+ */ -#define PSR_EVENT_HDCP_ENABLE (1 << 4) -#define PSR_EVENT_KVMR_SESSION_ENABLE (1 << 3) -#define PSR_EVENT_VBI_ENABLE (1 << 2) -#define PSR_EVENT_LPSP_MODE_EXIT (1 << 1) -#define PSR_EVENT_PSR_DISABLE (1 << 0) - -#define _PSR2_STATUS_A 0x60940 -#define _PSR2_STATUS_EDP 0x6f940 -#define EDP_PSR2_STATUS(tran) _MMIO_TRANS2(tran, _PSR2_STATUS_A) -#define EDP_PSR2_STATUS_STATE_MASK REG_GENMASK(31, 28) -#define EDP_PSR2_STATUS_STATE_DEEP_SLEEP REG_FIELD_PREP(EDP_PSR2_STATUS_STATE_MASK, 0x8) - -#define _PSR2_SU_STATUS_A 0x60914 -#define _PSR2_SU_STATUS_EDP 0x6f914 -#define _PSR2_SU_STATUS(tran, index) _MMIO_TRANS2(tran, _PSR2_SU_STATUS_A + (index) * 4) -#define PSR2_SU_STATUS(tran, frame) (_PSR2_SU_STATUS(tran, (frame) / 3)) -#define PSR2_SU_STATUS_SHIFT(frame) (((frame) % 3) * 10) -#define PSR2_SU_STATUS_MASK(frame) (0x3ff << PSR2_SU_STATUS_SHIFT(frame)) -#define PSR2_SU_STATUS_FRAMES 8 - -#define _PSR2_MAN_TRK_CTL_A 0x60910 -#define _PSR2_MAN_TRK_CTL_EDP 0x6f910 -#define PSR2_MAN_TRK_CTL(tran) _MMIO_TRANS2(tran, _PSR2_MAN_TRK_CTL_A) -#define PSR2_MAN_TRK_CTL_ENABLE REG_BIT(31) -#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(30, 21) -#define PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) -#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(20, 11) -#define PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) -#define PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(3) -#define PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(2) -#define PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(1) -#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK REG_GENMASK(28, 16) -#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) -#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0) -#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) -#define ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31) -#define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14) -#define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13) - /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA _MMIO(0xe1100) @@ -2566,73 +2330,6 @@ #define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) -/* Panel power sequencing */ -#define PPS_BASE 0x61200 -#define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) -#define PCH_PPS_BASE 0xC7200 - -#define _MMIO_PPS(pps_idx, reg) _MMIO(dev_priv->display.pps.mmio_base - \ - PPS_BASE + (reg) + \ - (pps_idx) * 0x100) - -#define _PP_STATUS 0x61200 -#define PP_STATUS(pps_idx) _MMIO_PPS(pps_idx, _PP_STATUS) -#define PP_ON REG_BIT(31) -/* - * Indicates that all dependencies of the panel are on: - * - * - PLL enabled - * - pipe enabled - * - LVDS/DVOB/DVOC on - */ -#define PP_READY REG_BIT(30) -#define PP_SEQUENCE_MASK REG_GENMASK(29, 28) -#define PP_SEQUENCE_NONE REG_FIELD_PREP(PP_SEQUENCE_MASK, 0) -#define PP_SEQUENCE_POWER_UP REG_FIELD_PREP(PP_SEQUENCE_MASK, 1) -#define PP_SEQUENCE_POWER_DOWN REG_FIELD_PREP(PP_SEQUENCE_MASK, 2) -#define PP_CYCLE_DELAY_ACTIVE REG_BIT(27) -#define PP_SEQUENCE_STATE_MASK REG_GENMASK(3, 0) -#define PP_SEQUENCE_STATE_OFF_IDLE REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x0) -#define PP_SEQUENCE_STATE_OFF_S0_1 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x1) -#define PP_SEQUENCE_STATE_OFF_S0_2 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x2) -#define PP_SEQUENCE_STATE_OFF_S0_3 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x3) -#define PP_SEQUENCE_STATE_ON_IDLE REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x8) -#define PP_SEQUENCE_STATE_ON_S1_1 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0x9) -#define PP_SEQUENCE_STATE_ON_S1_2 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xa) -#define PP_SEQUENCE_STATE_ON_S1_3 REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xb) -#define PP_SEQUENCE_STATE_RESET REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xf) - -#define _PP_CONTROL 0x61204 -#define PP_CONTROL(pps_idx) _MMIO_PPS(pps_idx, _PP_CONTROL) -#define PANEL_UNLOCK_MASK REG_GENMASK(31, 16) -#define PANEL_UNLOCK_REGS REG_FIELD_PREP(PANEL_UNLOCK_MASK, 0xabcd) -#define BXT_POWER_CYCLE_DELAY_MASK REG_GENMASK(8, 4) -#define EDP_FORCE_VDD REG_BIT(3) -#define EDP_BLC_ENABLE REG_BIT(2) -#define PANEL_POWER_RESET REG_BIT(1) -#define PANEL_POWER_ON REG_BIT(0) - -#define _PP_ON_DELAYS 0x61208 -#define PP_ON_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_ON_DELAYS) -#define PANEL_PORT_SELECT_MASK REG_GENMASK(31, 30) -#define PANEL_PORT_SELECT_LVDS REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 0) -#define PANEL_PORT_SELECT_DPA REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 1) -#define PANEL_PORT_SELECT_DPC REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 2) -#define PANEL_PORT_SELECT_DPD REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 3) -#define PANEL_PORT_SELECT_VLV(port) REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, port) -#define PANEL_POWER_UP_DELAY_MASK REG_GENMASK(28, 16) -#define PANEL_LIGHT_ON_DELAY_MASK REG_GENMASK(12, 0) - -#define _PP_OFF_DELAYS 0x6120C -#define PP_OFF_DELAYS(pps_idx) _MMIO_PPS(pps_idx, _PP_OFF_DELAYS) -#define PANEL_POWER_DOWN_DELAY_MASK REG_GENMASK(28, 16) -#define PANEL_LIGHT_OFF_DELAY_MASK REG_GENMASK(12, 0) - -#define _PP_DIVISOR 0x61210 -#define PP_DIVISOR(pps_idx) _MMIO_PPS(pps_idx, _PP_DIVISOR) -#define PP_REFERENCE_DIVIDER_MASK REG_GENMASK(31, 8) -#define PANEL_POWER_CYCLE_DELAY_MASK REG_GENMASK(4, 0) - /* Panel fitting */ #define PFIT_CONTROL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230) #define PFIT_ENABLE (1 << 31) @@ -2670,485 +2367,6 @@ #define PCH_GTC_CTL _MMIO(0xe7000) #define PCH_GTC_ENABLE (1 << 31) -/* TV port control */ -#define TV_CTL _MMIO(0x68000) -/* Enables the TV encoder */ -# define TV_ENC_ENABLE (1 << 31) -/* Sources the TV encoder input from pipe B instead of A. */ -# define TV_ENC_PIPE_SEL_SHIFT 30 -# define TV_ENC_PIPE_SEL_MASK (1 << 30) -# define TV_ENC_PIPE_SEL(pipe) ((pipe) << 30) -/* Outputs composite video (DAC A only) */ -# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) -/* Outputs SVideo video (DAC B/C) */ -# define TV_ENC_OUTPUT_SVIDEO (1 << 28) -/* Outputs Component video (DAC A/B/C) */ -# define TV_ENC_OUTPUT_COMPONENT (2 << 28) -/* Outputs Composite and SVideo (DAC A/B/C) */ -# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28) -# define TV_TRILEVEL_SYNC (1 << 21) -/* Enables slow sync generation (945GM only) */ -# define TV_SLOW_SYNC (1 << 20) -/* Selects 4x oversampling for 480i and 576p */ -# define TV_OVERSAMPLE_4X (0 << 18) -/* Selects 2x oversampling for 720p and 1080i */ -# define TV_OVERSAMPLE_2X (1 << 18) -/* Selects no oversampling for 1080p */ -# define TV_OVERSAMPLE_NONE (2 << 18) -/* Selects 8x oversampling */ -# define TV_OVERSAMPLE_8X (3 << 18) -# define TV_OVERSAMPLE_MASK (3 << 18) -/* Selects progressive mode rather than interlaced */ -# define TV_PROGRESSIVE (1 << 17) -/* Sets the colorburst to PAL mode. Required for non-M PAL modes. */ -# define TV_PAL_BURST (1 << 16) -/* Field for setting delay of Y compared to C */ -# define TV_YC_SKEW_MASK (7 << 12) -/* Enables a fix for 480p/576p standard definition modes on the 915GM only */ -# define TV_ENC_SDP_FIX (1 << 11) -/* - * Enables a fix for the 915GM only. - * - * Not sure what it does. - */ -# define TV_ENC_C0_FIX (1 << 10) -/* Bits that must be preserved by software */ -# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) -# define TV_FUSE_STATE_MASK (3 << 4) -/* Read-only state that reports all features enabled */ -# define TV_FUSE_STATE_ENABLED (0 << 4) -/* Read-only state that reports that Macrovision is disabled in hardware*/ -# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) -/* Read-only state that reports that TV-out is disabled in hardware. */ -# define TV_FUSE_STATE_DISABLED (2 << 4) -/* Normal operation */ -# define TV_TEST_MODE_NORMAL (0 << 0) -/* Encoder test pattern 1 - combo pattern */ -# define TV_TEST_MODE_PATTERN_1 (1 << 0) -/* Encoder test pattern 2 - full screen vertical 75% color bars */ -# define TV_TEST_MODE_PATTERN_2 (2 << 0) -/* Encoder test pattern 3 - full screen horizontal 75% color bars */ -# define TV_TEST_MODE_PATTERN_3 (3 << 0) -/* Encoder test pattern 4 - random noise */ -# define TV_TEST_MODE_PATTERN_4 (4 << 0) -/* Encoder test pattern 5 - linear color ramps */ -# define TV_TEST_MODE_PATTERN_5 (5 << 0) -/* - * This test mode forces the DACs to 50% of full output. - * - * This is used for load detection in combination with TVDAC_SENSE_MASK - */ -# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) -# define TV_TEST_MODE_MASK (7 << 0) - -#define TV_DAC _MMIO(0x68004) -# define TV_DAC_SAVE 0x00ffff00 -/* - * Reports that DAC state change logic has reported change (RO). - * - * This gets cleared when TV_DAC_STATE_EN is cleared -*/ -# define TVDAC_STATE_CHG (1 << 31) -# define TVDAC_SENSE_MASK (7 << 28) -/* Reports that DAC A voltage is above the detect threshold */ -# define TVDAC_A_SENSE (1 << 30) -/* Reports that DAC B voltage is above the detect threshold */ -# define TVDAC_B_SENSE (1 << 29) -/* Reports that DAC C voltage is above the detect threshold */ -# define TVDAC_C_SENSE (1 << 28) -/* - * Enables DAC state detection logic, for load-based TV detection. - * - * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set - * to off, for load detection to work. - */ -# define TVDAC_STATE_CHG_EN (1 << 27) -/* Sets the DAC A sense value to high */ -# define TVDAC_A_SENSE_CTL (1 << 26) -/* Sets the DAC B sense value to high */ -# define TVDAC_B_SENSE_CTL (1 << 25) -/* Sets the DAC C sense value to high */ -# define TVDAC_C_SENSE_CTL (1 << 24) -/* Overrides the ENC_ENABLE and DAC voltage levels */ -# define DAC_CTL_OVERRIDE (1 << 7) -/* Sets the slew rate. Must be preserved in software */ -# define ENC_TVDAC_SLEW_FAST (1 << 6) -# define DAC_A_1_3_V (0 << 4) -# define DAC_A_1_1_V (1 << 4) -# define DAC_A_0_7_V (2 << 4) -# define DAC_A_MASK (3 << 4) -# define DAC_B_1_3_V (0 << 2) -# define DAC_B_1_1_V (1 << 2) -# define DAC_B_0_7_V (2 << 2) -# define DAC_B_MASK (3 << 2) -# define DAC_C_1_3_V (0 << 0) -# define DAC_C_1_1_V (1 << 0) -# define DAC_C_0_7_V (2 << 0) -# define DAC_C_MASK (3 << 0) - -/* - * CSC coefficients are stored in a floating point format with 9 bits of - * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, - * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with - * -1 (0x3) being the only legal negative value. - */ -#define TV_CSC_Y _MMIO(0x68010) -# define TV_RY_MASK 0x07ff0000 -# define TV_RY_SHIFT 16 -# define TV_GY_MASK 0x00000fff -# define TV_GY_SHIFT 0 - -#define TV_CSC_Y2 _MMIO(0x68014) -# define TV_BY_MASK 0x07ff0000 -# define TV_BY_SHIFT 16 -/* - * Y attenuation for component video. - * - * Stored in 1.9 fixed point. - */ -# define TV_AY_MASK 0x000003ff -# define TV_AY_SHIFT 0 - -#define TV_CSC_U _MMIO(0x68018) -# define TV_RU_MASK 0x07ff0000 -# define TV_RU_SHIFT 16 -# define TV_GU_MASK 0x000007ff -# define TV_GU_SHIFT 0 - -#define TV_CSC_U2 _MMIO(0x6801c) -# define TV_BU_MASK 0x07ff0000 -# define TV_BU_SHIFT 16 -/* - * U attenuation for component video. - * - * Stored in 1.9 fixed point. - */ -# define TV_AU_MASK 0x000003ff -# define TV_AU_SHIFT 0 - -#define TV_CSC_V _MMIO(0x68020) -# define TV_RV_MASK 0x0fff0000 -# define TV_RV_SHIFT 16 -# define TV_GV_MASK 0x000007ff -# define TV_GV_SHIFT 0 - -#define TV_CSC_V2 _MMIO(0x68024) -# define TV_BV_MASK 0x07ff0000 -# define TV_BV_SHIFT 16 -/* - * V attenuation for component video. - * - * Stored in 1.9 fixed point. - */ -# define TV_AV_MASK 0x000007ff -# define TV_AV_SHIFT 0 - -#define TV_CLR_KNOBS _MMIO(0x68028) -/* 2s-complement brightness adjustment */ -# define TV_BRIGHTNESS_MASK 0xff000000 -# define TV_BRIGHTNESS_SHIFT 24 -/* Contrast adjustment, as a 2.6 unsigned floating point number */ -# define TV_CONTRAST_MASK 0x00ff0000 -# define TV_CONTRAST_SHIFT 16 -/* Saturation adjustment, as a 2.6 unsigned floating point number */ -# define TV_SATURATION_MASK 0x0000ff00 -# define TV_SATURATION_SHIFT 8 -/* Hue adjustment, as an integer phase angle in degrees */ -# define TV_HUE_MASK 0x000000ff -# define TV_HUE_SHIFT 0 - -#define TV_CLR_LEVEL _MMIO(0x6802c) -/* Controls the DAC level for black */ -# define TV_BLACK_LEVEL_MASK 0x01ff0000 -# define TV_BLACK_LEVEL_SHIFT 16 -/* Controls the DAC level for blanking */ -# define TV_BLANK_LEVEL_MASK 0x000001ff -# define TV_BLANK_LEVEL_SHIFT 0 - -#define TV_H_CTL_1 _MMIO(0x68030) -/* Number of pixels in the hsync. */ -# define TV_HSYNC_END_MASK 0x1fff0000 -# define TV_HSYNC_END_SHIFT 16 -/* Total number of pixels minus one in the line (display and blanking). */ -# define TV_HTOTAL_MASK 0x00001fff -# define TV_HTOTAL_SHIFT 0 - -#define TV_H_CTL_2 _MMIO(0x68034) -/* Enables the colorburst (needed for non-component color) */ -# define TV_BURST_ENA (1 << 31) -/* Offset of the colorburst from the start of hsync, in pixels minus one. */ -# define TV_HBURST_START_SHIFT 16 -# define TV_HBURST_START_MASK 0x1fff0000 -/* Length of the colorburst */ -# define TV_HBURST_LEN_SHIFT 0 -# define TV_HBURST_LEN_MASK 0x0001fff - -#define TV_H_CTL_3 _MMIO(0x68038) -/* End of hblank, measured in pixels minus one from start of hsync */ -# define TV_HBLANK_END_SHIFT 16 -# define TV_HBLANK_END_MASK 0x1fff0000 -/* Start of hblank, measured in pixels minus one from start of hsync */ -# define TV_HBLANK_START_SHIFT 0 -# define TV_HBLANK_START_MASK 0x0001fff - -#define TV_V_CTL_1 _MMIO(0x6803c) -/* XXX */ -# define TV_NBR_END_SHIFT 16 -# define TV_NBR_END_MASK 0x07ff0000 -/* XXX */ -# define TV_VI_END_F1_SHIFT 8 -# define TV_VI_END_F1_MASK 0x00003f00 -/* XXX */ -# define TV_VI_END_F2_SHIFT 0 -# define TV_VI_END_F2_MASK 0x0000003f - -#define TV_V_CTL_2 _MMIO(0x68040) -/* Length of vsync, in half lines */ -# define TV_VSYNC_LEN_MASK 0x07ff0000 -# define TV_VSYNC_LEN_SHIFT 16 -/* Offset of the start of vsync in field 1, measured in one less than the - * number of half lines. - */ -# define TV_VSYNC_START_F1_MASK 0x00007f00 -# define TV_VSYNC_START_F1_SHIFT 8 -/* - * Offset of the start of vsync in field 2, measured in one less than the - * number of half lines. - */ -# define TV_VSYNC_START_F2_MASK 0x0000007f -# define TV_VSYNC_START_F2_SHIFT 0 - -#define TV_V_CTL_3 _MMIO(0x68044) -/* Enables generation of the equalization signal */ -# define TV_EQUAL_ENA (1 << 31) -/* Length of vsync, in half lines */ -# define TV_VEQ_LEN_MASK 0x007f0000 -# define TV_VEQ_LEN_SHIFT 16 -/* Offset of the start of equalization in field 1, measured in one less than - * the number of half lines. - */ -# define TV_VEQ_START_F1_MASK 0x0007f00 -# define TV_VEQ_START_F1_SHIFT 8 -/* - * Offset of the start of equalization in field 2, measured in one less than - * the number of half lines. - */ -# define TV_VEQ_START_F2_MASK 0x000007f -# define TV_VEQ_START_F2_SHIFT 0 - -#define TV_V_CTL_4 _MMIO(0x68048) -/* - * Offset to start of vertical colorburst, measured in one less than the - * number of lines from vertical start. - */ -# define TV_VBURST_START_F1_MASK 0x003f0000 -# define TV_VBURST_START_F1_SHIFT 16 -/* - * Offset to the end of vertical colorburst, measured in one less than the - * number of lines from the start of NBR. - */ -# define TV_VBURST_END_F1_MASK 0x000000ff -# define TV_VBURST_END_F1_SHIFT 0 - -#define TV_V_CTL_5 _MMIO(0x6804c) -/* - * Offset to start of vertical colorburst, measured in one less than the - * number of lines from vertical start. - */ -# define TV_VBURST_START_F2_MASK 0x003f0000 -# define TV_VBURST_START_F2_SHIFT 16 -/* - * Offset to the end of vertical colorburst, measured in one less than the - * number of lines from the start of NBR. - */ -# define TV_VBURST_END_F2_MASK 0x000000ff -# define TV_VBURST_END_F2_SHIFT 0 - -#define TV_V_CTL_6 _MMIO(0x68050) -/* - * Offset to start of vertical colorburst, measured in one less than the - * number of lines from vertical start. - */ -# define TV_VBURST_START_F3_MASK 0x003f0000 -# define TV_VBURST_START_F3_SHIFT 16 -/* - * Offset to the end of vertical colorburst, measured in one less than the - * number of lines from the start of NBR. - */ -# define TV_VBURST_END_F3_MASK 0x000000ff -# define TV_VBURST_END_F3_SHIFT 0 - -#define TV_V_CTL_7 _MMIO(0x68054) -/* - * Offset to start of vertical colorburst, measured in one less than the - * number of lines from vertical start. - */ -# define TV_VBURST_START_F4_MASK 0x003f0000 -# define TV_VBURST_START_F4_SHIFT 16 -/* - * Offset to the end of vertical colorburst, measured in one less than the - * number of lines from the start of NBR. - */ -# define TV_VBURST_END_F4_MASK 0x000000ff -# define TV_VBURST_END_F4_SHIFT 0 - -#define TV_SC_CTL_1 _MMIO(0x68060) -/* Turns on the first subcarrier phase generation DDA */ -# define TV_SC_DDA1_EN (1 << 31) -/* Turns on the first subcarrier phase generation DDA */ -# define TV_SC_DDA2_EN (1 << 30) -/* Turns on the first subcarrier phase generation DDA */ -# define TV_SC_DDA3_EN (1 << 29) -/* Sets the subcarrier DDA to reset frequency every other field */ -# define TV_SC_RESET_EVERY_2 (0 << 24) -/* Sets the subcarrier DDA to reset frequency every fourth field */ -# define TV_SC_RESET_EVERY_4 (1 << 24) -/* Sets the subcarrier DDA to reset frequency every eighth field */ -# define TV_SC_RESET_EVERY_8 (2 << 24) -/* Sets the subcarrier DDA to never reset the frequency */ -# define TV_SC_RESET_NEVER (3 << 24) -/* Sets the peak amplitude of the colorburst.*/ -# define TV_BURST_LEVEL_MASK 0x00ff0000 -# define TV_BURST_LEVEL_SHIFT 16 -/* Sets the increment of the first subcarrier phase generation DDA */ -# define TV_SCDDA1_INC_MASK 0x00000fff -# define TV_SCDDA1_INC_SHIFT 0 - -#define TV_SC_CTL_2 _MMIO(0x68064) -/* Sets the rollover for the second subcarrier phase generation DDA */ -# define TV_SCDDA2_SIZE_MASK 0x7fff0000 -# define TV_SCDDA2_SIZE_SHIFT 16 -/* Sets the increent of the second subcarrier phase generation DDA */ -# define TV_SCDDA2_INC_MASK 0x00007fff -# define TV_SCDDA2_INC_SHIFT 0 - -#define TV_SC_CTL_3 _MMIO(0x68068) -/* Sets the rollover for the third subcarrier phase generation DDA */ -# define TV_SCDDA3_SIZE_MASK 0x7fff0000 -# define TV_SCDDA3_SIZE_SHIFT 16 -/* Sets the increent of the third subcarrier phase generation DDA */ -# define TV_SCDDA3_INC_MASK 0x00007fff -# define TV_SCDDA3_INC_SHIFT 0 - -#define TV_WIN_POS _MMIO(0x68070) -/* X coordinate of the display from the start of horizontal active */ -# define TV_XPOS_MASK 0x1fff0000 -# define TV_XPOS_SHIFT 16 -/* Y coordinate of the display from the start of vertical active (NBR) */ -# define TV_YPOS_MASK 0x00000fff -# define TV_YPOS_SHIFT 0 - -#define TV_WIN_SIZE _MMIO(0x68074) -/* Horizontal size of the display window, measured in pixels*/ -# define TV_XSIZE_MASK 0x1fff0000 -# define TV_XSIZE_SHIFT 16 -/* - * Vertical size of the display window, measured in pixels. - * - * Must be even for interlaced modes. - */ -# define TV_YSIZE_MASK 0x00000fff -# define TV_YSIZE_SHIFT 0 - -#define TV_FILTER_CTL_1 _MMIO(0x68080) -/* - * Enables automatic scaling calculation. - * - * If set, the rest of the registers are ignored, and the calculated values can - * be read back from the register. - */ -# define TV_AUTO_SCALE (1 << 31) -/* - * Disables the vertical filter. - * - * This is required on modes more than 1024 pixels wide */ -# define TV_V_FILTER_BYPASS (1 << 29) -/* Enables adaptive vertical filtering */ -# define TV_VADAPT (1 << 28) -# define TV_VADAPT_MODE_MASK (3 << 26) -/* Selects the least adaptive vertical filtering mode */ -# define TV_VADAPT_MODE_LEAST (0 << 26) -/* Selects the moderately adaptive vertical filtering mode */ -# define TV_VADAPT_MODE_MODERATE (1 << 26) -/* Selects the most adaptive vertical filtering mode */ -# define TV_VADAPT_MODE_MOST (3 << 26) -/* - * Sets the horizontal scaling factor. - * - * This should be the fractional part of the horizontal scaling factor divided - * by the oversampling rate. TV_HSCALE should be less than 1, and set to: - * - * (src width - 1) / ((oversample * dest width) - 1) - */ -# define TV_HSCALE_FRAC_MASK 0x00003fff -# define TV_HSCALE_FRAC_SHIFT 0 - -#define TV_FILTER_CTL_2 _MMIO(0x68084) -/* - * Sets the integer part of the 3.15 fixed-point vertical scaling factor. - * - * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) - */ -# define TV_VSCALE_INT_MASK 0x00038000 -# define TV_VSCALE_INT_SHIFT 15 -/* - * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. - * - * \sa TV_VSCALE_INT_MASK - */ -# define TV_VSCALE_FRAC_MASK 0x00007fff -# define TV_VSCALE_FRAC_SHIFT 0 - -#define TV_FILTER_CTL_3 _MMIO(0x68088) -/* - * Sets the integer part of the 3.15 fixed-point vertical scaling factor. - * - * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) - * - * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. - */ -# define TV_VSCALE_IP_INT_MASK 0x00038000 -# define TV_VSCALE_IP_INT_SHIFT 15 -/* - * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. - * - * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. - * - * \sa TV_VSCALE_IP_INT_MASK - */ -# define TV_VSCALE_IP_FRAC_MASK 0x00007fff -# define TV_VSCALE_IP_FRAC_SHIFT 0 - -#define TV_CC_CONTROL _MMIO(0x68090) -# define TV_CC_ENABLE (1 << 31) -/* - * Specifies which field to send the CC data in. - * - * CC data is usually sent in field 0. - */ -# define TV_CC_FID_MASK (1 << 27) -# define TV_CC_FID_SHIFT 27 -/* Sets the horizontal position of the CC data. Usually 135. */ -# define TV_CC_HOFF_MASK 0x03ff0000 -# define TV_CC_HOFF_SHIFT 16 -/* Sets the vertical position of the CC data. Usually 21 */ -# define TV_CC_LINE_MASK 0x0000003f -# define TV_CC_LINE_SHIFT 0 - -#define TV_CC_DATA _MMIO(0x68094) -# define TV_CC_RDY (1 << 31) -/* Second word of CC data to be transmitted. */ -# define TV_CC_DATA_2_MASK 0x007f0000 -# define TV_CC_DATA_2_SHIFT 16 -/* First word of CC data to be transmitted. */ -# define TV_CC_DATA_1_MASK 0x0000007f -# define TV_CC_DATA_1_SHIFT 0 - -#define TV_H_LUMA(i) _MMIO(0x68100 + (i) * 4) /* 60 registers */ -#define TV_H_CHROMA(i) _MMIO(0x68200 + (i) * 4) /* 60 registers */ -#define TV_V_LUMA(i) _MMIO(0x68300 + (i) * 4) /* 43 registers */ -#define TV_V_CHROMA(i) _MMIO(0x68400 + (i) * 4) /* 43 registers */ - /* Display Port */ #define DP_A _MMIO(0x64000) /* eDP */ #define DP_B _MMIO(0x64100) @@ -3242,79 +2460,6 @@ /* A fantasy */ #define DP_DETECTED (1 << 2) -/* The aux channel provides a way to talk to the - * signal sink for DDC etc. Max packet size supported - * is 20 bytes in each direction, hence the 5 fixed - * data registers - */ -#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010) -#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014) - -#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110) -#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114) - -#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL) -#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ - -#define _XELPDP_USBC1_AUX_CH_CTL 0x16F210 -#define _XELPDP_USBC2_AUX_CH_CTL 0x16F410 -#define _XELPDP_USBC3_AUX_CH_CTL 0x16F610 -#define _XELPDP_USBC4_AUX_CH_CTL 0x16F810 - -#define XELPDP_DP_AUX_CH_CTL(aux_ch) _MMIO(_PICK(aux_ch, \ - _DPA_AUX_CH_CTL, \ - _DPB_AUX_CH_CTL, \ - 0, /* port/aux_ch C is non-existent */ \ - _XELPDP_USBC1_AUX_CH_CTL, \ - _XELPDP_USBC2_AUX_CH_CTL, \ - _XELPDP_USBC3_AUX_CH_CTL, \ - _XELPDP_USBC4_AUX_CH_CTL)) - -#define _XELPDP_USBC1_AUX_CH_DATA1 0x16F214 -#define _XELPDP_USBC2_AUX_CH_DATA1 0x16F414 -#define _XELPDP_USBC3_AUX_CH_DATA1 0x16F614 -#define _XELPDP_USBC4_AUX_CH_DATA1 0x16F814 - -#define XELPDP_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PICK(aux_ch, \ - _DPA_AUX_CH_DATA1, \ - _DPB_AUX_CH_DATA1, \ - 0, /* port/aux_ch C is non-existent */ \ - _XELPDP_USBC1_AUX_CH_DATA1, \ - _XELPDP_USBC2_AUX_CH_DATA1, \ - _XELPDP_USBC3_AUX_CH_DATA1, \ - _XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4) - -#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) -#define DP_AUX_CH_CTL_DONE (1 << 30) -#define DP_AUX_CH_CTL_INTERRUPT (1 << 29) -#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28) -#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) -#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) -#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) -#define DP_AUX_CH_CTL_TIME_OUT_MAX (3 << 26) /* Varies per platform */ -#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) -#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) -#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) -#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20 -#define XELPDP_DP_AUX_CH_CTL_POWER_REQUEST REG_BIT(19) -#define XELPDP_DP_AUX_CH_CTL_POWER_STATUS REG_BIT(18) -#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16) -#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16 -#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15) -#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14) -#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13) -#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12) -#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11) -#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff) -#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0 -#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL (1 << 14) -#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL (1 << 13) -#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL (1 << 12) -#define DP_AUX_CH_CTL_TBT_IO (1 << 11) -#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (0x1f << 5) -#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5) -#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) ((c) - 1) - /* * Computing GMCH M and N values for the Display Port link * @@ -3819,66 +2964,6 @@ #define I965_CURSOR_MAX_WM 32 #define I965_CURSOR_DFT_WM 8 -/* Watermark register definitions for SKL */ -#define _CUR_WM_A_0 0x70140 -#define _CUR_WM_B_0 0x71140 -#define _CUR_WM_SAGV_A 0x70158 -#define _CUR_WM_SAGV_B 0x71158 -#define _CUR_WM_SAGV_TRANS_A 0x7015C -#define _CUR_WM_SAGV_TRANS_B 0x7115C -#define _CUR_WM_TRANS_A 0x70168 -#define _CUR_WM_TRANS_B 0x71168 -#define _PLANE_WM_1_A_0 0x70240 -#define _PLANE_WM_1_B_0 0x71240 -#define _PLANE_WM_2_A_0 0x70340 -#define _PLANE_WM_2_B_0 0x71340 -#define _PLANE_WM_SAGV_1_A 0x70258 -#define _PLANE_WM_SAGV_1_B 0x71258 -#define _PLANE_WM_SAGV_2_A 0x70358 -#define _PLANE_WM_SAGV_2_B 0x71358 -#define _PLANE_WM_SAGV_TRANS_1_A 0x7025C -#define _PLANE_WM_SAGV_TRANS_1_B 0x7125C -#define _PLANE_WM_SAGV_TRANS_2_A 0x7035C -#define _PLANE_WM_SAGV_TRANS_2_B 0x7135C -#define _PLANE_WM_TRANS_1_A 0x70268 -#define _PLANE_WM_TRANS_1_B 0x71268 -#define _PLANE_WM_TRANS_2_A 0x70368 -#define _PLANE_WM_TRANS_2_B 0x71368 -#define PLANE_WM_EN (1 << 31) -#define PLANE_WM_IGNORE_LINES (1 << 30) -#define PLANE_WM_LINES_MASK REG_GENMASK(26, 14) -#define PLANE_WM_BLOCKS_MASK REG_GENMASK(11, 0) - -#define _CUR_WM_0(pipe) _PIPE(pipe, _CUR_WM_A_0, _CUR_WM_B_0) -#define CUR_WM(pipe, level) _MMIO(_CUR_WM_0(pipe) + ((4) * (level))) -#define CUR_WM_SAGV(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_A, _CUR_WM_SAGV_B) -#define CUR_WM_SAGV_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_SAGV_TRANS_A, _CUR_WM_SAGV_TRANS_B) -#define CUR_WM_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_TRANS_A, _CUR_WM_TRANS_B) -#define _PLANE_WM_1(pipe) _PIPE(pipe, _PLANE_WM_1_A_0, _PLANE_WM_1_B_0) -#define _PLANE_WM_2(pipe) _PIPE(pipe, _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) -#define _PLANE_WM_BASE(pipe, plane) \ - _PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe)) -#define PLANE_WM(pipe, plane, level) \ - _MMIO(_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) -#define _PLANE_WM_SAGV_1(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_1_A, _PLANE_WM_SAGV_1_B) -#define _PLANE_WM_SAGV_2(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_2_A, _PLANE_WM_SAGV_2_B) -#define PLANE_WM_SAGV(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_SAGV_1(pipe), _PLANE_WM_SAGV_2(pipe))) -#define _PLANE_WM_SAGV_TRANS_1(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_TRANS_1_A, _PLANE_WM_SAGV_TRANS_1_B) -#define _PLANE_WM_SAGV_TRANS_2(pipe) \ - _PIPE(pipe, _PLANE_WM_SAGV_TRANS_2_A, _PLANE_WM_SAGV_TRANS_2_B) -#define PLANE_WM_SAGV_TRANS(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_SAGV_TRANS_1(pipe), _PLANE_WM_SAGV_TRANS_2(pipe))) -#define _PLANE_WM_TRANS_1(pipe) \ - _PIPE(pipe, _PLANE_WM_TRANS_1_A, _PLANE_WM_TRANS_1_B) -#define _PLANE_WM_TRANS_2(pipe) \ - _PIPE(pipe, _PLANE_WM_TRANS_2_A, _PLANE_WM_TRANS_2_B) -#define PLANE_WM_TRANS(pipe, plane) \ - _MMIO(_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))) - /* define the Watermark register on Ironlake */ #define _WM0_PIPEA_ILK 0x45100 #define _WM0_PIPEB_ILK 0x45104 @@ -3988,6 +3073,7 @@ #define CUR_FBC_EN REG_BIT(31) #define CUR_FBC_HEIGHT_MASK REG_GENMASK(7, 0) #define CUR_FBC_HEIGHT(h) REG_FIELD_PREP(CUR_FBC_HEIGHT_MASK, (h)) +#define _CUR_CHICKEN_A 0x700a4 /* mtl+ */ #define _CURASURFLIVE 0x700ac /* g4x+ */ #define _CURBCNTR 0x700c0 #define _CURBBASE 0x700c4 @@ -4002,6 +3088,7 @@ #define CURPOS(pipe) _MMIO_CURSOR2(pipe, _CURAPOS) #define CURSIZE(pipe) _MMIO_CURSOR2(pipe, _CURASIZE) #define CUR_FBC_CTL(pipe) _MMIO_CURSOR2(pipe, _CUR_FBC_CTL_A) +#define CUR_CHICKEN(pipe) _MMIO_CURSOR2(pipe, _CUR_CHICKEN_A) #define CURSURFLIVE(pipe) _MMIO_CURSOR2(pipe, _CURASURFLIVE) #define CURSOR_A_OFFSET 0x70080 @@ -4654,8 +3741,16 @@ #define PLANE_COLOR_ALPHA_DISABLE REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 0) #define PLANE_COLOR_ALPHA_SW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 2) #define PLANE_COLOR_ALPHA_HW_PREMULTIPLY REG_FIELD_PREP(PLANE_COLOR_ALPHA_MASK, 3) +#define _PLANE_CHICKEN_1_A 0x7026C /* tgl+ */ +#define _PLANE_CHICKEN_2_A 0x7036C /* tgl+ */ +#define PLANE_CHICKEN_DISABLE_DPT REG_BIT(19) /* mtl+ */ #define _PLANE_BUF_CFG_1_A 0x7027c #define _PLANE_BUF_CFG_2_A 0x7037c +/* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ +#define PLANE_BUF_END_MASK REG_GENMASK(27, 16) +#define PLANE_BUF_END(end) REG_FIELD_PREP(PLANE_BUF_END_MASK, (end)) +#define PLANE_BUF_START_MASK REG_GENMASK(11, 0) +#define PLANE_BUF_START(start) REG_FIELD_PREP(PLANE_BUF_START_MASK, (start)) #define _PLANE_NV12_BUF_CFG_1_A 0x70278 #define _PLANE_NV12_BUF_CFG_2_A 0x70378 @@ -4799,28 +3894,12 @@ #define PLANE_SURFLIVE(pipe, plane) \ _MMIO_PLANE(plane, _PLANE_SURFLIVE_1(pipe), _PLANE_SURFLIVE_2(pipe)) -#define _PLANE_BUF_CFG_1_B 0x7127c -#define _PLANE_BUF_CFG_2_B 0x7137c -/* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ -#define PLANE_BUF_END_MASK REG_GENMASK(27, 16) -#define PLANE_BUF_END(end) REG_FIELD_PREP(PLANE_BUF_END_MASK, (end)) -#define PLANE_BUF_START_MASK REG_GENMASK(11, 0) -#define PLANE_BUF_START(start) REG_FIELD_PREP(PLANE_BUF_START_MASK, (start)) -#define _PLANE_BUF_CFG_1(pipe) \ - _PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) -#define _PLANE_BUF_CFG_2(pipe) \ - _PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) -#define PLANE_BUF_CFG(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) - -#define _PLANE_NV12_BUF_CFG_1_B 0x71278 -#define _PLANE_NV12_BUF_CFG_2_B 0x71378 -#define _PLANE_NV12_BUF_CFG_1(pipe) \ - _PIPE(pipe, _PLANE_NV12_BUF_CFG_1_A, _PLANE_NV12_BUF_CFG_1_B) -#define _PLANE_NV12_BUF_CFG_2(pipe) \ - _PIPE(pipe, _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B) -#define PLANE_NV12_BUF_CFG(pipe, plane) \ - _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) +#define _PLANE_CHICKEN_1_B 0x7126c +#define _PLANE_CHICKEN_2_B 0x7136c +#define _PLANE_CHICKEN_1(pipe) _PIPE(pipe, _PLANE_CHICKEN_1_A, _PLANE_CHICKEN_1_B) +#define _PLANE_CHICKEN_2(pipe) _PIPE(pipe, _PLANE_CHICKEN_2_A, _PLANE_CHICKEN_2_B) +#define PLANE_CHICKEN(pipe, plane) \ + _MMIO_PLANE(plane, _PLANE_CHICKEN_1(pipe), _PLANE_CHICKEN_2(pipe)) #define _PLANE_AUX_DIST_1_B 0x711c0 #define _PLANE_AUX_DIST_2_B 0x712c0 @@ -4859,56 +3938,6 @@ #define PLANE_COLOR_CTL(pipe, plane) \ _MMIO_PLANE(plane, _PLANE_COLOR_CTL_1(pipe), _PLANE_COLOR_CTL_2(pipe)) -#define _SEL_FETCH_PLANE_BASE_1_A 0x70890 -#define _SEL_FETCH_PLANE_BASE_2_A 0x708B0 -#define _SEL_FETCH_PLANE_BASE_3_A 0x708D0 -#define _SEL_FETCH_PLANE_BASE_4_A 0x708F0 -#define _SEL_FETCH_PLANE_BASE_5_A 0x70920 -#define _SEL_FETCH_PLANE_BASE_6_A 0x70940 -#define _SEL_FETCH_PLANE_BASE_7_A 0x70960 -#define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880 -#define _SEL_FETCH_PLANE_BASE_1_B 0x71890 - -#define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \ - _SEL_FETCH_PLANE_BASE_1_A, \ - _SEL_FETCH_PLANE_BASE_2_A, \ - _SEL_FETCH_PLANE_BASE_3_A, \ - _SEL_FETCH_PLANE_BASE_4_A, \ - _SEL_FETCH_PLANE_BASE_5_A, \ - _SEL_FETCH_PLANE_BASE_6_A, \ - _SEL_FETCH_PLANE_BASE_7_A, \ - _SEL_FETCH_PLANE_BASE_CUR_A) -#define _SEL_FETCH_PLANE_BASE_1(pipe) _PIPE(pipe, _SEL_FETCH_PLANE_BASE_1_A, _SEL_FETCH_PLANE_BASE_1_B) -#define _SEL_FETCH_PLANE_BASE(pipe, plane) (_SEL_FETCH_PLANE_BASE_1(pipe) - \ - _SEL_FETCH_PLANE_BASE_1_A + \ - _SEL_FETCH_PLANE_BASE_A(plane)) - -#define _SEL_FETCH_PLANE_CTL_1_A 0x70890 -#define PLANE_SEL_FETCH_CTL(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_CTL_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) -#define PLANE_SEL_FETCH_CTL_ENABLE REG_BIT(31) - -#define _SEL_FETCH_PLANE_POS_1_A 0x70894 -#define PLANE_SEL_FETCH_POS(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_POS_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) - -#define _SEL_FETCH_PLANE_SIZE_1_A 0x70898 -#define PLANE_SEL_FETCH_SIZE(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_SIZE_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) - -#define _SEL_FETCH_PLANE_OFFSET_1_A 0x7089C -#define PLANE_SEL_FETCH_OFFSET(pipe, plane) _MMIO(_SEL_FETCH_PLANE_BASE(pipe, plane) + \ - _SEL_FETCH_PLANE_OFFSET_1_A - \ - _SEL_FETCH_PLANE_BASE_1_A) - -/* SKL new cursor registers */ -#define _CUR_BUF_CFG_A 0x7017c -#define _CUR_BUF_CFG_B 0x7117c -#define CUR_BUF_CFG(pipe) _MMIO_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) - /* VBIOS regs */ #define VGACNTRL _MMIO(0x71400) # define VGA_DISP_DISABLE (1 << 31) @@ -4938,14 +3967,6 @@ #define RR_HW_LOW_POWER_FRAMES_MASK 0xff #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 -#define FDI_PLL_BIOS_0 _MMIO(0x46000) -#define FDI_PLL_FB_CLOCK_MASK 0xff -#define FDI_PLL_BIOS_1 _MMIO(0x46004) -#define FDI_PLL_BIOS_2 _MMIO(0x46008) -#define DISPLAY_PORT_PLL_BIOS_0 _MMIO(0x4600c) -#define DISPLAY_PORT_PLL_BIOS_1 _MMIO(0x46010) -#define DISPLAY_PORT_PLL_BIOS_2 _MMIO(0x46014) - #define PCH_3DCGDIS0 _MMIO(0x46020) # define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18) # define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1) @@ -4953,12 +3974,6 @@ #define PCH_3DCGDIS1 _MMIO(0x46024) # define VFMUNIT_CLOCK_GATE_DISABLE (1 << 11) -#define FDI_PLL_FREQ_CTL _MMIO(0x46030) -#define FDI_PLL_FREQ_CHANGE_REQUEST (1 << 24) -#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 -#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff - - #define _PIPEA_DATA_M1 0x60030 #define _PIPEA_DATA_N1 0x60034 #define _PIPEA_DATA_M2 0x60038 @@ -5511,6 +4526,7 @@ #define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT (1 << 14) #define CHICKEN_MISC_2 _MMIO(0x42084) +#define CHICKEN_MISC_DISABLE_DPT REG_BIT(30) /* adl,dg2 */ #define KBL_ARB_FILL_SPARE_14 REG_BIT(14) #define KBL_ARB_FILL_SPARE_13 REG_BIT(13) #define GLK_CL2_PWR_DOWN (1 << 12) @@ -5581,30 +4597,6 @@ #define DISP_DATA_PARTITION_5_6 (1 << 6) #define DISP_IPC_ENABLE (1 << 3) -/* - * The below are numbered starting from "S1" on gen11/gen12, but starting - * with display 13, the bspec switches to a 0-based numbering scheme - * (although the addresses stay the same so new S0 = old S1, new S1 = old S2). - * We'll just use the 0-based numbering here for all platforms since it's the - * way things will be named by the hardware team going forward, plus it's more - * consistent with how most of the rest of our registers are named. - */ -#define _DBUF_CTL_S0 0x45008 -#define _DBUF_CTL_S1 0x44FE8 -#define _DBUF_CTL_S2 0x44300 -#define _DBUF_CTL_S3 0x44304 -#define DBUF_CTL_S(slice) _MMIO(_PICK(slice, \ - _DBUF_CTL_S0, \ - _DBUF_CTL_S1, \ - _DBUF_CTL_S2, \ - _DBUF_CTL_S3)) -#define DBUF_POWER_REQUEST REG_BIT(31) -#define DBUF_POWER_STATE REG_BIT(30) -#define DBUF_TRACKER_STATE_SERVICE_MASK REG_GENMASK(23, 19) -#define DBUF_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_TRACKER_STATE_SERVICE_MASK, x) -#define DBUF_MIN_TRACKER_STATE_SERVICE_MASK REG_GENMASK(18, 16) /* ADL-P+ */ -#define DBUF_MIN_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_MIN_TRACKER_STATE_SERVICE_MASK, x) /* ADL-P+ */ - #define GEN7_MSG_CTL _MMIO(0x45010) #define WAIT_FOR_PCH_RESET_ACK (1 << 1) #define WAIT_FOR_PCH_FLR_ACK (1 << 0) @@ -6148,12 +5140,6 @@ #define LPT_PWM_GRANULARITY (1 << 5) #define DPLS_EDP_PPS_FIX_DIS (1 << 0) -#define _FDI_RXA_CHICKEN 0xc200c -#define _FDI_RXB_CHICKEN 0xc2010 -#define FDI_RX_PHASE_SYNC_POINTER_OVR (1 << 1) -#define FDI_RX_PHASE_SYNC_POINTER_EN (1 << 0) -#define FDI_RX_CHICKEN(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) - #define SOUTH_DSPCLK_GATE_D _MMIO(0xc2020) #define PCH_GMBUSUNIT_CLOCK_GATE_DISABLE (1 << 31) #define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1 << 30) @@ -6163,127 +5149,6 @@ #define CNP_PWM_CGE_GATING_DISABLE (1 << 13) #define PCH_LP_PARTITION_LEVEL_DISABLE (1 << 12) -/* CPU: FDI_TX */ -#define _FDI_TXA_CTL 0x60100 -#define _FDI_TXB_CTL 0x61100 -#define FDI_TX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL) -#define FDI_TX_DISABLE (0 << 31) -#define FDI_TX_ENABLE (1 << 31) -#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28) -#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28) -#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28) -#define FDI_LINK_TRAIN_NONE (3 << 28) -#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) -/* ILK always use 400mV 0dB for voltage swing and pre-emphasis level. - SNB has different settings. */ -/* SNB A-stepping */ -#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) -#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) -#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) -#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x0 << 22) -/* SNB B-stepping */ -#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x0 << 22) -#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22) -#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22) -#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22) -#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22) -#define FDI_DP_PORT_WIDTH_SHIFT 19 -#define FDI_DP_PORT_WIDTH_MASK (7 << FDI_DP_PORT_WIDTH_SHIFT) -#define FDI_DP_PORT_WIDTH(width) (((width) - 1) << FDI_DP_PORT_WIDTH_SHIFT) -#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18) -/* Ironlake: hardwired to 1 */ -#define FDI_TX_PLL_ENABLE (1 << 14) - -/* Ivybridge has different bits for lolz */ -#define FDI_LINK_TRAIN_PATTERN_1_IVB (0 << 8) -#define FDI_LINK_TRAIN_PATTERN_2_IVB (1 << 8) -#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2 << 8) -#define FDI_LINK_TRAIN_NONE_IVB (3 << 8) - -/* both Tx and Rx */ -#define FDI_COMPOSITE_SYNC (1 << 11) -#define FDI_LINK_TRAIN_AUTO (1 << 10) -#define FDI_SCRAMBLING_ENABLE (0 << 7) -#define FDI_SCRAMBLING_DISABLE (1 << 7) - -/* FDI_RX, FDI_X is hard-wired to Transcoder_X */ -#define _FDI_RXA_CTL 0xf000c -#define _FDI_RXB_CTL 0xf100c -#define FDI_RX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) -#define FDI_RX_ENABLE (1 << 31) -/* train, dp width same as FDI_TX */ -#define FDI_FS_ERRC_ENABLE (1 << 27) -#define FDI_FE_ERRC_ENABLE (1 << 26) -#define FDI_RX_POLARITY_REVERSED_LPT (1 << 16) -#define FDI_8BPC (0 << 16) -#define FDI_10BPC (1 << 16) -#define FDI_6BPC (2 << 16) -#define FDI_12BPC (3 << 16) -#define FDI_RX_LINK_REVERSAL_OVERRIDE (1 << 15) -#define FDI_DMI_LINK_REVERSE_MASK (1 << 14) -#define FDI_RX_PLL_ENABLE (1 << 13) -#define FDI_FS_ERR_CORRECT_ENABLE (1 << 11) -#define FDI_FE_ERR_CORRECT_ENABLE (1 << 10) -#define FDI_FS_ERR_REPORT_ENABLE (1 << 9) -#define FDI_FE_ERR_REPORT_ENABLE (1 << 8) -#define FDI_RX_ENHANCE_FRAME_ENABLE (1 << 6) -#define FDI_PCDCLK (1 << 4) -/* CPT */ -#define FDI_AUTO_TRAINING (1 << 10) -#define FDI_LINK_TRAIN_PATTERN_1_CPT (0 << 8) -#define FDI_LINK_TRAIN_PATTERN_2_CPT (1 << 8) -#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2 << 8) -#define FDI_LINK_TRAIN_NORMAL_CPT (3 << 8) -#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3 << 8) - -#define _FDI_RXA_MISC 0xf0010 -#define _FDI_RXB_MISC 0xf1010 -#define FDI_RX_PWRDN_LANE1_MASK (3 << 26) -#define FDI_RX_PWRDN_LANE1_VAL(x) ((x) << 26) -#define FDI_RX_PWRDN_LANE0_MASK (3 << 24) -#define FDI_RX_PWRDN_LANE0_VAL(x) ((x) << 24) -#define FDI_RX_TP1_TO_TP2_48 (2 << 20) -#define FDI_RX_TP1_TO_TP2_64 (3 << 20) -#define FDI_RX_FDI_DELAY_90 (0x90 << 0) -#define FDI_RX_MISC(pipe) _MMIO_PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) - -#define _FDI_RXA_TUSIZE1 0xf0030 -#define _FDI_RXA_TUSIZE2 0xf0038 -#define _FDI_RXB_TUSIZE1 0xf1030 -#define _FDI_RXB_TUSIZE2 0xf1038 -#define FDI_RX_TUSIZE1(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) -#define FDI_RX_TUSIZE2(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) - -/* FDI_RX interrupt register format */ -#define FDI_RX_INTER_LANE_ALIGN (1 << 10) -#define FDI_RX_SYMBOL_LOCK (1 << 9) /* train 2 */ -#define FDI_RX_BIT_LOCK (1 << 8) /* train 1 */ -#define FDI_RX_TRAIN_PATTERN_2_FAIL (1 << 7) -#define FDI_RX_FS_CODE_ERR (1 << 6) -#define FDI_RX_FE_CODE_ERR (1 << 5) -#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1 << 4) -#define FDI_RX_HDCP_LINK_FAIL (1 << 3) -#define FDI_RX_PIXEL_FIFO_OVERFLOW (1 << 2) -#define FDI_RX_CROSS_CLOCK_OVERFLOW (1 << 1) -#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1 << 0) - -#define _FDI_RXA_IIR 0xf0014 -#define _FDI_RXA_IMR 0xf0018 -#define _FDI_RXB_IIR 0xf1014 -#define _FDI_RXB_IMR 0xf1018 -#define FDI_RX_IIR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR) -#define FDI_RX_IMR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR) - -#define FDI_PLL_CTL_1 _MMIO(0xfe000) -#define FDI_PLL_CTL_2 _MMIO(0xfe004) - #define _PCH_DP_B 0xe4100 #define PCH_DP_B _MMIO(_PCH_DP_B) #define _PCH_DPB_AUX_CH_CTL 0xe4110 @@ -7653,62 +6518,6 @@ enum skl_power_gate { #define OROM_OFFSET _MMIO(0x1020c0) #define OROM_OFFSET_MASK REG_GENMASK(20, 16) -/* This register controls the Display State Buffer (DSB) engines. */ -#define _DSBSL_INSTANCE_BASE 0x70B00 -#define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \ - (pipe) * 0x1000 + (id) * 0x100) -#define DSB_HEAD(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x0) -#define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) -#define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) -#define DSB_ENABLE REG_BIT(31) -#define DSB_BUF_REITERATE REG_BIT(29) -#define DSB_WAIT_FOR_VBLANK REG_BIT(28) -#define DSB_WAIT_FOR_LINE_IN REG_BIT(27) -#define DSB_HALT REG_BIT(16) -#define DSB_NON_POSTED REG_BIT(8) -#define DSB_STATUS_BUSY REG_BIT(0) -#define DSB_MMIOCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xc) -#define DSB_MMIO_DEAD_CLOCKS_ENABLE REG_BIT(31) -#define DSB_MMIO_DEAD_CLOCKS_COUNT_MASK REG_GENMASK(15, 8) -#define DSB_MMIO_DEAD_CLOCKS_COUNT(x) REG_FIELD_PREP(DSB_MMIO_DEAD_CLOCK_COUNT_MASK, (x)) -#define DSB_MMIO_CYCLES_MASK REG_GENMASK(7, 0) -#define DSB_MMIO_CYCLES(x) REG_FIELD_PREP(DSB_MMIO_CYCLES_MASK, (x)) -#define DSB_POLLFUNC(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x10) -#define DSB_POLL_ENABLE REG_BIT(31) -#define DSB_POLL_WAIT_MASK REG_GENMASK(30, 23) -#define DSB_POLL_WAIT(x) REG_FIELD_PREP(DSB_POLL_WAIT_MASK, (x)) /* usec */ -#define DSB_POLL_COUNT_MASK REG_GENMASK(22, 15) -#define DSB_POLL_COUNT(x) REG_FIELD_PREP(DSB_POLL_COUNT_MASK, (x)) -#define DSB_DEBUG(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x14) -#define DSB_POLLMASK(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x1c) -#define DSB_STATUS(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x24) -#define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28) -#define DSB_ATS_FAULT_INT_EN REG_BIT(20) -#define DSB_GTT_FAULT_INT_EN REG_BIT(19) -#define DSB_RSPTIMEOUT_INT_EN REG_BIT(18) -#define DSB_POLL_ERR_INT_EN REG_BIT(17) -#define DSB_PROG_INT_EN REG_BIT(16) -#define DSB_ATS_FAULT_INT_STATUS REG_BIT(4) -#define DSB_GTT_FAULT_INT_STATUS REG_BIT(3) -#define DSB_RSPTIMEOUT_INT_STATUS REG_BIT(2) -#define DSB_POLL_ERR_INT_STATUS REG_BIT(1) -#define DSB_PROG_INT_STATUS REG_BIT(0) -#define DSB_CURRENT_HEAD(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x2c) -#define DSB_RM_TIMEOUT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x30) -#define DSB_RM_CLAIM_TIMEOUT REG_BIT(31) -#define DSB_RM_READY_TIMEOUT REG_BIT(30) -#define DSB_RM_CLAIM_TIMEOUT_COUNT_MASK REG_GENMASK(23, 16) -#define DSB_RM_CLAIM_TIMEOUT_COUNT(x) REG_FIELD_PREP(DSB_RM_CLAIM_TIMEOUT_COUNT_MASK, (x)) /* clocks */ -#define DSB_RM_READY_TIMEOUT_VALUE_MASK REG_GENMASK(15, 0) -#define DSB_RM_READY_TIMEOUT_VALUE(x) REG_FIELD_PREP(DSB_RM_READY_TIMEOUT_VALUE, (x)) /* usec */ -#define DSB_RMTIMEOUTREG_CAPTURE(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x34) -#define DSB_PMCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x38) -#define DSB_PMCTRL_2(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x3c) -#define DSB_PF_LN_LOWER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x40) -#define DSB_PF_LN_UPPER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x44) -#define DSB_BUFRPT_CNT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x48) -#define DSB_CHICKEN(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xf0) - #define CLKREQ_POLICY _MMIO(0x101038) #define CLKREQ_POLICY_MEM_UP_OVRD REG_BIT(1) @@ -7720,26 +6529,18 @@ enum skl_power_gate { #define MTL_CLKGATE_DIS_TRANS(trans) _MMIO_TRANS2(trans, _MTL_CLKGATE_DIS_TRANS_A) #define MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS REG_BIT(7) -#define MTL_LATENCY_LP0_LP1 _MMIO(0x45780) -#define MTL_LATENCY_LP2_LP3 _MMIO(0x45784) -#define MTL_LATENCY_LP4_LP5 _MMIO(0x45788) -#define MTL_LATENCY_LEVEL_EVEN_MASK REG_GENMASK(12, 0) -#define MTL_LATENCY_LEVEL_ODD_MASK REG_GENMASK(28, 16) - -#define MTL_LATENCY_SAGV _MMIO(0x4578b) -#define MTL_LATENCY_QCLK_SAGV REG_GENMASK(12, 0) - #define MTL_MEM_SS_INFO_GLOBAL _MMIO(0x45700) #define MTL_N_OF_ENABLED_QGV_POINTS_MASK REG_GENMASK(11, 8) #define MTL_N_OF_POPULATED_CH_MASK REG_GENMASK(7, 4) #define MTL_DDR_TYPE_MASK REG_GENMASK(3, 0) -#define MTL_MEM_SS_INFO_QGV_POINT_LOW(point) _MMIO(0x45710 + (point) * 2) +#define MTL_MEM_SS_INFO_QGV_POINT_OFFSET 0x45710 +#define MTL_MEM_SS_INFO_QGV_POINT_LOW(point) _MMIO(MTL_MEM_SS_INFO_QGV_POINT_OFFSET + (point) * 8) #define MTL_TRCD_MASK REG_GENMASK(31, 24) #define MTL_TRP_MASK REG_GENMASK(23, 16) #define MTL_DCLK_MASK REG_GENMASK(15, 0) -#define MTL_MEM_SS_INFO_QGV_POINT_HIGH(point) _MMIO(0x45714 + (point) * 2) +#define MTL_MEM_SS_INFO_QGV_POINT_HIGH(point) _MMIO(MTL_MEM_SS_INFO_QGV_POINT_OFFSET + (point) * 8 + 4) #define MTL_TRAS_MASK REG_GENMASK(16, 8) #define MTL_TRDPRE_MASK REG_GENMASK(7, 0) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c new file mode 100644 index 000000000000..2c5302bcba19 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -0,0 +1,888 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eugeni Dodonov <eugeni.dodonov@intel.com> + * + */ + +#include "display/intel_de.h" +#include "display/intel_display.h" +#include "display/intel_display_trace.h" +#include "display/skl_watermark.h" + +#include "gt/intel_engine_regs.h" +#include "gt/intel_gt.h" +#include "gt/intel_gt_mcr.h" +#include "gt/intel_gt_regs.h" + +#include "i915_drv.h" +#include "intel_clock_gating.h" +#include "intel_mchbar_regs.h" +#include "vlv_sideband.h" + +struct drm_i915_clock_gating_funcs { + void (*init_clock_gating)(struct drm_i915_private *i915); +}; + +static void gen9_init_clock_gating(struct drm_i915_private *i915) +{ + if (HAS_LLC(i915)) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl + * Display WA #0390: skl,kbl + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); + } + + /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP); + + /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */ + intel_uncore_rmw(&i915->uncore, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM); + + /* + * WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl + * Display WA #0859: skl,bxt,kbl,glk,cfl + */ + intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE); +} + +static void bxt_init_clock_gating(struct drm_i915_private *i915) +{ + gen9_init_clock_gating(i915); + + /* WaDisableSDEUnitClockGating:bxt */ + intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + + /* + * FIXME: + * GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only. + */ + intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); + + /* + * Wa: Backlight PWM may stop in the asserted state, causing backlight + * to stay fully on. + */ + intel_uncore_write(&i915->uncore, GEN9_CLKGATE_DIS_0, + intel_uncore_read(&i915->uncore, GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); + + /* + * Lower the display internal timeout. + * This is needed to avoid any hard hangs when DSI port PLL + * is off and a MMIO access is attempted by any privilege + * application, using batch buffers or any other means. + */ + intel_uncore_write(&i915->uncore, RM_TIMEOUT, MMIO_TIMEOUT_US(950)); + + /* + * WaFbcTurnOffFbcWatermark:bxt + * Display WA #0562: bxt + */ + intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + + /* + * WaFbcHighMemBwCorruptionAvoidance:bxt + * Display WA #0883: bxt + */ + intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); +} + +static void glk_init_clock_gating(struct drm_i915_private *i915) +{ + gen9_init_clock_gating(i915); + + /* + * WaDisablePWMClockGating:glk + * Backlight PWM may stop in the asserted state, causing backlight + * to stay fully on. + */ + intel_uncore_write(&i915->uncore, GEN9_CLKGATE_DIS_0, + intel_uncore_read(&i915->uncore, GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); +} + +static void ibx_init_clock_gating(struct drm_i915_private *i915) +{ + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + intel_uncore_write(&i915->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); +} + +static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) +{ + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(pipe), 0, DISP_TRICKLE_FEED_DISABLE); + + intel_uncore_rmw(&dev_priv->uncore, DSPSURF(pipe), 0, 0); + intel_uncore_posting_read(&dev_priv->uncore, DSPSURF(pipe)); + } +} + +static void ilk_init_clock_gating(struct drm_i915_private *i915) +{ + u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; + + /* + * Required for FBC + * WaFbcDisableDpfcClockGating:ilk + */ + dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | + ILK_DPFCUNIT_CLOCK_GATE_DISABLE | + ILK_DPFDUNIT_CLOCK_GATE_ENABLE; + + intel_uncore_write(&i915->uncore, PCH_3DCGDIS0, + MARIUNIT_CLOCK_GATE_DISABLE | + SVSMUNIT_CLOCK_GATE_DISABLE); + intel_uncore_write(&i915->uncore, PCH_3DCGDIS1, + VFMUNIT_CLOCK_GATE_DISABLE); + + /* + * According to the spec the following bits should be set in + * order to enable memory self-refresh + * The bit 22/21 of 0x42004 + * The bit 5 of 0x42020 + * The bit 15 of 0x45000 + */ + intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN2, + (intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL)); + dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; + intel_uncore_write(&i915->uncore, DISP_ARB_CTL, + (intel_uncore_read(&i915->uncore, DISP_ARB_CTL) | + DISP_FBC_WM_DIS)); + + /* + * Based on the document from hardware guys the following bits + * should be set unconditionally in order to enable FBC. + * The bit 22 of 0x42000 + * The bit 22 of 0x42004 + * The bit 7,8,9 of 0x42020. + */ + if (IS_IRONLAKE_M(i915)) { + /* WaFbcAsynchFlipDisableFbcQueue:ilk */ + intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); + intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE); + } + + intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); + + intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); + + g4x_disable_trickle_feed(i915); + + ibx_init_clock_gating(i915); +} + +static void cpt_init_clock_gating(struct drm_i915_private *i915) +{ + enum pipe pipe; + u32 val; + + /* + * On Ibex Peak and Cougar Point, we need to disable clock + * gating for the panel power sequencer or it will fail to + * start up when no ports are active. + */ + intel_uncore_write(&i915->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE | + PCH_DPLUNIT_CLOCK_GATE_DISABLE | + PCH_CPUNIT_CLOCK_GATE_DISABLE); + intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN2, 0, DPLS_EDP_PPS_FIX_DIS); + /* The below fixes the weird display corruption, a few pixels shifted + * downward, on (only) LVDS of some HP laptops with IVY. + */ + for_each_pipe(i915, pipe) { + val = intel_uncore_read(&i915->uncore, TRANS_CHICKEN2(pipe)); + val |= TRANS_CHICKEN2_TIMING_OVERRIDE; + val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; + if (i915->display.vbt.fdi_rx_polarity_inverted) + val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; + val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER; + val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH; + intel_uncore_write(&i915->uncore, TRANS_CHICKEN2(pipe), val); + } + /* WADP0ClockGatingDisable */ + for_each_pipe(i915, pipe) { + intel_uncore_write(&i915->uncore, TRANS_CHICKEN1(pipe), + TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); + } +} + +static void gen6_check_mch_setup(struct drm_i915_private *i915) +{ + u32 tmp; + + tmp = intel_uncore_read(&i915->uncore, MCH_SSKPD); + if (REG_FIELD_GET(SSKPD_WM0_MASK_SNB, tmp) != 12) + drm_dbg_kms(&i915->drm, + "Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n", + tmp); +} + +static void gen6_init_clock_gating(struct drm_i915_private *i915) +{ + u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; + + intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); + + intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); + + intel_uncore_write(&i915->uncore, GEN6_UCGCTL1, + intel_uncore_read(&i915->uncore, GEN6_UCGCTL1) | + GEN6_BLBUNIT_CLOCK_GATE_DISABLE | + GEN6_CSUNIT_CLOCK_GATE_DISABLE); + + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after + * some amount of runtime in the Mesa "fire" demo, and Unigine + * Sanctuary and Tropics, and apparently anything else with + * alpha test or pixel discard. + * + * According to the spec, bit 11 (RCCUNIT) must also be set, + * but we didn't debug actual testcases to find it out. + * + * WaDisableRCCUnitClockGating:snb + * WaDisableRCPBUnitClockGating:snb + */ + intel_uncore_write(&i915->uncore, GEN6_UCGCTL2, + GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | + GEN6_RCCUNIT_CLOCK_GATE_DISABLE); + + /* + * According to the spec the following bits should be + * set in order to enable memory self-refresh and fbc: + * The bit21 and bit22 of 0x42000 + * The bit21 and bit22 of 0x42004 + * The bit5 and bit7 of 0x42020 + * The bit14 of 0x70180 + * The bit14 of 0x71180 + * + * WaFbcAsynchFlipDisableFbcQueue:snb + */ + intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN1, + intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); + intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN2, + intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL); + intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, + intel_uncore_read(&i915->uncore, ILK_DSPCLK_GATE_D) | + ILK_DPARBUNIT_CLOCK_GATE_ENABLE | + ILK_DPFDUNIT_CLOCK_GATE_ENABLE); + + g4x_disable_trickle_feed(i915); + + cpt_init_clock_gating(i915); + + gen6_check_mch_setup(i915); +} + +static void lpt_init_clock_gating(struct drm_i915_private *i915) +{ + /* + * TODO: this bit should only be enabled when really needed, then + * disabled when not needed anymore in order to save power. + */ + if (HAS_PCH_LPT_LP(i915)) + intel_uncore_rmw(&i915->uncore, SOUTH_DSPCLK_GATE_D, + 0, PCH_LP_PARTITION_LEVEL_DISABLE); + + /* WADPOClockGatingDisable:hsw */ + intel_uncore_rmw(&i915->uncore, TRANS_CHICKEN1(PIPE_A), + 0, TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); +} + +static void gen8_set_l3sqc_credits(struct drm_i915_private *i915, + int general_prio_credits, + int high_prio_credits) +{ + u32 misccpctl; + u32 val; + + /* WaTempDisableDOPClkGating:bdw */ + misccpctl = intel_uncore_rmw(&i915->uncore, GEN7_MISCCPCTL, + GEN7_DOP_CLOCK_GATE_ENABLE, 0); + + val = intel_gt_mcr_read_any(to_gt(i915), GEN8_L3SQCREG1); + val &= ~L3_PRIO_CREDITS_MASK; + val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits); + val |= L3_HIGH_PRIO_CREDITS(high_prio_credits); + intel_gt_mcr_multicast_write(to_gt(i915), GEN8_L3SQCREG1, val); + + /* + * Wait at least 100 clocks before re-enabling clock gating. + * See the definition of L3SQCREG1 in BSpec. + */ + intel_gt_mcr_read_any(to_gt(i915), GEN8_L3SQCREG1); + udelay(1); + intel_uncore_write(&i915->uncore, GEN7_MISCCPCTL, misccpctl); +} + +static void icl_init_clock_gating(struct drm_i915_private *i915) +{ + /* Wa_1409120013:icl,ehl */ + intel_uncore_write(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), + DPFC_CHICKEN_COMP_DUMMY_PIXEL); + + /*Wa_14010594013:icl, ehl */ + intel_uncore_rmw(&i915->uncore, GEN8_CHICKEN_DCPR_1, + 0, ICL_DELAY_PMRSP); +} + +static void gen12lp_init_clock_gating(struct drm_i915_private *i915) +{ + /* Wa_1409120013 */ + if (DISPLAY_VER(i915) == 12) + intel_uncore_write(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), + DPFC_CHICKEN_COMP_DUMMY_PIXEL); + + /* Wa_14013723622:tgl,rkl,dg1,adl-s */ + if (DISPLAY_VER(i915) == 12) + intel_uncore_rmw(&i915->uncore, CLKREQ_POLICY, + CLKREQ_POLICY_MEM_UP_OVRD, 0); +} + +static void adlp_init_clock_gating(struct drm_i915_private *i915) +{ + gen12lp_init_clock_gating(i915); + + /* Wa_22011091694:adlp */ + intel_de_rmw(i915, GEN9_CLKGATE_DIS_5, 0, DPCE_GATING_DIS); + + /* Bspec/49189 Initialize Sequence */ + intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0); +} + +static void xehpsdv_init_clock_gating(struct drm_i915_private *i915) +{ + /* Wa_22010146351:xehpsdv */ + if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A0, STEP_B0)) + intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); +} + +static void dg2_init_clock_gating(struct drm_i915_private *i915) +{ + /* Wa_22010954014:dg2 */ + intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, + SGSI_SIDECLK_DIS); + + /* + * Wa_14010733611:dg2_g10 + * Wa_22010146351:dg2_g10 + */ + if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) + intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, + SGR_DIS | SGGI_DIS); +} + +static void pvc_init_clock_gating(struct drm_i915_private *i915) +{ + /* Wa_14012385139:pvc */ + if (IS_PVC_BD_STEP(i915, STEP_A0, STEP_B0)) + intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); + + /* Wa_22010954014:pvc */ + if (IS_PVC_BD_STEP(i915, STEP_A0, STEP_B0)) + intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGSI_SIDECLK_DIS); +} + +static void cnp_init_clock_gating(struct drm_i915_private *i915) +{ + if (!HAS_PCH_CNP(i915)) + return; + + /* Display WA #1181 WaSouthDisplayDisablePWMCGEGating: cnp */ + intel_uncore_rmw(&i915->uncore, SOUTH_DSPCLK_GATE_D, 0, CNP_PWM_CGE_GATING_DISABLE); +} + +static void cfl_init_clock_gating(struct drm_i915_private *i915) +{ + cnp_init_clock_gating(i915); + gen9_init_clock_gating(i915); + + /* WAC6entrylatency:cfl */ + intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); + + /* + * WaFbcTurnOffFbcWatermark:cfl + * Display WA #0562: cfl + */ + intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + + /* + * WaFbcNukeOnHostModify:cfl + * Display WA #0873: cfl + */ + intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), + 0, DPFC_NUKE_ON_ANY_MODIFICATION); +} + +static void kbl_init_clock_gating(struct drm_i915_private *i915) +{ + gen9_init_clock_gating(i915); + + /* WAC6entrylatency:kbl */ + intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); + + /* WaDisableSDEUnitClockGating:kbl */ + if (IS_KBL_GRAPHICS_STEP(i915, 0, STEP_C0)) + intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, + 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + + /* WaDisableGamClockGating:kbl */ + if (IS_KBL_GRAPHICS_STEP(i915, 0, STEP_C0)) + intel_uncore_rmw(&i915->uncore, GEN6_UCGCTL1, + 0, GEN6_GAMUNIT_CLOCK_GATE_DISABLE); + + /* + * WaFbcTurnOffFbcWatermark:kbl + * Display WA #0562: kbl + */ + intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + + /* + * WaFbcNukeOnHostModify:kbl + * Display WA #0873: kbl + */ + intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), + 0, DPFC_NUKE_ON_ANY_MODIFICATION); +} + +static void skl_init_clock_gating(struct drm_i915_private *i915) +{ + gen9_init_clock_gating(i915); + + /* WaDisableDopClockGating:skl */ + intel_uncore_rmw(&i915->uncore, GEN7_MISCCPCTL, + GEN7_DOP_CLOCK_GATE_ENABLE, 0); + + /* WAC6entrylatency:skl */ + intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); + + /* + * WaFbcTurnOffFbcWatermark:skl + * Display WA #0562: skl + */ + intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + + /* + * WaFbcNukeOnHostModify:skl + * Display WA #0873: skl + */ + intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), + 0, DPFC_NUKE_ON_ANY_MODIFICATION); + + /* + * WaFbcHighMemBwCorruptionAvoidance:skl + * Display WA #0883: skl + */ + intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); +} + +static void bdw_init_clock_gating(struct drm_i915_private *i915) +{ + enum pipe pipe; + + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); + + /* WaSwitchSolVfFArbitrationPriority:bdw */ + intel_uncore_rmw(&i915->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL); + + /* WaPsrDPAMaskVBlankInSRD:bdw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, DPA_MASK_VBLANK_SRD); + + for_each_pipe(i915, pipe) { + /* WaPsrDPRSUnmaskVBlankInSRD:bdw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(pipe), + 0, BDW_DPRS_MASK_VBLANK_SRD); + } + + /* WaVSRefCountFullforceMissDisable:bdw */ + /* WaDSRefCountFullforceMissDisable:bdw */ + intel_uncore_rmw(&i915->uncore, GEN7_FF_THREAD_MODE, + GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0); + + intel_uncore_write(&i915->uncore, RING_PSMI_CTL(RENDER_RING_BASE), + _MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE)); + + /* WaDisableSDEUnitClockGating:bdw */ + intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + + /* WaProgramL3SqcReg1Default:bdw */ + gen8_set_l3sqc_credits(i915, 30, 2); + + /* WaKVMNotificationOnConfigChange:bdw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PAR2_1, + 0, KVM_CONFIG_CHANGE_NOTIFICATION_SELECT); + + lpt_init_clock_gating(i915); + + /* WaDisableDopClockGating:bdw + * + * Also see the CHICKEN2 write in bdw_init_workarounds() to disable DOP + * clock gating. + */ + intel_uncore_rmw(&i915->uncore, GEN6_UCGCTL1, 0, GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE); +} + +static void hsw_init_clock_gating(struct drm_i915_private *i915) +{ + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); + + /* This is required by WaCatErrorRejectionIssue:hsw */ + intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, + 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + + /* WaSwitchSolVfFArbitrationPriority:hsw */ + intel_uncore_rmw(&i915->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL); + + lpt_init_clock_gating(i915); +} + +static void ivb_init_clock_gating(struct drm_i915_private *i915) +{ + intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); + + /* WaFbcAsynchFlipDisableFbcQueue:ivb */ + intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); + + /* WaDisableBackToBackFlipFix:ivb */ + intel_uncore_write(&i915->uncore, IVB_CHICKEN3, + CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | + CHICKEN3_DGMG_DONE_FIX_DISABLE); + + if (IS_IVB_GT1(i915)) + intel_uncore_write(&i915->uncore, GEN7_ROW_CHICKEN2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + else { + /* must write both registers */ + intel_uncore_write(&i915->uncore, GEN7_ROW_CHICKEN2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + intel_uncore_write(&i915->uncore, GEN7_ROW_CHICKEN2_GT2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + } + + /* + * According to the spec, bit 13 (RCZUNIT) must be set on IVB. + * This implements the WaDisableRCZUnitClockGating:ivb workaround. + */ + intel_uncore_write(&i915->uncore, GEN6_UCGCTL2, + GEN6_RCZUNIT_CLOCK_GATE_DISABLE); + + /* This is required by WaCatErrorRejectionIssue:ivb */ + intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, + 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + + g4x_disable_trickle_feed(i915); + + intel_uncore_rmw(&i915->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK, + GEN6_MBC_SNPCR_MED); + + if (!HAS_PCH_NOP(i915)) + cpt_init_clock_gating(i915); + + gen6_check_mch_setup(i915); +} + +static void vlv_init_clock_gating(struct drm_i915_private *i915) +{ + /* WaDisableBackToBackFlipFix:vlv */ + intel_uncore_write(&i915->uncore, IVB_CHICKEN3, + CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | + CHICKEN3_DGMG_DONE_FIX_DISABLE); + + /* WaDisableDopClockGating:vlv */ + intel_uncore_write(&i915->uncore, GEN7_ROW_CHICKEN2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + + /* This is required by WaCatErrorRejectionIssue:vlv */ + intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, + 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + + /* + * According to the spec, bit 13 (RCZUNIT) must be set on IVB. + * This implements the WaDisableRCZUnitClockGating:vlv workaround. + */ + intel_uncore_write(&i915->uncore, GEN6_UCGCTL2, + GEN6_RCZUNIT_CLOCK_GATE_DISABLE); + + /* WaDisableL3Bank2xClockGate:vlv + * Disabling L3 clock gating- MMIO 940c[25] = 1 + * Set bit 25, to disable L3_BANK_2x_CLK_GATING */ + intel_uncore_rmw(&i915->uncore, GEN7_UCGCTL4, 0, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); + + /* + * WaDisableVLVClockGating_VBIIssue:vlv + * Disable clock gating on th GCFG unit to prevent a delay + * in the reporting of vblank events. + */ + intel_uncore_write(&i915->uncore, VLV_GUNIT_CLOCK_GATE, GCFG_DIS); +} + +static void chv_init_clock_gating(struct drm_i915_private *i915) +{ + /* WaVSRefCountFullforceMissDisable:chv */ + /* WaDSRefCountFullforceMissDisable:chv */ + intel_uncore_rmw(&i915->uncore, GEN7_FF_THREAD_MODE, + GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0); + + /* WaDisableSemaphoreAndSyncFlipWait:chv */ + intel_uncore_write(&i915->uncore, RING_PSMI_CTL(RENDER_RING_BASE), + _MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE)); + + /* WaDisableCSUnitClockGating:chv */ + intel_uncore_rmw(&i915->uncore, GEN6_UCGCTL1, 0, GEN6_CSUNIT_CLOCK_GATE_DISABLE); + + /* WaDisableSDEUnitClockGating:chv */ + intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); + + /* + * WaProgramL3SqcReg1Default:chv + * See gfxspecs/Related Documents/Performance Guide/ + * LSQC Setting Recommendations. + */ + gen8_set_l3sqc_credits(i915, 38, 2); +} + +static void g4x_init_clock_gating(struct drm_i915_private *i915) +{ + u32 dspclk_gate; + + intel_uncore_write(&i915->uncore, RENCLK_GATE_D1, 0); + intel_uncore_write(&i915->uncore, RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | + GS_UNIT_CLOCK_GATE_DISABLE | + CL_UNIT_CLOCK_GATE_DISABLE); + intel_uncore_write(&i915->uncore, RAMCLK_GATE_D, 0); + dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | + OVRUNIT_CLOCK_GATE_DISABLE | + OVCUNIT_CLOCK_GATE_DISABLE; + if (IS_GM45(i915)) + dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; + intel_uncore_write(&i915->uncore, DSPCLK_GATE_D(i915), dspclk_gate); + + g4x_disable_trickle_feed(i915); +} + +static void i965gm_init_clock_gating(struct drm_i915_private *i915) +{ + struct intel_uncore *uncore = &i915->uncore; + + intel_uncore_write(uncore, RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); + intel_uncore_write(uncore, RENCLK_GATE_D2, 0); + intel_uncore_write(uncore, DSPCLK_GATE_D(i915), 0); + intel_uncore_write(uncore, RAMCLK_GATE_D, 0); + intel_uncore_write16(uncore, DEUC, 0); + intel_uncore_write(uncore, + MI_ARB_STATE, + _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); +} + +static void i965g_init_clock_gating(struct drm_i915_private *i915) +{ + intel_uncore_write(&i915->uncore, RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | + I965_RCC_CLOCK_GATE_DISABLE | + I965_RCPB_CLOCK_GATE_DISABLE | + I965_ISC_CLOCK_GATE_DISABLE | + I965_FBC_CLOCK_GATE_DISABLE); + intel_uncore_write(&i915->uncore, RENCLK_GATE_D2, 0); + intel_uncore_write(&i915->uncore, MI_ARB_STATE, + _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); +} + +static void gen3_init_clock_gating(struct drm_i915_private *i915) +{ + u32 dstate = intel_uncore_read(&i915->uncore, D_STATE); + + dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | + DSTATE_DOT_CLOCK_GATING; + intel_uncore_write(&i915->uncore, D_STATE, dstate); + + if (IS_PINEVIEW(i915)) + intel_uncore_write(&i915->uncore, ECOSKPD(RENDER_RING_BASE), + _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); + + /* IIR "flip pending" means done if this bit is set */ + intel_uncore_write(&i915->uncore, ECOSKPD(RENDER_RING_BASE), + _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); + + /* interrupts should cause a wake up from C3 */ + intel_uncore_write(&i915->uncore, INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_INT_EN)); + + /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ + intel_uncore_write(&i915->uncore, MI_ARB_STATE, + _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE)); + + intel_uncore_write(&i915->uncore, MI_ARB_STATE, + _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); +} + +static void i85x_init_clock_gating(struct drm_i915_private *i915) +{ + intel_uncore_write(&i915->uncore, RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); + + /* interrupts should cause a wake up from C3 */ + intel_uncore_write(&i915->uncore, MI_STATE, _MASKED_BIT_ENABLE(MI_AGPBUSY_INT_EN) | + _MASKED_BIT_DISABLE(MI_AGPBUSY_830_MODE)); + + intel_uncore_write(&i915->uncore, MEM_MODE, + _MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE)); + + /* + * Have FBC ignore 3D activity since we use software + * render tracking, and otherwise a pure 3D workload + * (even if it just renders a single frame and then does + * abosultely nothing) would not allow FBC to recompress + * until a 2D blit occurs. + */ + intel_uncore_write(&i915->uncore, SCPD0, + _MASKED_BIT_ENABLE(SCPD_FBC_IGNORE_3D)); +} + +static void i830_init_clock_gating(struct drm_i915_private *i915) +{ + intel_uncore_write(&i915->uncore, MEM_MODE, + _MASKED_BIT_ENABLE(MEM_DISPLAY_A_TRICKLE_FEED_DISABLE) | + _MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE)); +} + +void intel_clock_gating_init(struct drm_i915_private *i915) +{ + i915->clock_gating_funcs->init_clock_gating(i915); +} + +static void nop_init_clock_gating(struct drm_i915_private *i915) +{ + drm_dbg_kms(&i915->drm, + "No clock gating settings or workarounds applied.\n"); +} + +#define CG_FUNCS(platform) \ +static const struct drm_i915_clock_gating_funcs platform##_clock_gating_funcs = { \ + .init_clock_gating = platform##_init_clock_gating, \ +} + +CG_FUNCS(pvc); +CG_FUNCS(dg2); +CG_FUNCS(xehpsdv); +CG_FUNCS(adlp); +CG_FUNCS(gen12lp); +CG_FUNCS(icl); +CG_FUNCS(cfl); +CG_FUNCS(skl); +CG_FUNCS(kbl); +CG_FUNCS(bxt); +CG_FUNCS(glk); +CG_FUNCS(bdw); +CG_FUNCS(chv); +CG_FUNCS(hsw); +CG_FUNCS(ivb); +CG_FUNCS(vlv); +CG_FUNCS(gen6); +CG_FUNCS(ilk); +CG_FUNCS(g4x); +CG_FUNCS(i965gm); +CG_FUNCS(i965g); +CG_FUNCS(gen3); +CG_FUNCS(i85x); +CG_FUNCS(i830); +CG_FUNCS(nop); +#undef CG_FUNCS + +/** + * intel_clock_gating_hooks_init - setup the clock gating hooks + * @i915: device private + * + * Setup the hooks that configure which clocks of a given platform can be + * gated and also apply various GT and display specific workarounds for these + * platforms. Note that some GT specific workarounds are applied separately + * when GPU contexts or batchbuffers start their execution. + */ +void intel_clock_gating_hooks_init(struct drm_i915_private *i915) +{ + if (IS_METEORLAKE(i915)) + i915->clock_gating_funcs = &nop_clock_gating_funcs; + else if (IS_PONTEVECCHIO(i915)) + i915->clock_gating_funcs = &pvc_clock_gating_funcs; + else if (IS_DG2(i915)) + i915->clock_gating_funcs = &dg2_clock_gating_funcs; + else if (IS_XEHPSDV(i915)) + i915->clock_gating_funcs = &xehpsdv_clock_gating_funcs; + else if (IS_ALDERLAKE_P(i915)) + i915->clock_gating_funcs = &adlp_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 12) + i915->clock_gating_funcs = &gen12lp_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 11) + i915->clock_gating_funcs = &icl_clock_gating_funcs; + else if (IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) + i915->clock_gating_funcs = &cfl_clock_gating_funcs; + else if (IS_SKYLAKE(i915)) + i915->clock_gating_funcs = &skl_clock_gating_funcs; + else if (IS_KABYLAKE(i915)) + i915->clock_gating_funcs = &kbl_clock_gating_funcs; + else if (IS_BROXTON(i915)) + i915->clock_gating_funcs = &bxt_clock_gating_funcs; + else if (IS_GEMINILAKE(i915)) + i915->clock_gating_funcs = &glk_clock_gating_funcs; + else if (IS_BROADWELL(i915)) + i915->clock_gating_funcs = &bdw_clock_gating_funcs; + else if (IS_CHERRYVIEW(i915)) + i915->clock_gating_funcs = &chv_clock_gating_funcs; + else if (IS_HASWELL(i915)) + i915->clock_gating_funcs = &hsw_clock_gating_funcs; + else if (IS_IVYBRIDGE(i915)) + i915->clock_gating_funcs = &ivb_clock_gating_funcs; + else if (IS_VALLEYVIEW(i915)) + i915->clock_gating_funcs = &vlv_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 6) + i915->clock_gating_funcs = &gen6_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 5) + i915->clock_gating_funcs = &ilk_clock_gating_funcs; + else if (IS_G4X(i915)) + i915->clock_gating_funcs = &g4x_clock_gating_funcs; + else if (IS_I965GM(i915)) + i915->clock_gating_funcs = &i965gm_clock_gating_funcs; + else if (IS_I965G(i915)) + i915->clock_gating_funcs = &i965g_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 3) + i915->clock_gating_funcs = &gen3_clock_gating_funcs; + else if (IS_I85X(i915) || IS_I865G(i915)) + i915->clock_gating_funcs = &i85x_clock_gating_funcs; + else if (GRAPHICS_VER(i915) == 2) + i915->clock_gating_funcs = &i830_clock_gating_funcs; + else { + MISSING_CASE(INTEL_DEVID(i915)); + i915->clock_gating_funcs = &nop_clock_gating_funcs; + } +} diff --git a/drivers/gpu/drm/i915/intel_clock_gating.h b/drivers/gpu/drm/i915/intel_clock_gating.h new file mode 100644 index 000000000000..5b4e4c55b2c2 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_clock_gating.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_CLOCK_GATING_H__ +#define __INTEL_CLOCK_GATING_H__ + +struct drm_i915_private; + +void intel_clock_gating_init(struct drm_i915_private *i915); +void intel_clock_gating_hooks_init(struct drm_i915_private *i915); + +#endif /* __INTEL_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 0aad8e48d27d..080a4557899b 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -193,7 +193,6 @@ enum intel_ppgtt_type { func(has_hotplug); \ func(has_hti); \ func(has_ipc); \ - func(has_modular_fia); \ func(has_overlay); \ func(has_psr); \ func(has_psr_hw_tracking); \ diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index 091743e32e17..5d08774029cc 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -7,8 +7,12 @@ #include "display/intel_backlight_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" +#include "display/intel_dp_aux_regs.h" #include "display/intel_dpio_phy.h" +#include "display/intel_fdi_regs.h" #include "display/intel_lvds_regs.h" +#include "display/intel_psr_regs.h" +#include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" #include "gvt/gvt.h" diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c deleted file mode 100644 index c45af0d981fd..000000000000 --- a/drivers/gpu/drm/i915/intel_pm.c +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eugeni Dodonov <eugeni.dodonov@intel.com> - * - */ - -#include "display/intel_de.h" -#include "display/intel_display.h" -#include "display/intel_display_trace.h" -#include "display/skl_watermark.h" - -#include "gt/intel_engine_regs.h" -#include "gt/intel_gt.h" -#include "gt/intel_gt_mcr.h" -#include "gt/intel_gt_regs.h" - -#include "i915_drv.h" -#include "intel_mchbar_regs.h" -#include "intel_pm.h" -#include "vlv_sideband.h" - -struct drm_i915_clock_gating_funcs { - void (*init_clock_gating)(struct drm_i915_private *i915); -}; - -static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) -{ - if (HAS_LLC(dev_priv)) { - /* - * WaCompressedResourceDisplayNewHashMode:skl,kbl - * Display WA #0390: skl,kbl - * - * Must match Sampler, Pixel Back End, and Media. See - * WaCompressedResourceSamplerPbeMediaNewHashMode. - */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); - } - - /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP); - - /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM); - - /* - * WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl - * Display WA #0859: skl,bxt,kbl,glk,cfl - */ - intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE); -} - -static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) -{ - gen9_init_clock_gating(dev_priv); - - /* WaDisableSDEUnitClockGating:bxt */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - - /* - * FIXME: - * GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only. - */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); - - /* - * Wa: Backlight PWM may stop in the asserted state, causing backlight - * to stay fully on. - */ - intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_0, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_0) | - PWM1_GATING_DIS | PWM2_GATING_DIS); - - /* - * Lower the display internal timeout. - * This is needed to avoid any hard hangs when DSI port PLL - * is off and a MMIO access is attempted by any privilege - * application, using batch buffers or any other means. - */ - intel_uncore_write(&dev_priv->uncore, RM_TIMEOUT, MMIO_TIMEOUT_US(950)); - - /* - * WaFbcTurnOffFbcWatermark:bxt - * Display WA #0562: bxt - */ - intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcHighMemBwCorruptionAvoidance:bxt - * Display WA #0883: bxt - */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); -} - -static void glk_init_clock_gating(struct drm_i915_private *dev_priv) -{ - gen9_init_clock_gating(dev_priv); - - /* - * WaDisablePWMClockGating:glk - * Backlight PWM may stop in the asserted state, causing backlight - * to stay fully on. - */ - intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_0, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_0) | - PWM1_GATING_DIS | PWM2_GATING_DIS); -} - -static void ibx_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - intel_uncore_write(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); -} - -static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) -{ - enum pipe pipe; - - for_each_pipe(dev_priv, pipe) { - intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(pipe), 0, DISP_TRICKLE_FEED_DISABLE); - - intel_uncore_rmw(&dev_priv->uncore, DSPSURF(pipe), 0, 0); - intel_uncore_posting_read(&dev_priv->uncore, DSPSURF(pipe)); - } -} - -static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) -{ - u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; - - /* - * Required for FBC - * WaFbcDisableDpfcClockGating:ilk - */ - dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | - ILK_DPFCUNIT_CLOCK_GATE_DISABLE | - ILK_DPFDUNIT_CLOCK_GATE_ENABLE; - - intel_uncore_write(&dev_priv->uncore, PCH_3DCGDIS0, - MARIUNIT_CLOCK_GATE_DISABLE | - SVSMUNIT_CLOCK_GATE_DISABLE); - intel_uncore_write(&dev_priv->uncore, PCH_3DCGDIS1, - VFMUNIT_CLOCK_GATE_DISABLE); - - /* - * According to the spec the following bits should be set in - * order to enable memory self-refresh - * The bit 22/21 of 0x42004 - * The bit 5 of 0x42020 - * The bit 15 of 0x45000 - */ - intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, - (intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL)); - dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; - intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, - (intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) | - DISP_FBC_WM_DIS)); - - /* - * Based on the document from hardware guys the following bits - * should be set unconditionally in order to enable FBC. - * The bit 22 of 0x42000 - * The bit 22 of 0x42004 - * The bit 7,8,9 of 0x42020. - */ - if (IS_IRONLAKE_M(dev_priv)) { - /* WaFbcAsynchFlipDisableFbcQueue:ilk */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); - intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE); - } - - intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); - - intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); - - g4x_disable_trickle_feed(dev_priv); - - ibx_init_clock_gating(dev_priv); -} - -static void cpt_init_clock_gating(struct drm_i915_private *dev_priv) -{ - enum pipe pipe; - u32 val; - - /* - * On Ibex Peak and Cougar Point, we need to disable clock - * gating for the panel power sequencer or it will fail to - * start up when no ports are active. - */ - intel_uncore_write(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE | - PCH_DPLUNIT_CLOCK_GATE_DISABLE | - PCH_CPUNIT_CLOCK_GATE_DISABLE); - intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN2, 0, DPLS_EDP_PPS_FIX_DIS); - /* The below fixes the weird display corruption, a few pixels shifted - * downward, on (only) LVDS of some HP laptops with IVY. - */ - for_each_pipe(dev_priv, pipe) { - val = intel_uncore_read(&dev_priv->uncore, TRANS_CHICKEN2(pipe)); - val |= TRANS_CHICKEN2_TIMING_OVERRIDE; - val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; - if (dev_priv->display.vbt.fdi_rx_polarity_inverted) - val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; - val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER; - val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH; - intel_uncore_write(&dev_priv->uncore, TRANS_CHICKEN2(pipe), val); - } - /* WADP0ClockGatingDisable */ - for_each_pipe(dev_priv, pipe) { - intel_uncore_write(&dev_priv->uncore, TRANS_CHICKEN1(pipe), - TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); - } -} - -static void gen6_check_mch_setup(struct drm_i915_private *dev_priv) -{ - u32 tmp; - - tmp = intel_uncore_read(&dev_priv->uncore, MCH_SSKPD); - if (REG_FIELD_GET(SSKPD_WM0_MASK_SNB, tmp) != 12) - drm_dbg_kms(&dev_priv->drm, - "Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n", - tmp); -} - -static void gen6_init_clock_gating(struct drm_i915_private *dev_priv) -{ - u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; - - intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); - - intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); - - intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1, - intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) | - GEN6_BLBUNIT_CLOCK_GATE_DISABLE | - GEN6_CSUNIT_CLOCK_GATE_DISABLE); - - /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock - * gating disable must be set. Failure to set it results in - * flickering pixels due to Z write ordering failures after - * some amount of runtime in the Mesa "fire" demo, and Unigine - * Sanctuary and Tropics, and apparently anything else with - * alpha test or pixel discard. - * - * According to the spec, bit 11 (RCCUNIT) must also be set, - * but we didn't debug actual testcases to find it out. - * - * WaDisableRCCUnitClockGating:snb - * WaDisableRCPBUnitClockGating:snb - */ - intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL2, - GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | - GEN6_RCCUNIT_CLOCK_GATE_DISABLE); - - /* - * According to the spec the following bits should be - * set in order to enable memory self-refresh and fbc: - * The bit21 and bit22 of 0x42000 - * The bit21 and bit22 of 0x42004 - * The bit5 and bit7 of 0x42020 - * The bit14 of 0x70180 - * The bit14 of 0x71180 - * - * WaFbcAsynchFlipDisableFbcQueue:snb - */ - intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1, - intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1) | - ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); - intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, - intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL); - intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, - intel_uncore_read(&dev_priv->uncore, ILK_DSPCLK_GATE_D) | - ILK_DPARBUNIT_CLOCK_GATE_ENABLE | - ILK_DPFDUNIT_CLOCK_GATE_ENABLE); - - g4x_disable_trickle_feed(dev_priv); - - cpt_init_clock_gating(dev_priv); - - gen6_check_mch_setup(dev_priv); -} - -static void lpt_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* - * TODO: this bit should only be enabled when really needed, then - * disabled when not needed anymore in order to save power. - */ - if (HAS_PCH_LPT_LP(dev_priv)) - intel_uncore_rmw(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, - 0, PCH_LP_PARTITION_LEVEL_DISABLE); - - /* WADPOClockGatingDisable:hsw */ - intel_uncore_rmw(&dev_priv->uncore, TRANS_CHICKEN1(PIPE_A), - 0, TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); -} - -static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, - int general_prio_credits, - int high_prio_credits) -{ - u32 misccpctl; - u32 val; - - /* WaTempDisableDOPClkGating:bdw */ - misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, - GEN7_DOP_CLOCK_GATE_ENABLE, 0); - - val = intel_gt_mcr_read_any(to_gt(dev_priv), GEN8_L3SQCREG1); - val &= ~L3_PRIO_CREDITS_MASK; - val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits); - val |= L3_HIGH_PRIO_CREDITS(high_prio_credits); - intel_gt_mcr_multicast_write(to_gt(dev_priv), GEN8_L3SQCREG1, val); - - /* - * Wait at least 100 clocks before re-enabling clock gating. - * See the definition of L3SQCREG1 in BSpec. - */ - intel_gt_mcr_read_any(to_gt(dev_priv), GEN8_L3SQCREG1); - udelay(1); - intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); -} - -static void icl_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* Wa_1409120013:icl,ehl */ - intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - DPFC_CHICKEN_COMP_DUMMY_PIXEL); - - /*Wa_14010594013:icl, ehl */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1, - 0, ICL_DELAY_PMRSP); -} - -static void gen12lp_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* Wa_1409120013 */ - if (DISPLAY_VER(dev_priv) == 12) - intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - DPFC_CHICKEN_COMP_DUMMY_PIXEL); - - /* Wa_14013723622:tgl,rkl,dg1,adl-s */ - if (DISPLAY_VER(dev_priv) == 12) - intel_uncore_rmw(&dev_priv->uncore, CLKREQ_POLICY, - CLKREQ_POLICY_MEM_UP_OVRD, 0); -} - -static void adlp_init_clock_gating(struct drm_i915_private *dev_priv) -{ - gen12lp_init_clock_gating(dev_priv); - - /* Wa_22011091694:adlp */ - intel_de_rmw(dev_priv, GEN9_CLKGATE_DIS_5, 0, DPCE_GATING_DIS); - - /* Bspec/49189 Initialize Sequence */ - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0); -} - -static void xehpsdv_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* Wa_22010146351:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(dev_priv, STEP_A0, STEP_B0)) - intel_uncore_rmw(&dev_priv->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); -} - -static void dg2_init_clock_gating(struct drm_i915_private *i915) -{ - /* Wa_22010954014:dg2 */ - intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, - SGSI_SIDECLK_DIS); - - /* - * Wa_14010733611:dg2_g10 - * Wa_22010146351:dg2_g10 - */ - if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) - intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, - SGR_DIS | SGGI_DIS); -} - -static void pvc_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* Wa_14012385139:pvc */ - if (IS_PVC_BD_STEP(dev_priv, STEP_A0, STEP_B0)) - intel_uncore_rmw(&dev_priv->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); - - /* Wa_22010954014:pvc */ - if (IS_PVC_BD_STEP(dev_priv, STEP_A0, STEP_B0)) - intel_uncore_rmw(&dev_priv->uncore, XEHP_CLOCK_GATE_DIS, 0, SGSI_SIDECLK_DIS); -} - -static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) -{ - if (!HAS_PCH_CNP(dev_priv)) - return; - - /* Display WA #1181 WaSouthDisplayDisablePWMCGEGating: cnp */ - intel_uncore_rmw(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, 0, CNP_PWM_CGE_GATING_DISABLE); -} - -static void cfl_init_clock_gating(struct drm_i915_private *dev_priv) -{ - cnp_init_clock_gating(dev_priv); - gen9_init_clock_gating(dev_priv); - - /* WAC6entrylatency:cfl */ - intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); - - /* - * WaFbcTurnOffFbcWatermark:cfl - * Display WA #0562: cfl - */ - intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:cfl - * Display WA #0873: cfl - */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); -} - -static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) -{ - gen9_init_clock_gating(dev_priv); - - /* WAC6entrylatency:kbl */ - intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); - - /* WaDisableSDEUnitClockGating:kbl */ - if (IS_KBL_GRAPHICS_STEP(dev_priv, 0, STEP_C0)) - intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, - 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - - /* WaDisableGamClockGating:kbl */ - if (IS_KBL_GRAPHICS_STEP(dev_priv, 0, STEP_C0)) - intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1, - 0, GEN6_GAMUNIT_CLOCK_GATE_DISABLE); - - /* - * WaFbcTurnOffFbcWatermark:kbl - * Display WA #0562: kbl - */ - intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:kbl - * Display WA #0873: kbl - */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); -} - -static void skl_init_clock_gating(struct drm_i915_private *dev_priv) -{ - gen9_init_clock_gating(dev_priv); - - /* WaDisableDopClockGating:skl */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, - GEN7_DOP_CLOCK_GATE_ENABLE, 0); - - /* WAC6entrylatency:skl */ - intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); - - /* - * WaFbcTurnOffFbcWatermark:skl - * Display WA #0562: skl - */ - intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:skl - * Display WA #0873: skl - */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); - - /* - * WaFbcHighMemBwCorruptionAvoidance:skl - * Display WA #0883: skl - */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); -} - -static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) -{ - enum pipe pipe; - - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); - - /* WaSwitchSolVfFArbitrationPriority:bdw */ - intel_uncore_rmw(&dev_priv->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL); - - /* WaPsrDPAMaskVBlankInSRD:bdw */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, DPA_MASK_VBLANK_SRD); - - for_each_pipe(dev_priv, pipe) { - /* WaPsrDPRSUnmaskVBlankInSRD:bdw */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe), - 0, BDW_DPRS_MASK_VBLANK_SRD); - } - - /* WaVSRefCountFullforceMissDisable:bdw */ - /* WaDSRefCountFullforceMissDisable:bdw */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_FF_THREAD_MODE, - GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0); - - intel_uncore_write(&dev_priv->uncore, RING_PSMI_CTL(RENDER_RING_BASE), - _MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE)); - - /* WaDisableSDEUnitClockGating:bdw */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - - /* WaProgramL3SqcReg1Default:bdw */ - gen8_set_l3sqc_credits(dev_priv, 30, 2); - - /* WaKVMNotificationOnConfigChange:bdw */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR2_1, - 0, KVM_CONFIG_CHANGE_NOTIFICATION_SELECT); - - lpt_init_clock_gating(dev_priv); - - /* WaDisableDopClockGating:bdw - * - * Also see the CHICKEN2 write in bdw_init_workarounds() to disable DOP - * clock gating. - */ - intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1, 0, GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE); -} - -static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); - - /* This is required by WaCatErrorRejectionIssue:hsw */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, - 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - - /* WaSwitchSolVfFArbitrationPriority:hsw */ - intel_uncore_rmw(&dev_priv->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL); - - lpt_init_clock_gating(dev_priv); -} - -static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) -{ - intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); - - /* WaFbcAsynchFlipDisableFbcQueue:ivb */ - intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); - - /* WaDisableBackToBackFlipFix:ivb */ - intel_uncore_write(&dev_priv->uncore, IVB_CHICKEN3, - CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | - CHICKEN3_DGMG_DONE_FIX_DISABLE); - - if (IS_IVB_GT1(dev_priv)) - intel_uncore_write(&dev_priv->uncore, GEN7_ROW_CHICKEN2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); - else { - /* must write both registers */ - intel_uncore_write(&dev_priv->uncore, GEN7_ROW_CHICKEN2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); - intel_uncore_write(&dev_priv->uncore, GEN7_ROW_CHICKEN2_GT2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); - } - - /* - * According to the spec, bit 13 (RCZUNIT) must be set on IVB. - * This implements the WaDisableRCZUnitClockGating:ivb workaround. - */ - intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL2, - GEN6_RCZUNIT_CLOCK_GATE_DISABLE); - - /* This is required by WaCatErrorRejectionIssue:ivb */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, - 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - - g4x_disable_trickle_feed(dev_priv); - - intel_uncore_rmw(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK, - GEN6_MBC_SNPCR_MED); - - if (!HAS_PCH_NOP(dev_priv)) - cpt_init_clock_gating(dev_priv); - - gen6_check_mch_setup(dev_priv); -} - -static void vlv_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* WaDisableBackToBackFlipFix:vlv */ - intel_uncore_write(&dev_priv->uncore, IVB_CHICKEN3, - CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | - CHICKEN3_DGMG_DONE_FIX_DISABLE); - - /* WaDisableDopClockGating:vlv */ - intel_uncore_write(&dev_priv->uncore, GEN7_ROW_CHICKEN2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); - - /* This is required by WaCatErrorRejectionIssue:vlv */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, - 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - - /* - * According to the spec, bit 13 (RCZUNIT) must be set on IVB. - * This implements the WaDisableRCZUnitClockGating:vlv workaround. - */ - intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL2, - GEN6_RCZUNIT_CLOCK_GATE_DISABLE); - - /* WaDisableL3Bank2xClockGate:vlv - * Disabling L3 clock gating- MMIO 940c[25] = 1 - * Set bit 25, to disable L3_BANK_2x_CLK_GATING */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_UCGCTL4, 0, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); - - /* - * WaDisableVLVClockGating_VBIIssue:vlv - * Disable clock gating on th GCFG unit to prevent a delay - * in the reporting of vblank events. - */ - intel_uncore_write(&dev_priv->uncore, VLV_GUNIT_CLOCK_GATE, GCFG_DIS); -} - -static void chv_init_clock_gating(struct drm_i915_private *dev_priv) -{ - /* WaVSRefCountFullforceMissDisable:chv */ - /* WaDSRefCountFullforceMissDisable:chv */ - intel_uncore_rmw(&dev_priv->uncore, GEN7_FF_THREAD_MODE, - GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0); - - /* WaDisableSemaphoreAndSyncFlipWait:chv */ - intel_uncore_write(&dev_priv->uncore, RING_PSMI_CTL(RENDER_RING_BASE), - _MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE)); - - /* WaDisableCSUnitClockGating:chv */ - intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1, 0, GEN6_CSUNIT_CLOCK_GATE_DISABLE); - - /* WaDisableSDEUnitClockGating:chv */ - intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - - /* - * WaProgramL3SqcReg1Default:chv - * See gfxspecs/Related Documents/Performance Guide/ - * LSQC Setting Recommendations. - */ - gen8_set_l3sqc_credits(dev_priv, 38, 2); -} - -static void g4x_init_clock_gating(struct drm_i915_private *dev_priv) -{ - u32 dspclk_gate; - - intel_uncore_write(&dev_priv->uncore, RENCLK_GATE_D1, 0); - intel_uncore_write(&dev_priv->uncore, RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | - GS_UNIT_CLOCK_GATE_DISABLE | - CL_UNIT_CLOCK_GATE_DISABLE); - intel_uncore_write(&dev_priv->uncore, RAMCLK_GATE_D, 0); - dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | - OVRUNIT_CLOCK_GATE_DISABLE | - OVCUNIT_CLOCK_GATE_DISABLE; - if (IS_GM45(dev_priv)) - dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; - intel_uncore_write(&dev_priv->uncore, DSPCLK_GATE_D(dev_priv), dspclk_gate); - - g4x_disable_trickle_feed(dev_priv); -} - -static void i965gm_init_clock_gating(struct drm_i915_private *dev_priv) -{ - struct intel_uncore *uncore = &dev_priv->uncore; - - intel_uncore_write(uncore, RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); - intel_uncore_write(uncore, RENCLK_GATE_D2, 0); - intel_uncore_write(uncore, DSPCLK_GATE_D(dev_priv), 0); - intel_uncore_write(uncore, RAMCLK_GATE_D, 0); - intel_uncore_write16(uncore, DEUC, 0); - intel_uncore_write(uncore, - MI_ARB_STATE, - _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); -} - -static void i965g_init_clock_gating(struct drm_i915_private *dev_priv) -{ - intel_uncore_write(&dev_priv->uncore, RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | - I965_RCC_CLOCK_GATE_DISABLE | - I965_RCPB_CLOCK_GATE_DISABLE | - I965_ISC_CLOCK_GATE_DISABLE | - I965_FBC_CLOCK_GATE_DISABLE); - intel_uncore_write(&dev_priv->uncore, RENCLK_GATE_D2, 0); - intel_uncore_write(&dev_priv->uncore, MI_ARB_STATE, - _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); -} - -static void gen3_init_clock_gating(struct drm_i915_private *dev_priv) -{ - u32 dstate = intel_uncore_read(&dev_priv->uncore, D_STATE); - - dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | - DSTATE_DOT_CLOCK_GATING; - intel_uncore_write(&dev_priv->uncore, D_STATE, dstate); - - if (IS_PINEVIEW(dev_priv)) - intel_uncore_write(&dev_priv->uncore, ECOSKPD(RENDER_RING_BASE), - _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); - - /* IIR "flip pending" means done if this bit is set */ - intel_uncore_write(&dev_priv->uncore, ECOSKPD(RENDER_RING_BASE), - _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); - - /* interrupts should cause a wake up from C3 */ - intel_uncore_write(&dev_priv->uncore, INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_INT_EN)); - - /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ - intel_uncore_write(&dev_priv->uncore, MI_ARB_STATE, _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE)); - - intel_uncore_write(&dev_priv->uncore, MI_ARB_STATE, - _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); -} - -static void i85x_init_clock_gating(struct drm_i915_private *dev_priv) -{ - intel_uncore_write(&dev_priv->uncore, RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); - - /* interrupts should cause a wake up from C3 */ - intel_uncore_write(&dev_priv->uncore, MI_STATE, _MASKED_BIT_ENABLE(MI_AGPBUSY_INT_EN) | - _MASKED_BIT_DISABLE(MI_AGPBUSY_830_MODE)); - - intel_uncore_write(&dev_priv->uncore, MEM_MODE, - _MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE)); - - /* - * Have FBC ignore 3D activity since we use software - * render tracking, and otherwise a pure 3D workload - * (even if it just renders a single frame and then does - * abosultely nothing) would not allow FBC to recompress - * until a 2D blit occurs. - */ - intel_uncore_write(&dev_priv->uncore, SCPD0, - _MASKED_BIT_ENABLE(SCPD_FBC_IGNORE_3D)); -} - -static void i830_init_clock_gating(struct drm_i915_private *dev_priv) -{ - intel_uncore_write(&dev_priv->uncore, MEM_MODE, - _MASKED_BIT_ENABLE(MEM_DISPLAY_A_TRICKLE_FEED_DISABLE) | - _MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE)); -} - -void intel_init_clock_gating(struct drm_i915_private *dev_priv) -{ - dev_priv->clock_gating_funcs->init_clock_gating(dev_priv); -} - -static void nop_init_clock_gating(struct drm_i915_private *dev_priv) -{ - drm_dbg_kms(&dev_priv->drm, - "No clock gating settings or workarounds applied.\n"); -} - -#define CG_FUNCS(platform) \ -static const struct drm_i915_clock_gating_funcs platform##_clock_gating_funcs = { \ - .init_clock_gating = platform##_init_clock_gating, \ -} - -CG_FUNCS(pvc); -CG_FUNCS(dg2); -CG_FUNCS(xehpsdv); -CG_FUNCS(adlp); -CG_FUNCS(gen12lp); -CG_FUNCS(icl); -CG_FUNCS(cfl); -CG_FUNCS(skl); -CG_FUNCS(kbl); -CG_FUNCS(bxt); -CG_FUNCS(glk); -CG_FUNCS(bdw); -CG_FUNCS(chv); -CG_FUNCS(hsw); -CG_FUNCS(ivb); -CG_FUNCS(vlv); -CG_FUNCS(gen6); -CG_FUNCS(ilk); -CG_FUNCS(g4x); -CG_FUNCS(i965gm); -CG_FUNCS(i965g); -CG_FUNCS(gen3); -CG_FUNCS(i85x); -CG_FUNCS(i830); -CG_FUNCS(nop); -#undef CG_FUNCS - -/** - * intel_init_clock_gating_hooks - setup the clock gating hooks - * @dev_priv: device private - * - * Setup the hooks that configure which clocks of a given platform can be - * gated and also apply various GT and display specific workarounds for these - * platforms. Note that some GT specific workarounds are applied separately - * when GPU contexts or batchbuffers start their execution. - */ -void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) -{ - if (IS_METEORLAKE(dev_priv)) - dev_priv->clock_gating_funcs = &nop_clock_gating_funcs; - else if (IS_PONTEVECCHIO(dev_priv)) - dev_priv->clock_gating_funcs = &pvc_clock_gating_funcs; - else if (IS_DG2(dev_priv)) - dev_priv->clock_gating_funcs = &dg2_clock_gating_funcs; - else if (IS_XEHPSDV(dev_priv)) - dev_priv->clock_gating_funcs = &xehpsdv_clock_gating_funcs; - else if (IS_ALDERLAKE_P(dev_priv)) - dev_priv->clock_gating_funcs = &adlp_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 12) - dev_priv->clock_gating_funcs = &gen12lp_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 11) - dev_priv->clock_gating_funcs = &icl_clock_gating_funcs; - else if (IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv)) - dev_priv->clock_gating_funcs = &cfl_clock_gating_funcs; - else if (IS_SKYLAKE(dev_priv)) - dev_priv->clock_gating_funcs = &skl_clock_gating_funcs; - else if (IS_KABYLAKE(dev_priv)) - dev_priv->clock_gating_funcs = &kbl_clock_gating_funcs; - else if (IS_BROXTON(dev_priv)) - dev_priv->clock_gating_funcs = &bxt_clock_gating_funcs; - else if (IS_GEMINILAKE(dev_priv)) - dev_priv->clock_gating_funcs = &glk_clock_gating_funcs; - else if (IS_BROADWELL(dev_priv)) - dev_priv->clock_gating_funcs = &bdw_clock_gating_funcs; - else if (IS_CHERRYVIEW(dev_priv)) - dev_priv->clock_gating_funcs = &chv_clock_gating_funcs; - else if (IS_HASWELL(dev_priv)) - dev_priv->clock_gating_funcs = &hsw_clock_gating_funcs; - else if (IS_IVYBRIDGE(dev_priv)) - dev_priv->clock_gating_funcs = &ivb_clock_gating_funcs; - else if (IS_VALLEYVIEW(dev_priv)) - dev_priv->clock_gating_funcs = &vlv_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 6) - dev_priv->clock_gating_funcs = &gen6_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 5) - dev_priv->clock_gating_funcs = &ilk_clock_gating_funcs; - else if (IS_G4X(dev_priv)) - dev_priv->clock_gating_funcs = &g4x_clock_gating_funcs; - else if (IS_I965GM(dev_priv)) - dev_priv->clock_gating_funcs = &i965gm_clock_gating_funcs; - else if (IS_I965G(dev_priv)) - dev_priv->clock_gating_funcs = &i965g_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 3) - dev_priv->clock_gating_funcs = &gen3_clock_gating_funcs; - else if (IS_I85X(dev_priv) || IS_I865G(dev_priv)) - dev_priv->clock_gating_funcs = &i85x_clock_gating_funcs; - else if (GRAPHICS_VER(dev_priv) == 2) - dev_priv->clock_gating_funcs = &i830_clock_gating_funcs; - else { - MISSING_CASE(INTEL_DEVID(dev_priv)); - dev_priv->clock_gating_funcs = &nop_clock_gating_funcs; - } -} diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h deleted file mode 100644 index f774bddcdca6..000000000000 --- a/drivers/gpu/drm/i915/intel_pm.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2019 Intel Corporation - */ - -#ifndef __INTEL_PM_H__ -#define __INTEL_PM_H__ - -#include <linux/types.h> - -struct drm_i915_private; -struct intel_crtc_state; -struct intel_plane_state; - -void intel_init_clock_gating(struct drm_i915_private *dev_priv); -void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); - -#endif /* __INTEL_PM_H__ */ diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 71b8a63f6f10..0b6b4852ab23 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -105,7 +105,7 @@ __intel_wakeref_get(struct intel_wakeref *wf) } /** - * intel_wakeref_get_if_in_use: Acquire the wakeref + * intel_wakeref_get_if_active: Acquire the wakeref * @wf: the wakeref * * Acquire a hold on the wakeref, but only if the wakeref is already diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h index ae9b151b7cb7..6f6541d5e49a 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h @@ -18,6 +18,9 @@ enum pxp_status { PXP_STATUS_SUCCESS = 0x0, PXP_STATUS_ERROR_API_VERSION = 0x1002, + PXP_STATUS_NOT_READY = 0x100e, + PXP_STATUS_PLATFCONFIG_KF1_NOVERIF = 0x101a, + PXP_STATUS_PLATFCONFIG_KF1_BAD = 0x101f, PXP_STATUS_OP_NOT_PERMITTED = 0x4013 }; diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c index 448cacb0465d..7de849cb6c47 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c @@ -74,7 +74,7 @@ static int pxp_create_arb_session(struct intel_pxp *pxp) ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true); if (ret) { - drm_err(>->i915->drm, "arb session failed to go in play\n"); + drm_dbg(>->i915->drm, "arb session failed to go in play\n"); return ret; } drm_dbg(>->i915->drm, "PXP ARB session is alive\n"); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index d9d248b48093..a2846b1dbbee 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -19,6 +19,37 @@ #include "intel_pxp_tee.h" #include "intel_pxp_types.h" +static bool +is_fw_err_platform_config(u32 type) +{ + switch (type) { + case PXP_STATUS_ERROR_API_VERSION: + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: + case PXP_STATUS_PLATFCONFIG_KF1_BAD: + return true; + default: + break; + } + return false; +} + +static const char * +fw_err_to_string(u32 type) +{ + switch (type) { + case PXP_STATUS_ERROR_API_VERSION: + return "ERR_API_VERSION"; + case PXP_STATUS_NOT_READY: + return "ERR_NOT_READY"; + case PXP_STATUS_PLATFCONFIG_KF1_NOVERIF: + case PXP_STATUS_PLATFCONFIG_KF1_BAD: + return "ERR_PLATFORM_CONFIG"; + default: + break; + } + return NULL; +} + static int intel_pxp_tee_io_message(struct intel_pxp *pxp, void *msg_in, u32 msg_in_size, void *msg_out, u32 msg_out_max_size, @@ -307,15 +338,22 @@ int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp, &msg_out, sizeof(msg_out), NULL); - if (ret) - drm_err(&i915->drm, "Failed to send tee msg ret=[%d]\n", ret); - else if (msg_out.header.status == PXP_STATUS_ERROR_API_VERSION) - drm_dbg(&i915->drm, "PXP firmware version unsupported, requested: " - "CMD-ID-[0x%08x] on API-Ver-[0x%08x]\n", - msg_in.header.command_id, msg_in.header.api_version); - else if (msg_out.header.status != 0x0) - drm_warn(&i915->drm, "PXP firmware failed arb session init request ret=[0x%08x]\n", - msg_out.header.status); + if (ret) { + drm_err(&i915->drm, "Failed to send tee msg init arb session, ret=[%d]\n", ret); + } else if (msg_out.header.status != 0) { + if (is_fw_err_platform_config(msg_out.header.status)) { + drm_info_once(&i915->drm, + "PXP init-arb-session-%d failed due to BIOS/SOC:0x%08x:%s\n", + arb_session_id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + } else { + drm_dbg(&i915->drm, "PXP init-arb-session--%d failed 0x%08x:%st:\n", + arb_session_id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + drm_dbg(&i915->drm, " cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n", + msg_in.header.command_id, msg_in.header.api_version); + } + } return ret; } @@ -347,10 +385,21 @@ try_again: if ((ret || msg_out.header.status != 0x0) && ++trials < 3) goto try_again; - if (ret) - drm_err(&i915->drm, "Failed to send tee msg for inv-stream-key-%d, ret=[%d]\n", + if (ret) { + drm_err(&i915->drm, "Failed to send tee msg for inv-stream-key-%u, ret=[%d]\n", session_id, ret); - else if (msg_out.header.status != 0x0) - drm_warn(&i915->drm, "PXP firmware failed inv-stream-key-%d with status 0x%08x\n", - session_id, msg_out.header.status); + } else if (msg_out.header.status != 0) { + if (is_fw_err_platform_config(msg_out.header.status)) { + drm_info_once(&i915->drm, + "PXP inv-stream-key-%u failed due to BIOS/SOC :0x%08x:%s\n", + session_id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + } else { + drm_dbg(&i915->drm, "PXP inv-stream-key-%u failed 0x%08x:%s:\n", + session_id, msg_out.header.status, + fw_err_to_string(msg_out.header.status)); + drm_dbg(&i915->drm, " cmd-detail: ID=[0x%08x],API-Ver-[0x%08x]\n", + msg_in.header.command_id, msg_in.header.api_version); + } + } } diff --git a/drivers/gpu/drm/i915/vlv_suspend.c b/drivers/gpu/drm/i915/vlv_suspend.c index 02e63ed77f60..94595dde2b96 100644 --- a/drivers/gpu/drm/i915/vlv_suspend.c +++ b/drivers/gpu/drm/i915/vlv_suspend.c @@ -12,7 +12,7 @@ #include "i915_reg.h" #include "i915_trace.h" #include "i915_utils.h" -#include "intel_pm.h" +#include "intel_clock_gating.h" #include "vlv_suspend.h" #include "gt/intel_gt_regs.h" @@ -451,7 +451,7 @@ int vlv_resume_prepare(struct drm_i915_private *dev_priv, bool rpm_resume) vlv_check_no_gt_access(dev_priv); if (rpm_resume) - intel_init_clock_gating(dev_priv); + intel_clock_gating_init(dev_priv); return ret; } |