aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display')
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c1
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c1
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c4
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c27
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c35
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c32
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c452
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_csr.h21
-rw-r--r--drivers/gpu/drm/i915/display/intel_cursor.c5
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c162
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c64
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_de.h41
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c1038
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h31
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c39
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c686
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h39
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c (renamed from drivers/gpu/drm/i915/display/intel_csr.c)418
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.h43
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c133
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c24
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c79
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c77
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c115
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c28
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c51
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fifo_underrun.c62
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c16
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c230
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c16
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c67
-rw-r--r--drivers/gpu/drm/i915/display/intel_pipe_crc.c56
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.c20
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c282
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h5
-rw-r--r--drivers/gpu/drm/i915/display/intel_qp_tables.c309
-rw-r--r--drivers/gpu/drm/i915/display/intel_qp_tables.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c175
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c184
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c59
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c1
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c217
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c79
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.c1
80 files changed, 4078 insertions, 1697 deletions
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index dfe3cf328d13..de0f358184aa 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -8,6 +8,7 @@
#include "g4x_dp.h"
#include "intel_audio.h"
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 78f93506ffaf..be352e9f0afc 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -8,6 +8,7 @@
#include "g4x_hdmi.h"
#include "intel_audio.h"
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dpio_phy.h"
#include "intel_fifo_underrun.h"
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index 456374ddf37a..9643c45a2209 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -10,6 +10,7 @@
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_sprite.h"
@@ -144,7 +145,7 @@ static bool i9xx_plane_has_windowing(struct intel_plane *plane)
return i9xx_plane == PLANE_B;
else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
return false;
- else if (IS_DISPLAY_VER(dev_priv, 4))
+ else if (DISPLAY_VER(dev_priv) == 4)
return i9xx_plane == PLANE_C;
else
return i9xx_plane == PLANE_B ||
@@ -1039,4 +1040,3 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->fb = intel_fb;
}
-
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 9282978060b0..16812488c5dd 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -31,7 +31,9 @@
#include "intel_atomic.h"
#include "intel_combo_phy.h"
#include "intel_connector.h"
+#include "intel_crtc.h"
#include "intel_ddi.h"
+#include "intel_de.h"
#include "intel_dsi.h"
#include "intel_panel.h"
#include "intel_vdsc.h"
@@ -361,10 +363,19 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
int afe_clk_khz;
- u32 esc_clk_div_m;
+ int theo_word_clk, act_word_clk;
+ u32 esc_clk_div_m, esc_clk_div_m_phy;
afe_clk_khz = afe_clk(encoder, crtc_state);
- esc_clk_div_m = DIV_ROUND_UP(afe_clk_khz, DSI_MAX_ESC_CLK);
+
+ if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
+ theo_word_clk = DIV_ROUND_UP(afe_clk_khz, 8 * DSI_MAX_ESC_CLK);
+ act_word_clk = max(3, theo_word_clk + (theo_word_clk + 1) % 2);
+ esc_clk_div_m = act_word_clk * 8;
+ esc_clk_div_m_phy = (act_word_clk - 1) / 2;
+ } else {
+ esc_clk_div_m = DIV_ROUND_UP(afe_clk_khz, DSI_MAX_ESC_CLK);
+ }
for_each_dsi_port(port, intel_dsi->ports) {
intel_de_write(dev_priv, ICL_DSI_ESC_CLK_DIV(port),
@@ -377,6 +388,14 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
esc_clk_div_m & ICL_ESC_CLK_DIV_MASK);
intel_de_posting_read(dev_priv, ICL_DPHY_ESC_CLK_DIV(port));
}
+
+ if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
+ for_each_dsi_port(port, intel_dsi->ports) {
+ intel_de_write(dev_priv, ADL_MIPIO_DW(port, 8),
+ esc_clk_div_m_phy & TX_ESC_CLK_DIV_PHY);
+ intel_de_posting_read(dev_priv, ADL_MIPIO_DW(port, 8));
+ }
+ }
}
static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
@@ -592,7 +611,7 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
* a value '0' inside TA_PARAM_REGISTERS otherwise
* leave all fields at HW default values.
*/
- if (IS_DISPLAY_VER(dev_priv, 11)) {
+ if (DISPLAY_VER(dev_priv) == 11) {
if (afe_clk(encoder, crtc_state) <= 800000) {
for_each_dsi_port(port, intel_dsi->ports) {
tmp = intel_de_read(dev_priv,
@@ -1158,7 +1177,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
gen11_dsi_configure_transcoder(encoder, crtc_state);
/* Step 4l: Gate DDI clocks */
- if (IS_DISPLAY_VER(dev_priv, 11))
+ if (DISPLAY_VER(dev_priv) == 11)
gen11_dsi_gate_clocks(encoder);
}
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 4fa389fce8cb..b4e7ac51aa31 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -109,16 +109,6 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
return -EINVAL;
}
-static bool blob_equal(const struct drm_property_blob *a,
- const struct drm_property_blob *b)
-{
- if (a && b)
- return a->length == b->length &&
- !memcmp(a->data, b->data, a->length);
-
- return !a == !b;
-}
-
int intel_digital_connector_atomic_check(struct drm_connector *conn,
struct drm_atomic_state *state)
{
@@ -149,8 +139,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
new_conn_state->base.content_type != old_conn_state->base.content_type ||
new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode ||
- !blob_equal(new_conn_state->base.hdr_output_metadata,
- old_conn_state->base.hdr_output_metadata))
+ !drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
crtc_state->mode_changed = true;
return 0;
@@ -198,6 +187,26 @@ intel_connector_needs_modeset(struct intel_atomic_state *state,
new_conn_state->crtc)));
}
+/**
+ * intel_any_crtc_needs_modeset - check if any CRTC needs a modeset
+ * @state: the atomic state corresponding to this modeset
+ *
+ * Returns true if any CRTC in @state needs a modeset.
+ */
+bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state)
+{
+ struct intel_crtc *crtc;
+ struct intel_crtc_state *crtc_state;
+ int i;
+
+ for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+ if (intel_crtc_needs_modeset(crtc_state))
+ return true;
+ }
+
+ return false;
+}
+
struct intel_digital_connector_state *
intel_atomic_get_digital_connector_state(struct intel_atomic_state *state,
struct intel_connector *connector)
@@ -332,7 +341,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
plane_state->hw.fb->format->is_yuv &&
plane_state->hw.fb->format->num_planes > 1) {
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
- if (IS_DISPLAY_VER(dev_priv, 9)) {
+ if (DISPLAY_VER(dev_priv) == 9) {
mode = SKL_PS_SCALER_MODE_NV12;
} else if (icl_is_hdr_plane(dev_priv, plane->id)) {
/*
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
index 62a3365ed5e6..d2700c74c9da 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic.h
@@ -35,6 +35,7 @@ struct drm_connector_state *
intel_digital_connector_duplicate_state(struct drm_connector *connector);
bool intel_connector_needs_modeset(struct intel_atomic_state *state,
struct drm_connector *connector);
+bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state);
struct intel_digital_connector_state *
intel_atomic_get_digital_connector_state(struct intel_atomic_state *state,
struct intel_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index c3f2962aa1eb..36f52a1d7552 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -102,7 +102,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)
__drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi);
- intel_state->vma = NULL;
+ intel_state->ggtt_vma = NULL;
+ intel_state->dpt_vma = NULL;
intel_state->flags = 0;
/* add reference to fb */
@@ -125,7 +126,9 @@ intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct intel_plane_state *plane_state = to_intel_plane_state(state);
- drm_WARN_ON(plane->dev, plane_state->vma);
+
+ drm_WARN_ON(plane->dev, plane_state->ggtt_vma);
+ drm_WARN_ON(plane->dev, plane_state->dpt_vma);
__drm_atomic_helper_plane_destroy_state(&plane_state->uapi);
if (plane_state->hw.fb)
@@ -133,25 +136,45 @@ intel_plane_destroy_state(struct drm_plane *plane,
kfree(plane_state);
}
-unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
- const struct intel_plane_state *plane_state)
+unsigned int intel_adjusted_rate(const struct drm_rect *src,
+ const struct drm_rect *dst,
+ unsigned int rate)
{
unsigned int src_w, src_h, dst_w, dst_h;
- unsigned int pixel_rate = crtc_state->pixel_rate;
- src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
- src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
- dst_w = drm_rect_width(&plane_state->uapi.dst);
- dst_h = drm_rect_height(&plane_state->uapi.dst);
+ src_w = drm_rect_width(src) >> 16;
+ src_h = drm_rect_height(src) >> 16;
+ dst_w = drm_rect_width(dst);
+ dst_h = drm_rect_height(dst);
/* Downscaling limits the maximum pixel rate */
dst_w = min(src_w, dst_w);
dst_h = min(src_h, dst_h);
- return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, src_w * src_h),
+ return DIV_ROUND_UP_ULL(mul_u32_u32(rate, src_w * src_h),
dst_w * dst_h);
}
+unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state)
+{
+ /*
+ * Note we don't check for plane visibility here as
+ * we want to use this when calculating the cursor
+ * watermarks even if the cursor is fully offscreen.
+ * That depends on the src/dst rectangles being
+ * correctly populated whenever the watermark code
+ * considers the cursor to be visible, whether or not
+ * it is actually visible.
+ *
+ * See: intel_wm_plane_visible() and intel_check_cursor()
+ */
+
+ return intel_adjusted_rate(&plane_state->uapi.src,
+ &plane_state->uapi.dst,
+ crtc_state->pixel_rate);
+}
+
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
index 5c78a087ed86..dc4d05e75e1c 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h
@@ -10,6 +10,7 @@
struct drm_plane;
struct drm_property;
+struct drm_rect;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
@@ -18,6 +19,9 @@ struct intel_plane_state;
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
+unsigned int intel_adjusted_rate(const struct drm_rect *src,
+ const struct drm_rect *dst,
+ unsigned int rate);
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 9671c8f6e892..5f4f316b3ab5 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -31,6 +31,7 @@
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_cdclk.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_lpe_audio.h"
@@ -591,40 +592,33 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
val = intel_de_read(i915, AUD_CONFIG_BE);
- if (IS_DISPLAY_VER(i915, 11))
+ if (DISPLAY_VER(i915) == 11)
val |= HBLANK_EARLY_ENABLE_ICL(pipe);
else if (DISPLAY_VER(i915) >= 12)
val |= HBLANK_EARLY_ENABLE_TGL(pipe);
if (crtc_state->dsc.compression_enable &&
- (crtc_state->hw.adjusted_mode.hdisplay >= 3840 &&
- crtc_state->hw.adjusted_mode.vdisplay >= 2160)) {
+ crtc_state->hw.adjusted_mode.hdisplay >= 3840 &&
+ crtc_state->hw.adjusted_mode.vdisplay >= 2160) {
/* Get hblank early enable value required */
+ val &= ~HBLANK_START_COUNT_MASK(pipe);
hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state);
- if (hblank_early_prog < 32) {
- val &= ~HBLANK_START_COUNT_MASK(pipe);
+ if (hblank_early_prog < 32)
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_32);
- } else if (hblank_early_prog < 64) {
- val &= ~HBLANK_START_COUNT_MASK(pipe);
+ else if (hblank_early_prog < 64)
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_64);
- } else if (hblank_early_prog < 96) {
- val &= ~HBLANK_START_COUNT_MASK(pipe);
+ else if (hblank_early_prog < 96)
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_96);
- } else {
- val &= ~HBLANK_START_COUNT_MASK(pipe);
+ else
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_128);
- }
/* Get samples room value required */
+ val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe);
samples_room = calc_samples_room(crtc_state);
- if (samples_room < 3) {
- val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe);
+ if (samples_room < 3)
val |= NUMBER_SAMPLES_PER_LINE(pipe, samples_room);
- } else {
- /* Program 0 i.e "All Samples available in buffer" */
- val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe);
+ else /* Program 0 i.e "All Samples available in buffer" */
val |= NUMBER_SAMPLES_PER_LINE(pipe, 0x0);
- }
}
intel_de_write(i915, AUD_CONFIG_BE, val);
@@ -1309,7 +1303,7 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv)
if (DISPLAY_VER(dev_priv) >= 9) {
aud_freq_init = intel_de_read(dev_priv, AUD_FREQ_CNTRL);
- if (INTEL_GEN(dev_priv) >= 12)
+ if (DISPLAY_VER(dev_priv) >= 12)
aud_freq = AUD_FREQ_GEN12;
else
aud_freq = aud_freq_init;
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 3d0c035b5e38..5b6922e28ef2 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -610,7 +610,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
* Only parse SDVO mappings on gens that could have SDVO. This isn't
* accurate and doesn't have to be, as long as it's not too strict.
*/
- if (!IS_DISPLAY_RANGE(i915, 3, 7)) {
+ if (!IS_DISPLAY_VER(i915, 3, 7)) {
drm_dbg_kms(&i915->drm, "Skipping SDVO device mapping\n");
return;
}
@@ -917,7 +917,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
* Old decimal value is wake up time in multiples of 100 us.
*/
if (bdb->version >= 205 &&
- (IS_GEN9_BC(i915) || DISPLAY_VER(i915) >= 10)) {
+ (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
switch (psr_table->tp1_wakeup_time) {
case 0:
i915->vbt.psr.tp1_wakeup_time_us = 500;
@@ -1651,7 +1651,7 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
const u8 *ddc_pin_map;
int n_entries;
- if (HAS_PCH_ADP(i915)) {
+ if (IS_ALDERLAKE_S(i915)) {
ddc_pin_map = adls_ddc_pin_map;
n_entries = ARRAY_SIZE(adls_ddc_pin_map);
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
@@ -1659,7 +1659,7 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
} else if (IS_ROCKETLAKE(i915) && INTEL_PCH_TYPE(i915) == PCH_TGP) {
ddc_pin_map = rkl_pch_tgp_ddc_pin_map;
n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map);
- } else if (HAS_PCH_TGP(i915) && IS_GEN9_BC(i915)) {
+ } else if (HAS_PCH_TGP(i915) && DISPLAY_VER(i915) == 9) {
ddc_pin_map = gen9bc_tgp_ddc_pin_map;
n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map);
} else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
@@ -1743,8 +1743,24 @@ static enum port dvo_port_to_port(struct drm_i915_private *i915,
[PORT_TC3] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
[PORT_TC4] = { DVO_PORT_HDMIE, DVO_PORT_DPE, -1 },
};
+ static const int xelpd_port_mapping[][3] = {
+ [PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
+ [PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
+ [PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
+ [PORT_D_XELPD] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
+ [PORT_E_XELPD] = { DVO_PORT_HDMIE, DVO_PORT_DPE, -1 },
+ [PORT_TC1] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1 },
+ [PORT_TC2] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1 },
+ [PORT_TC3] = { DVO_PORT_HDMIH, DVO_PORT_DPH, -1 },
+ [PORT_TC4] = { DVO_PORT_HDMII, DVO_PORT_DPI, -1 },
+ };
- if (IS_ALDERLAKE_S(i915))
+ if (DISPLAY_VER(i915) == 13)
+ return __dvo_port_to_port(ARRAY_SIZE(xelpd_port_mapping),
+ ARRAY_SIZE(xelpd_port_mapping[0]),
+ xelpd_port_mapping,
+ dvo_port);
+ else if (IS_ALDERLAKE_S(i915))
return __dvo_port_to_port(ARRAY_SIZE(adls_port_mapping),
ARRAY_SIZE(adls_port_mapping[0]),
adls_port_mapping,
@@ -1852,6 +1868,19 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata)
devdata->child.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR;
}
+static bool is_port_valid(struct drm_i915_private *i915, enum port port)
+{
+ /*
+ * On some ICL/CNL SKUs port F is not present, but broken VBTs mark
+ * the port as present. Only try to initialize port F for the
+ * SKUs that may actually have it.
+ */
+ if (port == PORT_F && (IS_ICELAKE(i915) || IS_CANNONLAKE(i915)))
+ return IS_ICL_WITH_PORT_F(i915) || IS_CNL_WITH_PORT_F(i915);
+
+ return true;
+}
+
static void parse_ddi_port(struct drm_i915_private *i915,
struct intel_bios_encoder_data *devdata)
{
@@ -1865,6 +1894,13 @@ static void parse_ddi_port(struct drm_i915_private *i915,
if (port == PORT_NONE)
return;
+ if (!is_port_valid(i915, port)) {
+ drm_dbg_kms(&i915->drm,
+ "VBT reports port %c as supported, but that can't be true: skipping\n",
+ port_name(port));
+ return;
+ }
+
info = &i915->vbt.ddi_port_info[port];
if (info->devdata) {
@@ -2770,7 +2806,8 @@ intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata =
i915->vbt.ddi_port_info[port].devdata;
- if (drm_WARN_ON_ONCE(&i915->drm, !IS_GEN9_LP(i915)))
+ if (drm_WARN_ON_ONCE(&i915->drm,
+ !IS_GEMINILAKE(i915) && !IS_BROXTON(i915)))
return false;
return devdata && devdata->child.hpd_invert;
@@ -2852,7 +2889,9 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915,
aux_ch = AUX_CH_C;
break;
case DP_AUX_D:
- if (IS_ALDERLAKE_S(i915))
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_D_XELPD;
+ else if (IS_ALDERLAKE_S(i915))
aux_ch = AUX_CH_USBC3;
else if (IS_DG1(i915) || IS_ROCKETLAKE(i915))
aux_ch = AUX_CH_USBC2;
@@ -2860,22 +2899,36 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *i915,
aux_ch = AUX_CH_D;
break;
case DP_AUX_E:
- if (IS_ALDERLAKE_S(i915))
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_E_XELPD;
+ else if (IS_ALDERLAKE_S(i915))
aux_ch = AUX_CH_USBC4;
else
aux_ch = AUX_CH_E;
break;
case DP_AUX_F:
- aux_ch = AUX_CH_F;
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_USBC1;
+ else
+ aux_ch = AUX_CH_F;
break;
case DP_AUX_G:
- aux_ch = AUX_CH_G;
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_USBC2;
+ else
+ aux_ch = AUX_CH_G;
break;
case DP_AUX_H:
- aux_ch = AUX_CH_H;
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_USBC3;
+ else
+ aux_ch = AUX_CH_H;
break;
case DP_AUX_I:
- aux_ch = AUX_CH_I;
+ if (DISPLAY_VER(i915) == 13)
+ aux_ch = AUX_CH_USBC4;
+ else
+ aux_ch = AUX_CH_I;
break;
default:
MISSING_CASE(info->alternate_aux_channel);
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index 584ab5ce4106..bfb398f0432e 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -77,7 +77,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
qi->num_points = dram_info->num_qgv_points;
- if (IS_DISPLAY_VER(dev_priv, 12))
+ if (DISPLAY_VER(dev_priv) == 12)
switch (dram_info->type) {
case INTEL_DRAM_DDR4:
qi->t_bl = 4;
@@ -89,7 +89,7 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
qi->t_bl = 16;
break;
}
- else if (IS_DISPLAY_VER(dev_priv, 11))
+ else if (DISPLAY_VER(dev_priv) == 11)
qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 8;
if (drm_WARN_ON(&dev_priv->drm,
@@ -162,7 +162,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
{
struct intel_qgv_info qi = {};
bool is_y_tile = true; /* assume y tile may be used */
- int num_channels = dev_priv->dram_info.num_channels;
+ int num_channels = max_t(u8, 1, dev_priv->dram_info.num_channels);
int deinterleave;
int ipqdepth, ipqdepthpch;
int dclk_max;
@@ -267,13 +267,13 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- if (IS_ALDERLAKE_S(dev_priv))
+ if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
icl_get_bw_info(dev_priv, &adls_sa_info);
else if (IS_ROCKETLAKE(dev_priv))
icl_get_bw_info(dev_priv, &rkl_sa_info);
- else if (IS_DISPLAY_VER(dev_priv, 12))
+ else if (DISPLAY_VER(dev_priv) == 12)
icl_get_bw_info(dev_priv, &tgl_sa_info);
- else if (IS_DISPLAY_VER(dev_priv, 11))
+ else if (DISPLAY_VER(dev_priv) == 11)
icl_get_bw_info(dev_priv, &icl_sa_info);
}
@@ -344,6 +344,9 @@ static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
for_each_pipe(dev_priv, pipe)
data_rate += bw_state->data_rate[pipe];
+ if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active())
+ data_rate = data_rate * 105 / 100;
+
return data_rate;
}
@@ -390,7 +393,6 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int max_bw = 0;
- int slice_id;
enum pipe pipe;
int i;
@@ -418,6 +420,7 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
&crtc_state->wm.skl.plane_ddb_uv[plane_id];
unsigned int data_rate = crtc_state->data_rate[plane_id];
unsigned int dbuf_mask = 0;
+ enum dbuf_slice slice;
dbuf_mask |= skl_ddb_dbuf_slice_mask(dev_priv, plane_alloc);
dbuf_mask |= skl_ddb_dbuf_slice_mask(dev_priv, uv_plane_alloc);
@@ -435,8 +438,8 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
* pessimistic, which shouldn't pose any significant
* problem anyway.
*/
- for_each_dbuf_slice_in_mask(slice_id, dbuf_mask)
- crtc_bw->used_bw[slice_id] += data_rate;
+ for_each_dbuf_slice_in_mask(dev_priv, slice, dbuf_mask)
+ crtc_bw->used_bw[slice] += data_rate;
}
}
@@ -445,10 +448,11 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
for_each_pipe(dev_priv, pipe) {
struct intel_dbuf_bw *crtc_bw;
+ enum dbuf_slice slice;
crtc_bw = &new_bw_state->dbuf_bw[pipe];
- for_each_dbuf_slice(slice_id) {
+ for_each_dbuf_slice(dev_priv, slice) {
/*
* Current experimental observations show that contrary
* to BSpec we get underruns once we exceed 64 * CDCLK
@@ -457,7 +461,7 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state)
* bumped up all the time we calculate CDCLK according
* to this formula for overall bw consumed by slices.
*/
- max_bw += crtc_bw->used_bw[slice_id];
+ max_bw += crtc_bw->used_bw[slice];
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 3f43ad4d7362..613ffcc68eba 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -26,7 +26,9 @@
#include "intel_atomic.h"
#include "intel_bw.h"
#include "intel_cdclk.h"
+#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_psr.h"
#include "intel_sideband.h"
/**
@@ -723,12 +725,28 @@ static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
bdw_calc_voltage_level(cdclk_config->cdclk);
}
+static u32 bdw_cdclk_freq_sel(int cdclk)
+{
+ switch (cdclk) {
+ default:
+ MISSING_CASE(cdclk);
+ fallthrough;
+ case 337500:
+ return LCPLL_CLK_FREQ_337_5_BDW;
+ case 450000:
+ return LCPLL_CLK_FREQ_450;
+ case 540000:
+ return LCPLL_CLK_FREQ_54O_BDW;
+ case 675000:
+ return LCPLL_CLK_FREQ_675_BDW;
+ }
+}
+
static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
int cdclk = cdclk_config->cdclk;
- u32 val;
int ret;
if (drm_WARN(&dev_priv->drm,
@@ -748,9 +766,8 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
- val = intel_de_read(dev_priv, LCPLL_CTL);
- val |= LCPLL_CD_SOURCE_FCLK;
- intel_de_write(dev_priv, LCPLL_CTL, val);
+ intel_de_rmw(dev_priv, LCPLL_CTL,
+ 0, LCPLL_CD_SOURCE_FCLK);
/*
* According to the spec, it should be enough to poll for this 1 us.
@@ -760,32 +777,11 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
LCPLL_CD_SOURCE_FCLK_DONE, 100))
drm_err(&dev_priv->drm, "Switching to FCLK failed\n");
- val = intel_de_read(dev_priv, LCPLL_CTL);
- val &= ~LCPLL_CLK_FREQ_MASK;
-
- switch (cdclk) {
- default:
- MISSING_CASE(cdclk);
- fallthrough;
- case 337500:
- val |= LCPLL_CLK_FREQ_337_5_BDW;
- break;
- case 450000:
- val |= LCPLL_CLK_FREQ_450;
- break;
- case 540000:
- val |= LCPLL_CLK_FREQ_54O_BDW;
- break;
- case 675000:
- val |= LCPLL_CLK_FREQ_675_BDW;
- break;
- }
-
- intel_de_write(dev_priv, LCPLL_CTL, val);
+ intel_de_rmw(dev_priv, LCPLL_CTL,
+ LCPLL_CLK_FREQ_MASK, bdw_cdclk_freq_sel(cdclk));
- val = intel_de_read(dev_priv, LCPLL_CTL);
- val &= ~LCPLL_CD_SOURCE_FCLK;
- intel_de_write(dev_priv, LCPLL_CTL, val);
+ intel_de_rmw(dev_priv, LCPLL_CTL,
+ LCPLL_CD_SOURCE_FCLK, 0);
if (wait_for_us((intel_de_read(dev_priv, LCPLL_CTL) &
LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
@@ -954,10 +950,8 @@ static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
intel_update_max_cdclk(dev_priv);
}
-static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
+static u32 skl_dpll0_link_rate(struct drm_i915_private *dev_priv, int vco)
{
- u32 val;
-
drm_WARN_ON(&dev_priv->drm, vco != 8100000 && vco != 8640000);
/*
@@ -969,23 +963,24 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
* rate later on, with the constraint of choosing a frequency that
* works with vco.
*/
- val = intel_de_read(dev_priv, DPLL_CTRL1);
-
- val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
- DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
- val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
if (vco == 8640000)
- val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
- SKL_DPLL0);
+ return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0);
else
- val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
- SKL_DPLL0);
+ return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0);
+}
- intel_de_write(dev_priv, DPLL_CTRL1, val);
+static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
+{
+ intel_de_rmw(dev_priv, DPLL_CTRL1,
+ DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
+ DPLL_CTRL1_SSC(SKL_DPLL0) |
+ DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0),
+ DPLL_CTRL1_OVERRIDE(SKL_DPLL0) |
+ skl_dpll0_link_rate(dev_priv, vco));
intel_de_posting_read(dev_priv, DPLL_CTRL1);
- intel_de_write(dev_priv, LCPLL1_CTL,
- intel_de_read(dev_priv, LCPLL1_CTL) | LCPLL_PLL_ENABLE);
+ intel_de_rmw(dev_priv, LCPLL1_CTL,
+ 0, LCPLL_PLL_ENABLE);
if (intel_de_wait_for_set(dev_priv, LCPLL1_CTL, LCPLL_PLL_LOCK, 5))
drm_err(&dev_priv->drm, "DPLL0 not locked\n");
@@ -998,14 +993,38 @@ static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
{
- intel_de_write(dev_priv, LCPLL1_CTL,
- intel_de_read(dev_priv, LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
+ intel_de_rmw(dev_priv, LCPLL1_CTL,
+ LCPLL_PLL_ENABLE, 0);
+
if (intel_de_wait_for_clear(dev_priv, LCPLL1_CTL, LCPLL_PLL_LOCK, 1))
drm_err(&dev_priv->drm, "Couldn't disable DPLL0\n");
dev_priv->cdclk.hw.vco = 0;
}
+static u32 skl_cdclk_freq_sel(struct drm_i915_private *dev_priv,
+ int cdclk, int vco)
+{
+ switch (cdclk) {
+ default:
+ drm_WARN_ON(&dev_priv->drm,
+ cdclk != dev_priv->cdclk.hw.bypass);
+ drm_WARN_ON(&dev_priv->drm, vco != 0);
+ fallthrough;
+ case 308571:
+ case 337500:
+ return CDCLK_FREQ_337_308;
+ case 450000:
+ case 432000:
+ return CDCLK_FREQ_450_432;
+ case 540000:
+ return CDCLK_FREQ_540;
+ case 617143:
+ case 675000:
+ return CDCLK_FREQ_675_617;
+ }
+}
+
static void skl_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
@@ -1036,29 +1055,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
- /* Choose frequency for this cdclk */
- switch (cdclk) {
- default:
- drm_WARN_ON(&dev_priv->drm,
- cdclk != dev_priv->cdclk.hw.bypass);
- drm_WARN_ON(&dev_priv->drm, vco != 0);
- fallthrough;
- case 308571:
- case 337500:
- freq_select = CDCLK_FREQ_337_308;
- break;
- case 450000:
- case 432000:
- freq_select = CDCLK_FREQ_450_432;
- break;
- case 540000:
- freq_select = CDCLK_FREQ_540;
- break;
- case 617143:
- case 675000:
- freq_select = CDCLK_FREQ_675_617;
- break;
- }
+ freq_select = skl_cdclk_freq_sel(dev_priv, cdclk, vco);
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
@@ -1257,6 +1254,42 @@ static const struct intel_cdclk_vals rkl_cdclk_table[] = {
{}
};
+static const struct intel_cdclk_vals adlp_a_step_cdclk_table[] = {
+ { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
+
+ { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
+ { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
+
+ { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ {}
+};
+
+static const struct intel_cdclk_vals adlp_cdclk_table[] = {
+ { .refclk = 19200, .cdclk = 172800, .divider = 3, .ratio = 27 },
+ { .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
+ { .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
+ { .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
+ { .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
+
+ { .refclk = 24000, .cdclk = 176000, .divider = 3, .ratio = 22 },
+ { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
+ { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
+ { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
+ { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
+
+ { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
+ { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
+ { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
+ { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
+ { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
+ {}
+};
+
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
{
const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
@@ -1432,18 +1465,12 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
div = 2;
break;
case BXT_CDCLK_CD2X_DIV_SEL_1_5:
- drm_WARN(&dev_priv->drm,
- DISPLAY_VER(dev_priv) >= 10,
- "Unsupported divider\n");
div = 3;
break;
case BXT_CDCLK_CD2X_DIV_SEL_2:
div = 4;
break;
case BXT_CDCLK_CD2X_DIV_SEL_4:
- drm_WARN(&dev_priv->drm,
- DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv),
- "Unsupported divider\n");
div = 8;
break;
default:
@@ -1477,12 +1504,9 @@ static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
{
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
- u32 val;
- val = intel_de_read(dev_priv, BXT_DE_PLL_CTL);
- val &= ~BXT_DE_PLL_RATIO_MASK;
- val |= BXT_DE_PLL_RATIO(ratio);
- intel_de_write(dev_priv, BXT_DE_PLL_CTL, val);
+ intel_de_rmw(dev_priv, BXT_DE_PLL_CTL,
+ BXT_DE_PLL_RATIO_MASK, BXT_DE_PLL_RATIO(ratio));
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
@@ -1496,16 +1520,12 @@ static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
{
- u32 val;
-
- val = intel_de_read(dev_priv, BXT_DE_PLL_ENABLE);
- val &= ~BXT_DE_PLL_PLL_ENABLE;
- intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
+ intel_de_rmw(dev_priv, BXT_DE_PLL_ENABLE,
+ BXT_DE_PLL_PLL_ENABLE, 0);
/* Timeout 200us */
- if (wait_for((intel_de_read(dev_priv, BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) == 0, 1))
- drm_err(&dev_priv->drm,
- "timeout waiting for CDCLK PLL unlock\n");
+ if (intel_de_wait_for_clear(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
+ drm_err(&dev_priv->drm, "timeout waiting for CDCLK PLL unlock\n");
dev_priv->cdclk.hw.vco = 0;
}
@@ -1522,9 +1542,37 @@ static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
/* Timeout 200us */
- if (wait_for((intel_de_read(dev_priv, BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) != 0, 1))
- drm_err(&dev_priv->drm,
- "timeout waiting for CDCLK PLL lock\n");
+ if (intel_de_wait_for_set(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
+ drm_err(&dev_priv->drm, "timeout waiting for CDCLK PLL lock\n");
+
+ dev_priv->cdclk.hw.vco = vco;
+}
+
+static bool has_cdclk_crawl(struct drm_i915_private *i915)
+{
+ return INTEL_INFO(i915)->has_cdclk_crawl;
+}
+
+static void adlp_cdclk_pll_crawl(struct drm_i915_private *dev_priv, int vco)
+{
+ int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
+ u32 val;
+
+ /* Write PLL ratio without disabling */
+ val = CNL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
+ intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
+
+ /* Submit freq change request */
+ val |= BXT_DE_PLL_FREQ_REQ;
+ intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
+
+ /* Timeout 200us */
+ if (intel_de_wait_for_set(dev_priv, BXT_DE_PLL_ENABLE,
+ BXT_DE_PLL_LOCK | BXT_DE_PLL_FREQ_REQ_ACK, 1))
+ DRM_ERROR("timeout waiting for FREQ change request ack\n");
+
+ val &= ~BXT_DE_PLL_FREQ_REQ;
+ intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
dev_priv->cdclk.hw.vco = vco;
}
@@ -1549,13 +1597,34 @@ static u32 bxt_cdclk_cd2x_pipe(struct drm_i915_private *dev_priv, enum pipe pipe
}
}
+static u32 bxt_cdclk_cd2x_div_sel(struct drm_i915_private *dev_priv,
+ int cdclk, int vco)
+{
+ /* cdclk = vco / 2 / div{1,1.5,2,4} */
+ switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
+ default:
+ drm_WARN_ON(&dev_priv->drm,
+ cdclk != dev_priv->cdclk.hw.bypass);
+ drm_WARN_ON(&dev_priv->drm, vco != 0);
+ fallthrough;
+ case 2:
+ return BXT_CDCLK_CD2X_DIV_SEL_1;
+ case 3:
+ return BXT_CDCLK_CD2X_DIV_SEL_1_5;
+ case 4:
+ return BXT_CDCLK_CD2X_DIV_SEL_2;
+ case 8:
+ return BXT_CDCLK_CD2X_DIV_SEL_4;
+ }
+}
+
static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
int cdclk = cdclk_config->cdclk;
int vco = cdclk_config->vco;
- u32 val, divider;
+ u32 val;
int ret;
/* Inform power controller of upcoming frequency change. */
@@ -1580,41 +1649,16 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
return;
}
- /* cdclk = vco / 2 / div{1,1.5,2,4} */
- switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
- default:
- drm_WARN_ON(&dev_priv->drm,
- cdclk != dev_priv->cdclk.hw.bypass);
- drm_WARN_ON(&dev_priv->drm, vco != 0);
- fallthrough;
- case 2:
- divider = BXT_CDCLK_CD2X_DIV_SEL_1;
- break;
- case 3:
- drm_WARN(&dev_priv->drm,
- DISPLAY_VER(dev_priv) >= 10,
- "Unsupported divider\n");
- divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
- break;
- case 4:
- divider = BXT_CDCLK_CD2X_DIV_SEL_2;
- break;
- case 8:
- drm_WARN(&dev_priv->drm,
- DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv),
- "Unsupported divider\n");
- divider = BXT_CDCLK_CD2X_DIV_SEL_4;
- break;
- }
-
- if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
+ if (has_cdclk_crawl(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
+ if (dev_priv->cdclk.hw.vco != vco)
+ adlp_cdclk_pll_crawl(dev_priv, vco);
+ } else if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
cnl_cdclk_pll_disable(dev_priv);
if (dev_priv->cdclk.hw.vco != vco)
cnl_cdclk_pll_enable(dev_priv, vco);
-
} else {
if (dev_priv->cdclk.hw.vco != 0 &&
dev_priv->cdclk.hw.vco != vco)
@@ -1624,14 +1668,16 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
bxt_de_pll_enable(dev_priv, vco);
}
- val = divider | skl_cdclk_decimal(cdclk) |
- bxt_cdclk_cd2x_pipe(dev_priv, pipe);
+ val = bxt_cdclk_cd2x_div_sel(dev_priv, cdclk, vco) |
+ bxt_cdclk_cd2x_pipe(dev_priv, pipe) |
+ skl_cdclk_decimal(cdclk);
/*
* Disable SSA Precharge when CD clock frequency < 500 MHz,
* enable otherwise.
*/
- if (IS_GEN9_LP(dev_priv) && cdclk >= 500000)
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ cdclk >= 500000)
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
intel_de_write(dev_priv, CDCLK_CTL, val);
@@ -1710,29 +1756,16 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
expected = skl_cdclk_decimal(cdclk);
/* Figure out what CD2X divider we should be using for this cdclk */
- switch (DIV_ROUND_CLOSEST(dev_priv->cdclk.hw.vco,
- dev_priv->cdclk.hw.cdclk)) {
- case 2:
- expected |= BXT_CDCLK_CD2X_DIV_SEL_1;
- break;
- case 3:
- expected |= BXT_CDCLK_CD2X_DIV_SEL_1_5;
- break;
- case 4:
- expected |= BXT_CDCLK_CD2X_DIV_SEL_2;
- break;
- case 8:
- expected |= BXT_CDCLK_CD2X_DIV_SEL_4;
- break;
- default:
- goto sanitize;
- }
+ expected |= bxt_cdclk_cd2x_div_sel(dev_priv,
+ dev_priv->cdclk.hw.cdclk,
+ dev_priv->cdclk.hw.vco);
/*
* Disable SSA Precharge when CD clock frequency < 500 MHz,
* enable otherwise.
*/
- if (IS_GEN9_LP(dev_priv) && dev_priv->cdclk.hw.cdclk >= 500000)
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ dev_priv->cdclk.hw.cdclk >= 500000)
expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
if (cdctl == expected)
@@ -1797,9 +1830,9 @@ static void bxt_cdclk_uninit_hw(struct drm_i915_private *dev_priv)
*/
void intel_cdclk_init_hw(struct drm_i915_private *i915)
{
- if (IS_GEN9_LP(i915) || DISPLAY_VER(i915) >= 10)
+ if (DISPLAY_VER(i915) >= 10 || IS_BROXTON(i915))
bxt_cdclk_init_hw(i915);
- else if (IS_GEN9_BC(i915))
+ else if (DISPLAY_VER(i915) == 9)
skl_cdclk_init_hw(i915);
}
@@ -1812,12 +1845,34 @@ void intel_cdclk_init_hw(struct drm_i915_private *i915)
*/
void intel_cdclk_uninit_hw(struct drm_i915_private *i915)
{
- if (DISPLAY_VER(i915) >= 10 || IS_GEN9_LP(i915))
+ if (DISPLAY_VER(i915) >= 10 || IS_BROXTON(i915))
bxt_cdclk_uninit_hw(i915);
- else if (IS_GEN9_BC(i915))
+ else if (DISPLAY_VER(i915) == 9)
skl_cdclk_uninit_hw(i915);
}
+static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
+ const struct intel_cdclk_config *a,
+ const struct intel_cdclk_config *b)
+{
+ int a_div, b_div;
+
+ if (!has_cdclk_crawl(dev_priv))
+ return false;
+
+ /*
+ * The vco and cd2x divider will change independently
+ * from each, so we disallow cd2x change when crawling.
+ */
+ a_div = DIV_ROUND_CLOSEST(a->vco, a->cdclk);
+ b_div = DIV_ROUND_CLOSEST(b->vco, b->cdclk);
+
+ return a->vco != 0 && b->vco != 0 &&
+ a->vco != b->vco &&
+ a_div == b_div &&
+ a->ref == b->ref;
+}
+
/**
* intel_cdclk_needs_modeset - Determine if changong between the CDCLK
* configurations requires a modeset on all pipes
@@ -1852,7 +1907,7 @@ static bool intel_cdclk_can_cd2x_update(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *b)
{
/* Older hw doesn't have the capability */
- if (DISPLAY_VER(dev_priv) < 10 && !IS_GEN9_LP(dev_priv))
+ if (DISPLAY_VER(dev_priv) < 10 && !IS_BROXTON(dev_priv))
return false;
return a->cdclk != b->cdclk &&
@@ -1907,6 +1962,12 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
intel_dump_cdclk_config(cdclk_config, "Changing CDCLK to");
+ for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ intel_psr_pause(intel_dp);
+ }
+
/*
* Lock aux/gmbus while we change cdclk in case those
* functions use cdclk. Not all platforms/ports do,
@@ -1929,6 +1990,12 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
}
mutex_unlock(&dev_priv->gmbus_mutex);
+ for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ intel_psr_resume(intel_dp);
+ }
+
if (drm_WARN(&dev_priv->drm,
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
"cdclk state doesn't match!\n")) {
@@ -2002,7 +2069,7 @@ static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
if (DISPLAY_VER(dev_priv) >= 10)
return DIV_ROUND_UP(pixel_rate, 2);
- else if (IS_DISPLAY_VER(dev_priv, 9) ||
+ else if (DISPLAY_VER(dev_priv) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return pixel_rate;
else if (IS_CHERRYVIEW(dev_priv))
@@ -2050,10 +2117,10 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
crtc_state->has_audio &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
- if (IS_DISPLAY_VER(dev_priv, 10)) {
+ if (DISPLAY_VER(dev_priv) == 10) {
/* Display WA #1145: glk,cnl */
min_cdclk = max(316800, min_cdclk);
- } else if (IS_DISPLAY_VER(dev_priv, 9) || IS_BROADWELL(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
min_cdclk = max(432000, min_cdclk);
}
@@ -2389,44 +2456,6 @@ static int bxt_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
return 0;
}
-static int intel_modeset_all_pipes(struct intel_atomic_state *state)
-{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- struct intel_crtc *crtc;
-
- /*
- * Add all pipes to the state, and force
- * a modeset on all the active ones.
- */
- for_each_intel_crtc(&dev_priv->drm, crtc) {
- struct intel_crtc_state *crtc_state;
- int ret;
-
- crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
- if (IS_ERR(crtc_state))
- return PTR_ERR(crtc_state);
-
- if (!crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
- continue;
-
- crtc_state->uapi.mode_changed = true;
-
- ret = drm_atomic_add_affected_connectors(&state->base,
- &crtc->base);
- if (ret)
- return ret;
-
- ret = intel_atomic_add_affected_planes(state, crtc);
- if (ret)
- return ret;
-
- crtc_state->update_planes |= crtc_state->active_planes;
- }
-
- return 0;
-}
-
static int fixed_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
{
int min_cdclk;
@@ -2499,7 +2528,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
const struct intel_cdclk_state *old_cdclk_state;
struct intel_cdclk_state *new_cdclk_state;
- enum pipe pipe;
+ enum pipe pipe = INVALID_PIPE;
int ret;
new_cdclk_state = intel_atomic_get_cdclk_state(state);
@@ -2551,15 +2580,18 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
pipe = INVALID_PIPE;
- } else {
- pipe = INVALID_PIPE;
}
- if (pipe != INVALID_PIPE) {
+ if (intel_cdclk_can_crawl(dev_priv,
+ &old_cdclk_state->actual,
+ &new_cdclk_state->actual)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "Can change cdclk via crawl\n");
+ } else if (pipe != INVALID_PIPE) {
new_cdclk_state->pipe = pipe;
drm_dbg_kms(&dev_priv->drm,
- "Can change cdclk with pipe %c active\n",
+ "Can change cdclk cd2x divider with pipe %c active\n",
pipe_name(pipe));
} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
@@ -2568,8 +2600,6 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
if (ret)
return ret;
- new_cdclk_state->pipe = INVALID_PIPE;
-
drm_dbg_kms(&dev_priv->drm,
"Modeset required for cdclk change\n");
}
@@ -2592,7 +2622,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
if (DISPLAY_VER(dev_priv) >= 10)
return 2 * max_cdclk_freq;
- else if (IS_DISPLAY_VER(dev_priv, 9) ||
+ else if (DISPLAY_VER(dev_priv) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return max_cdclk_freq;
else if (IS_CHERRYVIEW(dev_priv))
@@ -2625,7 +2655,11 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
dev_priv->max_cdclk_freq = 652800;
} else if (IS_CANNONLAKE(dev_priv)) {
dev_priv->max_cdclk_freq = 528000;
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv)) {
+ dev_priv->max_cdclk_freq = 316800;
+ } else if (IS_BROXTON(dev_priv)) {
+ dev_priv->max_cdclk_freq = 624000;
+ } else if (DISPLAY_VER(dev_priv) == 9) {
u32 limit = intel_de_read(dev_priv, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
int max_cdclk, vco;
@@ -2647,10 +2681,6 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
max_cdclk = 308571;
dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
- } else if (IS_GEMINILAKE(dev_priv)) {
- dev_priv->max_cdclk_freq = 316800;
- } else if (IS_BROXTON(dev_priv)) {
- dev_priv->max_cdclk_freq = 624000;
} else if (IS_BROADWELL(dev_priv)) {
/*
* FIXME with extra cooling we can allow
@@ -2848,7 +2878,17 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
*/
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
{
- if (IS_ROCKETLAKE(dev_priv)) {
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ dev_priv->display.set_cdclk = bxt_set_cdclk;
+ dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
+ dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
+ dev_priv->display.calc_voltage_level = tgl_calc_voltage_level;
+ /* Wa_22011320316:adlp[a0] */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ dev_priv->cdclk.table = adlp_a_step_cdclk_table;
+ else
+ dev_priv->cdclk.table = adlp_cdclk_table;
+ } else if (IS_ROCKETLAKE(dev_priv)) {
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
@@ -2878,7 +2918,7 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
dev_priv->display.calc_voltage_level = cnl_calc_voltage_level;
dev_priv->cdclk.table = cnl_cdclk_table;
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.set_cdclk = bxt_set_cdclk;
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
@@ -2887,7 +2927,7 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
dev_priv->cdclk.table = glk_cdclk_table;
else
dev_priv->cdclk.table = bxt_cdclk_table;
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
dev_priv->display.bw_calc_min_cdclk = skl_bw_calc_min_cdclk;
dev_priv->display.set_cdclk = skl_set_cdclk;
dev_priv->display.modeset_calc_cdclk = skl_modeset_calc_cdclk;
@@ -2908,9 +2948,9 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
dev_priv->display.modeset_calc_cdclk = fixed_modeset_calc_cdclk;
}
- if (DISPLAY_VER(dev_priv) >= 10 || IS_GEN9_LP(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 10 || IS_BROXTON(dev_priv))
dev_priv->display.get_cdclk = bxt_get_cdclk;
- else if (IS_GEN9_BC(dev_priv))
+ else if (DISPLAY_VER(dev_priv) == 9)
dev_priv->display.get_cdclk = skl_get_cdclk;
else if (IS_BROADWELL(dev_priv))
dev_priv->display.get_cdclk = bdw_get_cdclk;
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index c75d7124d57a..dab892d2251b 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -23,6 +23,7 @@
*/
#include "intel_color.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#define CTM_COEFF_SIGN (1ULL << 63)
@@ -225,7 +226,7 @@ static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
*/
return crtc_state->limited_color_range &&
(IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) ||
- IS_DISPLAY_RANGE(dev_priv, 9, 10));
+ IS_DISPLAY_VER(dev_priv, 9, 10));
}
static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
@@ -1711,7 +1712,7 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat
} else {
if (DISPLAY_VER(dev_priv) >= 11)
return icl_gamma_precision(crtc_state);
- else if (IS_DISPLAY_VER(dev_priv, 10))
+ else if (DISPLAY_VER(dev_priv) == 10)
return glk_gamma_precision(crtc_state);
else if (IS_IRONLAKE(dev_priv))
return ilk_gamma_precision(crtc_state);
@@ -2136,7 +2137,7 @@ void intel_color_init(struct intel_crtc *crtc)
if (DISPLAY_VER(dev_priv) >= 11) {
dev_priv->display.load_luts = icl_load_luts;
dev_priv->display.read_luts = icl_read_luts;
- } else if (IS_DISPLAY_VER(dev_priv, 10)) {
+ } else if (DISPLAY_VER(dev_priv) == 10) {
dev_priv->display.load_luts = glk_load_luts;
dev_priv->display.read_luts = glk_read_luts;
} else if (DISPLAY_VER(dev_priv) >= 8) {
diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index 5df57d16a401..487c54cd5982 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -4,6 +4,7 @@
*/
#include "intel_combo_phy.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#define for_each_combo_phy(__dev_priv, __phy) \
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index d5ceb7bdc14b..9bed1ccecea0 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -282,14 +282,12 @@ void
intel_attach_hdmi_colorspace_property(struct drm_connector *connector)
{
if (!drm_mode_create_hdmi_colorspace_property(connector))
- drm_object_attach_property(&connector->base,
- connector->colorspace_property, 0);
+ drm_connector_attach_colorspace_property(connector);
}
void
intel_attach_dp_colorspace_property(struct drm_connector *connector)
{
if (!drm_mode_create_dp_colorspace_property(connector))
- drm_object_attach_property(&connector->base,
- connector->colorspace_property, 0);
+ drm_connector_attach_colorspace_property(connector);
}
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 580d652c3276..648f1c0d3d39 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -36,7 +36,9 @@
#include "i915_drv.h"
#include "intel_connector.h"
#include "intel_crt.h"
+#include "intel_crtc.h"
#include "intel_ddi.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
@@ -356,7 +358,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
* DAC limit supposedly 355 MHz.
*/
max_clock = 270000;
- else if (IS_DISPLAY_RANGE(dev_priv, 3, 4))
+ else if (IS_DISPLAY_VER(dev_priv, 3, 4))
max_clock = 400000;
else
max_clock = 350000;
@@ -711,7 +713,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
/* Set the border color to purple. */
intel_uncore_write(uncore, bclrpat_reg, 0x500050);
- if (!IS_DISPLAY_VER(dev_priv, 2)) {
+ if (DISPLAY_VER(dev_priv) != 2) {
u32 pipeconf = intel_uncore_read(uncore, pipeconf_reg);
intel_uncore_write(uncore,
pipeconf_reg,
@@ -1047,7 +1049,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
else
crt->base.pipe_mask = ~0;
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
connector->interlace_allowed = 0;
else
connector->interlace_allowed = 1;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 39358076c05b..95ff1707b4bd 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -302,11 +302,11 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
if (IS_CHERRYVIEW(dev_priv) ||
IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
funcs = &g4x_crtc_funcs;
- else if (IS_DISPLAY_VER(dev_priv, 4))
+ else if (DISPLAY_VER(dev_priv) == 4)
funcs = &i965_crtc_funcs;
else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
funcs = &i915gm_crtc_funcs;
- else if (IS_DISPLAY_VER(dev_priv, 3))
+ else if (DISPLAY_VER(dev_priv) == 3)
funcs = &i915_crtc_funcs;
else
funcs = &i8xx_crtc_funcs;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h
index 08112d557411..a5ae997581aa 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -18,5 +18,8 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
struct intel_crtc *crtc);
+u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
+void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state);
+void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state);
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_csr.h b/drivers/gpu/drm/i915/display/intel_csr.h
deleted file mode 100644
index 03c64f8af7ab..000000000000
--- a/drivers/gpu/drm/i915/display/intel_csr.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#ifndef __INTEL_CSR_H__
-#define __INTEL_CSR_H__
-
-struct drm_i915_private;
-
-#define CSR_VERSION(major, minor) ((major) << 16 | (minor))
-#define CSR_VERSION_MAJOR(version) ((version) >> 16)
-#define CSR_VERSION_MINOR(version) ((version) & 0xffff)
-
-void intel_csr_ucode_init(struct drm_i915_private *i915);
-void intel_csr_load_program(struct drm_i915_private *i915);
-void intel_csr_ucode_fini(struct drm_i915_private *i915);
-void intel_csr_ucode_suspend(struct drm_i915_private *i915);
-void intel_csr_ucode_resume(struct drm_i915_private *i915);
-
-#endif /* __INTEL_CSR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index 2345f2efd60b..966e020331fb 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -13,6 +13,7 @@
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_cursor.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_display.h"
#include "intel_fb.h"
@@ -382,6 +383,10 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
cntl |= MCURSOR_ROTATE_180;
+ /* Wa_22012358565:adlp */
+ if (DISPLAY_VER(dev_priv) == 13)
+ cntl |= MCURSOR_ARB_SLOTS(1);
+
return cntl;
}
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 953de42e277c..390869bd6b63 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -31,8 +31,10 @@
#include "intel_audio.h"
#include "intel_combo_phy.h"
#include "intel_connector.h"
+#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"
@@ -113,7 +115,8 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
&n_entries);
/* If we're boosting the current, set bit 31 of trans1 */
- if (IS_GEN9_BC(dev_priv) && intel_bios_encoder_dp_boost_level(encoder->devdata))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) &&
+ intel_bios_encoder_dp_boost_level(encoder->devdata))
iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
for (i = 0; i < n_entries; i++) {
@@ -146,7 +149,8 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
level = n_entries - 1;
/* If we're boosting the current, set bit 31 of trans1 */
- if (IS_GEN9_BC(dev_priv) && intel_bios_encoder_hdmi_boost_level(encoder->devdata))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) &&
+ intel_bios_encoder_hdmi_boost_level(encoder->devdata))
iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
/* Entry 9 is for HDMI: */
@@ -174,7 +178,7 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
enum port port)
{
/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
- if (DISPLAY_VER(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) < 10) {
usleep_range(518, 1000);
return;
}
@@ -245,15 +249,48 @@ static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
}
}
+static u32 ddi_buf_phy_link_rate(int port_clock)
+{
+ switch (port_clock) {
+ case 162000:
+ return DDI_BUF_PHY_LINK_RATE(0);
+ case 216000:
+ return DDI_BUF_PHY_LINK_RATE(4);
+ case 243000:
+ return DDI_BUF_PHY_LINK_RATE(5);
+ case 270000:
+ return DDI_BUF_PHY_LINK_RATE(1);
+ case 324000:
+ return DDI_BUF_PHY_LINK_RATE(6);
+ case 432000:
+ return DDI_BUF_PHY_LINK_RATE(7);
+ case 540000:
+ return DDI_BUF_PHY_LINK_RATE(2);
+ case 810000:
+ return DDI_BUF_PHY_LINK_RATE(3);
+ default:
+ MISSING_CASE(port_clock);
+ return DDI_BUF_PHY_LINK_RATE(0);
+ }
+}
+
static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
intel_dp->DP = dig_port->saved_port_bits |
DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0);
intel_dp->DP |= DDI_PORT_WIDTH(crtc_state->lane_count);
+
+ if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) {
+ intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
+ if (dig_port->tc_mode != TC_PORT_TBT_ALT)
+ intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+ }
}
static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
@@ -471,7 +508,7 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
}
- if (IS_DISPLAY_RANGE(dev_priv, 8, 10) &&
+ if (IS_DISPLAY_VER(dev_priv, 8, 10) &&
crtc_state->master_transcoder != INVALID_TRANSCODER) {
u8 master_select =
bdw_trans_port_sync_master_select(crtc_state->master_transcoder);
@@ -546,7 +583,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
ctl &= ~TRANS_DDI_FUNC_ENABLE;
- if (IS_DISPLAY_RANGE(dev_priv, 8, 10))
+ if (IS_DISPLAY_VER(dev_priv, 8, 10))
ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE |
TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK);
@@ -759,7 +796,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
*is_dp_mst = mst_pipe_mask;
out:
- if (*pipe_mask && IS_GEN9_LP(dev_priv)) {
+ if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) {
tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port));
if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
BXT_PHY_LANE_POWERDOWN_ACK |
@@ -850,18 +887,19 @@ void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum port port = encoder->port;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ u32 val;
if (cpu_transcoder != TRANSCODER_EDP) {
- if (DISPLAY_VER(dev_priv) >= 12)
- intel_de_write(dev_priv,
- TRANS_CLK_SEL(cpu_transcoder),
- TGL_TRANS_CLK_SEL_PORT(port));
+ if (DISPLAY_VER(dev_priv) >= 13)
+ val = TGL_TRANS_CLK_SEL_PORT(phy);
+ else if (DISPLAY_VER(dev_priv) >= 12)
+ val = TGL_TRANS_CLK_SEL_PORT(encoder->port);
else
- intel_de_write(dev_priv,
- TRANS_CLK_SEL(cpu_transcoder),
- TRANS_CLK_SEL_PORT(port));
+ val = TRANS_CLK_SEL_PORT(encoder->port);
+
+ intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
}
}
@@ -974,9 +1012,11 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
if (DISPLAY_VER(dev_priv) >= 12) {
if (intel_phy_is_combo(dev_priv, phy))
tgl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
+ else if (IS_ALDERLAKE_P(dev_priv))
+ adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
else
tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
- } else if (IS_DISPLAY_VER(dev_priv, 11)) {
+ } else if (DISPLAY_VER(dev_priv) == 11) {
if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE))
jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries);
else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE))
@@ -987,7 +1027,7 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
icl_get_mg_buf_trans(encoder, crtc_state, &n_entries);
} else if (IS_CANNONLAKE(dev_priv)) {
cnl_get_buf_trans(encoder, crtc_state, &n_entries);
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
bxt_get_buf_trans(encoder, crtc_state, &n_entries);
} else {
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
@@ -1420,7 +1460,10 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
if (enc_to_dig_port(encoder)->tc_mode == TC_PORT_TBT_ALT)
return;
- ddi_translations = tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
+ if (IS_ALDERLAKE_P(dev_priv))
+ ddi_translations = adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
+ else
+ ddi_translations = tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations))
return;
@@ -1454,6 +1497,14 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
val = intel_de_read(dev_priv, DKL_TX_DPCNTL2(tc_port));
val &= ~DKL_TX_DP20BITMODE;
intel_de_write(dev_priv, DKL_TX_DPCNTL2(tc_port), val);
+
+ if ((intel_crtc_has_dp_encoder(crtc_state) &&
+ crtc_state->port_clock == 162000) ||
+ (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
+ crtc_state->port_clock == 594000))
+ val |= DKL_TX_LOADGEN_SHARING_PMD_DISABLE;
+ else
+ val &= ~DKL_TX_LOADGEN_SHARING_PMD_DISABLE;
}
}
@@ -1555,7 +1606,7 @@ hsw_set_signal_levels(struct intel_dp *intel_dp,
intel_dp->DP &= ~DDI_BUF_EMP_MASK;
intel_dp->DP |= signal_levels;
- if (IS_GEN9_BC(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
skl_ddi_set_iboost(encoder, crtc_state, level);
intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
@@ -2332,8 +2383,8 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL,
enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
drm_dbg_kms(&i915->drm,
- "Failed to set MSA_TIMING_PAR_IGNORE %s in the sink\n",
- enable ? "enable" : "disable");
+ "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
+ enabledisable(enable));
}
static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
@@ -2648,7 +2699,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
icl_ddi_vswing_sequence(encoder, crtc_state, level);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_vswing_sequence(encoder, crtc_state, level);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_ddi_vswing_sequence(encoder, crtc_state, level);
else
intel_prepare_dp_ddi_buffers(encoder, crtc_state);
@@ -2759,7 +2810,6 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
conn_state);
/* FIXME precompute everything properly */
- /* FIXME how do we turn infoframes off again? */
if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
dig_port->set_infoframes(encoder,
crtc_state->has_infoframe,
@@ -3092,20 +3142,20 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
if (DISPLAY_VER(dev_priv) >= 12)
tgl_ddi_vswing_sequence(encoder, crtc_state, level);
- else if (IS_DISPLAY_VER(dev_priv, 11))
+ else if (DISPLAY_VER(dev_priv) == 11)
icl_ddi_vswing_sequence(encoder, crtc_state, level);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_vswing_sequence(encoder, crtc_state, level);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_ddi_vswing_sequence(encoder, crtc_state, level);
else
intel_prepare_hdmi_ddi_buffers(encoder, level);
- if (IS_GEN9_BC(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
skl_ddi_set_iboost(encoder, crtc_state, level);
/* Display WA #1143: skl,kbl,cfl */
- if (IS_GEN9_BC(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
/*
* For some reason these chicken bits have been
* stuffed into a transcoder register, event though
@@ -3144,6 +3194,9 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
/* In HDMI/DVI mode, the port width, and swing/emphasis values
* are ignored so nothing special needs to be done besides
* enabling the port.
+ *
+ * On ADL_P the PHY link rate and lane count must be programmed but
+ * these are both 0 for HDMI.
*/
intel_de_write(dev_priv, DDI_BUF_CTL(port),
dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE);
@@ -3321,7 +3374,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
* Type-C ports. Skip this step for TBT.
*/
intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_ddi_phy_set_lane_optim_mask(encoder,
crtc_state->lane_lat_optim_mask);
}
@@ -3679,7 +3732,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
if (!pipe_config->bigjoiner_slave)
ddi_dotclock_get(pipe_config);
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_get_lane_lat_optim_mask(encoder);
@@ -3705,6 +3758,8 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
+
+ intel_psr_get_config(encoder, pipe_config);
}
void intel_ddi_get_clock(struct intel_encoder *encoder,
@@ -3885,7 +3940,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
pipe_config->pch_pfit.enabled ||
pipe_config->crc_enabled;
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
@@ -4007,9 +4062,11 @@ static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
{
+ struct drm_i915_private *i915 = to_i915(encoder->dev);
struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
intel_dp_encoder_flush_work(encoder);
+ intel_display_power_flush_work(i915);
drm_encoder_cleanup(encoder);
if (dig_port)
@@ -4053,7 +4110,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
dig_port->dp.set_signal_levels = icl_set_signal_levels;
else if (IS_CANNONLAKE(dev_priv))
dig_port->dp.set_signal_levels = cnl_set_signal_levels;
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
dig_port->dp.set_signal_levels = bxt_set_signal_levels;
else
dig_port->dp.set_signal_levels = hsw_set_signal_levels;
@@ -4296,7 +4353,7 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
* supported configuration
*/
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
return true;
/* Cannonlake: Most of SKUs don't support DDI_E, and the only
@@ -4350,6 +4407,17 @@ static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy)
i915->hti_state & HDPORT_DDI_USED(phy);
}
+static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ if (port >= PORT_D_XELPD)
+ return HPD_PORT_D + port - PORT_D_XELPD;
+ else if (port >= PORT_TC1)
+ return HPD_PORT_TC1 + port - PORT_TC1;
+ else
+ return HPD_PORT_A + port - PORT_A;
+}
+
static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv,
enum port port)
{
@@ -4489,7 +4557,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder = &dig_port->base;
encoder->devdata = devdata;
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) {
+ drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
+ DRM_MODE_ENCODER_TMDS,
+ "DDI %c/PHY %c",
+ port_name(port - PORT_D_XELPD + PORT_D),
+ phy_name(phy));
+ } else if (DISPLAY_VER(dev_priv) >= 12) {
enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
@@ -4585,10 +4659,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->disable_clock = cnl_ddi_disable_clock;
encoder->is_clock_enabled = cnl_ddi_is_clock_enabled;
encoder->get_config = cnl_ddi_get_config;
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
/* BXT/GLK have fixed PLL->port mapping */
encoder->get_config = bxt_ddi_get_config;
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
encoder->enable_clock = skl_ddi_enable_clock;
encoder->disable_clock = skl_ddi_disable_clock;
encoder->is_clock_enabled = skl_ddi_is_clock_enabled;
@@ -4600,7 +4674,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->get_config = hsw_ddi_get_config;
}
- if (IS_DG1(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 13)
+ encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
+ else if (IS_DG1(dev_priv))
encoder->hpd_pin = dg1_hpd_pin(dev_priv, port);
else if (IS_ROCKETLAKE(dev_priv))
encoder->hpd_pin = rkl_hpd_pin(dev_priv, port);
@@ -4608,11 +4684,11 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
encoder->hpd_pin = tgl_hpd_pin(dev_priv, port);
else if (IS_JSL_EHL(dev_priv))
encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
- else if (IS_DISPLAY_VER(dev_priv, 11))
+ else if (DISPLAY_VER(dev_priv) == 11)
encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
- else if (IS_DISPLAY_VER(dev_priv, 10))
+ else if (IS_CANNONLAKE(dev_priv))
encoder->hpd_pin = cnl_hpd_pin(dev_priv, port);
- else if (IS_DISPLAY_VER(dev_priv, 9))
+ else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
else
encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
@@ -4654,9 +4730,12 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
dig_port->hpd_pulse = intel_dp_hpd_pulse;
- /* Splitter enable for eDP MSO is supported for pipe A only. */
- if (dig_port->dp.mso_link_count)
+ /* Splitter enable for eDP MSO is limited to certain pipes. */
+ if (dig_port->dp.mso_link_count) {
encoder->pipe_mask = BIT(PIPE_A);
+ if (IS_ALDERLAKE_P(dev_priv))
+ encoder->pipe_mask |= BIT(PIPE_B);
+ }
}
/* In theory we don't need the encoder->type check, but leave it just in
@@ -4672,7 +4751,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
else
dig_port->connected = lpt_digital_port_connected;
} else if (DISPLAY_VER(dev_priv) >= 8) {
- if (port == PORT_A || IS_GEN9_LP(dev_priv))
+ if (port == PORT_A || IS_GEMINILAKE(dev_priv) ||
+ IS_BROXTON(dev_priv))
dig_port->connected = bdw_digital_port_connected;
else
dig_port->connected = lpt_digital_port_connected;
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index 5d9ce6042e87..8bfd00f49f2a 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -6,6 +6,7 @@
#include "i915_drv.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
+#include "intel_de.h"
#include "intel_display_types.h"
/* HDMI/DVI modes ignore everything but the last 2 items. So we share
@@ -734,6 +735,34 @@ static const struct cnl_ddi_buf_trans rkl_combo_phy_ddi_translations_dp_hbr2_hbr
{ 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */
};
+static const struct tgl_dkl_phy_ddi_buf_trans adlp_dkl_phy_dp_ddi_trans_hbr[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { 0x7, 0x0, 0x01 }, /* 0 0 400mV 0 dB */
+ { 0x5, 0x0, 0x06 }, /* 0 1 400mV 3.5 dB */
+ { 0x2, 0x0, 0x0B }, /* 0 2 400mV 6 dB */
+ { 0x0, 0x0, 0x17 }, /* 0 3 400mV 9.5 dB */
+ { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
+ { 0x2, 0x0, 0x08 }, /* 1 1 600mV 3.5 dB */
+ { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
+ { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
+ { 0x0, 0x0, 0x0B }, /* 2 1 800mV 3.5 dB */
+ { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB */
+};
+
+static const struct tgl_dkl_phy_ddi_buf_trans adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3[] = {
+ /* VS pre-emp Non-trans mV Pre-emph dB */
+ { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */
+ { 0x5, 0x0, 0x04 }, /* 0 1 400mV 3.5 dB */
+ { 0x2, 0x0, 0x0A }, /* 0 2 400mV 6 dB */
+ { 0x0, 0x0, 0x18 }, /* 0 3 400mV 9.5 dB */
+ { 0x5, 0x0, 0x00 }, /* 1 0 600mV 0 dB */
+ { 0x2, 0x0, 0x06 }, /* 1 1 600mV 3.5 dB */
+ { 0x0, 0x0, 0x14 }, /* 1 2 600mV 6 dB */
+ { 0x2, 0x0, 0x00 }, /* 2 0 800mV 0 dB */
+ { 0x0, 0x0, 0x09 }, /* 2 1 800mV 3.5 dB */
+ { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB */
+};
+
bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table)
{
return table == tgl_combo_phy_ddi_translations_edp_hbr2_hobl;
@@ -881,7 +910,7 @@ intel_ddi_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_GEN9_BC(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
const struct ddi_buf_trans *ddi_translations =
skl_get_buf_trans_edp(encoder, n_entries);
*n_entries = skl_buf_trans_num_entries(encoder->port, *n_entries);
@@ -919,7 +948,7 @@ intel_ddi_get_buf_trans_hdmi(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- if (IS_GEN9_BC(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
return skl_get_buf_trans_hdmi(dev_priv, n_entries);
} else if (IS_BROADWELL(dev_priv)) {
*n_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
@@ -1347,6 +1376,31 @@ tgl_get_dkl_buf_trans(struct intel_encoder *encoder,
return tgl_get_dkl_buf_trans_dp(encoder, crtc_state, n_entries);
}
+static const struct tgl_dkl_phy_ddi_buf_trans *
+adlp_get_dkl_buf_trans_dp(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (crtc_state->port_clock > 270000) {
+ *n_entries = ARRAY_SIZE(adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3);
+ return adlp_dkl_phy_dp_ddi_trans_hbr2_hbr3;
+ }
+
+ *n_entries = ARRAY_SIZE(adlp_dkl_phy_dp_ddi_trans_hbr);
+ return adlp_dkl_phy_dp_ddi_trans_hbr;
+}
+
+const struct tgl_dkl_phy_ddi_buf_trans *
+adlp_get_dkl_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries)
+{
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return tgl_get_dkl_buf_trans_hdmi(encoder, crtc_state, n_entries);
+ else
+ return adlp_get_dkl_buf_trans_dp(encoder, crtc_state, n_entries);
+}
+
int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *default_entry)
@@ -1361,7 +1415,7 @@ int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
else
tgl_get_dkl_buf_trans_hdmi(encoder, crtc_state, &n_entries);
*default_entry = n_entries - 1;
- } else if (IS_DISPLAY_VER(dev_priv, 11)) {
+ } else if (DISPLAY_VER(dev_priv) == 11) {
if (intel_phy_is_combo(dev_priv, phy))
icl_get_combo_buf_trans_hdmi(encoder, crtc_state, &n_entries);
else
@@ -1370,10 +1424,10 @@ int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
} else if (IS_CANNONLAKE(dev_priv)) {
cnl_get_buf_trans_hdmi(encoder, &n_entries);
*default_entry = n_entries - 1;
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
bxt_get_buf_trans_hdmi(encoder, &n_entries);
*default_entry = n_entries - 1;
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
intel_ddi_get_buf_trans_hdmi(encoder, &n_entries);
*default_entry = 8;
} else if (IS_BROADWELL(dev_priv)) {
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
index f8f0ef87e977..4c2efab38642 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
@@ -67,6 +67,10 @@ bxt_get_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
+const struct tgl_dkl_phy_ddi_buf_trans *
+adlp_get_dkl_buf_trans(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ int *n_entries);
const struct cnl_ddi_buf_trans *
tgl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h
index 00da10bf35f5..9d8c177aa228 100644
--- a/drivers/gpu/drm/i915/display/intel_de.h
+++ b/drivers/gpu/drm/i915/display/intel_de.h
@@ -8,6 +8,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
+#include "i915_trace.h"
#include "intel_uncore.h"
static inline u32
@@ -22,26 +23,12 @@ intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg)
intel_uncore_posting_read(&i915->uncore, reg);
}
-/* Note: read the warnings for intel_uncore_*_fw() functions! */
-static inline u32
-intel_de_read_fw(struct drm_i915_private *i915, i915_reg_t reg)
-{
- return intel_uncore_read_fw(&i915->uncore, reg);
-}
-
static inline void
intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
{
intel_uncore_write(&i915->uncore, reg, val);
}
-/* Note: read the warnings for intel_uncore_*_fw() functions! */
-static inline void
-intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
-{
- intel_uncore_write_fw(&i915->uncore, reg, val);
-}
-
static inline void
intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set)
{
@@ -69,4 +56,30 @@ intel_de_wait_for_clear(struct drm_i915_private *i915, i915_reg_t reg,
return intel_de_wait_for_register(i915, reg, mask, 0, timeout);
}
+/*
+ * Unlocked mmio-accessors, think carefully before using these.
+ *
+ * Certain architectures will die if the same cacheline is concurrently accessed
+ * by different clients (e.g. on Ivybridge). Access to registers should
+ * therefore generally be serialised, by either the dev_priv->uncore.lock or
+ * a more localised lock guarding all access to that bank of registers.
+ */
+static inline u32
+intel_de_read_fw(struct drm_i915_private *i915, i915_reg_t reg)
+{
+ u32 val;
+
+ val = intel_uncore_read_fw(&i915->uncore, reg);
+ trace_i915_reg_rw(false, reg, val, sizeof(val), true);
+
+ return val;
+}
+
+static inline void
+intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
+{
+ trace_i915_reg_rw(true, reg, val, sizeof(val), true);
+ intel_uncore_write_fw(&i915->uncore, reg, val);
+}
+
#endif /* __INTEL_DE_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 64e9107d70f7..3bad4e00f7be 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -63,9 +63,11 @@
#include "display/intel_vdsc.h"
#include "display/intel_vrr.h"
+#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_object.h"
#include "gt/intel_rps.h"
+#include "gt/gen8_ppgtt.h"
#include "g4x_dp.h"
#include "g4x_hdmi.h"
@@ -77,8 +79,9 @@
#include "intel_cdclk.h"
#include "intel_color.h"
#include "intel_crtc.h"
-#include "intel_csr.h"
+#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dmc.h"
#include "intel_dp_link_training.h"
#include "intel_fbc.h"
#include "intel_fdi.h"
@@ -122,6 +125,182 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
static void intel_modeset_setup_hw_state(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx);
+struct i915_dpt {
+ struct i915_address_space vm;
+
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
+ void __iomem *iomem;
+};
+
+#define i915_is_dpt(vm) ((vm)->is_dpt)
+
+static inline struct i915_dpt *
+i915_vm_to_dpt(struct i915_address_space *vm)
+{
+ BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
+ GEM_BUG_ON(!i915_is_dpt(vm));
+ return container_of(vm, struct i915_dpt, vm);
+}
+
+#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT)
+
+static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
+{
+ writeq(pte, addr);
+}
+
+static void dpt_insert_page(struct i915_address_space *vm,
+ dma_addr_t addr,
+ u64 offset,
+ enum i915_cache_level level,
+ u32 flags)
+{
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+ gen8_pte_t __iomem *base = dpt->iomem;
+
+ gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
+ vm->pte_encode(addr, level, flags));
+}
+
+static void dpt_insert_entries(struct i915_address_space *vm,
+ struct i915_vma *vma,
+ enum i915_cache_level level,
+ u32 flags)
+{
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+ gen8_pte_t __iomem *base = dpt->iomem;
+ const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
+ struct sgt_iter sgt_iter;
+ dma_addr_t addr;
+ int i;
+
+ /*
+ * Note that we ignore PTE_READ_ONLY here. The caller must be careful
+ * not to allow the user to override access to a read only page.
+ */
+
+ i = vma->node.start / I915_GTT_PAGE_SIZE;
+ for_each_sgt_daddr(addr, sgt_iter, vma->pages)
+ gen8_set_pte(&base[i++], pte_encode | addr);
+}
+
+static void dpt_clear_range(struct i915_address_space *vm,
+ u64 start, u64 length)
+{
+}
+
+static void dpt_bind_vma(struct i915_address_space *vm,
+ struct i915_vm_pt_stash *stash,
+ struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
+{
+ struct drm_i915_gem_object *obj = vma->obj;
+ u32 pte_flags;
+
+ /* Applicable to VLV (gen8+ do not support RO in the GGTT) */
+ pte_flags = 0;
+ if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
+ pte_flags |= PTE_READ_ONLY;
+ if (i915_gem_object_is_lmem(obj))
+ pte_flags |= PTE_LM;
+
+ vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
+
+ vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
+
+ /*
+ * Without aliasing PPGTT there's no difference between
+ * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
+ * upgrade to both bound if we bind either to avoid double-binding.
+ */
+ atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
+}
+
+static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
+{
+ vm->clear_range(vm, vma->node.start, vma->size);
+}
+
+static void dpt_cleanup(struct i915_address_space *vm)
+{
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+
+ i915_gem_object_put(dpt->obj);
+}
+
+static struct i915_address_space *
+intel_dpt_create(struct intel_framebuffer *fb)
+{
+ struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
+ struct drm_i915_private *i915 = to_i915(obj->dev);
+ struct drm_i915_gem_object *dpt_obj;
+ struct i915_address_space *vm;
+ struct i915_dpt *dpt;
+ size_t size;
+ int ret;
+
+ if (intel_fb_needs_pot_stride_remap(fb))
+ size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
+ else
+ size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
+
+ size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
+
+ if (HAS_LMEM(i915))
+ dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
+ else
+ dpt_obj = i915_gem_object_create_stolen(i915, size);
+ if (IS_ERR(dpt_obj))
+ return ERR_CAST(dpt_obj);
+
+ ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
+ if (ret) {
+ i915_gem_object_put(dpt_obj);
+ return ERR_PTR(ret);
+ }
+
+ dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
+ if (!dpt) {
+ i915_gem_object_put(dpt_obj);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ vm = &dpt->vm;
+
+ vm->gt = &i915->gt;
+ vm->i915 = i915;
+ vm->dma = i915->drm.dev;
+ vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
+ vm->is_dpt = true;
+
+ i915_address_space_init(vm, VM_CLASS_DPT);
+
+ vm->insert_page = dpt_insert_page;
+ vm->clear_range = dpt_clear_range;
+ vm->insert_entries = dpt_insert_entries;
+ vm->cleanup = dpt_cleanup;
+
+ vm->vma_ops.bind_vma = dpt_bind_vma;
+ vm->vma_ops.unbind_vma = dpt_unbind_vma;
+ vm->vma_ops.set_pages = ggtt_set_pages;
+ vm->vma_ops.clear_pages = clear_pages;
+
+ vm->pte_encode = gen8_ggtt_pte_encode;
+
+ dpt->obj = dpt_obj;
+
+ return &dpt->vm;
+}
+
+static void intel_dpt_destroy(struct i915_address_space *vm)
+{
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+
+ i915_vm_close(&dpt->vm);
+}
+
/* returns HPLL frequency in kHz */
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
{
@@ -230,7 +409,7 @@ static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,
u32 line1, line2;
u32 line_mask;
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
line_mask = DSL_LINEMASK_GEN2;
else
line_mask = DSL_LINEMASK_GEN3;
@@ -796,6 +975,11 @@ void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
/* FIXME: assert CPU port conditions for SNB+ */
}
+ /* Wa_22012358565:adlp */
+ if (DISPLAY_VER(dev_priv) == 13)
+ intel_de_rmw(dev_priv, PIPE_ARB_CTL(pipe),
+ 0, PIPE_ARB_USE_PROG_SLOTS);
+
reg = PIPECONF(cpu_transcoder);
val = intel_de_read(dev_priv, reg);
if (val & PIPECONF_ENABLE) {
@@ -874,7 +1058,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
case DRM_FORMAT_MOD_LINEAR:
return intel_tile_size(dev_priv);
case I915_FORMAT_MOD_X_TILED:
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
return 128;
else
return 512;
@@ -889,7 +1073,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
return 64;
fallthrough;
case I915_FORMAT_MOD_Y_TILED:
- if (IS_DISPLAY_VER(dev_priv, 2) || HAS_128_BYTE_Y_TILING(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 2 || HAS_128_BYTE_Y_TILING(dev_priv))
return 128;
else
return 512;
@@ -972,10 +1156,29 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
{
struct drm_i915_private *dev_priv = to_i915(fb->dev);
+ if (intel_fb_uses_dpt(fb))
+ return 512 * 4096;
+
/* AUX_DIST needs only 4K alignment */
- if ((DISPLAY_VER(dev_priv) < 12 && is_aux_plane(fb, color_plane)) ||
- is_ccs_plane(fb, color_plane))
+ if (is_ccs_plane(fb, color_plane))
+ return 4096;
+
+ if (is_semiplanar_uv_plane(fb, color_plane)) {
+ /*
+ * TODO: cross-check wrt. the bspec stride in bytes * 64 bytes
+ * alignment for linear UV planes on all platforms.
+ */
+ if (DISPLAY_VER(dev_priv) >= 12) {
+ if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
+ return intel_linear_alignment(dev_priv);
+
+ return intel_tile_row_size(fb, color_plane);
+ }
+
return 4096;
+ }
+
+ drm_WARN_ON(&dev_priv->drm, color_plane != 0);
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
@@ -985,19 +1188,12 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
return 256 * 1024;
return 0;
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
- if (is_semiplanar_uv_plane(fb, color_plane))
- return intel_tile_row_size(fb, color_plane);
- fallthrough;
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
return 16 * 1024;
case I915_FORMAT_MOD_Y_TILED_CCS:
case I915_FORMAT_MOD_Yf_TILED_CCS:
case I915_FORMAT_MOD_Y_TILED:
- if (DISPLAY_VER(dev_priv) >= 12 &&
- is_semiplanar_uv_plane(fb, color_plane))
- return intel_tile_row_size(fb, color_plane);
- fallthrough;
case I915_FORMAT_MOD_Yf_TILED:
return 1 * 1024 * 1024;
default:
@@ -1016,6 +1212,62 @@ static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
plane_state->view.gtt.type == I915_GGTT_VIEW_NORMAL);
}
+static struct i915_vma *
+intel_pin_fb_obj_dpt(struct drm_framebuffer *fb,
+ const struct i915_ggtt_view *view,
+ bool uses_fence,
+ unsigned long *out_flags,
+ struct i915_address_space *vm)
+{
+ struct drm_device *dev = fb->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ struct i915_vma *vma;
+ u32 alignment;
+ int ret;
+
+ if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
+ return ERR_PTR(-EINVAL);
+
+ alignment = 4096 * 512;
+
+ atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
+
+ ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+ if (ret) {
+ vma = ERR_PTR(ret);
+ goto err;
+ }
+
+ vma = i915_vma_instance(obj, vm, view);
+ if (IS_ERR(vma))
+ goto err;
+
+ if (i915_vma_misplaced(vma, 0, alignment, 0)) {
+ ret = i915_vma_unbind(vma);
+ if (ret) {
+ vma = ERR_PTR(ret);
+ goto err;
+ }
+ }
+
+ ret = i915_vma_pin(vma, 0, alignment, PIN_GLOBAL);
+ if (ret) {
+ vma = ERR_PTR(ret);
+ goto err;
+ }
+
+ vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
+
+ i915_gem_object_flush_if_display(obj);
+
+ i915_vma_get(vma);
+err:
+ atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
+
+ return vma;
+}
+
struct i915_vma *
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
bool phys_cursor,
@@ -1253,6 +1505,9 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_VYUY, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_XYUV8888, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV12, .num_planes = 4,
.char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 },
.hsub = 2, .vsub = 2, .is_yuv = true },
@@ -1335,6 +1590,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
struct intel_crtc *crtc;
struct intel_plane *plane;
+ if (!HAS_DISPLAY(dev_priv))
+ return 0;
+
/*
* We assume the primary plane for pipe A has
* the highest stride limits of them all,
@@ -1360,14 +1618,13 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv,
*
* The new CCS hash mode makes remapping impossible
*/
- if (!is_ccs_modifier(modifier)) {
- if (DISPLAY_VER(dev_priv) >= 7)
- return 256*1024;
- else if (DISPLAY_VER(dev_priv) >= 4)
- return 128*1024;
- }
-
- return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier);
+ if (DISPLAY_VER(dev_priv) < 4 || is_ccs_modifier(modifier) ||
+ intel_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;
+ else
+ return 128 * 1024;
}
static u32
@@ -1403,7 +1660,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
* require the entire fb to accommodate that to avoid
* potential runtime errors at plane configuration time.
*/
- if ((IS_DISPLAY_VER(dev_priv, 9) || IS_GEMINILAKE(dev_priv)) &&
+ if ((DISPLAY_VER(dev_priv) == 9 || IS_GEMINILAKE(dev_priv)) &&
color_plane == 0 && fb->width > 3840)
tile_width *= 4;
/*
@@ -1438,7 +1695,8 @@ initial_plane_vma(struct drm_i915_private *i915,
* important and we should probably use that space with FBC or other
* features.
*/
- if (size * 2 > i915->stolen_usable_size)
+ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
+ size * 2 > i915->stolen_usable_size)
return NULL;
obj = i915_gem_object_create_stolen_for_preallocated(i915, base, size);
@@ -1606,13 +1864,56 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
* Gen2 reports pipe underruns whenever all planes are disabled.
* So disable underrun reporting before all the planes get disabled.
*/
- if (IS_DISPLAY_VER(dev_priv, 2) && !crtc_state->active_planes)
+ if (DISPLAY_VER(dev_priv) == 2 && !crtc_state->active_planes)
intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
intel_disable_plane(plane, crtc_state);
intel_wait_for_vblank(dev_priv, crtc->pipe);
}
+static struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
+{
+ struct drm_i915_private *i915 = vm->i915;
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+ intel_wakeref_t wakeref;
+ struct i915_vma *vma;
+ void __iomem *iomem;
+
+ wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+ atomic_inc(&i915->gpu_error.pending_fb_pin);
+
+ vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096,
+ HAS_LMEM(i915) ? 0 : PIN_MAPPABLE);
+ if (IS_ERR(vma))
+ goto err;
+
+ iomem = i915_vma_pin_iomap(vma);
+ i915_vma_unpin(vma);
+ if (IS_ERR(iomem)) {
+ vma = iomem;
+ goto err;
+ }
+
+ dpt->vma = vma;
+ dpt->iomem = iomem;
+
+ i915_vma_get(vma);
+
+err:
+ atomic_dec(&i915->gpu_error.pending_fb_pin);
+ intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+
+ return vma;
+}
+
+static void intel_dpt_unpin(struct i915_address_space *vm)
+{
+ struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+
+ i915_vma_unpin_iomap(dpt->vma);
+ i915_vma_put(dpt->vma);
+}
+
static void
intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct intel_initial_plane_config *plane_config)
@@ -1658,12 +1959,12 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
continue;
state = to_intel_plane_state(c->primary->state);
- if (!state->vma)
+ if (!state->ggtt_vma)
continue;
if (intel_plane_ggtt_offset(state) == plane_config->base) {
fb = state->hw.fb;
- vma = state->vma;
+ vma = state->ggtt_vma;
goto valid_fb;
}
}
@@ -1690,7 +1991,7 @@ valid_fb:
&intel_state->view);
__i915_vma_pin(vma);
- intel_state->vma = i915_vma_get(vma);
+ intel_state->ggtt_vma = i915_vma_get(vma);
if (intel_plane_uses_fence(intel_state) && i915_vma_pin_fence(vma) == 0)
if (vma->fence)
intel_state->flags |= PLANE_HAS_FENCE;
@@ -1913,6 +2214,21 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)
* across pipe
*/
tmp |= PIXEL_ROUNDING_TRUNC_FB_PASSTHRU;
+
+ /*
+ * "The underrun recovery mechanism should be disabled
+ * when the following is enabled for this pipe:
+ * WiDi
+ * Downscaling (this includes YUV420 fullblend)
+ * COG
+ * DSC
+ * PSR2"
+ *
+ * FIXME: enable whenever possible...
+ */
+ if (IS_ALDERLAKE_P(dev_priv))
+ tmp |= UNDERRUN_RECOVERY_DISABLE;
+
intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp);
}
@@ -2469,7 +2785,7 @@ static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state)
return false;
/* WA Display #0827: Gen9:all */
- if (IS_DISPLAY_VER(dev_priv, 9))
+ if (DISPLAY_VER(dev_priv) == 9)
return true;
return false;
@@ -2480,7 +2796,7 @@ static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
/* Wa_2006604312:icl,ehl */
- if (crtc_state->scaler_state.scaler_users > 0 && IS_DISPLAY_VER(dev_priv, 11))
+ if (crtc_state->scaler_state.scaler_users > 0 && DISPLAY_VER(dev_priv) == 11)
return true;
return false;
@@ -2680,7 +2996,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
* chance of catching underruns with the intermediate watermarks
* vs. the old plane configuration.
*/
- if (IS_DISPLAY_VER(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state))
+ if (DISPLAY_VER(dev_priv) == 2 && planes_disabling(old_crtc_state, new_crtc_state))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
/*
@@ -3116,6 +3432,7 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(master->base.dev);
struct intel_crtc_state *master_crtc_state;
struct drm_connector_state *conn_state;
struct drm_connector *conn;
@@ -3149,6 +3466,9 @@ static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
/* and DSC on slave */
intel_dsc_enable(NULL, crtc_state);
}
+
+ if (DISPLAY_VER(dev_priv) >= 13)
+ intel_uncompressed_joiner_enable(crtc_state);
}
static void hsw_crtc_enable(struct intel_atomic_state *state,
@@ -3199,7 +3519,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
crtc->active = true;
/* Display WA #1180: WaDisableScalarClockGating: glk, cnl */
- psl_clkgate_wa = IS_DISPLAY_VER(dev_priv, 10) &&
+ psl_clkgate_wa = DISPLAY_VER(dev_priv) == 10 &&
new_crtc_state->pch_pfit.enabled;
if (psl_clkgate_wa)
glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true);
@@ -3376,7 +3696,9 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy)
bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
{
- if (IS_TIGERLAKE(dev_priv))
+ if (IS_ALDERLAKE_P(dev_priv))
+ return phy >= PHY_F && phy <= PHY_I;
+ else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
else if (IS_ICELAKE(dev_priv))
return phy >= PHY_C && phy <= PHY_F;
@@ -3386,7 +3708,11 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port)
{
- if (IS_ALDERLAKE_S(i915) && port >= PORT_TC1)
+ if (DISPLAY_VER(i915) >= 13 && port >= PORT_D_XELPD)
+ return PHY_D + port - PORT_D_XELPD;
+ else if (DISPLAY_VER(i915) >= 13 && port >= PORT_TC1)
+ return PHY_F + port - PORT_TC1;
+ else if (IS_ALDERLAKE_S(i915) && port >= PORT_TC1)
return PHY_B + port - PORT_TC1;
else if ((IS_DG1(i915) || IS_ROCKETLAKE(i915)) && port >= PORT_TC1)
return PHY_C + port - PORT_TC1;
@@ -3653,7 +3979,7 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
crtc->active = true;
- if (!IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) != 2)
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_encoders_pre_enable(state, crtc);
@@ -3678,7 +4004,7 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
intel_encoders_enable(state, crtc);
/* prevents spurious underruns */
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
intel_wait_for_vblank(dev_priv, pipe);
}
@@ -3709,7 +4035,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state,
* On gen2 planes are double buffered but the pipe isn't, so we must
* wait for planes to fully turn off before disabling the pipe.
*/
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
intel_wait_for_vblank(dev_priv, pipe);
intel_encoders_disable(state, crtc);
@@ -3733,7 +4059,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state,
intel_encoders_post_pll_disable(state, crtc);
- if (!IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) != 2)
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
if (!dev_priv->display.initial_watermarks)
@@ -3839,6 +4165,9 @@ int intel_display_suspend(struct drm_device *dev)
struct drm_atomic_state *state;
int ret;
+ if (!HAS_DISPLAY(dev_priv))
+ return 0;
+
state = drm_atomic_helper_suspend(dev);
ret = PTR_ERR_OR_ZERO(state);
if (ret)
@@ -3979,7 +4308,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state)
{
u32 pixel_rate = crtc_state->hw.pipe_mode.crtc_clock;
- unsigned int pipe_w, pipe_h, pfit_w, pfit_h;
+ struct drm_rect src;
/*
* We only use IF-ID interlacing. If we ever use
@@ -3989,23 +4318,12 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state)
if (!crtc_state->pch_pfit.enabled)
return pixel_rate;
- pipe_w = crtc_state->pipe_src_w;
- pipe_h = crtc_state->pipe_src_h;
-
- pfit_w = drm_rect_width(&crtc_state->pch_pfit.dst);
- pfit_h = drm_rect_height(&crtc_state->pch_pfit.dst);
-
- if (pipe_w < pfit_w)
- pipe_w = pfit_w;
- if (pipe_h < pfit_h)
- pipe_h = pfit_h;
+ drm_rect_init(&src, 0, 0,
+ crtc_state->pipe_src_w << 16,
+ crtc_state->pipe_src_h << 16);
- if (drm_WARN_ON(crtc_state->uapi.crtc->dev,
- !pfit_w || !pfit_h))
- return pixel_rate;
-
- return div_u64(mul_u32_u32(pixel_rate, pipe_w * pipe_h),
- pfit_w * pfit_h);
+ return intel_adjusted_rate(&src, &crtc_state->pch_pfit.dst,
+ pixel_rate);
}
static void intel_mode_from_crtc_timings(struct drm_display_mode *mode,
@@ -4297,7 +4615,7 @@ static bool transcoder_has_m2_n2(struct drm_i915_private *dev_priv,
* Strictly speaking some registers are available before
* gen7, but we only support DRRS on gen7+
*/
- return IS_DISPLAY_VER(dev_priv, 7) || IS_CHERRYVIEW(dev_priv);
+ return DISPLAY_VER(dev_priv) == 7 || IS_CHERRYVIEW(dev_priv);
}
static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
@@ -4444,7 +4762,7 @@ static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
return false;
if (DISPLAY_VER(dev_priv) >= 9 ||
@@ -5419,8 +5737,12 @@ static void hsw_set_pipeconf(const struct intel_crtc_state *crtc_state)
static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct intel_crtc_scaler_state *scaler_state =
+ &crtc_state->scaler_state;
+
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 val = 0;
+ int i;
switch (crtc_state->pipe_bpp) {
case 18:
@@ -5459,6 +5781,23 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
if (DISPLAY_VER(dev_priv) >= 12)
val |= PIPEMISC_PIXEL_ROUNDING_TRUNC;
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ bool scaler_in_use = false;
+
+ for (i = 0; i < crtc->num_scalers; i++) {
+ if (!scaler_state->scalers[i].in_use)
+ continue;
+
+ scaler_in_use = true;
+ break;
+ }
+
+ intel_de_rmw(dev_priv, PIPE_MISC2(crtc->pipe),
+ PIPE_MISC2_UNDERRUN_BUBBLE_COUNTER_MASK,
+ scaler_in_use ? PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN :
+ PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS);
+ }
+
intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val);
}
@@ -5639,7 +5978,7 @@ static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state)
* ivb/hsw (since we don't use the higher upscaling modes which
* differentiates them) so just WARN about this case for now.
*/
- drm_WARN_ON(&dev_priv->drm, IS_DISPLAY_VER(dev_priv, 7) &&
+ drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 7 &&
(ctl & PF_PIPE_SEL_MASK_IVB) != PF_PIPE_SEL_IVB(crtc->pipe));
}
@@ -5952,13 +6291,15 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_set);
- if (IS_GEN9_LP(dev_priv) &&
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_set)) {
drm_WARN_ON(&dev_priv->drm, active);
active = true;
}
intel_dsc_get_config(pipe_config);
+ if (DISPLAY_VER(dev_priv) >= 13 && !pipe_config->dsc.compression_enable)
+ intel_uncompressed_joiner_get_config(pipe_config);
if (!active) {
/* bigjoiner slave doesn't enable transcoder */
@@ -6322,7 +6663,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
return dev_priv->vbt.lvds_ssc_freq;
else if (HAS_PCH_SPLIT(dev_priv))
return 120000;
- else if (!IS_DISPLAY_VER(dev_priv, 2))
+ else if (DISPLAY_VER(dev_priv) != 2)
return 96000;
else
return 48000;
@@ -6355,7 +6696,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
}
- if (!IS_DISPLAY_VER(dev_priv, 2)) {
+ if (DISPLAY_VER(dev_priv) != 2) {
if (IS_PINEVIEW(dev_priv))
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
@@ -6870,7 +7211,8 @@ static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state)
crtc_state->pixel_rate);
/* Display WA #1135: BXT:ALL GLK:ALL */
- if (IS_GEN9_LP(dev_priv) && dev_priv->ipc_enabled)
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ dev_priv->ipc_enabled)
linetime_wm /= 2;
return min(linetime_wm, 0x1ff);
@@ -7333,10 +7675,11 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
intel_hdmi_infoframe_enable(DP_SDP_VSC))
intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc);
- drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
+ drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
yesno(pipe_config->vrr.enable),
pipe_config->vrr.vmin, pipe_config->vrr.vmax,
- pipe_config->vrr.pipeline_full, pipe_config->vrr.flipline,
+ pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband,
+ pipe_config->vrr.flipline,
intel_vrr_vmin_vblank_start(pipe_config),
intel_vrr_vmax_vblank_start(pipe_config));
@@ -7972,6 +8315,16 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} \
} while (0)
+#define PIPE_CONF_CHECK_X_WITH_MASK(name, mask) do { \
+ if ((current_config->name & (mask)) != (pipe_config->name & (mask))) { \
+ pipe_config_mismatch(fastset, crtc, __stringify(name), \
+ "(expected 0x%08x, found 0x%08x)", \
+ current_config->name & (mask), \
+ pipe_config->name & (mask)); \
+ ret = false; \
+ } \
+} while (0)
+
#define PIPE_CONF_CHECK_I(name) do { \
if (current_config->name != pipe_config->name) { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
@@ -8260,6 +8613,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
if (bp_gamma)
PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma);
+
+ PIPE_CONF_CHECK_BOOL(has_psr);
+ PIPE_CONF_CHECK_BOOL(has_psr2);
+ PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch);
+ PIPE_CONF_CHECK_I(dc3co_exitline);
}
PIPE_CONF_CHECK_BOOL(double_wide);
@@ -8313,7 +8671,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(min_voltage_level);
}
- PIPE_CONF_CHECK_X(infoframes.enable);
+ if (fastset && (current_config->has_psr || pipe_config->has_psr))
+ PIPE_CONF_CHECK_X_WITH_MASK(infoframes.enable,
+ ~intel_hdmi_infoframe_enable(DP_SDP_VSC));
+ else
+ PIPE_CONF_CHECK_X(infoframes.enable);
+
PIPE_CONF_CHECK_X(infoframes.gcp);
PIPE_CONF_CHECK_INFOFRAME(avi);
PIPE_CONF_CHECK_INFOFRAME(spd);
@@ -8342,6 +8705,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(vrr.vmax);
PIPE_CONF_CHECK_I(vrr.flipline);
PIPE_CONF_CHECK_I(vrr.pipeline_full);
+ PIPE_CONF_CHECK_I(vrr.guardband);
#undef PIPE_CONF_CHECK_X
#undef PIPE_CONF_CHECK_I
@@ -8447,6 +8811,38 @@ static void verify_wm_state(struct intel_crtc *crtc,
hw_wm_level->lines);
}
+ hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0;
+ sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0;
+
+ if (HAS_HW_SAGV_WM(dev_priv) &&
+ !skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
+ drm_err(&dev_priv->drm,
+ "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ plane->base.base.id, plane->base.name,
+ sw_wm_level->enable,
+ sw_wm_level->blocks,
+ sw_wm_level->lines,
+ hw_wm_level->enable,
+ hw_wm_level->blocks,
+ hw_wm_level->lines);
+ }
+
+ hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm;
+ sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm;
+
+ if (HAS_HW_SAGV_WM(dev_priv) &&
+ !skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
+ drm_err(&dev_priv->drm,
+ "[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+ plane->base.base.id, plane->base.name,
+ sw_wm_level->enable,
+ sw_wm_level->blocks,
+ sw_wm_level->lines,
+ hw_wm_level->enable,
+ hw_wm_level->blocks,
+ hw_wm_level->lines);
+ }
+
/* DDB */
hw_ddb_entry = &hw->ddb_y[plane->id];
sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb_y[plane->id];
@@ -8736,6 +9132,44 @@ intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
verify_disabled_dpll_state(dev_priv);
}
+int intel_modeset_all_pipes(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct intel_crtc *crtc;
+
+ /*
+ * Add all pipes to the state, and force
+ * a modeset on all the active ones.
+ */
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ struct intel_crtc_state *crtc_state;
+ int ret;
+
+ crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (!crtc_state->hw.active ||
+ drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
+ continue;
+
+ crtc_state->uapi.mode_changed = true;
+
+ ret = drm_atomic_add_affected_connectors(&state->base,
+ &crtc->base);
+ if (ret)
+ return ret;
+
+ ret = intel_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ return ret;
+
+ crtc_state->update_planes |= crtc_state->active_planes;
+ }
+
+ return 0;
+}
+
static void
intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
{
@@ -8782,7 +9216,7 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
* However if queried just before the start of vblank we'll get an
* answer that's slightly in the future.
*/
- if (IS_DISPLAY_VER(dev_priv, 2)) {
+ if (DISPLAY_VER(dev_priv) == 2) {
int vtotal;
vtotal = adjusted_mode.crtc_vtotal;
@@ -9184,7 +9618,6 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *new_crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *slave_crtc_state, *master_crtc_state;
struct intel_crtc *slave, *master;
@@ -9200,15 +9633,15 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
if (!new_crtc_state->bigjoiner)
return 0;
- if (1 + crtc->pipe >= INTEL_NUM_PIPES(dev_priv)) {
+ slave = intel_dsc_get_bigjoiner_secondary(crtc);
+ if (!slave) {
DRM_DEBUG_KMS("[CRTC:%d:%s] Big joiner configuration requires "
"CRTC + 1 to be used, doesn't exist\n",
crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
- slave = new_crtc_state->bigjoiner_linked_crtc =
- intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1);
+ new_crtc_state->bigjoiner_linked_crtc = slave;
slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave);
master = crtc;
if (IS_ERR(slave_crtc_state))
@@ -9582,6 +10015,9 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
+ if (intel_any_crtc_needs_modeset(state))
+ any_ms = true;
+
if (any_ms) {
ret = intel_modeset_checks(state);
if (ret)
@@ -9659,7 +10095,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- if (!IS_DISPLAY_VER(dev_priv, 2) || crtc_state->active_planes)
+ if (DISPLAY_VER(dev_priv) != 2 || crtc_state->active_planes)
intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
if (crtc_state->has_pch_encoder) {
@@ -9688,8 +10124,6 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
/* on skylake this is done by detaching scalers */
if (DISPLAY_VER(dev_priv) >= 9) {
- skl_detach_scalers(new_crtc_state);
-
if (new_crtc_state->pch_pfit.enabled)
skl_pfit_enable(new_crtc_state);
} else if (HAS_PCH_SPLIT(dev_priv)) {
@@ -9715,8 +10149,8 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
icl_set_pipe_chicken(crtc);
}
-static void commit_pipe_config(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
+static void commit_pipe_pre_planes(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state =
@@ -9734,9 +10168,6 @@ static void commit_pipe_config(struct intel_atomic_state *state,
new_crtc_state->update_pipe)
intel_color_commit(new_crtc_state);
- if (DISPLAY_VER(dev_priv) >= 9)
- skl_detach_scalers(new_crtc_state);
-
if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
@@ -9750,6 +10181,23 @@ static void commit_pipe_config(struct intel_atomic_state *state,
dev_priv->display.atomic_update_watermarks(state, crtc);
}
+static void commit_pipe_post_planes(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+
+ /*
+ * Disable the scaler(s) after the plane(s) so that we don't
+ * get a catastrophic underrun even if the two operations
+ * end up happening in two different frames.
+ */
+ if (DISPLAY_VER(dev_priv) >= 9 &&
+ !intel_crtc_needs_modeset(new_crtc_state))
+ skl_detach_scalers(new_crtc_state);
+}
+
static void intel_enable_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -9801,13 +10249,15 @@ static void intel_update_crtc(struct intel_atomic_state *state,
/* Perform vblank evasion around commit operation */
intel_pipe_update_start(new_crtc_state);
- commit_pipe_config(state, crtc);
+ commit_pipe_pre_planes(state, crtc);
if (DISPLAY_VER(dev_priv) >= 9)
skl_update_planes_on_crtc(state, crtc);
else
i9xx_update_planes_on_crtc(state, crtc);
+ commit_pipe_post_planes(state, crtc);
+
intel_pipe_update_end(new_crtc_state);
/*
@@ -10277,7 +10727,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* chance of catching underruns with the intermediate watermarks
* vs. the new plane configuration.
*/
- if (IS_DISPLAY_VER(dev_priv, 2) && planes_enabling(old_crtc_state, new_crtc_state))
+ if (DISPLAY_VER(dev_priv) == 2 && planes_enabling(old_crtc_state, new_crtc_state))
intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
if (dev_priv->display.optimize_watermarks)
@@ -10541,25 +10991,60 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
plane->id == PLANE_CURSOR &&
INTEL_INFO(dev_priv)->display.cursor_needs_physical;
- vma = intel_pin_and_fence_fb_obj(fb, phys_cursor,
- &plane_state->view.gtt,
- intel_plane_uses_fence(plane_state),
- &plane_state->flags);
- if (IS_ERR(vma))
- return PTR_ERR(vma);
+ if (!intel_fb_uses_dpt(fb)) {
+ vma = intel_pin_and_fence_fb_obj(fb, phys_cursor,
+ &plane_state->view.gtt,
+ intel_plane_uses_fence(plane_state),
+ &plane_state->flags);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+
+ plane_state->ggtt_vma = vma;
+ } else {
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+ vma = intel_dpt_pin(intel_fb->dpt_vm);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
- plane_state->vma = vma;
+ plane_state->ggtt_vma = vma;
+
+ vma = intel_pin_fb_obj_dpt(fb, &plane_state->view.gtt, false,
+ &plane_state->flags, intel_fb->dpt_vm);
+ if (IS_ERR(vma)) {
+ intel_dpt_unpin(intel_fb->dpt_vm);
+ plane_state->ggtt_vma = NULL;
+ return PTR_ERR(vma);
+ }
+
+ plane_state->dpt_vma = vma;
+
+ WARN_ON(plane_state->ggtt_vma == plane_state->dpt_vma);
+ }
return 0;
}
void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
{
+ struct drm_framebuffer *fb = old_plane_state->hw.fb;
struct i915_vma *vma;
- vma = fetch_and_zero(&old_plane_state->vma);
- if (vma)
- intel_unpin_fb_vma(vma, old_plane_state->flags);
+ if (!intel_fb_uses_dpt(fb)) {
+ vma = fetch_and_zero(&old_plane_state->ggtt_vma);
+ if (vma)
+ intel_unpin_fb_vma(vma, old_plane_state->flags);
+ } else {
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+ vma = fetch_and_zero(&old_plane_state->dpt_vma);
+ if (vma)
+ intel_unpin_fb_vma(vma, old_plane_state->flags);
+
+ vma = fetch_and_zero(&old_plane_state->ggtt_vma);
+ if (vma)
+ intel_dpt_unpin(intel_fb->dpt_vm);
+ }
}
/**
@@ -10650,7 +11135,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
if (ret < 0)
goto unpin_fb;
- fence = dma_resv_get_excl_rcu(obj->base.resv);
+ fence = dma_resv_get_excl_unlocked(obj->base.resv);
if (fence) {
add_rps_boost_after_vblank(new_plane_state->hw.crtc,
fence);
@@ -10829,7 +11314,14 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
- if (IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ intel_ddi_init(dev_priv, PORT_A);
+ intel_ddi_init(dev_priv, PORT_B);
+ intel_ddi_init(dev_priv, PORT_TC1);
+ intel_ddi_init(dev_priv, PORT_TC2);
+ intel_ddi_init(dev_priv, PORT_TC3);
+ intel_ddi_init(dev_priv, PORT_TC4);
+ } else if (IS_ALDERLAKE_S(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_TC1);
intel_ddi_init(dev_priv, PORT_TC2);
@@ -10856,61 +11348,38 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_ddi_init(dev_priv, PORT_C);
intel_ddi_init(dev_priv, PORT_D);
icl_dsi_init(dev_priv);
- } else if (IS_DISPLAY_VER(dev_priv, 11)) {
+ } else if (DISPLAY_VER(dev_priv) == 11) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
intel_ddi_init(dev_priv, PORT_D);
intel_ddi_init(dev_priv, PORT_E);
- /*
- * On some ICL SKUs port F is not present. No strap bits for
- * this, so rely on VBT.
- * Work around broken VBTs on SKUs known to have no port F.
- */
- if (IS_ICL_WITH_PORT_F(dev_priv) &&
- intel_bios_is_port_present(dev_priv, PORT_F))
- intel_ddi_init(dev_priv, PORT_F);
-
+ intel_ddi_init(dev_priv, PORT_F);
icl_dsi_init(dev_priv);
- } else if (IS_GEN9_LP(dev_priv)) {
- /*
- * FIXME: Broxton doesn't support port detection via the
- * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
- * detect the ports.
- */
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
-
vlv_dsi_init(dev_priv);
+ } else if (DISPLAY_VER(dev_priv) >= 9) {
+ intel_ddi_init(dev_priv, PORT_A);
+ intel_ddi_init(dev_priv, PORT_B);
+ intel_ddi_init(dev_priv, PORT_C);
+ intel_ddi_init(dev_priv, PORT_D);
+ intel_ddi_init(dev_priv, PORT_E);
+ intel_ddi_init(dev_priv, PORT_F);
} else if (HAS_DDI(dev_priv)) {
- int found;
+ u32 found;
if (intel_ddi_crt_present(dev_priv))
intel_crt_init(dev_priv);
- /*
- * Haswell uses DDI functions to detect digital outputs.
- * On SKL pre-D0 the strap isn't connected. Later SKUs may or
- * may not have it - it was supposed to be fixed by the same
- * time we stopped using straps. Assume it's there.
- */
+ /* Haswell uses DDI functions to detect digital outputs. */
found = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
- /* WaIgnoreDDIAStrap: skl */
- if (found || IS_GEN9_BC(dev_priv))
+ if (found)
intel_ddi_init(dev_priv, PORT_A);
- /* DDI B, C, D, and F detection is indicated by the SFUSE_STRAP
- * register */
- if (HAS_PCH_TGP(dev_priv)) {
- /* W/A due to lack of STRAP config on TGP PCH*/
- found = (SFUSE_STRAP_DDIB_DETECTED |
- SFUSE_STRAP_DDIC_DETECTED |
- SFUSE_STRAP_DDID_DETECTED);
- } else {
- found = intel_de_read(dev_priv, SFUSE_STRAP);
- }
-
+ found = intel_de_read(dev_priv, SFUSE_STRAP);
if (found & SFUSE_STRAP_DDIB_DETECTED)
intel_ddi_init(dev_priv, PORT_B);
if (found & SFUSE_STRAP_DDIC_DETECTED)
@@ -10919,13 +11388,6 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_ddi_init(dev_priv, PORT_D);
if (found & SFUSE_STRAP_DDIF_DETECTED)
intel_ddi_init(dev_priv, PORT_F);
- /*
- * On SKL we don't have a way to detect DDI-E so we rely on VBT.
- */
- if (IS_GEN9_BC(dev_priv) &&
- intel_bios_is_port_present(dev_priv, PORT_E))
- intel_ddi_init(dev_priv, PORT_E);
-
} else if (HAS_PCH_SPLIT(dev_priv)) {
int found;
@@ -11013,7 +11475,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
} else if (IS_PINEVIEW(dev_priv)) {
intel_lvds_init(dev_priv);
intel_crt_init(dev_priv);
- } else if (IS_DISPLAY_RANGE(dev_priv, 3, 4)) {
+ } else if (IS_DISPLAY_VER(dev_priv, 3, 4)) {
bool found = false;
if (IS_MOBILE(dev_priv))
@@ -11057,7 +11519,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
if (SUPPORTS_TV(dev_priv))
intel_tv_init(dev_priv);
- } else if (IS_DISPLAY_VER(dev_priv, 2)) {
+ } else if (DISPLAY_VER(dev_priv) == 2) {
if (IS_I85X(dev_priv))
intel_lvds_init(dev_priv);
@@ -11082,6 +11544,10 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
drm_framebuffer_cleanup(fb);
+
+ if (intel_fb_uses_dpt(fb))
+ intel_dpt_destroy(intel_fb->dpt_vm);
+
intel_frontbuffer_put(intel_fb->frontbuffer);
kfree(intel_fb);
@@ -11245,13 +11711,36 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
}
}
+ /* TODO: Add POT stride remapping support for CCS formats as well. */
+ if (IS_ALDERLAKE_P(dev_priv) &&
+ mode_cmd->modifier[i] != DRM_FORMAT_MOD_LINEAR &&
+ !intel_fb_needs_pot_stride_remap(intel_fb) &&
+ !is_power_of_2(mode_cmd->pitches[i])) {
+ drm_dbg_kms(&dev_priv->drm,
+ "plane %d pitch (%d) must be power of two for tiled buffers\n",
+ i, mode_cmd->pitches[i]);
+ goto err;
+ }
+
fb->obj[i] = &obj->base;
}
- ret = intel_fill_fb_info(dev_priv, fb);
+ ret = intel_fill_fb_info(dev_priv, intel_fb);
if (ret)
goto err;
+ if (intel_fb_uses_dpt(fb)) {
+ struct i915_address_space *vm;
+
+ vm = intel_dpt_create(intel_fb);
+ if (IS_ERR(vm)) {
+ ret = PTR_ERR(vm);
+ goto err;
+ }
+
+ intel_fb->dpt_vm = vm;
+ }
+
ret = drm_framebuffer_init(&dev_priv->drm, fb, &intel_fb_funcs);
if (ret) {
drm_err(&dev_priv->drm, "framebuffer init failed %d\n", ret);
@@ -11273,11 +11762,20 @@ intel_user_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
+ struct drm_i915_private *i915;
obj = i915_gem_object_lookup(filp, mode_cmd.handles[0]);
if (!obj)
return ERR_PTR(-ENOENT);
+ /* object is backed with LMEM for discrete */
+ i915 = to_i915(obj->base.dev);
+ if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) {
+ /* object is "remote", not in local memory */
+ i915_gem_object_put(obj);
+ return ERR_PTR(-EREMOTE);
+ }
+
fb = intel_framebuffer_create(obj, &mode_cmd);
i915_gem_object_put(obj);
@@ -11429,6 +11927,9 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
*/
void intel_init_display_hooks(struct drm_i915_private *dev_priv)
{
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
intel_init_cdclk_hooks(dev_priv);
intel_init_audio_hooks(dev_priv);
@@ -11471,8 +11972,12 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
void intel_modeset_init_hw(struct drm_i915_private *i915)
{
- struct intel_cdclk_state *cdclk_state =
- to_intel_cdclk_state(i915->cdclk.obj.state);
+ struct intel_cdclk_state *cdclk_state;
+
+ if (!HAS_DISPLAY(i915))
+ return;
+
+ cdclk_state = to_intel_cdclk_state(i915->cdclk.obj.state);
intel_update_cdclk(i915);
intel_dump_cdclk_config(&i915->cdclk.hw, "Current CDCLK");
@@ -11705,8 +12210,6 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
mode_config->preferred_depth = 24;
mode_config->prefer_shadow = 1;
- mode_config->allow_fb_modifiers = true;
-
mode_config->funcs = &intel_mode_funcs;
mode_config->async_page_flip = has_async_flips(i915);
@@ -11721,7 +12224,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
} else if (DISPLAY_VER(i915) >= 4) {
mode_config->max_width = 8192;
mode_config->max_height = 8192;
- } else if (IS_DISPLAY_VER(i915, 3)) {
+ } else if (DISPLAY_VER(i915) == 3) {
mode_config->max_width = 4096;
mode_config->max_height = 4096;
} else {
@@ -11788,7 +12291,10 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
/* FIXME: completely on the wrong abstraction layer */
intel_power_domains_init_hw(i915, false);
- intel_csr_ucode_init(i915);
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
+ intel_dmc_ucode_init(i915);
i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI |
@@ -11796,19 +12302,21 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
i915->framestart_delay = 1; /* 1-4 */
+ i915->window2_delay = 0; /* No DSB so no window2 delay */
+
intel_mode_config_init(i915);
ret = intel_cdclk_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_csr;
+ goto cleanup_vga_client_pw_domain_dmc;
ret = intel_dbuf_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_csr;
+ goto cleanup_vga_client_pw_domain_dmc;
ret = intel_bw_init(i915);
if (ret)
- goto cleanup_vga_client_pw_domain_csr;
+ goto cleanup_vga_client_pw_domain_dmc;
init_llist_head(&i915->atomic_helper.free_list);
INIT_WORK(&i915->atomic_helper.free_work,
@@ -11820,8 +12328,8 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
return 0;
-cleanup_vga_client_pw_domain_csr:
- intel_csr_ucode_fini(i915);
+cleanup_vga_client_pw_domain_dmc:
+ intel_dmc_ucode_fini(i915);
intel_power_domains_driver_remove(i915);
intel_vga_unregister(i915);
cleanup_bios:
@@ -11838,6 +12346,9 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
struct intel_crtc *crtc;
int ret;
+ if (!HAS_DISPLAY(i915))
+ return 0;
+
intel_init_pm(i915);
intel_panel_sanitize_ssc(i915);
@@ -11850,13 +12361,11 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
INTEL_NUM_PIPES(i915),
INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
- if (HAS_DISPLAY(i915)) {
- for_each_pipe(i915, pipe) {
- ret = intel_crtc_init(i915, pipe);
- if (ret) {
- intel_mode_config_cleanup(i915);
- return ret;
- }
+ for_each_pipe(i915, pipe) {
+ ret = intel_crtc_init(i915, pipe);
+ if (ret) {
+ intel_mode_config_cleanup(i915);
+ return ret;
}
}
@@ -12610,7 +13119,7 @@ static void intel_early_display_was(struct drm_i915_private *dev_priv)
* Display WA #1185 WaDisableDARBFClkGating:cnl,glk,icl,ehl,tgl
* Also known as Wa_14010480278.
*/
- if (IS_DISPLAY_RANGE(dev_priv, 10, 12))
+ if (IS_DISPLAY_VER(dev_priv, 10, 12))
intel_de_write(dev_priv, GEN9_CLKGATE_DIS_0,
intel_de_read(dev_priv, GEN9_CLKGATE_DIS_0) | DARBF_GATING_DIS);
@@ -12791,6 +13300,9 @@ void intel_display_resume(struct drm_device *dev)
struct drm_modeset_acquire_ctx ctx;
int ret;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
dev_priv->modeset_restore_state = NULL;
if (state)
state->acquire_ctx = &ctx;
@@ -12840,6 +13352,9 @@ static void intel_hpd_poll_fini(struct drm_i915_private *i915)
/* part #1: call before irq uninstall */
void intel_modeset_driver_remove(struct drm_i915_private *i915)
{
+ if (!HAS_DISPLAY(i915))
+ return;
+
flush_workqueue(i915->flip_wq);
flush_workqueue(i915->modeset_wq);
@@ -12850,6 +13365,9 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915)
/* part #2: call after irq uninstall */
void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
{
+ if (!HAS_DISPLAY(i915))
+ return;
+
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
* poll handlers. Hence disable polling after hpd handling is shut down.
@@ -12890,7 +13408,7 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
/* part #3: call after gem init */
void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915)
{
- intel_csr_ucode_fini(i915);
+ intel_dmc_ucode_fini(i915);
intel_power_domains_driver_remove(i915);
@@ -12949,207 +13467,3 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)
acpi_video_unregister();
intel_opregion_unregister(i915);
}
-
-#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
-
-struct intel_display_error_state {
-
- u32 power_well_driver;
-
- struct intel_cursor_error_state {
- u32 control;
- u32 position;
- u32 base;
- u32 size;
- } cursor[I915_MAX_PIPES];
-
- struct intel_pipe_error_state {
- bool power_domain_on;
- u32 source;
- u32 stat;
- } pipe[I915_MAX_PIPES];
-
- struct intel_plane_error_state {
- u32 control;
- u32 stride;
- u32 size;
- u32 pos;
- u32 addr;
- u32 surface;
- u32 tile_offset;
- } plane[I915_MAX_PIPES];
-
- struct intel_transcoder_error_state {
- bool available;
- bool power_domain_on;
- enum transcoder cpu_transcoder;
-
- u32 conf;
-
- u32 htotal;
- u32 hblank;
- u32 hsync;
- u32 vtotal;
- u32 vblank;
- u32 vsync;
- } transcoder[5];
-};
-
-struct intel_display_error_state *
-intel_display_capture_error_state(struct drm_i915_private *dev_priv)
-{
- struct intel_display_error_state *error;
- int transcoders[] = {
- TRANSCODER_A,
- TRANSCODER_B,
- TRANSCODER_C,
- TRANSCODER_D,
- TRANSCODER_EDP,
- };
- int i;
-
- BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder));
-
- if (!HAS_DISPLAY(dev_priv))
- return NULL;
-
- error = kzalloc(sizeof(*error), GFP_ATOMIC);
- if (error == NULL)
- return NULL;
-
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- error->power_well_driver = intel_de_read(dev_priv,
- HSW_PWR_WELL_CTL2);
-
- for_each_pipe(dev_priv, i) {
- error->pipe[i].power_domain_on =
- __intel_display_power_is_enabled(dev_priv,
- POWER_DOMAIN_PIPE(i));
- if (!error->pipe[i].power_domain_on)
- continue;
-
- error->cursor[i].control = intel_de_read(dev_priv, CURCNTR(i));
- error->cursor[i].position = intel_de_read(dev_priv, CURPOS(i));
- error->cursor[i].base = intel_de_read(dev_priv, CURBASE(i));
-
- error->plane[i].control = intel_de_read(dev_priv, DSPCNTR(i));
- error->plane[i].stride = intel_de_read(dev_priv, DSPSTRIDE(i));
- if (DISPLAY_VER(dev_priv) <= 3) {
- error->plane[i].size = intel_de_read(dev_priv,
- DSPSIZE(i));
- error->plane[i].pos = intel_de_read(dev_priv,
- DSPPOS(i));
- }
- if (DISPLAY_VER(dev_priv) <= 7 && !IS_HASWELL(dev_priv))
- error->plane[i].addr = intel_de_read(dev_priv,
- DSPADDR(i));
- if (DISPLAY_VER(dev_priv) >= 4) {
- error->plane[i].surface = intel_de_read(dev_priv,
- DSPSURF(i));
- error->plane[i].tile_offset = intel_de_read(dev_priv,
- DSPTILEOFF(i));
- }
-
- error->pipe[i].source = intel_de_read(dev_priv, PIPESRC(i));
-
- if (HAS_GMCH(dev_priv))
- error->pipe[i].stat = intel_de_read(dev_priv,
- PIPESTAT(i));
- }
-
- for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
- enum transcoder cpu_transcoder = transcoders[i];
-
- if (!HAS_TRANSCODER(dev_priv, cpu_transcoder))
- continue;
-
- error->transcoder[i].available = true;
- error->transcoder[i].power_domain_on =
- __intel_display_power_is_enabled(dev_priv,
- POWER_DOMAIN_TRANSCODER(cpu_transcoder));
- if (!error->transcoder[i].power_domain_on)
- continue;
-
- error->transcoder[i].cpu_transcoder = cpu_transcoder;
-
- error->transcoder[i].conf = intel_de_read(dev_priv,
- PIPECONF(cpu_transcoder));
- error->transcoder[i].htotal = intel_de_read(dev_priv,
- HTOTAL(cpu_transcoder));
- error->transcoder[i].hblank = intel_de_read(dev_priv,
- HBLANK(cpu_transcoder));
- error->transcoder[i].hsync = intel_de_read(dev_priv,
- HSYNC(cpu_transcoder));
- error->transcoder[i].vtotal = intel_de_read(dev_priv,
- VTOTAL(cpu_transcoder));
- error->transcoder[i].vblank = intel_de_read(dev_priv,
- VBLANK(cpu_transcoder));
- error->transcoder[i].vsync = intel_de_read(dev_priv,
- VSYNC(cpu_transcoder));
- }
-
- return error;
-}
-
-#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
-
-void
-intel_display_print_error_state(struct drm_i915_error_state_buf *m,
- struct intel_display_error_state *error)
-{
- struct drm_i915_private *dev_priv = m->i915;
- int i;
-
- if (!error)
- return;
-
- err_printf(m, "Num Pipes: %d\n", INTEL_NUM_PIPES(dev_priv));
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- err_printf(m, "PWR_WELL_CTL2: %08x\n",
- error->power_well_driver);
- for_each_pipe(dev_priv, i) {
- err_printf(m, "Pipe [%d]:\n", i);
- err_printf(m, " Power: %s\n",
- onoff(error->pipe[i].power_domain_on));
- err_printf(m, " SRC: %08x\n", error->pipe[i].source);
- err_printf(m, " STAT: %08x\n", error->pipe[i].stat);
-
- err_printf(m, "Plane [%d]:\n", i);
- err_printf(m, " CNTR: %08x\n", error->plane[i].control);
- err_printf(m, " STRIDE: %08x\n", error->plane[i].stride);
- if (DISPLAY_VER(dev_priv) <= 3) {
- err_printf(m, " SIZE: %08x\n", error->plane[i].size);
- err_printf(m, " POS: %08x\n", error->plane[i].pos);
- }
- if (DISPLAY_VER(dev_priv) <= 7 && !IS_HASWELL(dev_priv))
- err_printf(m, " ADDR: %08x\n", error->plane[i].addr);
- if (DISPLAY_VER(dev_priv) >= 4) {
- err_printf(m, " SURF: %08x\n", error->plane[i].surface);
- err_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset);
- }
-
- err_printf(m, "Cursor [%d]:\n", i);
- err_printf(m, " CNTR: %08x\n", error->cursor[i].control);
- err_printf(m, " POS: %08x\n", error->cursor[i].position);
- err_printf(m, " BASE: %08x\n", error->cursor[i].base);
- }
-
- for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
- if (!error->transcoder[i].available)
- continue;
-
- err_printf(m, "CPU transcoder: %s\n",
- transcoder_name(error->transcoder[i].cpu_transcoder));
- err_printf(m, " Power: %s\n",
- onoff(error->transcoder[i].power_domain_on));
- err_printf(m, " CONF: %08x\n", error->transcoder[i].conf);
- err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal);
- err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank);
- err_printf(m, " HSYNC: %08x\n", error->transcoder[i].hsync);
- err_printf(m, " VTOTAL: %08x\n", error->transcoder[i].vtotal);
- err_printf(m, " VBLANK: %08x\n", error->transcoder[i].vblank);
- err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
- }
-}
-
-#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 105294ec2dcc..c9dbaf074d77 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -37,13 +37,13 @@ struct drm_encoder;
struct drm_file;
struct drm_format_info;
struct drm_framebuffer;
-struct drm_i915_error_state_buf;
struct drm_i915_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct drm_modeset_acquire_ctx;
struct drm_plane;
struct drm_plane_state;
+struct i915_address_space;
struct i915_ggtt_view;
struct intel_atomic_state;
struct intel_crtc;
@@ -188,12 +188,13 @@ enum plane_id {
for ((__p) = PLANE_PRIMARY; (__p) < I915_MAX_PLANES; (__p)++) \
for_each_if((__crtc)->plane_ids_mask & BIT(__p))
-#define for_each_dbuf_slice_in_mask(__slice, __mask) \
+#define for_each_dbuf_slice(__dev_priv, __slice) \
for ((__slice) = DBUF_S1; (__slice) < I915_MAX_DBUF_SLICES; (__slice)++) \
- for_each_if((BIT(__slice)) & (__mask))
+ for_each_if(INTEL_INFO(__dev_priv)->dbuf.slice_mask & BIT(__slice))
-#define for_each_dbuf_slice(__slice) \
- for_each_dbuf_slice_in_mask(__slice, BIT(I915_MAX_DBUF_SLICES) - 1)
+#define for_each_dbuf_slice_in_mask(__dev_priv, __slice, __mask) \
+ for_each_dbuf_slice((__dev_priv), (__slice)) \
+ for_each_if((__mask) & BIT(__slice))
enum port {
PORT_NONE = -1,
@@ -216,6 +217,10 @@ enum port {
PORT_TC5,
PORT_TC6,
+ /* XE_LPD repositions D/E offsets and bitfields */
+ PORT_D_XELPD = PORT_TC5,
+ PORT_E_XELPD,
+
I915_MAX_PORTS
};
@@ -299,6 +304,10 @@ enum aux_ch {
AUX_CH_USBC4,
AUX_CH_USBC5,
AUX_CH_USBC6,
+
+ /* XE_LPD repositions D/E offsets and bitfields */
+ AUX_CH_D_XELPD = AUX_CH_USBC5,
+ AUX_CH_E_XELPD,
};
#define aux_ch_name(a) ((a) + 'A')
@@ -556,9 +565,6 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
enum port port);
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
-void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state);
-void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state);
int ilk_get_lanes_required(int target_clock, int link_bw, int bpp);
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
@@ -597,9 +603,6 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,
void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state,
enum link_m_n_set m_n);
int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
-bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
- struct dpll *best_clock);
-int chv_calc_dpll_params(int refclk, struct dpll *pll_clock);
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state);
void hsw_enable_ips(const struct intel_crtc_state *crtc_state);
@@ -616,11 +619,6 @@ void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
int bdw_get_pipemisc_bpp(struct intel_crtc *crtc);
unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
-struct intel_display_error_state *
-intel_display_capture_error_state(struct drm_i915_private *dev_priv);
-void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
- struct intel_display_error_state *error);
-
bool
intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
u64 modifier);
@@ -648,6 +646,7 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915);
void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915);
void intel_display_resume(struct drm_device *dev);
void intel_init_pch_refclk(struct drm_i915_private *dev_priv);
+int intel_modeset_all_pipes(struct intel_atomic_state *state);
/* modesetting asserts */
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 564509a4e666..88bb05d5c483 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -7,10 +7,11 @@
#include <drm/drm_fourcc.h>
#include "i915_debugfs.h"
-#include "intel_csr.h"
#include "intel_display_debugfs.h"
#include "intel_display_power.h"
+#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dmc.h"
#include "intel_dp.h"
#include "intel_fbc.h"
#include "intel_hdcp.h"
@@ -531,24 +532,24 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
intel_wakeref_t wakeref;
- struct intel_csr *csr;
+ struct intel_dmc *dmc;
i915_reg_t dc5_reg, dc6_reg = {};
- if (!HAS_CSR(dev_priv))
+ if (!HAS_DMC(dev_priv))
return -ENODEV;
- csr = &dev_priv->csr;
+ dmc = &dev_priv->dmc;
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
- seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL));
- seq_printf(m, "path: %s\n", csr->fw_path);
+ seq_printf(m, "fw loaded: %s\n", yesno(intel_dmc_has_payload(dev_priv)));
+ seq_printf(m, "path: %s\n", dmc->fw_path);
- if (!csr->dmc_payload)
+ if (!intel_dmc_has_payload(dev_priv))
goto out;
- seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version),
- CSR_VERSION_MINOR(csr->version));
+ seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
+ DMC_VERSION_MINOR(dmc->version));
if (DISPLAY_VER(dev_priv) >= 12) {
if (IS_DGFX(dev_priv)) {
@@ -567,10 +568,10 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
seq_printf(m, "DC3CO count: %d\n",
intel_de_read(dev_priv, DMC_DEBUG3));
} else {
- dc5_reg = IS_BROXTON(dev_priv) ? BXT_CSR_DC3_DC5_COUNT :
- SKL_CSR_DC3_DC5_COUNT;
- if (!IS_GEN9_LP(dev_priv))
- dc6_reg = SKL_CSR_DC5_DC6_COUNT;
+ dc5_reg = IS_BROXTON(dev_priv) ? BXT_DMC_DC3_DC5_COUNT :
+ SKL_DMC_DC3_DC5_COUNT;
+ if (!IS_GEMINILAKE(dev_priv) && !IS_BROXTON(dev_priv))
+ dc6_reg = SKL_DMC_DC5_DC6_COUNT;
}
seq_printf(m, "DC3 -> DC5 count: %d\n",
@@ -581,10 +582,10 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
out:
seq_printf(m, "program base: 0x%08x\n",
- intel_de_read(dev_priv, CSR_PROGRAM(0)));
+ intel_de_read(dev_priv, DMC_PROGRAM(0)));
seq_printf(m, "ssp base: 0x%08x\n",
- intel_de_read(dev_priv, CSR_SSP_BASE));
- seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, CSR_HTP_SKL));
+ intel_de_read(dev_priv, DMC_SSP_BASE));
+ seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, DMC_HTP_SKL));
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
@@ -1339,6 +1340,12 @@ static int i915_lpsp_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
+ if (DISPLAY_VER(i915) >= 13) {
+ LPSP_STATUS(!intel_lpsp_power_well_enabled(i915,
+ SKL_DISP_PW_2));
+ return 0;
+ }
+
switch (DISPLAY_VER(i915)) {
case 12:
case 11:
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 99126caf5747..4298ae684d7d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -9,9 +9,10 @@
#include "i915_irq.h"
#include "intel_cdclk.h"
#include "intel_combo_phy.h"
-#include "intel_csr.h"
#include "intel_display_power.h"
+#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_dmc.h"
#include "intel_dpio_phy.h"
#include "intel_hotplug.h"
#include "intel_pm.h"
@@ -290,8 +291,7 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv,
#define ICL_TBT_AUX_PW_TO_CH(pw_idx) \
((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
-static enum aux_ch icl_tc_phy_aux_ch(struct drm_i915_private *dev_priv,
- struct i915_power_well *power_well)
+static enum aux_ch icl_aux_pw_to_ch(const struct i915_power_well *power_well)
{
int pw_idx = power_well->desc->hsw.idx;
@@ -326,6 +326,15 @@ aux_ch_to_digital_port(struct drm_i915_private *dev_priv,
return dig_port;
}
+static enum phy icl_aux_pw_to_phy(struct drm_i915_private *i915,
+ const struct i915_power_well *power_well)
+{
+ enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
+ struct intel_digital_port *dig_port = aux_ch_to_digital_port(i915, aux_ch);
+
+ return intel_port_to_phy(i915, dig_port->base.port);
+}
+
static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well,
bool timeout_expected)
@@ -467,15 +476,13 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
hsw_wait_for_power_well_disable(dev_priv, power_well);
}
-#define ICL_AUX_PW_TO_PHY(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_AUX_A)
-
static void
icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
int pw_idx = power_well->desc->hsw.idx;
- enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx);
+ enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
u32 val;
drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));
@@ -507,7 +514,7 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
{
const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
int pw_idx = power_well->desc->hsw.idx;
- enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx);
+ enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
u32 val;
drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));
@@ -550,7 +557,7 @@ static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
if (drm_WARN_ON(&dev_priv->drm, !dig_port))
return;
- if (IS_DISPLAY_VER(dev_priv, 11) && dig_port->tc_legacy_port)
+ if (DISPLAY_VER(dev_priv) == 11 && dig_port->tc_legacy_port)
return;
drm_WARN_ON(&dev_priv->drm, !intel_tc_port_ref_held(dig_port));
@@ -594,7 +601,7 @@ static void
icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+ enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
bool is_tbt = power_well->desc->hsw.is_tc_tbt;
@@ -618,11 +625,9 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
* or need to enable AUX on a legacy TypeC port as part of the TC-cold
* exit sequence.
*/
- timeout_expected = is_tbt;
- if (IS_DISPLAY_VER(dev_priv, 11) && dig_port->tc_legacy_port) {
+ timeout_expected = is_tbt || intel_tc_cold_requires_aux_pw(dig_port);
+ if (DISPLAY_VER(dev_priv) == 11 && dig_port->tc_legacy_port)
icl_tc_cold_exit(dev_priv);
- timeout_expected = true;
- }
hsw_wait_for_power_well_enable(dev_priv, power_well, timeout_expected);
@@ -644,7 +649,7 @@ static void
icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+ enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port);
@@ -656,11 +661,9 @@ static void
icl_aux_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- int pw_idx = power_well->desc->hsw.idx;
- enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx); /* non-TBT only */
- bool is_tbt = power_well->desc->hsw.is_tc_tbt;
+ enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
- if (is_tbt || intel_phy_is_tc(dev_priv, phy))
+ if (intel_phy_is_tc(dev_priv, phy))
return icl_tc_phy_aux_power_well_enable(dev_priv, power_well);
else if (IS_ICELAKE(dev_priv))
return icl_combo_phy_aux_power_well_enable(dev_priv,
@@ -673,11 +676,9 @@ static void
icl_aux_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- int pw_idx = power_well->desc->hsw.idx;
- enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx); /* non-TBT only */
- bool is_tbt = power_well->desc->hsw.is_tc_tbt;
+ enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
- if (is_tbt || intel_phy_is_tc(dev_priv, phy))
+ if (intel_phy_is_tc(dev_priv, phy))
return icl_tc_phy_aux_power_well_disable(dev_priv, power_well);
else if (IS_ICELAKE(dev_priv))
return icl_combo_phy_aux_power_well_disable(dev_priv,
@@ -709,7 +710,7 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
* BIOS's own request bits, which are forced-on for these power wells
* when exiting DC5/6.
*/
- if (IS_DISPLAY_VER(dev_priv, 9) && !IS_GEN9_LP(dev_priv) &&
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) &&
(id == SKL_DISP_PW_1 || id == SKL_DISP_PW_MISC_IO))
val |= intel_de_read(dev_priv, regs->bios);
@@ -807,9 +808,9 @@ static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
if (DISPLAY_VER(dev_priv) >= 12)
mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6
| DC_STATE_EN_DC9;
- else if (IS_DISPLAY_VER(dev_priv, 11))
+ else if (DISPLAY_VER(dev_priv) == 11)
mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9;
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
mask |= DC_STATE_EN_DC9;
else
mask |= DC_STATE_EN_UPTO_DC6;
@@ -821,12 +822,15 @@ static void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv)
{
u32 val;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
val = intel_de_read(dev_priv, DC_STATE_EN) & gen9_dc_mask(dev_priv);
drm_dbg_kms(&dev_priv->drm,
"Resetting DC state tracking from %02x to %02x\n",
- dev_priv->csr.dc_state, val);
- dev_priv->csr.dc_state = val;
+ dev_priv->dmc.dc_state, val);
+ dev_priv->dmc.dc_state = val;
}
/**
@@ -857,9 +861,12 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state)
u32 val;
u32 mask;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
if (drm_WARN_ON_ONCE(&dev_priv->drm,
- state & ~dev_priv->csr.allowed_dc_mask))
- state &= dev_priv->csr.allowed_dc_mask;
+ state & ~dev_priv->dmc.allowed_dc_mask))
+ state &= dev_priv->dmc.allowed_dc_mask;
val = intel_de_read(dev_priv, DC_STATE_EN);
mask = gen9_dc_mask(dev_priv);
@@ -867,16 +874,16 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state)
val & mask, state);
/* Check if DMC is ignoring our DC state requests */
- if ((val & mask) != dev_priv->csr.dc_state)
+ if ((val & mask) != dev_priv->dmc.dc_state)
drm_err(&dev_priv->drm, "DC state mismatch (0x%x -> 0x%x)\n",
- dev_priv->csr.dc_state, val & mask);
+ dev_priv->dmc.dc_state, val & mask);
val &= ~mask;
val |= state;
gen9_write_dc_state(dev_priv, val);
- dev_priv->csr.dc_state = val & mask;
+ dev_priv->dmc.dc_state = val & mask;
}
static u32
@@ -895,7 +902,7 @@ sanitize_target_dc_state(struct drm_i915_private *dev_priv,
if (target_dc_state != states[i])
continue;
- if (dev_priv->csr.allowed_dc_mask & target_dc_state)
+ if (dev_priv->dmc.allowed_dc_mask & target_dc_state)
break;
target_dc_state = states[i + 1];
@@ -951,15 +958,15 @@ static void bxt_disable_dc9(struct drm_i915_private *dev_priv)
intel_pps_unlock_regs_wa(dev_priv);
}
-static void assert_csr_loaded(struct drm_i915_private *dev_priv)
+static void assert_dmc_loaded(struct drm_i915_private *dev_priv)
{
drm_WARN_ONCE(&dev_priv->drm,
- !intel_de_read(dev_priv, CSR_PROGRAM(0)),
- "CSR program storage start is NULL\n");
- drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, CSR_SSP_BASE),
- "CSR SSP Base Not fine\n");
- drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, CSR_HTP_SKL),
- "CSR HTP Not fine\n");
+ !intel_de_read(dev_priv, DMC_PROGRAM(0)),
+ "DMC program storage start is NULL\n");
+ drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_SSP_BASE),
+ "DMC SSP Base Not fine\n");
+ drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_HTP_SKL),
+ "DMC HTP Not fine\n");
}
static struct i915_power_well *
@@ -1009,7 +1016,7 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
state = sanitize_target_dc_state(dev_priv, state);
- if (state == dev_priv->csr.target_dc_state)
+ if (state == dev_priv->dmc.target_dc_state)
goto unlock;
dc_off_enabled = power_well->desc->ops->is_enabled(dev_priv,
@@ -1021,7 +1028,7 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
if (!dc_off_enabled)
power_well->desc->ops->enable(dev_priv, power_well);
- dev_priv->csr.target_dc_state = state;
+ dev_priv->dmc.target_dc_state = state;
if (!dc_off_enabled)
power_well->desc->ops->disable(dev_priv, power_well);
@@ -1035,7 +1042,7 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
enum i915_power_well_id high_pg;
/* Power wells at this level and above must be disabled for DC5 entry */
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (DISPLAY_VER(dev_priv) == 12)
high_pg = ICL_DISP_PW_3;
else
high_pg = SKL_DISP_PW_2;
@@ -1050,7 +1057,7 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
"DC5 already programmed to be enabled.\n");
assert_rpm_wakelock_held(&dev_priv->runtime_pm);
- assert_csr_loaded(dev_priv);
+ assert_dmc_loaded(dev_priv);
}
static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
@@ -1060,7 +1067,7 @@ static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
drm_dbg_kms(&dev_priv->drm, "Enabling DC5\n");
/* Wa Display #1183: skl,kbl,cfl */
- if (IS_GEN9_BC(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
intel_de_write(dev_priv, GEN8_CHICKEN_DCPR_1,
intel_de_read(dev_priv, GEN8_CHICKEN_DCPR_1) | SKL_SELECT_ALTERNATE_DC_EXIT);
@@ -1077,7 +1084,7 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
DC_STATE_EN_UPTO_DC6),
"DC6 already programmed to be enabled.\n");
- assert_csr_loaded(dev_priv);
+ assert_dmc_loaded(dev_priv);
}
static void skl_enable_dc6(struct drm_i915_private *dev_priv)
@@ -1087,7 +1094,7 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv)
drm_dbg_kms(&dev_priv->drm, "Enabling DC6\n");
/* Wa Display #1183: skl,kbl,cfl */
- if (IS_GEN9_BC(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
intel_de_write(dev_priv, GEN8_CHICKEN_DCPR_1,
intel_de_read(dev_priv, GEN8_CHICKEN_DCPR_1) | SKL_SELECT_ALTERNATE_DC_EXIT);
@@ -1174,13 +1181,16 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
{
struct intel_cdclk_config cdclk_config = {};
- if (dev_priv->csr.target_dc_state == DC_STATE_EN_DC3CO) {
+ if (dev_priv->dmc.target_dc_state == DC_STATE_EN_DC3CO) {
tgl_disable_dc3co(dev_priv);
return;
}
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
dev_priv->display.get_cdclk(dev_priv, &cdclk_config);
/* Can't read out voltage_level so can't use intel_cdclk_changed() */
drm_WARN_ON(&dev_priv->drm,
@@ -1189,7 +1199,7 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
gen9_assert_dbuf_enabled(dev_priv);
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_verify_ddi_phy_power_wells(dev_priv);
if (DISPLAY_VER(dev_priv) >= 11)
@@ -1210,10 +1220,10 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
- if (!dev_priv->csr.dmc_payload)
+ if (!intel_dmc_has_payload(dev_priv))
return;
- switch (dev_priv->csr.target_dc_state) {
+ switch (dev_priv->dmc.target_dc_state) {
case DC_STATE_EN_DC3CO:
tgl_enable_dc3co(dev_priv);
break;
@@ -2255,6 +2265,12 @@ intel_display_power_put_async_work(struct work_struct *work)
fetch_and_zero(&power_domains->async_put_domains[1]);
queue_async_put_domains_work(power_domains,
fetch_and_zero(&new_work_wakeref));
+ } else {
+ /*
+ * Cancel the work that got queued after this one got dequeued,
+ * since here we released the corresponding async-put reference.
+ */
+ cancel_delayed_work(&power_domains->async_put_work);
}
out_verify:
@@ -3012,6 +3028,116 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
BIT_ULL(POWER_DOMAIN_AUX_B) | \
BIT_ULL(POWER_DOMAIN_INIT))
+/*
+ * XE_LPD Power Domains
+ *
+ * Previous platforms required that PG(n-1) be enabled before PG(n). That
+ * dependency chain turns into a dependency tree on XE_LPD:
+ *
+ * PG0
+ * |
+ * --PG1--
+ * / \
+ * PGA --PG2--
+ * / | \
+ * PGB PGC PGD
+ *
+ * Power wells must be enabled from top to bottom and disabled from bottom
+ * to top. This allows pipes to be power gated independently.
+ */
+
+#define XELPD_PW_D_POWER_DOMAINS ( \
+ BIT_ULL(POWER_DOMAIN_PIPE_D) | \
+ BIT_ULL(POWER_DOMAIN_PIPE_D_PANEL_FITTER) | \
+ BIT_ULL(POWER_DOMAIN_TRANSCODER_D) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define XELPD_PW_C_POWER_DOMAINS ( \
+ BIT_ULL(POWER_DOMAIN_PIPE_C) | \
+ BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \
+ BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define XELPD_PW_B_POWER_DOMAINS ( \
+ BIT_ULL(POWER_DOMAIN_PIPE_B) | \
+ BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
+ BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define XELPD_PW_A_POWER_DOMAINS ( \
+ BIT_ULL(POWER_DOMAIN_PIPE_A) | \
+ BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define XELPD_PW_2_POWER_DOMAINS ( \
+ XELPD_PW_B_POWER_DOMAINS | \
+ XELPD_PW_C_POWER_DOMAINS | \
+ XELPD_PW_D_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_AUDIO) | \
+ BIT_ULL(POWER_DOMAIN_VGA) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_D_XELPD) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_E_XELPD) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC1) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC2) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC3) | \
+ BIT_ULL(POWER_DOMAIN_PORT_DDI_LANES_TC4) | \
+ BIT_ULL(POWER_DOMAIN_AUX_C) | \
+ BIT_ULL(POWER_DOMAIN_AUX_D_XELPD) | \
+ BIT_ULL(POWER_DOMAIN_AUX_E_XELPD) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC1) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC2) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC3) | \
+ BIT_ULL(POWER_DOMAIN_AUX_USBC4) | \
+ BIT_ULL(POWER_DOMAIN_AUX_TBT1) | \
+ BIT_ULL(POWER_DOMAIN_AUX_TBT2) | \
+ BIT_ULL(POWER_DOMAIN_AUX_TBT3) | \
+ BIT_ULL(POWER_DOMAIN_AUX_TBT4) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+/*
+ * XELPD PW_1/PG_1 domains (under HW/DMC control):
+ * - DBUF function (registers are in PW0)
+ * - Transcoder A
+ * - DDI_A and DDI_B
+ *
+ * XELPD PW_0/PW_1 domains (under HW/DMC control):
+ * - PCI
+ * - Clocks except port PLL
+ * - Shared functions:
+ * * interrupts except pipe interrupts
+ * * MBus except PIPE_MBUS_DBOX_CTL
+ * * DBUF registers
+ * - Central power except FBC
+ * - Top-level GTC (DDI-level GTC is in the well associated with the DDI)
+ */
+
+#define XELPD_DISPLAY_DC_OFF_POWER_DOMAINS ( \
+ XELPD_PW_2_POWER_DOMAINS | \
+ BIT_ULL(POWER_DOMAIN_MODESET) | \
+ BIT_ULL(POWER_DOMAIN_AUX_A) | \
+ BIT_ULL(POWER_DOMAIN_AUX_B) | \
+ BIT_ULL(POWER_DOMAIN_INIT))
+
+#define XELPD_AUX_IO_D_XELPD_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_D_XELPD)
+#define XELPD_AUX_IO_E_XELPD_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_E_XELPD)
+#define XELPD_AUX_IO_USBC1_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_USBC1)
+#define XELPD_AUX_IO_USBC2_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_USBC2)
+#define XELPD_AUX_IO_USBC3_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_USBC3)
+#define XELPD_AUX_IO_USBC4_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_USBC4)
+
+#define XELPD_AUX_IO_TBT1_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_TBT1)
+#define XELPD_AUX_IO_TBT2_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_TBT2)
+#define XELPD_AUX_IO_TBT3_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_TBT3)
+#define XELPD_AUX_IO_TBT4_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_AUX_TBT4)
+
+#define XELPD_DDI_IO_D_XELPD_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_D_XELPD)
+#define XELPD_DDI_IO_E_XELPD_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_E_XELPD)
+#define XELPD_DDI_IO_TC1_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_TC1)
+#define XELPD_DDI_IO_TC2_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_TC2)
+#define XELPD_DDI_IO_TC3_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_TC3)
+#define XELPD_DDI_IO_TC4_POWER_DOMAINS BIT_ULL(POWER_DOMAIN_PORT_DDI_IO_TC4)
+
static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.sync_hw = i9xx_power_well_sync_hw_noop,
.enable = i9xx_always_on_power_well_noop,
@@ -4516,6 +4642,319 @@ static const struct i915_power_well_desc rkl_power_wells[] = {
},
};
+static const struct i915_power_well_desc xelpd_power_wells[] = {
+ {
+ .name = "always-on",
+ .always_on = true,
+ .domains = POWER_DOMAIN_MASK,
+ .ops = &i9xx_always_on_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ },
+ {
+ .name = "power well 1",
+ /* Handled by the DMC firmware */
+ .always_on = true,
+ .domains = 0,
+ .ops = &hsw_power_well_ops,
+ .id = SKL_DISP_PW_1,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_1,
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "DC off",
+ .domains = XELPD_DISPLAY_DC_OFF_POWER_DOMAINS,
+ .ops = &gen9_dc_off_power_well_ops,
+ .id = SKL_DISP_DC_OFF,
+ },
+ {
+ .name = "power well 2",
+ .domains = XELPD_PW_2_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = SKL_DISP_PW_2,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_PW_2,
+ .hsw.has_vga = true,
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "power well A",
+ .domains = XELPD_PW_A_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_A,
+ .hsw.irq_pipe_mask = BIT(PIPE_A),
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "power well B",
+ .domains = XELPD_PW_B_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_B,
+ .hsw.irq_pipe_mask = BIT(PIPE_B),
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "power well C",
+ .domains = XELPD_PW_C_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_C,
+ .hsw.irq_pipe_mask = BIT(PIPE_C),
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "power well D",
+ .domains = XELPD_PW_D_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &hsw_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_PW_D,
+ .hsw.irq_pipe_mask = BIT(PIPE_D),
+ .hsw.has_fuses = true,
+ },
+ },
+ {
+ .name = "DDI A IO",
+ .domains = ICL_DDI_IO_A_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
+ }
+ },
+ {
+ .name = "DDI B IO",
+ .domains = ICL_DDI_IO_B_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
+ }
+ },
+ {
+ .name = "DDI C IO",
+ .domains = ICL_DDI_IO_C_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
+ }
+ },
+ {
+ .name = "DDI IO D_XELPD",
+ .domains = XELPD_DDI_IO_D_XELPD_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_DDI_D,
+ }
+ },
+ {
+ .name = "DDI IO E_XELPD",
+ .domains = XELPD_DDI_IO_E_XELPD_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_DDI_E,
+ }
+ },
+ {
+ .name = "DDI IO TC1",
+ .domains = XELPD_DDI_IO_TC1_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1,
+ }
+ },
+ {
+ .name = "DDI IO TC2",
+ .domains = XELPD_DDI_IO_TC2_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2,
+ }
+ },
+ {
+ .name = "DDI IO TC3",
+ .domains = XELPD_DDI_IO_TC3_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3,
+ }
+ },
+ {
+ .name = "DDI IO TC4",
+ .domains = XELPD_DDI_IO_TC4_POWER_DOMAINS,
+ .ops = &hsw_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_ddi_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4,
+ }
+ },
+ {
+ .name = "AUX A",
+ .domains = ICL_AUX_A_IO_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
+ },
+ },
+ {
+ .name = "AUX B",
+ .domains = ICL_AUX_B_IO_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
+ },
+ },
+ {
+ .name = "AUX C",
+ .domains = TGL_AUX_C_IO_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
+ },
+ },
+ {
+ .name = "AUX D_XELPD",
+ .domains = XELPD_AUX_IO_D_XELPD_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_AUX_D,
+ },
+ },
+ {
+ .name = "AUX E_XELPD",
+ .domains = XELPD_AUX_IO_E_XELPD_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = XELPD_PW_CTL_IDX_AUX_E,
+ },
+ },
+ {
+ .name = "AUX USBC1",
+ .domains = XELPD_AUX_IO_USBC1_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1,
+ },
+ },
+ {
+ .name = "AUX USBC2",
+ .domains = XELPD_AUX_IO_USBC2_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2,
+ },
+ },
+ {
+ .name = "AUX USBC3",
+ .domains = XELPD_AUX_IO_USBC3_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3,
+ },
+ },
+ {
+ .name = "AUX USBC4",
+ .domains = XELPD_AUX_IO_USBC4_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4,
+ },
+ },
+ {
+ .name = "AUX TBT1",
+ .domains = XELPD_AUX_IO_TBT1_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1,
+ .hsw.is_tc_tbt = true,
+ },
+ },
+ {
+ .name = "AUX TBT2",
+ .domains = XELPD_AUX_IO_TBT2_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2,
+ .hsw.is_tc_tbt = true,
+ },
+ },
+ {
+ .name = "AUX TBT3",
+ .domains = XELPD_AUX_IO_TBT3_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3,
+ .hsw.is_tc_tbt = true,
+ },
+ },
+ {
+ .name = "AUX TBT4",
+ .domains = XELPD_AUX_IO_TBT4_POWER_DOMAINS,
+ .ops = &icl_aux_power_well_ops,
+ .id = DISP_PW_ID_NONE,
+ {
+ .hsw.regs = &icl_aux_power_well_regs,
+ .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4,
+ .hsw.is_tc_tbt = true,
+ },
+ },
+};
+
static int
sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
int disable_power_well)
@@ -4533,14 +4972,17 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
int requested_dc;
int max_dc;
+ if (!HAS_DISPLAY(dev_priv))
+ return 0;
+
if (IS_DG1(dev_priv))
max_dc = 3;
else if (DISPLAY_VER(dev_priv) >= 12)
max_dc = 4;
- else if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv) || IS_GEN9_BC(dev_priv))
- max_dc = 2;
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
max_dc = 1;
+ else if (DISPLAY_VER(dev_priv) >= 9)
+ max_dc = 2;
else
max_dc = 0;
@@ -4549,7 +4991,8 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
* not depending on the DMC firmware. It's needed by system
* suspend/resume, so allow it unconditionally.
*/
- mask = IS_GEN9_LP(dev_priv) || DISPLAY_VER(dev_priv) >= 11 ?
+ mask = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ||
+ DISPLAY_VER(dev_priv) >= 11 ?
DC_STATE_EN_DC9 : 0;
if (!dev_priv->params.disable_power_well)
@@ -4656,10 +5099,10 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
dev_priv->params.disable_power_well =
sanitize_disable_power_well_option(dev_priv,
dev_priv->params.disable_power_well);
- dev_priv->csr.allowed_dc_mask =
+ dev_priv->dmc.allowed_dc_mask =
get_allowed_dc_mask(dev_priv, dev_priv->params.enable_dc);
- dev_priv->csr.target_dc_state =
+ dev_priv->dmc.target_dc_state =
sanitize_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
BUILD_BUG_ON(POWER_DOMAIN_NUM > 64);
@@ -4673,14 +5116,19 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
* The enabling order will be from lower to higher indexed wells,
* the disabling order is reversed.
*/
- if (IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv)) {
+ if (!HAS_DISPLAY(dev_priv)) {
+ power_domains->power_well_count = 0;
+ err = 0;
+ } else if (DISPLAY_VER(dev_priv) >= 13) {
+ err = set_power_wells(power_domains, xelpd_power_wells);
+ } else if (IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv)) {
err = set_power_wells_mask(power_domains, tgl_power_wells,
BIT_ULL(TGL_DISP_PW_TC_COLD_OFF));
} else if (IS_ROCKETLAKE(dev_priv)) {
err = set_power_wells(power_domains, rkl_power_wells);
- } else if (IS_DISPLAY_VER(dev_priv, 12)) {
+ } else if (DISPLAY_VER(dev_priv) == 12) {
err = set_power_wells(power_domains, tgl_power_wells);
- } else if (IS_DISPLAY_VER(dev_priv, 11)) {
+ } else if (DISPLAY_VER(dev_priv) == 11) {
err = set_power_wells(power_domains, icl_power_wells);
} else if (IS_CNL_WITH_PORT_F(dev_priv)) {
err = set_power_wells(power_domains, cnl_power_wells);
@@ -4692,7 +5140,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
err = set_power_wells(power_domains, glk_power_wells);
} else if (IS_BROXTON(dev_priv)) {
err = set_power_wells(power_domains, bxt_power_wells);
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
err = set_power_wells(power_domains, skl_power_wells);
} else if (IS_CHERRYVIEW(dev_priv)) {
err = set_power_wells(power_domains, chv_power_wells);
@@ -4741,33 +5189,28 @@ static void gen9_dbuf_slice_set(struct drm_i915_private *dev_priv,
{
i915_reg_t reg = DBUF_CTL_S(slice);
bool state;
- u32 val;
- val = intel_de_read(dev_priv, reg);
- if (enable)
- val |= DBUF_POWER_REQUEST;
- else
- val &= ~DBUF_POWER_REQUEST;
- intel_de_write(dev_priv, reg, val);
+ intel_de_rmw(dev_priv, reg, DBUF_POWER_REQUEST,
+ enable ? DBUF_POWER_REQUEST : 0);
intel_de_posting_read(dev_priv, reg);
udelay(10);
state = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE;
drm_WARN(&dev_priv->drm, enable != state,
"DBuf slice %d power %s timeout!\n",
- slice, enable ? "enable" : "disable");
+ slice, enabledisable(enable));
}
void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
u8 req_slices)
{
- int num_slices = INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ u8 slice_mask = INTEL_INFO(dev_priv)->dbuf.slice_mask;
enum dbuf_slice slice;
- drm_WARN(&dev_priv->drm, req_slices & ~(BIT(num_slices) - 1),
- "Invalid set of dbuf slices (0x%x) requested (num dbuf slices %d)\n",
- req_slices, num_slices);
+ drm_WARN(&dev_priv->drm, req_slices & ~slice_mask,
+ "Invalid set of dbuf slices (0x%x) requested (total dbuf slices 0x%x)\n",
+ req_slices, slice_mask);
drm_dbg_kms(&dev_priv->drm, "Updating dbuf slices to 0x%x\n",
req_slices);
@@ -4781,7 +5224,7 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
*/
mutex_lock(&power_domains->lock);
- for (slice = DBUF_S1; slice < num_slices; slice++)
+ for_each_dbuf_slice(dev_priv, slice)
gen9_dbuf_slice_set(dev_priv, slice, req_slices & BIT(slice));
dev_priv->dbuf.enabled_slices = req_slices;
@@ -4809,10 +5252,12 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)
{
- const int num_slices = INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
enum dbuf_slice slice;
- for (slice = DBUF_S1; slice < (DBUF_S1 + num_slices); slice++)
+ if (IS_ALDERLAKE_P(dev_priv))
+ return;
+
+ for_each_dbuf_slice(dev_priv, slice)
intel_de_rmw(dev_priv, DBUF_CTL_S(slice),
DBUF_TRACKER_STATE_SERVICE_MASK,
DBUF_TRACKER_STATE_SERVICE(8));
@@ -4823,6 +5268,9 @@ static void icl_mbus_init(struct drm_i915_private *dev_priv)
unsigned long abox_regs = INTEL_INFO(dev_priv)->abox_mask;
u32 mask, val, i;
+ if (IS_ALDERLAKE_P(dev_priv))
+ return;
+
mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK |
MBUS_ABOX_BT_CREDIT_POOL2_MASK |
MBUS_ABOX_B_CREDIT_MASK |
@@ -4837,7 +5285,7 @@ static void icl_mbus_init(struct drm_i915_private *dev_priv)
* expect us to program the abox_ctl0 register as well, even though
* we don't have to program other instance-0 registers like BW_BUDDY.
*/
- if (IS_DISPLAY_VER(dev_priv, 12))
+ if (DISPLAY_VER(dev_priv) == 12)
abox_regs |= BIT(0);
for_each_set_bit(i, &abox_regs, sizeof(abox_regs))
@@ -5122,6 +5570,9 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
/* enable PCH reset handshake */
intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
/* enable PG1 and Misc I/O */
mutex_lock(&power_domains->lock);
@@ -5137,8 +5588,8 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
gen9_dbuf_enable(dev_priv);
- if (resume && dev_priv->csr.dmc_payload)
- intel_csr_load_program(dev_priv);
+ if (resume && intel_dmc_has_payload(dev_priv))
+ intel_dmc_load_program(dev_priv);
}
static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
@@ -5146,6 +5597,9 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
struct i915_power_domains *power_domains = &dev_priv->power_domains;
struct i915_power_well *well;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
gen9_disable_dc_states(dev_priv);
gen9_dbuf_disable(dev_priv);
@@ -5186,6 +5640,9 @@ static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume
*/
intel_pch_reset_handshake(dev_priv, false);
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
/* Enable PG1 */
mutex_lock(&power_domains->lock);
@@ -5198,8 +5655,8 @@ static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume
gen9_dbuf_enable(dev_priv);
- if (resume && dev_priv->csr.dmc_payload)
- intel_csr_load_program(dev_priv);
+ if (resume && intel_dmc_has_payload(dev_priv))
+ intel_dmc_load_program(dev_priv);
}
static void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
@@ -5207,6 +5664,9 @@ static void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
struct i915_power_domains *power_domains = &dev_priv->power_domains;
struct i915_power_well *well;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
gen9_disable_dc_states(dev_priv);
gen9_dbuf_disable(dev_priv);
@@ -5240,6 +5700,9 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume
/* 1. Enable PCH Reset Handshake */
intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
/* 2-3. */
intel_combo_phy_init(dev_priv);
@@ -5258,8 +5721,8 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume
/* 6. Enable DBUF */
gen9_dbuf_enable(dev_priv);
- if (resume && dev_priv->csr.dmc_payload)
- intel_csr_load_program(dev_priv);
+ if (resume && intel_dmc_has_payload(dev_priv))
+ intel_dmc_load_program(dev_priv);
}
static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
@@ -5267,6 +5730,9 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
struct i915_power_domains *power_domains = &dev_priv->power_domains;
struct i915_power_well *well;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
gen9_disable_dc_states(dev_priv);
/* 1. Disable all display engine functions -> aready done */
@@ -5381,6 +5847,9 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
/* 1. Enable PCH reset handshake. */
intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
/* 2. Initialize all combo phys */
intel_combo_phy_init(dev_priv);
@@ -5409,15 +5878,19 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12)
tgl_bw_buddy_init(dev_priv);
- if (resume && dev_priv->csr.dmc_payload)
- intel_csr_load_program(dev_priv);
+ if (resume && intel_dmc_has_payload(dev_priv))
+ intel_dmc_load_program(dev_priv);
/* Wa_14011508470 */
- if (IS_DISPLAY_VER(dev_priv, 12)) {
+ if (DISPLAY_VER(dev_priv) == 12) {
val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |
DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR;
intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val);
}
+
+ /* Wa_14011503030:xelpd */
+ if (DISPLAY_VER(dev_priv) >= 13)
+ intel_de_write(dev_priv, XELPD_DISPLAY_ERR_FATAL_MASK, ~0);
}
static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
@@ -5425,6 +5898,9 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
struct i915_power_domains *power_domains = &dev_priv->power_domains;
struct i915_power_well *well;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
gen9_disable_dc_states(dev_priv);
/* 1. Disable all display engine functions -> aready done */
@@ -5623,10 +6099,10 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
icl_display_core_init(i915, resume);
} else if (IS_CANNONLAKE(i915)) {
cnl_display_core_init(i915, resume);
- } else if (IS_GEN9_BC(i915)) {
- skl_display_core_init(i915, resume);
- } else if (IS_GEN9_LP(i915)) {
+ } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_display_core_init(i915, resume);
+ } else if (DISPLAY_VER(i915) == 9) {
+ skl_display_core_init(i915, resume);
} else if (IS_CHERRYVIEW(i915)) {
mutex_lock(&power_domains->lock);
chv_phy_control_init(i915);
@@ -5757,13 +6233,13 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
/*
* In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
* support don't manually deinit the power domains. This also means the
- * CSR/DMC firmware will stay active, it will power down any HW
+ * DMC firmware will stay active, it will power down any HW
* resources as required and also enable deeper system power states
* that would be blocked if the firmware was inactive.
*/
- if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
+ if (!(i915->dmc.allowed_dc_mask & DC_STATE_EN_DC9) &&
suspend_mode == I915_DRM_SUSPEND_IDLE &&
- i915->csr.dmc_payload) {
+ intel_dmc_has_payload(i915)) {
intel_display_power_flush_work(i915);
intel_power_domains_verify_state(i915);
return;
@@ -5784,10 +6260,10 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
icl_display_core_uninit(i915);
else if (IS_CANNONLAKE(i915))
cnl_display_core_uninit(i915);
- else if (IS_GEN9_BC(i915))
- skl_display_core_uninit(i915);
- else if (IS_GEN9_LP(i915))
+ else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
bxt_display_core_uninit(i915);
+ else if (DISPLAY_VER(i915) == 9)
+ skl_display_core_uninit(i915);
power_domains->display_core_suspended = true;
}
@@ -5908,7 +6384,8 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915)
void intel_display_power_suspend_late(struct drm_i915_private *i915)
{
- if (DISPLAY_VER(i915) >= 11 || IS_GEN9_LP(i915)) {
+ if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
+ IS_BROXTON(i915)) {
bxt_enable_dc9(i915);
/* Tweaked Wa_14010685332:icp,jsp,mcc */
if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC)
@@ -5921,7 +6398,8 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915)
void intel_display_power_resume_early(struct drm_i915_private *i915)
{
- if (DISPLAY_VER(i915) >= 11 || IS_GEN9_LP(i915)) {
+ if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
+ IS_BROXTON(i915)) {
gen9_sanitize_dc_state(i915);
bxt_disable_dc9(i915);
/* Tweaked Wa_14010685332:icp,jsp,mcc */
@@ -5938,7 +6416,7 @@ void intel_display_power_suspend(struct drm_i915_private *i915)
if (DISPLAY_VER(i915) >= 11) {
icl_display_core_uninit(i915);
bxt_enable_dc9(i915);
- } else if (IS_GEN9_LP(i915)) {
+ } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_display_core_uninit(i915);
bxt_enable_dc9(i915);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
@@ -5951,19 +6429,19 @@ void intel_display_power_resume(struct drm_i915_private *i915)
if (DISPLAY_VER(i915) >= 11) {
bxt_disable_dc9(i915);
icl_display_core_init(i915, true);
- if (i915->csr.dmc_payload) {
- if (i915->csr.allowed_dc_mask &
+ if (intel_dmc_has_payload(i915)) {
+ if (i915->dmc.allowed_dc_mask &
DC_STATE_EN_UPTO_DC6)
skl_enable_dc6(i915);
- else if (i915->csr.allowed_dc_mask &
+ else if (i915->dmc.allowed_dc_mask &
DC_STATE_EN_UPTO_DC5)
gen9_enable_dc5(i915);
}
- } else if (IS_GEN9_LP(i915)) {
+ } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_disable_dc9(i915);
bxt_display_core_init(i915, true);
- if (i915->csr.dmc_payload &&
- (i915->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5))
+ if (intel_dmc_has_payload(i915) &&
+ (i915->dmc.allowed_dc_mask & DC_STATE_EN_UPTO_DC5))
gen9_enable_dc5(i915);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_disable_pc8(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index f3ca5d5c9778..4f0917df4375 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -49,6 +49,9 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_LANES_TC5,
POWER_DOMAIN_PORT_DDI_LANES_TC6,
+ POWER_DOMAIN_PORT_DDI_LANES_D_XELPD = POWER_DOMAIN_PORT_DDI_LANES_TC5, /* XELPD */
+ POWER_DOMAIN_PORT_DDI_LANES_E_XELPD,
+
POWER_DOMAIN_PORT_DDI_A_IO,
POWER_DOMAIN_PORT_DDI_B_IO,
POWER_DOMAIN_PORT_DDI_C_IO,
@@ -66,6 +69,9 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_IO_TC5,
POWER_DOMAIN_PORT_DDI_IO_TC6,
+ POWER_DOMAIN_PORT_DDI_IO_D_XELPD = POWER_DOMAIN_PORT_DDI_IO_TC5, /* XELPD */
+ POWER_DOMAIN_PORT_DDI_IO_E_XELPD,
+
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
@@ -88,6 +94,9 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_USBC5,
POWER_DOMAIN_AUX_USBC6,
+ POWER_DOMAIN_AUX_D_XELPD = POWER_DOMAIN_AUX_USBC5, /* XELPD */
+ POWER_DOMAIN_AUX_E_XELPD,
+
POWER_DOMAIN_AUX_IO_A,
POWER_DOMAIN_AUX_C_TBT,
POWER_DOMAIN_AUX_D_TBT,
@@ -380,6 +389,8 @@ intel_display_power_put_all_in_set(struct drm_i915_private *i915,
enum dbuf_slice {
DBUF_S1,
DBUF_S2,
+ DBUF_S3,
+ DBUF_S4,
I915_MAX_DBUF_SLICES
};
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index e2e707c4dff5..04613864cbe8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -45,7 +45,6 @@
#include <media/cec-notifier.h>
#include "i915_drv.h"
-#include "intel_de.h"
struct drm_printer;
struct __intel_global_objs_state;
@@ -127,8 +126,12 @@ struct intel_framebuffer {
/* Params to remap the FB pages and program the plane registers in each view. */
struct intel_fb_view normal_view;
- struct intel_fb_view rotated_view;
- struct intel_fb_view remapped_view;
+ union {
+ struct intel_fb_view rotated_view;
+ struct intel_fb_view remapped_view;
+ };
+
+ struct i915_address_space *dpt_vm;
};
struct intel_fbdev {
@@ -611,7 +614,8 @@ struct intel_plane_state {
enum drm_scaling_filter scaling_filter;
} hw;
- struct i915_vma *vma;
+ struct i915_vma *ggtt_vma;
+ struct i915_vma *dpt_vma;
unsigned long flags;
#define PLANE_HAS_FENCE BIT(0)
@@ -1198,7 +1202,7 @@ struct intel_crtc_state {
struct {
bool enable;
u8 pipeline_full;
- u16 flipline, vmin, vmax;
+ u16 flipline, vmin, vmax, guardband;
} vrr;
/* Stream Splitter for eDP MSO */
@@ -1478,6 +1482,7 @@ struct intel_psr {
bool sink_support;
bool source_support;
bool enabled;
+ bool paused;
enum pipe pipe;
enum transcoder transcoder;
bool active;
@@ -1494,7 +1499,7 @@ struct intel_psr {
bool sink_not_reliable;
bool irq_aux_error;
u16 su_x_granularity;
- bool dc3co_enabled;
+ u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
struct drm_dp_vsc_sdp vsc;
@@ -1718,6 +1723,14 @@ vlv_pipe_to_channel(enum pipe pipe)
}
}
+static inline bool intel_pipe_valid(struct drm_i915_private *i915, enum pipe pipe)
+{
+ return (pipe >= 0 &&
+ pipe < ARRAY_SIZE(i915->pipe_to_crtc_mapping) &&
+ INTEL_INFO(i915)->pipe_mask & BIT(pipe) &&
+ i915->pipe_to_crtc_mapping[pipe]);
+}
+
static inline struct intel_crtc *
intel_get_first_crtc(struct drm_i915_private *dev_priv)
{
@@ -1973,9 +1986,19 @@ intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, enum pipe pip
intel_wait_for_vblank(dev_priv, pipe);
}
-static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
+static inline bool intel_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier)
+{
+ return DISPLAY_VER(i915) >= 13 && modifier != DRM_FORMAT_MOD_LINEAR;
+}
+
+static inline bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)
+{
+ return fb && intel_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);
+}
+
+static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *plane_state)
{
- return i915_ggtt_offset(state->vma);
+ return i915_ggtt_offset(plane_state->ggtt_vma);
}
static inline struct intel_frontbuffer *
diff --git a/drivers/gpu/drm/i915/display/intel_csr.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 794efcc3ca08..97308da28059 100644
--- a/drivers/gpu/drm/i915/display/intel_csr.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -26,67 +26,72 @@
#include "i915_drv.h"
#include "i915_reg.h"
-#include "intel_csr.h"
#include "intel_de.h"
+#include "intel_dmc.h"
/**
- * DOC: csr support for dmc
+ * DOC: DMC Firmware Support
*
- * Display Context Save and Restore (CSR) firmware support added from gen9
- * onwards to drive newly added DMC (Display microcontroller) in display
+ * From gen9 onwards we have newly added DMC (Display microcontroller) in display
* engine to save and restore the state of display engine when it enter into
* low-power state and comes back to normal.
*/
-#define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE
-
-#define ADLS_CSR_PATH "i915/adls_dmc_ver2_01.bin"
-#define ADLS_CSR_VERSION_REQUIRED CSR_VERSION(2, 1)
-MODULE_FIRMWARE(ADLS_CSR_PATH);
-
-#define DG1_CSR_PATH "i915/dg1_dmc_ver2_02.bin"
-#define DG1_CSR_VERSION_REQUIRED CSR_VERSION(2, 2)
-MODULE_FIRMWARE(DG1_CSR_PATH);
-
-#define RKL_CSR_PATH "i915/rkl_dmc_ver2_02.bin"
-#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 2)
-MODULE_FIRMWARE(RKL_CSR_PATH);
-
-#define TGL_CSR_PATH "i915/tgl_dmc_ver2_08.bin"
-#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 8)
-MODULE_FIRMWARE(TGL_CSR_PATH);
-
-#define ICL_CSR_PATH "i915/icl_dmc_ver1_09.bin"
-#define ICL_CSR_VERSION_REQUIRED CSR_VERSION(1, 9)
-#define ICL_CSR_MAX_FW_SIZE 0x6000
-MODULE_FIRMWARE(ICL_CSR_PATH);
-
-#define CNL_CSR_PATH "i915/cnl_dmc_ver1_07.bin"
-#define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
-#define CNL_CSR_MAX_FW_SIZE GLK_CSR_MAX_FW_SIZE
-MODULE_FIRMWARE(CNL_CSR_PATH);
-
-#define GLK_CSR_PATH "i915/glk_dmc_ver1_04.bin"
-#define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
-#define GLK_CSR_MAX_FW_SIZE 0x4000
-MODULE_FIRMWARE(GLK_CSR_PATH);
-
-#define KBL_CSR_PATH "i915/kbl_dmc_ver1_04.bin"
-#define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
-#define KBL_CSR_MAX_FW_SIZE BXT_CSR_MAX_FW_SIZE
-MODULE_FIRMWARE(KBL_CSR_PATH);
-
-#define SKL_CSR_PATH "i915/skl_dmc_ver1_27.bin"
-#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 27)
-#define SKL_CSR_MAX_FW_SIZE BXT_CSR_MAX_FW_SIZE
-MODULE_FIRMWARE(SKL_CSR_PATH);
-
-#define BXT_CSR_PATH "i915/bxt_dmc_ver1_07.bin"
-#define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
-#define BXT_CSR_MAX_FW_SIZE 0x3000
-MODULE_FIRMWARE(BXT_CSR_PATH);
-
-#define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF
+#define DMC_PATH(platform, major, minor) \
+ "i915/" \
+ __stringify(platform) "_dmc_ver" \
+ __stringify(major) "_" \
+ __stringify(minor) ".bin"
+
+#define GEN12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
+
+#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01)
+#define ADLS_DMC_VERSION_REQUIRED DMC_VERSION(2, 1)
+MODULE_FIRMWARE(ADLS_DMC_PATH);
+
+#define DG1_DMC_PATH DMC_PATH(dg1, 2, 02)
+#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
+MODULE_FIRMWARE(DG1_DMC_PATH);
+
+#define RKL_DMC_PATH DMC_PATH(rkl, 2, 02)
+#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
+MODULE_FIRMWARE(RKL_DMC_PATH);
+
+#define TGL_DMC_PATH DMC_PATH(tgl, 2, 08)
+#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 8)
+MODULE_FIRMWARE(TGL_DMC_PATH);
+
+#define ICL_DMC_PATH DMC_PATH(icl, 1, 09)
+#define ICL_DMC_VERSION_REQUIRED DMC_VERSION(1, 9)
+#define ICL_DMC_MAX_FW_SIZE 0x6000
+MODULE_FIRMWARE(ICL_DMC_PATH);
+
+#define CNL_DMC_PATH DMC_PATH(cnl, 1, 07)
+#define CNL_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
+#define CNL_DMC_MAX_FW_SIZE GLK_DMC_MAX_FW_SIZE
+MODULE_FIRMWARE(CNL_DMC_PATH);
+
+#define GLK_DMC_PATH DMC_PATH(glk, 1, 04)
+#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
+#define GLK_DMC_MAX_FW_SIZE 0x4000
+MODULE_FIRMWARE(GLK_DMC_PATH);
+
+#define KBL_DMC_PATH DMC_PATH(kbl, 1, 04)
+#define KBL_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
+#define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE
+MODULE_FIRMWARE(KBL_DMC_PATH);
+
+#define SKL_DMC_PATH DMC_PATH(skl, 1, 27)
+#define SKL_DMC_VERSION_REQUIRED DMC_VERSION(1, 27)
+#define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE
+MODULE_FIRMWARE(SKL_DMC_PATH);
+
+#define BXT_DMC_PATH DMC_PATH(bxt, 1, 07)
+#define BXT_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
+#define BXT_DMC_MAX_FW_SIZE 0x3000
+MODULE_FIRMWARE(BXT_DMC_PATH);
+
+#define DMC_DEFAULT_FW_OFFSET 0xFFFFFFFF
#define PACKAGE_MAX_FW_INFO_ENTRIES 20
#define PACKAGE_V2_MAX_FW_INFO_ENTRIES 32
#define DMC_V1_MAX_MMIO_COUNT 8
@@ -232,6 +237,11 @@ struct stepping_info {
char substepping;
};
+bool intel_dmc_has_payload(struct drm_i915_private *i915)
+{
+ return i915->dmc.dmc_payload;
+}
+
static const struct stepping_info skl_stepping_info[] = {
{'A', '0'}, {'B', '0'}, {'C', '0'},
{'D', '0'}, {'E', '0'}, {'F', '0'},
@@ -284,7 +294,7 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
mask |= DC_STATE_DEBUG_MASK_CORES;
/* The below bit doesn't need to be cleared ever afterwards */
@@ -297,47 +307,47 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
}
/**
- * intel_csr_load_program() - write the firmware from memory to register.
+ * intel_dmc_load_program() - write the firmware from memory to register.
* @dev_priv: i915 drm device.
*
- * CSR firmware is read from a .bin file and kept in internal memory one time.
+ * DMC firmware is read from a .bin file and kept in internal memory one time.
* Everytime display comes back from low power state this function is called to
* copy the firmware from internal memory to registers.
*/
-void intel_csr_load_program(struct drm_i915_private *dev_priv)
+void intel_dmc_load_program(struct drm_i915_private *dev_priv)
{
- u32 *payload = dev_priv->csr.dmc_payload;
+ u32 *payload = dev_priv->dmc.dmc_payload;
u32 i, fw_size;
- if (!HAS_CSR(dev_priv)) {
+ if (!HAS_DMC(dev_priv)) {
drm_err(&dev_priv->drm,
- "No CSR support available for this platform\n");
+ "No DMC support available for this platform\n");
return;
}
- if (!dev_priv->csr.dmc_payload) {
+ if (!intel_dmc_has_payload(dev_priv)) {
drm_err(&dev_priv->drm,
"Tried to program CSR with empty payload\n");
return;
}
- fw_size = dev_priv->csr.dmc_fw_size;
+ fw_size = dev_priv->dmc.dmc_fw_size;
assert_rpm_wakelock_held(&dev_priv->runtime_pm);
preempt_disable();
for (i = 0; i < fw_size; i++)
- intel_uncore_write_fw(&dev_priv->uncore, CSR_PROGRAM(i),
+ intel_uncore_write_fw(&dev_priv->uncore, DMC_PROGRAM(i),
payload[i]);
preempt_enable();
- for (i = 0; i < dev_priv->csr.mmio_count; i++) {
- intel_de_write(dev_priv, dev_priv->csr.mmioaddr[i],
- dev_priv->csr.mmiodata[i]);
+ for (i = 0; i < dev_priv->dmc.mmio_count; i++) {
+ intel_de_write(dev_priv, dev_priv->dmc.mmioaddr[i],
+ dev_priv->dmc.mmiodata[i]);
}
- dev_priv->csr.dc_state = 0;
+ dev_priv->dmc.dc_state = 0;
gen9_set_dc_state_debugmask(dev_priv);
}
@@ -351,7 +361,7 @@ static u32 find_dmc_fw_offset(const struct intel_fw_info *fw_info,
const struct stepping_info *si,
u8 package_ver)
{
- u32 dmc_offset = CSR_DEFAULT_FW_OFFSET;
+ u32 dmc_offset = DMC_DEFAULT_FW_OFFSET;
unsigned int i;
for (i = 0; i < num_entries; i++) {
@@ -386,17 +396,18 @@ static u32 find_dmc_fw_offset(const struct intel_fw_info *fw_info,
return dmc_offset;
}
-static u32 parse_csr_fw_dmc(struct intel_csr *csr,
- const struct intel_dmc_header_base *dmc_header,
- size_t rem_size)
+static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
+ const struct intel_dmc_header_base *dmc_header,
+ size_t rem_size)
{
+ struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
unsigned int header_len_bytes, dmc_header_size, payload_size, i;
const u32 *mmioaddr, *mmiodata;
u32 mmio_count, mmio_count_max;
u8 *payload;
- BUILD_BUG_ON(ARRAY_SIZE(csr->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||
- ARRAY_SIZE(csr->mmioaddr) < DMC_V1_MAX_MMIO_COUNT);
+ BUILD_BUG_ON(ARRAY_SIZE(dmc->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||
+ ARRAY_SIZE(dmc->mmioaddr) < DMC_V1_MAX_MMIO_COUNT);
/*
* Check if we can access common fields, we will checkc again below
@@ -434,34 +445,34 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
header_len_bytes = dmc_header->header_len;
dmc_header_size = sizeof(*v1);
} else {
- DRM_ERROR("Unknown DMC fw header version: %u\n",
- dmc_header->header_ver);
+ drm_err(&i915->drm, "Unknown DMC fw header version: %u\n",
+ dmc_header->header_ver);
return 0;
}
if (header_len_bytes != dmc_header_size) {
- DRM_ERROR("DMC firmware has wrong dmc header length "
- "(%u bytes)\n", header_len_bytes);
+ drm_err(&i915->drm, "DMC firmware has wrong dmc header length "
+ "(%u bytes)\n", header_len_bytes);
return 0;
}
/* Cache the dmc header info. */
if (mmio_count > mmio_count_max) {
- DRM_ERROR("DMC firmware has wrong mmio count %u\n", mmio_count);
+ drm_err(&i915->drm, "DMC firmware has wrong mmio count %u\n", mmio_count);
return 0;
}
for (i = 0; i < mmio_count; i++) {
- if (mmioaddr[i] < CSR_MMIO_START_RANGE ||
- mmioaddr[i] > CSR_MMIO_END_RANGE) {
- DRM_ERROR("DMC firmware has wrong mmio address 0x%x\n",
- mmioaddr[i]);
+ if (mmioaddr[i] < DMC_MMIO_START_RANGE ||
+ mmioaddr[i] > DMC_MMIO_END_RANGE) {
+ drm_err(&i915->drm, "DMC firmware has wrong mmio address 0x%x\n",
+ mmioaddr[i]);
return 0;
}
- csr->mmioaddr[i] = _MMIO(mmioaddr[i]);
- csr->mmiodata[i] = mmiodata[i];
+ dmc->mmioaddr[i] = _MMIO(mmioaddr[i]);
+ dmc->mmiodata[i] = mmiodata[i];
}
- csr->mmio_count = mmio_count;
+ dmc->mmio_count = mmio_count;
rem_size -= header_len_bytes;
@@ -470,34 +481,33 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
if (rem_size < payload_size)
goto error_truncated;
- if (payload_size > csr->max_fw_size) {
- DRM_ERROR("DMC FW too big (%u bytes)\n", payload_size);
+ if (payload_size > dmc->max_fw_size) {
+ drm_err(&i915->drm, "DMC FW too big (%u bytes)\n", payload_size);
return 0;
}
- csr->dmc_fw_size = dmc_header->fw_size;
+ dmc->dmc_fw_size = dmc_header->fw_size;
- csr->dmc_payload = kmalloc(payload_size, GFP_KERNEL);
- if (!csr->dmc_payload) {
- DRM_ERROR("Memory allocation failed for dmc payload\n");
+ dmc->dmc_payload = kmalloc(payload_size, GFP_KERNEL);
+ if (!dmc->dmc_payload)
return 0;
- }
payload = (u8 *)(dmc_header) + header_len_bytes;
- memcpy(csr->dmc_payload, payload, payload_size);
+ memcpy(dmc->dmc_payload, payload, payload_size);
return header_len_bytes + payload_size;
error_truncated:
- DRM_ERROR("Truncated DMC firmware, refusing.\n");
+ drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
static u32
-parse_csr_fw_package(struct intel_csr *csr,
+parse_dmc_fw_package(struct intel_dmc *dmc,
const struct intel_package_header *package_header,
const struct stepping_info *si,
size_t rem_size)
{
+ struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
u32 package_size = sizeof(struct intel_package_header);
u32 num_entries, max_entries, dmc_offset;
const struct intel_fw_info *fw_info;
@@ -510,8 +520,8 @@ parse_csr_fw_package(struct intel_csr *csr,
} else if (package_header->header_ver == 2) {
max_entries = PACKAGE_V2_MAX_FW_INFO_ENTRIES;
} else {
- DRM_ERROR("DMC firmware has unknown header version %u\n",
- package_header->header_ver);
+ drm_err(&i915->drm, "DMC firmware has unknown header version %u\n",
+ package_header->header_ver);
return 0;
}
@@ -524,8 +534,8 @@ parse_csr_fw_package(struct intel_csr *csr,
goto error_truncated;
if (package_header->header_len * 4 != package_size) {
- DRM_ERROR("DMC firmware has wrong package header length "
- "(%u bytes)\n", package_size);
+ drm_err(&i915->drm, "DMC firmware has wrong package header length "
+ "(%u bytes)\n", package_size);
return 0;
}
@@ -537,9 +547,9 @@ parse_csr_fw_package(struct intel_csr *csr,
((u8 *)package_header + sizeof(*package_header));
dmc_offset = find_dmc_fw_offset(fw_info, num_entries, si,
package_header->header_ver);
- if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
- DRM_ERROR("DMC firmware not supported for %c stepping\n",
- si->stepping);
+ if (dmc_offset == DMC_DEFAULT_FW_OFFSET) {
+ drm_err(&i915->drm, "DMC firmware not supported for %c stepping\n",
+ si->stepping);
return 0;
}
@@ -547,51 +557,53 @@ parse_csr_fw_package(struct intel_csr *csr,
return package_size + dmc_offset * 4;
error_truncated:
- DRM_ERROR("Truncated DMC firmware, refusing.\n");
+ drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
/* Return number of bytes parsed or 0 on error */
-static u32 parse_csr_fw_css(struct intel_csr *csr,
+static u32 parse_dmc_fw_css(struct intel_dmc *dmc,
struct intel_css_header *css_header,
size_t rem_size)
{
+ struct drm_i915_private *i915 = container_of(dmc, typeof(*i915), dmc);
+
if (rem_size < sizeof(struct intel_css_header)) {
- DRM_ERROR("Truncated DMC firmware, refusing.\n");
+ drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
if (sizeof(struct intel_css_header) !=
(css_header->header_len * 4)) {
- DRM_ERROR("DMC firmware has wrong CSS header length "
- "(%u bytes)\n",
- (css_header->header_len * 4));
+ drm_err(&i915->drm, "DMC firmware has wrong CSS header length "
+ "(%u bytes)\n",
+ (css_header->header_len * 4));
return 0;
}
- if (csr->required_version &&
- css_header->version != csr->required_version) {
- DRM_INFO("Refusing to load DMC firmware v%u.%u,"
+ if (dmc->required_version &&
+ css_header->version != dmc->required_version) {
+ drm_info(&i915->drm, "Refusing to load DMC firmware v%u.%u,"
" please use v%u.%u\n",
- CSR_VERSION_MAJOR(css_header->version),
- CSR_VERSION_MINOR(css_header->version),
- CSR_VERSION_MAJOR(csr->required_version),
- CSR_VERSION_MINOR(csr->required_version));
+ DMC_VERSION_MAJOR(css_header->version),
+ DMC_VERSION_MINOR(css_header->version),
+ DMC_VERSION_MAJOR(dmc->required_version),
+ DMC_VERSION_MINOR(dmc->required_version));
return 0;
}
- csr->version = css_header->version;
+ dmc->version = css_header->version;
return sizeof(struct intel_css_header);
}
-static void parse_csr_fw(struct drm_i915_private *dev_priv,
+static void parse_dmc_fw(struct drm_i915_private *dev_priv,
const struct firmware *fw)
{
struct intel_css_header *css_header;
struct intel_package_header *package_header;
struct intel_dmc_header_base *dmc_header;
- struct intel_csr *csr = &dev_priv->csr;
+ struct intel_dmc *dmc = &dev_priv->dmc;
const struct stepping_info *si = intel_get_stepping_info(dev_priv);
u32 readcount = 0;
u32 r;
@@ -601,7 +613,7 @@ static void parse_csr_fw(struct drm_i915_private *dev_priv,
/* Extract CSS Header information */
css_header = (struct intel_css_header *)fw->data;
- r = parse_csr_fw_css(csr, css_header, fw->size);
+ r = parse_dmc_fw_css(dmc, css_header, fw->size);
if (!r)
return;
@@ -609,7 +621,7 @@ static void parse_csr_fw(struct drm_i915_private *dev_priv,
/* Extract Package Header information */
package_header = (struct intel_package_header *)&fw->data[readcount];
- r = parse_csr_fw_package(csr, package_header, si, fw->size - readcount);
+ r = parse_dmc_fw_package(dmc, package_header, si, fw->size - readcount);
if (!r)
return;
@@ -617,49 +629,49 @@ static void parse_csr_fw(struct drm_i915_private *dev_priv,
/* Extract dmc_header information */
dmc_header = (struct intel_dmc_header_base *)&fw->data[readcount];
- parse_csr_fw_dmc(csr, dmc_header, fw->size - readcount);
+ parse_dmc_fw_header(dmc, dmc_header, fw->size - readcount);
}
-static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
+static void intel_dmc_runtime_pm_get(struct drm_i915_private *dev_priv)
{
- drm_WARN_ON(&dev_priv->drm, dev_priv->csr.wakeref);
- dev_priv->csr.wakeref =
+ drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref);
+ dev_priv->dmc.wakeref =
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
}
-static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
+static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv)
{
intel_wakeref_t wakeref __maybe_unused =
- fetch_and_zero(&dev_priv->csr.wakeref);
+ fetch_and_zero(&dev_priv->dmc.wakeref);
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
}
-static void csr_load_work_fn(struct work_struct *work)
+static void dmc_load_work_fn(struct work_struct *work)
{
struct drm_i915_private *dev_priv;
- struct intel_csr *csr;
+ struct intel_dmc *dmc;
const struct firmware *fw = NULL;
- dev_priv = container_of(work, typeof(*dev_priv), csr.work);
- csr = &dev_priv->csr;
+ dev_priv = container_of(work, typeof(*dev_priv), dmc.work);
+ dmc = &dev_priv->dmc;
- request_firmware(&fw, dev_priv->csr.fw_path, dev_priv->drm.dev);
- parse_csr_fw(dev_priv, fw);
+ request_firmware(&fw, dev_priv->dmc.fw_path, dev_priv->drm.dev);
+ parse_dmc_fw(dev_priv, fw);
- if (dev_priv->csr.dmc_payload) {
- intel_csr_load_program(dev_priv);
- intel_csr_runtime_pm_put(dev_priv);
+ if (intel_dmc_has_payload(dev_priv)) {
+ intel_dmc_load_program(dev_priv);
+ intel_dmc_runtime_pm_put(dev_priv);
drm_info(&dev_priv->drm,
"Finished loading DMC firmware %s (v%u.%u)\n",
- dev_priv->csr.fw_path, CSR_VERSION_MAJOR(csr->version),
- CSR_VERSION_MINOR(csr->version));
+ dev_priv->dmc.fw_path, DMC_VERSION_MAJOR(dmc->version),
+ DMC_VERSION_MINOR(dmc->version));
} else {
drm_notice(&dev_priv->drm,
"Failed to load DMC firmware %s."
" Disabling runtime power management.\n",
- csr->fw_path);
+ dmc->fw_path);
drm_notice(&dev_priv->drm, "DMC firmware homepage: %s",
INTEL_UC_FIRMWARE_URL);
}
@@ -668,152 +680,152 @@ static void csr_load_work_fn(struct work_struct *work)
}
/**
- * intel_csr_ucode_init() - initialize the firmware loading.
+ * intel_dmc_ucode_init() - initialize the firmware loading.
* @dev_priv: i915 drm device.
*
* This function is called at the time of loading the display driver to read
* firmware from a .bin file and copied into a internal memory.
*/
-void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
+void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
{
- struct intel_csr *csr = &dev_priv->csr;
+ struct intel_dmc *dmc = &dev_priv->dmc;
- INIT_WORK(&dev_priv->csr.work, csr_load_work_fn);
+ INIT_WORK(&dev_priv->dmc.work, dmc_load_work_fn);
- if (!HAS_CSR(dev_priv))
+ if (!HAS_DMC(dev_priv))
return;
/*
- * Obtain a runtime pm reference, until CSR is loaded, to avoid entering
+ * Obtain a runtime pm reference, until DMC is loaded, to avoid entering
* runtime-suspend.
*
* On error, we return with the rpm wakeref held to prevent runtime
- * suspend as runtime suspend *requires* a working CSR for whatever
+ * suspend as runtime suspend *requires* a working DMC for whatever
* reason.
*/
- intel_csr_runtime_pm_get(dev_priv);
+ intel_dmc_runtime_pm_get(dev_priv);
if (IS_ALDERLAKE_S(dev_priv)) {
- csr->fw_path = ADLS_CSR_PATH;
- csr->required_version = ADLS_CSR_VERSION_REQUIRED;
- csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
+ dmc->fw_path = ADLS_DMC_PATH;
+ dmc->required_version = ADLS_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
} else if (IS_DG1(dev_priv)) {
- csr->fw_path = DG1_CSR_PATH;
- csr->required_version = DG1_CSR_VERSION_REQUIRED;
- csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
+ dmc->fw_path = DG1_DMC_PATH;
+ dmc->required_version = DG1_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
} else if (IS_ROCKETLAKE(dev_priv)) {
- csr->fw_path = RKL_CSR_PATH;
- csr->required_version = RKL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
+ dmc->fw_path = RKL_DMC_PATH;
+ dmc->required_version = RKL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
} else if (DISPLAY_VER(dev_priv) >= 12) {
- csr->fw_path = TGL_CSR_PATH;
- csr->required_version = TGL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
- } else if (IS_DISPLAY_VER(dev_priv, 11)) {
- csr->fw_path = ICL_CSR_PATH;
- csr->required_version = ICL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = ICL_CSR_MAX_FW_SIZE;
+ dmc->fw_path = TGL_DMC_PATH;
+ dmc->required_version = TGL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GEN12_DMC_MAX_FW_SIZE;
+ } else if (DISPLAY_VER(dev_priv) == 11) {
+ dmc->fw_path = ICL_DMC_PATH;
+ dmc->required_version = ICL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE;
} else if (IS_CANNONLAKE(dev_priv)) {
- csr->fw_path = CNL_CSR_PATH;
- csr->required_version = CNL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = CNL_CSR_MAX_FW_SIZE;
+ dmc->fw_path = CNL_DMC_PATH;
+ dmc->required_version = CNL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = CNL_DMC_MAX_FW_SIZE;
} else if (IS_GEMINILAKE(dev_priv)) {
- csr->fw_path = GLK_CSR_PATH;
- csr->required_version = GLK_CSR_VERSION_REQUIRED;
- csr->max_fw_size = GLK_CSR_MAX_FW_SIZE;
+ dmc->fw_path = GLK_DMC_PATH;
+ dmc->required_version = GLK_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE;
} else if (IS_KABYLAKE(dev_priv) ||
IS_COFFEELAKE(dev_priv) ||
IS_COMETLAKE(dev_priv)) {
- csr->fw_path = KBL_CSR_PATH;
- csr->required_version = KBL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = KBL_CSR_MAX_FW_SIZE;
+ dmc->fw_path = KBL_DMC_PATH;
+ dmc->required_version = KBL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE;
} else if (IS_SKYLAKE(dev_priv)) {
- csr->fw_path = SKL_CSR_PATH;
- csr->required_version = SKL_CSR_VERSION_REQUIRED;
- csr->max_fw_size = SKL_CSR_MAX_FW_SIZE;
+ dmc->fw_path = SKL_DMC_PATH;
+ dmc->required_version = SKL_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE;
} else if (IS_BROXTON(dev_priv)) {
- csr->fw_path = BXT_CSR_PATH;
- csr->required_version = BXT_CSR_VERSION_REQUIRED;
- csr->max_fw_size = BXT_CSR_MAX_FW_SIZE;
+ dmc->fw_path = BXT_DMC_PATH;
+ dmc->required_version = BXT_DMC_VERSION_REQUIRED;
+ dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE;
}
if (dev_priv->params.dmc_firmware_path) {
if (strlen(dev_priv->params.dmc_firmware_path) == 0) {
- csr->fw_path = NULL;
+ dmc->fw_path = NULL;
drm_info(&dev_priv->drm,
- "Disabling CSR firmware and runtime PM\n");
+ "Disabling DMC firmware and runtime PM\n");
return;
}
- csr->fw_path = dev_priv->params.dmc_firmware_path;
+ dmc->fw_path = dev_priv->params.dmc_firmware_path;
/* Bypass version check for firmware override. */
- csr->required_version = 0;
+ dmc->required_version = 0;
}
- if (csr->fw_path == NULL) {
+ if (!dmc->fw_path) {
drm_dbg_kms(&dev_priv->drm,
- "No known CSR firmware for platform, disabling runtime PM\n");
+ "No known DMC firmware for platform, disabling runtime PM\n");
return;
}
- drm_dbg_kms(&dev_priv->drm, "Loading %s\n", csr->fw_path);
- schedule_work(&dev_priv->csr.work);
+ drm_dbg_kms(&dev_priv->drm, "Loading %s\n", dmc->fw_path);
+ schedule_work(&dev_priv->dmc.work);
}
/**
- * intel_csr_ucode_suspend() - prepare CSR firmware before system suspend
+ * intel_dmc_ucode_suspend() - prepare DMC firmware before system suspend
* @dev_priv: i915 drm device
*
* Prepare the DMC firmware before entering system suspend. This includes
* flushing pending work items and releasing any resources acquired during
* init.
*/
-void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
+void intel_dmc_ucode_suspend(struct drm_i915_private *dev_priv)
{
- if (!HAS_CSR(dev_priv))
+ if (!HAS_DMC(dev_priv))
return;
- flush_work(&dev_priv->csr.work);
+ flush_work(&dev_priv->dmc.work);
/* Drop the reference held in case DMC isn't loaded. */
- if (!dev_priv->csr.dmc_payload)
- intel_csr_runtime_pm_put(dev_priv);
+ if (!intel_dmc_has_payload(dev_priv))
+ intel_dmc_runtime_pm_put(dev_priv);
}
/**
- * intel_csr_ucode_resume() - init CSR firmware during system resume
+ * intel_dmc_ucode_resume() - init DMC firmware during system resume
* @dev_priv: i915 drm device
*
* Reinitialize the DMC firmware during system resume, reacquiring any
- * resources released in intel_csr_ucode_suspend().
+ * resources released in intel_dmc_ucode_suspend().
*/
-void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
+void intel_dmc_ucode_resume(struct drm_i915_private *dev_priv)
{
- if (!HAS_CSR(dev_priv))
+ if (!HAS_DMC(dev_priv))
return;
/*
* Reacquire the reference to keep RPM disabled in case DMC isn't
* loaded.
*/
- if (!dev_priv->csr.dmc_payload)
- intel_csr_runtime_pm_get(dev_priv);
+ if (!intel_dmc_has_payload(dev_priv))
+ intel_dmc_runtime_pm_get(dev_priv);
}
/**
- * intel_csr_ucode_fini() - unload the CSR firmware.
+ * intel_dmc_ucode_fini() - unload the DMC firmware.
* @dev_priv: i915 drm device.
*
* Firmmware unloading includes freeing the internal memory and reset the
* firmware loading status.
*/
-void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
+void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv)
{
- if (!HAS_CSR(dev_priv))
+ if (!HAS_DMC(dev_priv))
return;
- intel_csr_ucode_suspend(dev_priv);
- drm_WARN_ON(&dev_priv->drm, dev_priv->csr.wakeref);
+ intel_dmc_ucode_suspend(dev_priv);
+ drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref);
- kfree(dev_priv->csr.dmc_payload);
+ kfree(dev_priv->dmc.dmc_payload);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h
new file mode 100644
index 000000000000..4c22f567b61b
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dmc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef __INTEL_DMC_H__
+#define __INTEL_DMC_H__
+
+#include "i915_reg.h"
+#include "intel_wakeref.h"
+#include <linux/workqueue.h>
+
+struct drm_i915_private;
+
+#define DMC_VERSION(major, minor) ((major) << 16 | (minor))
+#define DMC_VERSION_MAJOR(version) ((version) >> 16)
+#define DMC_VERSION_MINOR(version) ((version) & 0xffff)
+
+struct intel_dmc {
+ struct work_struct work;
+ const char *fw_path;
+ u32 required_version;
+ u32 max_fw_size; /* bytes */
+ u32 *dmc_payload;
+ u32 dmc_fw_size; /* dwords */
+ u32 version;
+ u32 mmio_count;
+ i915_reg_t mmioaddr[20];
+ u32 mmiodata[20];
+ u32 dc_state;
+ u32 target_dc_state;
+ u32 allowed_dc_mask;
+ intel_wakeref_t wakeref;
+};
+
+void intel_dmc_ucode_init(struct drm_i915_private *i915);
+void intel_dmc_load_program(struct drm_i915_private *i915);
+void intel_dmc_ucode_fini(struct drm_i915_private *i915);
+void intel_dmc_ucode_suspend(struct drm_i915_private *i915);
+void intel_dmc_ucode_resume(struct drm_i915_private *i915);
+bool intel_dmc_has_payload(struct drm_i915_private *i915);
+
+#endif /* __INTEL_DMC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 642c60f3d9b1..5c9222283044 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -46,13 +46,15 @@
#include "intel_audio.h"
#include "intel_connector.h"
#include "intel_ddi.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
+#include "intel_dp_hdcp.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
-#include "intel_dpll.h"
#include "intel_dpio_phy.h"
+#include "intel_dpll.h"
#include "intel_fifo_underrun.h"
#include "intel_hdcp.h"
#include "intel_hdmi.h"
@@ -107,6 +109,7 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
}
static void intel_dp_unset_edid(struct intel_dp *intel_dp);
+static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
/* update sink rates from dpcd */
static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
@@ -215,7 +218,7 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
return DISPLAY_VER(dev_priv) >= 12 ||
- (IS_DISPLAY_VER(dev_priv, 11) &&
+ (DISPLAY_VER(dev_priv) == 11 &&
encoder->port != PORT_A);
}
@@ -295,16 +298,16 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
source_rates = cnl_rates;
size = ARRAY_SIZE(cnl_rates);
- if (IS_DISPLAY_VER(dev_priv, 10))
+ if (DISPLAY_VER(dev_priv) == 10)
max_rate = cnl_max_source_rate(intel_dp);
else if (IS_JSL_EHL(dev_priv))
max_rate = ehl_max_source_rate(intel_dp);
else
max_rate = icl_max_source_rate(intel_dp);
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
source_rates = bxt_rates;
size = ARRAY_SIZE(bxt_rates);
- } else if (IS_GEN9_BC(dev_priv)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
source_rates = skl_rates;
size = ARRAY_SIZE(skl_rates);
} else if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) ||
@@ -492,7 +495,8 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915)
static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
- bool bigjoiner)
+ bool bigjoiner,
+ u32 pipe_bpp)
{
u32 bits_per_pixel, max_bpp_small_joiner_ram;
int i;
@@ -539,12 +543,17 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
return 0;
}
- /* Find the nearest match in the array of known BPPs from VESA */
- for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
- if (bits_per_pixel < valid_dsc_bpp[i + 1])
- break;
+ /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
+ if (DISPLAY_VER(i915) >= 13) {
+ bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
+ } else {
+ /* Find the nearest match in the array of known BPPs from VESA */
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
+ if (bits_per_pixel < valid_dsc_bpp[i + 1])
+ break;
+ }
+ bits_per_pixel = valid_dsc_bpp[i];
}
- bits_per_pixel = valid_dsc_bpp[i];
/*
* Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
@@ -778,6 +787,12 @@ intel_dp_mode_valid(struct drm_connector *connector,
*/
if (DISPLAY_VER(dev_priv) >= 10 &&
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
+ /*
+ * TBD pass the connector BPC,
+ * for now U8_MAX so that max BPC on that platform would be picked
+ */
+ int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
+
if (intel_dp_is_edp(intel_dp)) {
dsc_max_output_bpp =
drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd) >> 4;
@@ -791,7 +806,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
max_lanes,
target_clock,
mode->hdisplay,
- bigjoiner) >> 4;
+ bigjoiner,
+ pipe_bpp) >> 4;
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
target_clock,
@@ -802,8 +818,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
dsc = dsc_max_output_bpp && dsc_slice_count;
}
- /* big joiner configuration needs DSC */
- if (bigjoiner && !dsc)
+ /*
+ * Big joiner configuration needs DSC for TGL which is not true for
+ * XE_LPD where uncompressed joiner is supported.
+ */
+ if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc)
return MODE_CLOCK_HIGH;
if (mode_rate > max_rate && !dsc)
@@ -916,7 +935,7 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
if (DISPLAY_VER(dev_priv) >= 12)
return true;
- if (IS_DISPLAY_VER(dev_priv, 11) && pipe_config->cpu_transcoder != TRANSCODER_A)
+ if (DISPLAY_VER(dev_priv) == 11 && pipe_config->cpu_transcoder != TRANSCODER_A)
return true;
return false;
@@ -1095,10 +1114,18 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
return -EINVAL;
}
-static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
+static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
int i, num_bpc;
u8 dsc_bpc[3] = {0};
+ u8 dsc_max_bpc;
+
+ /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
+ if (DISPLAY_VER(i915) >= 12)
+ dsc_max_bpc = min_t(u8, 12, max_req_bpc);
+ else
+ dsc_max_bpc = min_t(u8, 10, max_req_bpc);
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
dsc_bpc);
@@ -1129,10 +1156,6 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
*/
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
- ret = intel_dsc_compute_params(encoder, crtc_state);
- if (ret)
- return ret;
-
/*
* Slice Height of 8 works for all currently available panels. So start
* with that if pic_height is an integral multiple of 8. Eventually add
@@ -1145,6 +1168,10 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
else
vdsc_cfg->slice_height = 2;
+ ret = intel_dsc_compute_params(encoder, crtc_state);
+ if (ret)
+ return ret;
+
vdsc_cfg->dsc_version_major =
(intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
@@ -1186,7 +1213,6 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
- u8 dsc_max_bpc;
int pipe_bpp;
int ret;
@@ -1196,14 +1222,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
if (!intel_dp_supports_dsc(intel_dp, pipe_config))
return -EINVAL;
- /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
- if (DISPLAY_VER(dev_priv) >= 12)
- dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc);
- else
- dsc_max_bpc = min_t(u8, 10,
- conn_state->max_requested_bpc);
-
- pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, dsc_max_bpc);
+ pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
/* Min Input BPC for ICL+ is 8 */
if (pipe_bpp < 8 * 3) {
@@ -1238,7 +1257,8 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
- pipe_config->bigjoiner);
+ pipe_config->bigjoiner,
+ pipe_bpp);
dsc_dp_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
adjusted_mode->crtc_clock,
@@ -1350,9 +1370,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
*/
ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
- /* enable compression if the mode doesn't fit available BW */
+ /*
+ * Pipe joiner needs compression upto display12 due to BW limitation. DG2
+ * onwards pipe joiner can be enabled without compression.
+ */
drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
- if (ret || intel_dp->force_dsc_en || pipe_config->bigjoiner) {
+ if (ret || intel_dp->force_dsc_en || (DISPLAY_VER(i915) < 13 &&
+ pipe_config->bigjoiner)) {
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits);
if (ret < 0)
@@ -1812,7 +1836,7 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
if (ret < 0)
drm_dbg_kms(&i915->drm,
"Failed to %s sink decompression state\n",
- enable ? "enable" : "disable");
+ enabledisable(enable));
}
static void
@@ -2244,8 +2268,8 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
if (drm_dp_dpcd_writeb(&intel_dp->aux,
DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
- drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
- enableddisabled(intel_dp->has_hdmi_sink));
+ drm_dbg_kms(&i915->drm, "Failed to %s protocol converter HDMI mode\n",
+ enabledisable(intel_dp->has_hdmi_sink));
tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
@@ -2253,8 +2277,8 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
if (drm_dp_dpcd_writeb(&intel_dp->aux,
DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
drm_dbg_kms(&i915->drm,
- "Failed to set protocol converter YCbCr 4:2:0 conversion mode to %s\n",
- enableddisabled(intel_dp->dfp.ycbcr_444_to_420));
+ "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n",
+ enabledisable(intel_dp->dfp.ycbcr_444_to_420));
tmp = 0;
if (intel_dp->dfp.rgb_to_ycbcr) {
@@ -2291,8 +2315,8 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0)
drm_dbg_kms(&i915->drm,
- "Failed to set protocol converter RGB->YCbCr conversion mode to %s\n",
- enableddisabled(tmp ? true : false));
+ "Failed to %s protocol converter RGB->YCbCr conversion mode\n",
+ enabledisable(tmp));
}
@@ -2812,31 +2836,25 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
u32 dip_enable = VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW |
VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW |
VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK;
- u32 val = intel_de_read(dev_priv, reg);
+ u32 val = intel_de_read(dev_priv, reg) & ~dip_enable;
/* TODO: Add DSC case (DIP_ENABLE_PPS) */
/* When PSR is enabled, this routine doesn't disable VSC DIP */
- if (intel_psr_enabled(intel_dp))
- val &= ~dip_enable;
- else
- val &= ~(dip_enable | VIDEO_DIP_ENABLE_VSC_HSW);
-
- if (!enable) {
- intel_de_write(dev_priv, reg, val);
- intel_de_posting_read(dev_priv, reg);
- return;
- }
+ if (!crtc_state->has_psr)
+ val &= ~VIDEO_DIP_ENABLE_VSC_HSW;
intel_de_write(dev_priv, reg, val);
intel_de_posting_read(dev_priv, reg);
+ if (!enable)
+ return;
+
/* When PSR is enabled, VSC SDP is handled by PSR routine */
- if (!intel_psr_enabled(intel_dp))
+ if (!crtc_state->has_psr)
intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC);
intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA);
@@ -2963,14 +2981,13 @@ static void intel_read_dp_vsc_sdp(struct intel_encoder *encoder,
struct drm_dp_vsc_sdp *vsc)
{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
unsigned int type = DP_SDP_VSC;
struct dp_sdp sdp = {};
int ret;
/* When PSR is enabled, VSC SDP is handled by PSR routine */
- if (intel_psr_enabled(intel_dp))
+ if (crtc_state->has_psr)
return;
if ((crtc_state->infoframes.enable &
@@ -5359,7 +5376,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
intel_dp_add_properties(intel_dp, connector);
if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
- int ret = intel_dp_init_hdcp(dig_port, intel_connector);
+ int ret = intel_dp_hdcp_init(dig_port, intel_connector);
if (ret)
drm_dbg_kms(&dev_priv->drm,
"HDCP init failed, skipping.\n");
@@ -5392,6 +5409,9 @@ void intel_dp_mst_suspend(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
for_each_intel_encoder(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp;
@@ -5412,6 +5432,9 @@ void intel_dp_mst_resume(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
for_each_intel_encoder(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp;
int ret;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 8db5062f6c4a..680631b5b437 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -119,9 +119,6 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
-int intel_dp_init_hdcp(struct intel_digital_port *dig_port,
- struct intel_connector *intel_connector);
-
bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
void intel_dp_sync_state(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 7e83bc2cc34a..7c048d2ecf43 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -126,12 +126,7 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv =
to_i915(dig_port->base.base.dev);
- u32 precharge, timeout;
-
- if (IS_SANDYBRIDGE(dev_priv))
- precharge = 3;
- else
- precharge = 5;
+ u32 timeout;
/* Max timeout value on G4x-BDW: 1.6ms */
if (IS_BROADWELL(dev_priv))
@@ -146,7 +141,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) |
- (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+ (3 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
(aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
}
@@ -607,8 +602,8 @@ static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp)
case AUX_CH_USBC2:
case AUX_CH_USBC3:
case AUX_CH_USBC4:
- case AUX_CH_USBC5:
- case AUX_CH_USBC6:
+ case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */
+ case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */
return DP_AUX_CH_CTL(aux_ch);
default:
MISSING_CASE(aux_ch);
@@ -630,8 +625,8 @@ static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index)
case AUX_CH_USBC2:
case AUX_CH_USBC3:
case AUX_CH_USBC4:
- case AUX_CH_USBC5:
- case AUX_CH_USBC6:
+ case AUX_CH_USBC5: /* aka AUX_CH_D_XELPD */
+ case AUX_CH_USBC6: /* aka AUX_CH_E_XELPD */
return DP_AUX_CH_DATA(aux_ch, index);
default:
MISSING_CASE(aux_ch);
@@ -682,10 +677,15 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
else
intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
+ intel_dp->aux.drm_dev = &dev_priv->drm;
drm_dp_aux_init(&intel_dp->aux);
/* Failure to allocate our preferred name is not critical */
- if (DISPLAY_VER(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
+ if (DISPLAY_VER(dev_priv) >= 13 && aux_ch >= AUX_CH_D_XELPD)
+ intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
+ aux_ch_name(aux_ch - AUX_CH_D_XELPD + AUX_CH_D),
+ encoder->base.name);
+ else if (DISPLAY_VER(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
aux_ch - AUX_CH_USBC1 + '1',
encoder->base.name);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 4f8337c7fd2e..8e9ac9ba1d38 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -291,7 +291,7 @@ static void set_vesa_backlight_enable(struct intel_dp *intel_dp, bool enable)
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
reg_val) != 1) {
drm_dbg_kms(&i915->drm, "Failed to %s aux backlight\n",
- enable ? "enable" : "disable");
+ enabledisable(enable));
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 90868e156c69..d697d169e8c1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -11,9 +11,11 @@
#include <drm/drm_hdcp.h>
#include <drm/drm_print.h>
-#include "intel_display_types.h"
#include "intel_ddi.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
#include "intel_dp.h"
+#include "intel_dp_hdcp.h"
#include "intel_hdcp.h"
static unsigned int transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)
@@ -532,7 +534,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
- ktime_t msg_end;
+ ktime_t msg_end = ktime_set(0, 0);
bool msg_expired;
hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
@@ -835,7 +837,7 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = {
.protocol = HDCP_PROTOCOL_DP,
};
-int intel_dp_init_hdcp(struct intel_digital_port *dig_port,
+int intel_dp_hdcp_init(struct intel_digital_port *dig_port,
struct intel_connector *intel_connector)
{
struct drm_device *dev = intel_connector->base.dev;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.h b/drivers/gpu/drm/i915/display/intel_dp_hdcp.h
new file mode 100644
index 000000000000..eff5ec5c5021
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __INTEL_DP_HDCP___
+#define __INTEL_DP_HDCP___
+
+struct intel_connector;
+struct intel_digital_port;
+
+int intel_dp_hdcp_init(struct intel_digital_port *dig_port,
+ struct intel_connector *intel_connector);
+
+#endif /* __INTEL_DP_HDCP___ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 02a003fd48fb..08bceae40aa8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -37,7 +37,7 @@ intel_dp_dump_link_status(struct drm_device *drm,
static void intel_dp_reset_lttpr_common_caps(struct intel_dp *intel_dp)
{
- memset(&intel_dp->lttpr_common_caps, 0, sizeof(intel_dp->lttpr_common_caps));
+ memset(intel_dp->lttpr_common_caps, 0, sizeof(intel_dp->lttpr_common_caps));
}
static void intel_dp_reset_lttpr_count(struct intel_dp *intel_dp)
@@ -128,49 +128,13 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
}
-/**
- * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the LTTPR link training mode
- * @intel_dp: Intel DP struct
- *
- * Read the LTTPR common and DPRX capabilities and switch to non-transparent
- * link training mode if any is detected and read the PHY capabilities for all
- * detected LTTPRs. In case of an LTTPR detection error or if the number of
- * LTTPRs is more than is supported (8), fall back to the no-LTTPR,
- * transparent mode link training mode.
- *
- * Returns:
- * >0 if LTTPRs were detected and the non-transparent LT mode was set. The
- * DPRX capabilities are read out.
- * 0 if no LTTPRs or more than 8 LTTPRs were detected or in case of a
- * detection failure and the transparent LT mode was set. The DPRX
- * capabilities are read out.
- * <0 Reading out the DPRX capabilities failed.
- */
-int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
+static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
{
int lttpr_count;
- bool ret;
int i;
- ret = intel_dp_read_lttpr_common_caps(intel_dp);
-
- /* The DPTX shall read the DPRX caps after LTTPR detection. */
- if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
- intel_dp_reset_lttpr_common_caps(intel_dp);
- return -EIO;
- }
-
- if (!ret)
- return 0;
-
- /*
- * The 0xF0000-0xF02FF range is only valid if the DPCD revision is
- * at least 1.4.
- */
- if (intel_dp->dpcd[DP_DPCD_REV] < 0x14) {
- intel_dp_reset_lttpr_common_caps(intel_dp);
+ if (!intel_dp_read_lttpr_common_caps(intel_dp))
return 0;
- }
lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
/*
@@ -211,6 +175,37 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
return lttpr_count;
}
+
+/**
+ * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the LTTPR link training mode
+ * @intel_dp: Intel DP struct
+ *
+ * Read the LTTPR common and DPRX capabilities and switch to non-transparent
+ * link training mode if any is detected and read the PHY capabilities for all
+ * detected LTTPRs. In case of an LTTPR detection error or if the number of
+ * LTTPRs is more than is supported (8), fall back to the no-LTTPR,
+ * transparent mode link training mode.
+ *
+ * Returns:
+ * >0 if LTTPRs were detected and the non-transparent LT mode was set. The
+ * DPRX capabilities are read out.
+ * 0 if no LTTPRs or more than 8 LTTPRs were detected or in case of a
+ * detection failure and the transparent LT mode was set. The DPRX
+ * capabilities are read out.
+ * <0 Reading out the DPRX capabilities failed.
+ */
+int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
+{
+ int lttpr_count = intel_dp_init_lttpr(intel_dp);
+
+ /* The DPTX shall read the DPRX caps after LTTPR detection. */
+ if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
+ intel_dp_reset_lttpr_common_caps(intel_dp);
+ return -EIO;
+ }
+
+ return lttpr_count;
+}
EXPORT_SYMBOL(intel_dp_init_lttpr_and_dprx_caps);
static u8 dp_voltage_max(u8 preemph)
@@ -513,7 +508,7 @@ static void intel_dp_link_training_clock_recovery_delay(struct intel_dp *intel_d
enum drm_dp_phy dp_phy)
{
if (dp_phy == DP_PHY_DPRX)
- drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
+ drm_dp_link_train_clock_recovery_delay(&intel_dp->aux, intel_dp->dpcd);
else
drm_dp_lttpr_link_train_clock_recovery_delay();
}
@@ -665,11 +660,11 @@ intel_dp_link_training_channel_equalization_delay(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy)
{
if (dp_phy == DP_PHY_DPRX) {
- drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
+ drm_dp_link_train_channel_eq_delay(&intel_dp->aux, intel_dp->dpcd);
} else {
const u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
- drm_dp_lttpr_link_train_channel_eq_delay(phy_caps);
+ drm_dp_lttpr_link_train_channel_eq_delay(&intel_dp->aux, phy_caps);
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2daa3f67791e..b170e272bdee 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -32,13 +32,16 @@
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"
+#include "intel_crtc.h"
#include "intel_ddi.h"
+#include "intel_de.h"
#include "intel_display_types.h"
-#include "intel_hotplug.h"
#include "intel_dp.h"
+#include "intel_dp_hdcp.h"
#include "intel_dp_mst.h"
#include "intel_dpio_phy.h"
#include "intel_hdcp.h"
+#include "intel_hotplug.h"
#include "skl_scaler.h"
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
@@ -70,7 +73,8 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr,
connector->port,
crtc_state->pbn,
- drm_dp_get_vc_payload_bw(crtc_state->port_clock,
+ drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
+ crtc_state->port_clock,
crtc_state->lane_count));
if (slots == -EDEADLK)
return slots;
@@ -154,7 +158,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
pipe_config->limited_color_range =
intel_dp_limited_color_range(pipe_config, conn_state);
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
@@ -832,7 +836,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_attach_broadcast_rgb_property(connector);
if (DISPLAY_VER(dev_priv) <= 12) {
- ret = intel_dp_init_hdcp(dig_port, intel_connector);
+ ret = intel_dp_hdcp_init(dig_port, intel_connector);
if (ret)
drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n",
connector->name, connector->base.id);
@@ -941,6 +945,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
struct intel_dp *intel_dp = &dig_port->dp;
enum port port = dig_port->base.port;
int ret;
+ int max_source_rate =
+ intel_dp->source_rates[intel_dp->num_source_rates - 1];
if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp))
return 0;
@@ -956,7 +962,10 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id)
/* create encoders */
intel_dp_create_fake_mst_encoders(dig_port);
ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm,
- &intel_dp->aux, 16, 3, conn_base_id);
+ &intel_dp->aux, 16, 3,
+ dig_port->max_lanes,
+ max_source_rate,
+ conn_base_id);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
index 514c4a7adffc..48507ed79950 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
@@ -23,6 +23,7 @@
#include "display/intel_dp.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dpio_phy.h"
#include "intel_sideband.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 3e3c5eed1600..89635da9f6f6 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -4,6 +4,7 @@
*/
#include <linux/kernel.h>
#include "intel_crtc.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_display.h"
#include "intel_dpll.h"
@@ -366,13 +367,11 @@ static bool intel_pll_is_valid(struct drm_i915_private *dev_priv,
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
return false;
- if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) &&
- !IS_CHERRYVIEW(dev_priv) && !IS_GEN9_LP(dev_priv))
+ if (!IS_PINEVIEW(dev_priv) && !IS_LP(dev_priv))
if (clock->m1 <= clock->m2)
return false;
- if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
- !IS_GEN9_LP(dev_priv)) {
+ if (!IS_LP(dev_priv)) {
if (clock->p < limit->p.min || limit->p.max < clock->p)
return false;
if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -1358,7 +1357,7 @@ intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv)
dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;
else if (IS_PINEVIEW(dev_priv))
dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
- else if (!IS_DISPLAY_VER(dev_priv, 2))
+ else if (DISPLAY_VER(dev_priv) != 2)
dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
else
dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.h b/drivers/gpu/drm/i915/display/intel_dpll.h
index 7ff4b0d29ed1..88247027fd5a 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll.h
@@ -6,6 +6,8 @@
#ifndef _INTEL_DPLL_H_
#define _INTEL_DPLL_H_
+#include <linux/types.h>
+
struct dpll;
struct drm_i915_private;
struct intel_crtc;
@@ -37,5 +39,8 @@ void vlv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
void chv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
+bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
+ struct dpll *best_clock);
+int chv_calc_dpll_params(int refclk, struct dpll *pll_clock);
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 1ae158d12c07..71ac57670043 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -21,8 +21,10 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dpio_phy.h"
+#include "intel_dpll.h"
#include "intel_dpll_mgr.h"
/**
@@ -147,6 +149,16 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
pll->info->name, onoff(state), onoff(cur_state));
}
+static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
+{
+ return TC_PORT_1 + id - DPLL_ID_ICL_MGPLL1;
+}
+
+enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port)
+{
+ return tc_port - TC_PORT_1 + DPLL_ID_ICL_MGPLL1;
+}
+
static i915_reg_t
intel_combo_pll_enable_reg(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
@@ -159,6 +171,19 @@ intel_combo_pll_enable_reg(struct drm_i915_private *i915,
return CNL_DPLL_ENABLE(pll->info->id);
}
+static i915_reg_t
+intel_tc_pll_enable_reg(struct drm_i915_private *i915,
+ struct intel_shared_dpll *pll)
+{
+ const enum intel_dpll_id id = pll->info->id;
+ enum tc_port tc_port = icl_pll_id_to_tc_port(id);
+
+ if (IS_ALDERLAKE_P(i915))
+ return ADLP_PORTTC_PLL_ENABLE(tc_port);
+
+ return MG_PLL_ENABLE(tc_port);
+}
+
/**
* intel_prepare_shared_dpll - call a dpll's prepare hook
* @crtc_state: CRTC, and its state, which has a shared dpll
@@ -3118,16 +3143,6 @@ static void icl_calc_dpll_state(struct drm_i915_private *i915,
pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400;
}
-static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
-{
- return id - DPLL_ID_ICL_MGPLL1;
-}
-
-enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port)
-{
- return tc_port + DPLL_ID_ICL_MGPLL1;
-}
-
static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
u32 *target_dco_khz,
struct intel_dpll_hw_state *state,
@@ -3726,12 +3741,14 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
bool ret = false;
u32 val;
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
+
wakeref = intel_display_power_get_if_enabled(dev_priv,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, MG_PLL_ENABLE(tc_port));
+ val = intel_de_read(dev_priv, enable_reg);
if (!(val & PLL_ENABLE))
goto out;
@@ -3795,7 +3812,7 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, MG_PLL_ENABLE(tc_port));
+ val = intel_de_read(dev_priv, intel_tc_pll_enable_reg(dev_priv, pll));
if (!(val & PLL_ENABLE))
goto out;
@@ -4167,8 +4184,7 @@ static void tbt_pll_enable(struct drm_i915_private *dev_priv,
static void mg_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg =
- MG_PLL_ENABLE(icl_pll_id_to_tc_port(pll->info->id));
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
icl_pll_power_enable(dev_priv, pll, enable_reg);
@@ -4247,8 +4263,7 @@ static void tbt_pll_disable(struct drm_i915_private *dev_priv,
static void mg_pll_disable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg =
- MG_PLL_ENABLE(icl_pll_id_to_tc_port(pll->info->id));
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
icl_pll_disable(dev_priv, pll, enable_reg);
}
@@ -4414,6 +4429,26 @@ static const struct intel_dpll_mgr adls_pll_mgr = {
.dump_hw_state = icl_dump_hw_state,
};
+static const struct dpll_info adlp_plls[] = {
+ { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
+ { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
+ { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 },
+ { "TC PLL 1", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
+ { "TC PLL 2", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
+ { "TC PLL 3", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
+ { "TC PLL 4", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
+ { },
+};
+
+static const struct intel_dpll_mgr adlp_pll_mgr = {
+ .dpll_info = adlp_plls,
+ .get_dplls = icl_get_dplls,
+ .put_dplls = icl_put_dplls,
+ .update_active_dpll = icl_update_active_dpll,
+ .update_ref_clks = icl_update_dpll_ref_clks,
+ .dump_hw_state = icl_dump_hw_state,
+};
+
/**
* intel_shared_dpll_init - Initialize shared DPLLs
* @dev: drm device
@@ -4427,7 +4462,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
const struct dpll_info *dpll_info;
int i;
- if (IS_ALDERLAKE_S(dev_priv))
+ if (IS_ALDERLAKE_P(dev_priv))
+ dpll_mgr = &adlp_pll_mgr;
+ else if (IS_ALDERLAKE_S(dev_priv))
dpll_mgr = &adls_pll_mgr;
else if (IS_DG1(dev_priv))
dpll_mgr = &dg1_pll_mgr;
@@ -4441,10 +4478,10 @@ void intel_shared_dpll_init(struct drm_device *dev)
dpll_mgr = &icl_pll_mgr;
else if (IS_CANNONLAKE(dev_priv))
dpll_mgr = &cnl_pll_mgr;
- else if (IS_GEN9_BC(dev_priv))
- dpll_mgr = &skl_pll_mgr;
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
dpll_mgr = &bxt_pll_mgr;
+ else if (DISPLAY_VER(dev_priv) == 9)
+ dpll_mgr = &skl_pll_mgr;
else if (HAS_DDI(dev_priv))
dpll_mgr = &hsw_pll_mgr;
else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index 857126822a88..62a8a69f9f5d 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -5,6 +5,7 @@
*/
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#define DSB_BUF_SIZE (2 * PAGE_SIZE)
diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h
index 625f2f1ae061..50d6da0b2419 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -124,6 +124,7 @@ struct intel_dsi {
u16 panel_on_delay;
u16 panel_off_delay;
u16 panel_pwr_cycle_delay;
+ ktime_t panel_power_off_time;
};
struct intel_dsi_host {
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c
index 090cd76266c6..77419f8c05e9 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -33,6 +33,7 @@
#include "i915_drv.h"
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dvo.h"
#include "intel_dvo_dev.h"
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index fca41ac5b8e1..c60a81a81c09 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -30,14 +30,6 @@ bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane)
plane == 2;
}
-bool is_aux_plane(const struct drm_framebuffer *fb, int plane)
-{
- if (is_ccs_modifier(fb->modifier))
- return is_ccs_plane(fb, plane);
-
- return plane == 1;
-}
-
bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane)
{
return intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
@@ -84,7 +76,7 @@ int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
unsigned int intel_tile_size(const struct drm_i915_private *i915)
{
- return IS_DISPLAY_VER(i915, 2) ? 2048 : 4096;
+ return DISPLAY_VER(i915) == 2 ? 2048 : 4096;
}
unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
@@ -171,17 +163,17 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
*vsub = 32;
}
-static void intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane)
+static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h)
{
- int main_plane = is_ccs_plane(fb, color_plane) ?
- skl_ccs_to_main_plane(fb, color_plane) : 0;
+ int main_plane = is_ccs_plane(&fb->base, color_plane) ?
+ skl_ccs_to_main_plane(&fb->base, color_plane) : 0;
int main_hsub, main_vsub;
int hsub, vsub;
- intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, main_plane);
- intel_fb_plane_get_subsampling(&hsub, &vsub, fb, color_plane);
- *w = fb->width / main_hsub / hsub;
- *h = fb->height / main_vsub / vsub;
+ intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane);
+ intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane);
+ *w = fb->base.width / main_hsub / hsub;
+ *h = fb->base.height / main_vsub / vsub;
}
static u32 intel_adjust_tile_offset(int *x, int *y,
@@ -363,8 +355,17 @@ static int intel_fb_offset_to_xy(int *x, int *y,
unsigned int height;
u32 alignment;
- if (DISPLAY_VER(i915) >= 12 &&
- is_semiplanar_uv_plane(fb, color_plane))
+ /*
+ * All DPT color planes must be 512*4k aligned (the amount mapped by a
+ * single DPT page). For ADL_P CCS FBs this only works by requiring
+ * the allocated offsets to be 2MB aligned. Once supoort to remap
+ * such FBs is added we can remove this requirement, as then all the
+ * planes can be remapped to an aligned offset.
+ */
+ if (IS_ALDERLAKE_P(i915) && is_ccs_modifier(fb->modifier))
+ alignment = 512 * 4096;
+ else if (DISPLAY_VER(i915) >= 12 &&
+ is_semiplanar_uv_plane(fb, color_plane))
alignment = intel_tile_row_size(fb, color_plane);
else if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
alignment = intel_tile_size(i915);
@@ -486,9 +487,12 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
return true;
}
-static bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
+bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
{
- return false;
+ struct drm_i915_private *i915 = to_i915(fb->base.dev);
+
+ return IS_ALDERLAKE_P(i915) && fb->base.modifier != DRM_FORMAT_MOD_LINEAR &&
+ !is_ccs_modifier(fb->base.modifier);
}
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
@@ -609,7 +613,11 @@ plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane,
unsigned int pitch_tiles)
{
if (intel_fb_needs_pot_stride_remap(fb))
- return roundup_pow_of_two(pitch_tiles);
+ /*
+ * ADL_P, the only platform needing a POT stride has a minimum
+ * of 8 stride tiles.
+ */
+ return roundup_pow_of_two(max(pitch_tiles, 8u));
else
return pitch_tiles;
}
@@ -743,19 +751,34 @@ static void intel_fb_view_init(struct intel_fb_view *view, enum i915_ggtt_view_t
view->gtt.type = view_type;
}
-int intel_fill_fb_info(struct drm_i915_private *i915, struct drm_framebuffer *fb)
+bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb)
{
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ if (DISPLAY_VER(to_i915(fb->base.dev)) >= 13)
+ return false;
+
+ return fb->base.modifier == I915_FORMAT_MOD_Y_TILED ||
+ fb->base.modifier == I915_FORMAT_MOD_Yf_TILED;
+}
+
+int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb)
+{
+ struct drm_i915_gem_object *obj = intel_fb_obj(&fb->base);
u32 gtt_offset_rotated = 0;
u32 gtt_offset_remapped = 0;
unsigned int max_size = 0;
- int i, num_planes = fb->format->num_planes;
+ int i, num_planes = fb->base.format->num_planes;
unsigned int tile_size = intel_tile_size(i915);
- intel_fb_view_init(&intel_fb->normal_view, I915_GGTT_VIEW_NORMAL);
- intel_fb_view_init(&intel_fb->rotated_view, I915_GGTT_VIEW_ROTATED);
- intel_fb_view_init(&intel_fb->remapped_view, I915_GGTT_VIEW_REMAPPED);
+ intel_fb_view_init(&fb->normal_view, I915_GGTT_VIEW_NORMAL);
+
+ drm_WARN_ON(&i915->drm,
+ intel_fb_supports_90_270_rotation(fb) &&
+ intel_fb_needs_pot_stride_remap(fb));
+
+ if (intel_fb_supports_90_270_rotation(fb))
+ intel_fb_view_init(&fb->rotated_view, I915_GGTT_VIEW_ROTATED);
+ if (intel_fb_needs_pot_stride_remap(fb))
+ intel_fb_view_init(&fb->remapped_view, I915_GGTT_VIEW_REMAPPED);
for (i = 0; i < num_planes; i++) {
struct fb_plane_view_dims view_dims;
@@ -770,45 +793,43 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct drm_framebuffer *fb
* is consumed by the driver and not passed to DE. Skip the
* arithmetic related to alignment and offset calculation.
*/
- if (is_gen12_ccs_cc_plane(fb, i)) {
- if (IS_ALIGNED(fb->offsets[i], PAGE_SIZE))
+ if (is_gen12_ccs_cc_plane(&fb->base, i)) {
+ if (IS_ALIGNED(fb->base.offsets[i], PAGE_SIZE))
continue;
else
return -EINVAL;
}
- cpp = fb->format->cpp[i];
- intel_fb_plane_dims(&width, &height, fb, i);
+ cpp = fb->base.format->cpp[i];
+ intel_fb_plane_dims(fb, i, &width, &height);
- ret = convert_plane_offset_to_xy(intel_fb, i, width, &x, &y);
+ ret = convert_plane_offset_to_xy(fb, i, width, &x, &y);
if (ret)
return ret;
- init_plane_view_dims(intel_fb, i, width, height, &view_dims);
+ init_plane_view_dims(fb, i, width, height, &view_dims);
/*
* First pixel of the framebuffer from
* the start of the normal gtt mapping.
*/
- intel_fb->normal_view.color_plane[i].x = x;
- intel_fb->normal_view.color_plane[i].y = y;
- intel_fb->normal_view.color_plane[i].stride = intel_fb->base.pitches[i];
+ fb->normal_view.color_plane[i].x = x;
+ fb->normal_view.color_plane[i].y = y;
+ fb->normal_view.color_plane[i].stride = fb->base.pitches[i];
- offset = calc_plane_aligned_offset(intel_fb, i, &x, &y);
+ offset = calc_plane_aligned_offset(fb, i, &x, &y);
- /* Y or Yf modifiers required for 90/270 rotation */
- if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier == I915_FORMAT_MOD_Yf_TILED)
- gtt_offset_rotated += calc_plane_remap_info(intel_fb, i, &view_dims,
+ if (intel_fb_supports_90_270_rotation(fb))
+ gtt_offset_rotated += calc_plane_remap_info(fb, i, &view_dims,
offset, gtt_offset_rotated, x, y,
- &intel_fb->rotated_view);
+ &fb->rotated_view);
- if (intel_fb_needs_pot_stride_remap(intel_fb))
- gtt_offset_remapped += calc_plane_remap_info(intel_fb, i, &view_dims,
+ if (intel_fb_needs_pot_stride_remap(fb))
+ gtt_offset_remapped += calc_plane_remap_info(fb, i, &view_dims,
offset, gtt_offset_remapped, x, y,
- &intel_fb->remapped_view);
+ &fb->remapped_view);
- size = calc_plane_normal_size(intel_fb, i, &view_dims, x, y);
+ size = calc_plane_normal_size(fb, i, &view_dims, x, y);
/* how many tiles in total needed in the bo */
max_size = max(max_size, offset + size);
}
diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h
index 6acf792a8c44..739d1b91754b 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fb.h
@@ -19,7 +19,6 @@ struct intel_plane_state;
bool is_ccs_plane(const struct drm_framebuffer *fb, int plane);
bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane);
bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane);
-bool is_aux_plane(const struct drm_framebuffer *fb, int plane);
bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane);
bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane);
@@ -46,7 +45,10 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
int color_plane);
-int intel_fill_fb_info(struct drm_i915_private *i915, struct drm_framebuffer *fb);
+bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb);
+bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb);
+
+int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb);
void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation,
struct intel_fb_view *view);
int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 957252b695d7..1847a161cb37 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -43,6 +43,7 @@
#include "i915_drv.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
@@ -67,7 +68,7 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
int lines;
intel_fbc_get_plane_source_size(cache, NULL, &lines);
- if (IS_DISPLAY_VER(dev_priv, 7))
+ if (DISPLAY_VER(dev_priv) == 7)
lines = min(lines, 2048);
else if (DISPLAY_VER(dev_priv) >= 8)
lines = min(lines, 2560);
@@ -109,7 +110,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
cfb_pitch = params->fb.stride;
/* FBC_CTL wants 32B or 64B units */
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
cfb_pitch = (cfb_pitch / 32) - 1;
else
cfb_pitch = (cfb_pitch / 64) - 1;
@@ -118,7 +119,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
intel_de_write(dev_priv, FBC_TAG(i), 0);
- if (IS_DISPLAY_VER(dev_priv, 4)) {
+ if (DISPLAY_VER(dev_priv) == 4) {
u32 fbc_ctl2;
/* Set it up... */
@@ -302,7 +303,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
int threshold = dev_priv->fbc.threshold;
/* Display WA #0529: skl, kbl, bxt. */
- if (IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) == 9) {
u32 val = intel_de_read(dev_priv, CHICKEN_MISC_4);
val &= ~(FBC_STRIDE_OVERRIDE | FBC_STRIDE_MASK);
@@ -445,7 +446,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
* reserved range size, so it always assumes the maximum (8mb) is used.
* If we enable FBC using a CFB on that memory range we'll get FIFO
* underruns, even if that range is not reserved by the BIOS. */
- if (IS_BROADWELL(dev_priv) || IS_GEN9_BC(dev_priv))
+ if (IS_BROADWELL(dev_priv) || (DISPLAY_VER(dev_priv) == 9 &&
+ !IS_BROXTON(dev_priv)))
end = resource_size(&dev_priv->dsm) - 8 * 1024 * 1024;
else
end = U64_MAX;
@@ -590,14 +592,14 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv,
if (stride < 512)
return false;
- if (IS_DISPLAY_VER(dev_priv, 2) || IS_DISPLAY_VER(dev_priv, 3))
+ if (DISPLAY_VER(dev_priv) == 2 || DISPLAY_VER(dev_priv) == 3)
return stride == 4096 || stride == 8192;
- if (IS_DISPLAY_VER(dev_priv, 4) && !IS_G4X(dev_priv) && stride < 2048)
+ if (DISPLAY_VER(dev_priv) == 4 && !IS_G4X(dev_priv) && stride < 2048)
return false;
/* Display WA #1105: skl,bxt,kbl,cfl,glk */
- if ((IS_DISPLAY_VER(dev_priv, 9) || IS_GEMINILAKE(dev_priv)) &&
+ if ((DISPLAY_VER(dev_priv) == 9 || IS_GEMINILAKE(dev_priv)) &&
modifier == DRM_FORMAT_MOD_LINEAR && stride & 511)
return false;
@@ -617,7 +619,7 @@ static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_RGB565:
/* 16bpp not supported on gen2 */
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
return false;
/* WaFbcOnly1to1Ratio:ctg */
if (IS_G4X(dev_priv))
@@ -735,11 +737,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
cache->fence_y_offset = intel_plane_fence_y_offset(plane_state);
drm_WARN_ON(&dev_priv->drm, plane_state->flags & PLANE_HAS_FENCE &&
- !plane_state->vma->fence);
+ !plane_state->ggtt_vma->fence);
if (plane_state->flags & PLANE_HAS_FENCE &&
- plane_state->vma->fence)
- cache->fence_id = plane_state->vma->fence->id;
+ plane_state->ggtt_vma->fence)
+ cache->fence_id = plane_state->ggtt_vma->fence->id;
else
cache->fence_id = -1;
@@ -759,7 +761,7 @@ static u16 intel_fbc_gen9_wa_cfb_stride(struct drm_i915_private *dev_priv)
struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache;
- if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) &&
+ if ((DISPLAY_VER(dev_priv) == 9) &&
cache->fb.modifier != I915_FORMAT_MOD_X_TILED)
return DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8;
else
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index ccd00e65a5fe..4af40229f5ec 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -41,6 +41,8 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
+#include "gem/i915_gem_lmem.h"
+
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_fbdev.h"
@@ -137,14 +139,22 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
- /* If the FB is too big, just don't use it since fbdev is not very
- * important and we should probably use that space with FBC or other
- * features. */
obj = ERR_PTR(-ENODEV);
- if (size * 2 < dev_priv->stolen_usable_size)
- obj = i915_gem_object_create_stolen(dev_priv, size);
- if (IS_ERR(obj))
- obj = i915_gem_object_create_shmem(dev_priv, size);
+ if (HAS_LMEM(dev_priv)) {
+ obj = i915_gem_object_create_lmem(dev_priv, size,
+ I915_BO_ALLOC_CONTIGUOUS);
+ } else {
+ /*
+ * If the FB is too big, just don't use it since fbdev is not very
+ * important and we should probably use that space with FBC or other
+ * features.
+ */
+ if (size * 2 < dev_priv->stolen_usable_size)
+ obj = i915_gem_object_create_stolen(dev_priv, size);
+ if (IS_ERR(obj))
+ obj = i915_gem_object_create_shmem(dev_priv, size);
+ }
+
if (IS_ERR(obj)) {
drm_err(&dev_priv->drm, "failed to allocate framebuffer\n");
return PTR_ERR(obj);
@@ -178,6 +188,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
unsigned long flags = 0;
bool prealloc = false;
void __iomem *vaddr;
+ struct drm_i915_gem_object *obj;
int ret;
if (intel_fb &&
@@ -232,13 +243,27 @@ static int intelfb_create(struct drm_fb_helper *helper,
info->fbops = &intelfb_ops;
/* setup aperture base/size for vesafb takeover */
- info->apertures->ranges[0].base = ggtt->gmadr.start;
- info->apertures->ranges[0].size = ggtt->mappable_end;
+ obj = intel_fb_obj(&intel_fb->base);
+ if (i915_gem_object_is_lmem(obj)) {
+ struct intel_memory_region *mem = obj->mm.region;
+
+ info->apertures->ranges[0].base = mem->io_start;
+ info->apertures->ranges[0].size = mem->total;
+
+ /* Use fbdev's framebuffer from lmem for discrete */
+ info->fix.smem_start =
+ (unsigned long)(mem->io_start +
+ i915_gem_object_get_dma_address(obj, 0));
+ info->fix.smem_len = obj->base.size;
+ } else {
+ info->apertures->ranges[0].base = ggtt->gmadr.start;
+ info->apertures->ranges[0].size = ggtt->mappable_end;
- /* Our framebuffer is the entirety of fbdev's system memory */
- info->fix.smem_start =
- (unsigned long)(ggtt->gmadr.start + vma->node.start);
- info->fix.smem_len = vma->node.size;
+ /* Our framebuffer is the entirety of fbdev's system memory */
+ info->fix.smem_start =
+ (unsigned long)(ggtt->gmadr.start + vma->node.start);
+ info->fix.smem_len = vma->node.size;
+ }
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index d719cd9c5b73..cef1061fd6cb 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -5,6 +5,7 @@
#include "intel_atomic.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
index 9605a1064366..eb841960840d 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
@@ -27,6 +27,7 @@
#include "i915_drv.h"
#include "i915_trace.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_fifo_underrun.h"
@@ -184,15 +185,34 @@ static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
}
}
+static u32
+icl_pipe_status_underrun_mask(struct drm_i915_private *dev_priv)
+{
+ u32 mask = PIPE_STATUS_UNDERRUN;
+
+ if (DISPLAY_VER(dev_priv) >= 13)
+ mask |= PIPE_STATUS_SOFT_UNDERRUN_XELPD |
+ PIPE_STATUS_HARD_UNDERRUN_XELPD |
+ PIPE_STATUS_PORT_UNDERRUN_XELPD;
+
+ return mask;
+}
+
static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ u32 mask = gen8_de_pipe_underrun_mask(dev_priv);
- if (enable)
- bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
- else
- bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
+ if (enable) {
+ if (DISPLAY_VER(dev_priv) >= 11)
+ intel_de_write(dev_priv, ICL_PIPESTATUS(pipe),
+ icl_pipe_status_underrun_mask(dev_priv));
+
+ bdw_enable_pipe_irq(dev_priv, pipe, mask);
+ } else {
+ bdw_disable_pipe_irq(dev_priv, pipe, mask);
+ }
}
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
@@ -271,7 +291,7 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv))
ilk_set_fifo_underrun_reporting(dev, pipe, enable);
- else if (IS_DISPLAY_VER(dev_priv, 7))
+ else if (DISPLAY_VER(dev_priv) == 7)
ivb_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (DISPLAY_VER(dev_priv) >= 8)
bdw_set_fifo_underrun_reporting(dev, pipe, enable);
@@ -372,6 +392,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+ u32 underruns = 0;
/* We may be called too early in init, thanks BIOS! */
if (crtc == NULL)
@@ -382,10 +403,35 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
crtc->cpu_fifo_underrun_disabled)
return;
+ /*
+ * Starting with display version 11, the PIPE_STAT register records
+ * whether an underrun has happened, and on XELPD+, it will also record
+ * whether the underrun was soft/hard and whether it was triggered by
+ * the downstream port logic. We should clear these bits (which use
+ * write-1-to-clear logic) too.
+ *
+ * Note that although the IIR gives us the same underrun and soft/hard
+ * information, PIPE_STAT is the only place we can find out whether
+ * the underrun was caused by the downstream port.
+ */
+ if (DISPLAY_VER(dev_priv) >= 11) {
+ underruns = intel_de_read(dev_priv, ICL_PIPESTATUS(pipe)) &
+ icl_pipe_status_underrun_mask(dev_priv);
+ intel_de_write(dev_priv, ICL_PIPESTATUS(pipe), underruns);
+ }
+
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
- drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n",
- pipe_name(pipe));
+
+ if (DISPLAY_VER(dev_priv) >= 11)
+ drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun: %s%s%s%s\n",
+ pipe_name(pipe),
+ underruns & PIPE_STATUS_SOFT_UNDERRUN_XELPD ? "soft," : "",
+ underruns & PIPE_STATUS_HARD_UNDERRUN_XELPD ? "hard," : "",
+ underruns & PIPE_STATUS_PORT_UNDERRUN_XELPD ? "port," : "",
+ underruns & PIPE_STATUS_UNDERRUN ? "transcoder," : "");
+ else
+ drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
}
intel_fbc_handle_fifo_underrun_irq(dev_priv);
@@ -432,7 +478,7 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
if (HAS_GMCH(dev_priv))
i9xx_check_fifo_underruns(crtc);
- else if (IS_DISPLAY_VER(dev_priv, 7))
+ else if (DISPLAY_VER(dev_priv) == 7)
ivb_check_fifo_underruns(crtc);
}
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 6fc6965b6133..8e75debcce1a 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -58,6 +58,7 @@
#include "display/intel_dp.h"
#include "i915_drv.h"
+#include "i915_trace.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
@@ -87,6 +88,8 @@ static void frontbuffer_flush(struct drm_i915_private *i915,
if (!frontbuffer_bits)
return;
+ trace_intel_frontbuffer_flush(frontbuffer_bits, origin);
+
might_sleep();
intel_edp_drrs_flush(i915, frontbuffer_bits);
intel_psr_flush(i915, frontbuffer_bits, origin);
@@ -173,6 +176,8 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front,
spin_unlock(&i915->fb_tracking.lock);
}
+ trace_intel_frontbuffer_invalidate(frontbuffer_bits, origin);
+
might_sleep();
intel_psr_invalidate(i915, frontbuffer_bits, origin);
intel_edp_drrs_invalidate(i915, frontbuffer_bits);
@@ -206,7 +211,6 @@ static int frontbuffer_active(struct i915_active *ref)
return 0;
}
-__i915_active_call
static void frontbuffer_retire(struct i915_active *ref)
{
struct intel_frontbuffer *front =
@@ -261,7 +265,8 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
atomic_set(&front->bits, 0);
i915_active_init(&front->write,
frontbuffer_active,
- i915_active_may_sleep(frontbuffer_retire));
+ frontbuffer_retire,
+ I915_ACTIVE_RETIRE_SLEEPS);
spin_lock(&i915->fb_tracking.lock);
if (rcu_access_pointer(obj->frontbuffer)) {
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 8ddc20daef64..fcf47f98ea36 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -34,6 +34,7 @@
#include <drm/drm_hdcp.h>
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"
@@ -107,9 +108,9 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
return &gmbus_pins_icp[pin];
else if (HAS_PCH_CNP(dev_priv))
return &gmbus_pins_cnp[pin];
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
return &gmbus_pins_bxt[pin];
- else if (IS_GEN9_BC(dev_priv))
+ else if (DISPLAY_VER(dev_priv) == 9)
return &gmbus_pins_skl[pin];
else if (IS_BROADWELL(dev_priv))
return &gmbus_pins_bdw[pin];
@@ -128,9 +129,9 @@ bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
size = ARRAY_SIZE(gmbus_pins_icp);
else if (HAS_PCH_CNP(dev_priv))
size = ARRAY_SIZE(gmbus_pins_cnp);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
size = ARRAY_SIZE(gmbus_pins_bxt);
- else if (IS_GEN9_BC(dev_priv))
+ else if (DISPLAY_VER(dev_priv) == 9)
size = ARRAY_SIZE(gmbus_pins_skl);
else if (IS_BROADWELL(dev_priv))
size = ARRAY_SIZE(gmbus_pins_bdw);
@@ -600,7 +601,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
int ret = 0;
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, false);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
pch_gmbus_clock_gating(dev_priv, false);
@@ -713,7 +714,7 @@ timeout:
out:
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_gmbus_clock_gating(dev_priv, true);
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
pch_gmbus_clock_gating(dev_priv, true);
@@ -845,9 +846,6 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv)
unsigned int pin;
int ret;
- if (!HAS_DISPLAY(dev_priv))
- return 0;
-
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
else if (!HAS_GMCH(dev_priv))
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index d8570e14fe60..ebc2e32aec0b 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -18,6 +18,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_display_power.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_hdcp.h"
#include "intel_sideband.h"
@@ -286,11 +287,12 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
/*
* Initiate loading the HDCP key from fuses.
*
- * BXT+ platforms, HDCP key needs to be loaded by SW. Only Gen 9
- * platforms except BXT and GLK, differ in the key load trigger process
- * from other platforms. So GEN9_BC uses the GT Driver Mailbox i/f.
+ * BXT+ platforms, HDCP key needs to be loaded by SW. Only display
+ * version 9 platforms (minus BXT) differ in the key load trigger
+ * process from other platforms. These platforms use the GT Driver
+ * Mailbox interface.
*/
- if (IS_GEN9_BC(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
ret = sandybridge_pcode_write(dev_priv,
SKL_PCODE_LOAD_HDCP_KEYS, 1);
if (ret) {
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index d69f0a6dc26d..7e51c98c475e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -43,6 +43,7 @@
#include "intel_atomic.h"
#include "intel_connector.h"
#include "intel_ddi.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_gmbus.h"
@@ -531,6 +532,11 @@ void hsw_write_infoframe(struct intel_encoder *encoder,
hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2),
0);
+ /* Wa_14013475917 */
+ if (DISPLAY_VER(dev_priv) == 13 && crtc_state->has_psr &&
+ type == DP_SDP_VSC)
+ return;
+
val |= hsw_infoframe_enable(type);
intel_de_write(dev_priv, ctl_reg, val);
intel_de_posting_read(dev_priv, ctl_reg);
@@ -542,11 +548,9 @@ void hsw_read_infoframe(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- u32 val, *data = frame;
+ u32 *data = frame;
int i;
- val = intel_de_read(dev_priv, HSW_TVIDEO_DIP_CTL(cpu_transcoder));
-
for (i = 0; i < len; i += 4)
*data++ = intel_de_read(dev_priv,
hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2));
@@ -1251,8 +1255,7 @@ void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n",
enable ? "Enabling" : "Disabling");
- drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type,
- adapter, enable);
+ drm_dp_dual_mode_set_tmds_output(&dev_priv->drm, hdmi->dp_dual_mode.type, adapter, enable);
}
static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
@@ -1841,7 +1844,8 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
return MODE_CLOCK_RANGE;
/* BXT/GLK DPLL can't generate 223-240 MHz */
- if (IS_GEN9_LP(dev_priv) && clock > 223333 && clock < 240000)
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ clock > 223333 && clock < 240000)
return MODE_CLOCK_RANGE;
/* CHV DPLL can't generate 216-240 MHz */
@@ -1861,6 +1865,73 @@ static int intel_hdmi_port_clock(int clock, int bpc)
return clock * bpc / 8;
}
+static bool intel_hdmi_bpc_possible(struct drm_connector *connector,
+ int bpc, bool has_hdmi_sink, bool ycbcr420_output)
+{
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+ const struct drm_display_info *info = &connector->display_info;
+ const struct drm_hdmi_info *hdmi = &info->hdmi;
+
+ switch (bpc) {
+ case 12:
+ if (HAS_GMCH(i915))
+ return false;
+
+ if (!has_hdmi_sink)
+ return false;
+
+ if (ycbcr420_output)
+ return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
+ else
+ return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36;
+ case 10:
+ if (DISPLAY_VER(i915) < 11)
+ return false;
+
+ if (!has_hdmi_sink)
+ return false;
+
+ if (ycbcr420_output)
+ return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
+ else
+ return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30;
+ case 8:
+ return true;
+ default:
+ MISSING_CASE(bpc);
+ return false;
+ }
+}
+
+static enum drm_mode_status
+intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
+ bool has_hdmi_sink, bool ycbcr420_output)
+{
+ struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
+ enum drm_mode_status status;
+
+ if (ycbcr420_output)
+ clock /= 2;
+
+ /* check if we can do 8bpc */
+ status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 8),
+ true, has_hdmi_sink);
+
+ /* if we can't do 8bpc we may still be able to do 12bpc */
+ if (status != MODE_OK &&
+ intel_hdmi_bpc_possible(connector, 12, has_hdmi_sink, ycbcr420_output))
+ status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12),
+ true, has_hdmi_sink);
+
+ /* if we can't do 8,12bpc we may still be able to do 10bpc */
+ if (status != MODE_OK &&
+ intel_hdmi_bpc_possible(connector, 10, has_hdmi_sink, ycbcr420_output))
+ status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10),
+ true, has_hdmi_sink);
+
+ return status;
+}
+
static enum drm_mode_status
intel_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
@@ -1872,6 +1943,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
int clock = mode->clock;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state);
+ bool ycbcr_420_only;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -1888,26 +1960,19 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
clock *= 2;
}
- if (drm_mode_is_420_only(&connector->display_info, mode))
- clock /= 2;
-
- /* check if we can do 8bpc */
- status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 8),
- true, has_hdmi_sink);
+ ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode);
- if (has_hdmi_sink) {
- /* if we can't do 8bpc we may still be able to do 12bpc */
- if (status != MODE_OK && !HAS_GMCH(dev_priv))
- status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 12),
- true, has_hdmi_sink);
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, ycbcr_420_only);
+ if (status != MODE_OK) {
+ if (ycbcr_420_only ||
+ !connector->ycbcr_420_allowed ||
+ !drm_mode_is_420_also(&connector->display_info, mode))
+ return status;
- /* if we can't do 8,12bpc we may still be able to do 10bpc */
- if (status != MODE_OK && DISPLAY_VER(dev_priv) >= 11)
- status = hdmi_port_clock_valid(hdmi, intel_hdmi_port_clock(clock, 10),
- true, has_hdmi_sink);
+ status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, true);
+ if (status != MODE_OK)
+ return status;
}
- if (status != MODE_OK)
- return status;
return intel_mode_valid_max_plane_size(dev_priv, mode, false);
}
@@ -1923,32 +1988,12 @@ bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
if (crtc_state->pipe_bpp < bpc * 3)
return false;
- if (!has_hdmi_sink)
- return false;
-
for_each_new_connector_in_state(state, connector, connector_state, i) {
- const struct drm_display_info *info = &connector->display_info;
-
if (connector_state->crtc != crtc_state->uapi.crtc)
continue;
- if (ycbcr420_output) {
- const struct drm_hdmi_info *hdmi = &info->hdmi;
-
- if (bpc == 12 && !(hdmi->y420_dc_modes &
- DRM_EDID_YCBCR420_DC_36))
- return false;
- else if (bpc == 10 && !(hdmi->y420_dc_modes &
- DRM_EDID_YCBCR420_DC_30))
- return false;
- } else {
- if (bpc == 12 && !(info->edid_hdmi_dc_modes &
- DRM_EDID_HDMI_DC_36))
- return false;
- else if (bpc == 10 && !(info->edid_hdmi_dc_modes &
- DRM_EDID_HDMI_DC_30))
- return false;
- }
+ if (!intel_hdmi_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output))
+ return false;
}
return true;
@@ -1962,12 +2007,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
- if (HAS_GMCH(dev_priv))
- return false;
-
- if (bpc == 10 && DISPLAY_VER(dev_priv) < 11)
- return false;
-
/*
* HDMI deep color affects the clocks, so it's only possible
* when not cloning with other encoder types.
@@ -1977,7 +2016,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
/* Display Wa_1405510057:icl,ehl */
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
- bpc == 10 && IS_DISPLAY_VER(dev_priv, 11) &&
+ bpc == 10 && DISPLAY_VER(dev_priv) == 11 &&
(adjusted_mode->crtc_hblank_end -
adjusted_mode->crtc_hblank_start) % 8 == 2)
return false;
@@ -1988,29 +2027,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
-static int
-intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
-{
- struct drm_connector *connector = conn_state->connector;
- struct drm_i915_private *i915 = to_i915(connector->dev);
- const struct drm_display_mode *adjusted_mode =
- &crtc_state->hw.adjusted_mode;
-
- if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
- return 0;
-
- if (!connector->ycbcr_420_allowed) {
- drm_err(&i915->drm,
- "Platform doesn't support YCBCR420 output\n");
- return -EINVAL;
- }
-
- crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
-
- return intel_pch_panel_fitting(crtc_state, conn_state);
-}
-
static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int clock)
@@ -2117,6 +2133,39 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
+static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct drm_connector *connector = conn_state->connector;
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int ret;
+ bool ycbcr_420_only;
+
+ ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, adjusted_mode);
+ if (connector->ycbcr_420_allowed && ycbcr_420_only) {
+ crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ } else {
+ if (!connector->ycbcr_420_allowed && ycbcr_420_only)
+ drm_dbg_kms(&i915->drm,
+ "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
+ crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
+ }
+
+ ret = intel_hdmi_compute_clock(encoder, crtc_state);
+ if (ret) {
+ if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 &&
+ connector->ycbcr_420_allowed &&
+ drm_mode_is_420_also(&connector->display_info, adjusted_mode)) {
+ crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+ ret = intel_hdmi_compute_clock(encoder, crtc_state);
+ }
+ }
+
+ return ret;
+}
+
int intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
@@ -2141,23 +2190,25 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
pipe_config->pixel_multiplier = 2;
- ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state);
- if (ret)
- return ret;
-
- pipe_config->limited_color_range =
- intel_hdmi_limited_color_range(pipe_config, conn_state);
-
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
pipe_config->has_pch_encoder = true;
pipe_config->has_audio =
intel_hdmi_has_audio(encoder, pipe_config, conn_state);
- ret = intel_hdmi_compute_clock(encoder, pipe_config);
+ ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state);
if (ret)
return ret;
+ if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
+ ret = intel_pch_panel_fitting(pipe_config, conn_state);
+ if (ret)
+ return ret;
+ }
+
+ pipe_config->limited_color_range =
+ intel_hdmi_limited_color_range(pipe_config, conn_state);
+
if (conn_state->picture_aspect_ratio)
adjusted_mode->picture_aspect_ratio =
conn_state->picture_aspect_ratio;
@@ -2223,7 +2274,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
enum port port = hdmi_to_dig_port(hdmi)->base.port;
struct i2c_adapter *adapter =
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
- enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter);
+ enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(&dev_priv->drm, adapter);
/*
* Type 1 DVI adaptors are not required to implement any
@@ -2256,7 +2307,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
hdmi->dp_dual_mode.type = type;
hdmi->dp_dual_mode.max_tmds_clock =
- drm_dp_dual_mode_max_tmds_clock(type, adapter);
+ drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, adapter);
drm_dbg_kms(&dev_priv->drm,
"DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",
@@ -2460,8 +2511,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
drm_connector_attach_content_type_property(connector);
if (DISPLAY_VER(dev_priv) >= 10)
- drm_object_attach_property(&connector->base,
- connector->dev->mode_config.hdr_output_metadata_property, 0);
+ drm_connector_attach_hdr_output_metadata_property(connector);
if (!HAS_GMCH(dev_priv))
drm_connector_attach_max_bpc_property(connector, 8, 12);
@@ -2708,13 +2758,13 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
return ddc_pin;
}
- if (HAS_PCH_ADP(dev_priv))
+ if (IS_ALDERLAKE_S(dev_priv))
ddc_pin = adls_port_to_ddc_pin(dev_priv, port);
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
ddc_pin = dg1_port_to_ddc_pin(dev_priv, port);
else if (IS_ROCKETLAKE(dev_priv))
ddc_pin = rkl_port_to_ddc_pin(dev_priv, port);
- else if (IS_GEN9_BC(dev_priv) && HAS_PCH_TGP(dev_priv))
+ else if (DISPLAY_VER(dev_priv) == 9 && HAS_PCH_TGP(dev_priv))
ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port);
else if (HAS_PCH_MCC(dev_priv))
ddc_pin = mcc_port_to_ddc_pin(dev_priv, port);
@@ -2722,7 +2772,7 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
ddc_pin = icl_port_to_ddc_pin(dev_priv, port);
else if (HAS_PCH_CNP(dev_priv))
ddc_pin = cnp_port_to_ddc_pin(dev_priv, port);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
ddc_pin = bxt_port_to_ddc_pin(dev_priv, port);
else if (IS_CHERRYVIEW(dev_priv))
ddc_pin = chv_port_to_ddc_pin(dev_priv, port);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index f46a1b7190b8..47c85ac97c87 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -595,6 +595,9 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
{
int i;
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
for_each_hpd_pin(i) {
dev_priv->hotplug.stats[i].count = 0;
dev_priv->hotplug.stats[i].state = HPD_ENABLED;
@@ -670,6 +673,9 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
*/
void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
{
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
WRITE_ONCE(dev_priv->hotplug.poll_enabled, true);
/*
@@ -702,6 +708,9 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
*/
void intel_hpd_poll_disable(struct drm_i915_private *dev_priv)
{
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
WRITE_ONCE(dev_priv->hotplug.poll_enabled, false);
schedule_work(&dev_priv->hotplug.poll_init_work);
}
@@ -718,6 +727,9 @@ void intel_hpd_init_work(struct drm_i915_private *dev_priv)
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
{
+ if (!HAS_DISPLAY(dev_priv))
+ return;
+
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->hotplug.long_port_mask = 0;
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c
index e4ff533e3a69..05d2d750fa53 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -27,6 +27,7 @@
#include <drm/drm_dp_dual_mode_helper.h>
#include <drm/drm_edid.h>
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_lspcon.h"
@@ -139,10 +140,11 @@ void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon)
static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
{
+ struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
enum drm_lspcon_mode current_mode;
- struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+ struct i2c_adapter *adapter = &intel_dp->aux.ddc;
- if (drm_lspcon_get_mode(adapter, &current_mode)) {
+ if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode)) {
DRM_DEBUG_KMS("Error reading LSPCON mode\n");
return DRM_LSPCON_MODE_INVALID;
}
@@ -175,11 +177,12 @@ out:
static int lspcon_change_mode(struct intel_lspcon *lspcon,
enum drm_lspcon_mode mode)
{
+ struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
int err;
enum drm_lspcon_mode current_mode;
- struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+ struct i2c_adapter *adapter = &intel_dp->aux.ddc;
- err = drm_lspcon_get_mode(adapter, &current_mode);
+ err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode);
if (err) {
DRM_ERROR("Error reading LSPCON mode\n");
return err;
@@ -190,7 +193,7 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
return 0;
}
- err = drm_lspcon_set_mode(adapter, mode);
+ err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, adapter, mode);
if (err < 0) {
DRM_ERROR("LSPCON mode change failed\n");
return err;
@@ -221,7 +224,8 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
{
int retry;
enum drm_dp_dual_mode_type adaptor_type;
- struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+ struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
+ struct i2c_adapter *adapter = &intel_dp->aux.ddc;
enum drm_lspcon_mode expected_mode;
expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
@@ -232,7 +236,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
if (retry)
usleep_range(500, 1000);
- adaptor_type = drm_dp_dual_mode_detect(adapter);
+ adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, adapter);
if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON)
break;
}
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index f31a368f34c5..7f40e9f60bc2 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -41,6 +41,7 @@
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"
#include "intel_lvds.h"
@@ -280,7 +281,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
* special lvds dither control bit on pch-split platforms, dithering is
* only controlled through the PIPECONF reg.
*/
- if (IS_DISPLAY_VER(dev_priv, 4)) {
+ if (DISPLAY_VER(dev_priv) == 4) {
/*
* Bspec wording suggests that LVDS port dithering only exists
* for 18bpp panels.
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
index bbaf05515e88..7e3f5c6ca484 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -34,6 +34,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_frontbuffer.h"
#include "intel_overlay.h"
@@ -383,8 +384,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
i830_overlay_clock_gating(dev_priv, true);
}
-__i915_active_call static void
-intel_overlay_last_flip_retire(struct i915_active *active)
+static void intel_overlay_last_flip_retire(struct i915_active *active)
{
struct intel_overlay *overlay =
container_of(active, typeof(*overlay), last_flip);
@@ -550,7 +550,7 @@ static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 widt
{
u32 sw;
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
sw = ALIGN((offset & 31) + width, 32);
else
sw = ALIGN((offset & 63) + width, 64);
@@ -820,7 +820,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
oconfig |= OCONF_CC_OUT_8BIT;
if (crtc_state->gamma_enable)
oconfig |= OCONF_GAMMA2_ENABLE;
- if (IS_DISPLAY_VER(dev_priv, 4))
+ if (DISPLAY_VER(dev_priv) == 4)
oconfig |= OCONF_CSC_MODE_BT709;
oconfig |= pipe == 0 ?
OCONF_PIPE_A : OCONF_PIPE_B;
@@ -1054,7 +1054,7 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
return -EINVAL;
- if (IS_DISPLAY_VER(dev_priv, 4) && rec->stride_Y < 512)
+ if (DISPLAY_VER(dev_priv) == 4 && rec->stride_Y < 512)
return -EINVAL;
tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
@@ -1281,7 +1281,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
attrs->contrast = overlay->contrast;
attrs->saturation = overlay->saturation;
- if (!IS_DISPLAY_VER(dev_priv, 2)) {
+ if (DISPLAY_VER(dev_priv) != 2) {
attrs->gamma0 = intel_de_read(dev_priv, OGAMC0);
attrs->gamma1 = intel_de_read(dev_priv, OGAMC1);
attrs->gamma2 = intel_de_read(dev_priv, OGAMC2);
@@ -1305,7 +1305,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
update_reg_attrs(overlay, overlay->regs);
if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
goto out_unlock;
if (overlay->active) {
@@ -1401,7 +1401,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
overlay->saturation = 146;
i915_active_init(&overlay->last_flip,
- NULL, intel_overlay_last_flip_retire);
+ NULL, intel_overlay_last_flip_retire, 0);
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 10022d1575e1..7d7a60b4d2de 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -35,6 +35,7 @@
#include <linux/pwm.h>
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp_aux_backlight.h"
#include "intel_dsi_dcs_backlight.h"
@@ -667,7 +668,7 @@ static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32
pci_write_config_byte(to_pci_dev(dev_priv->drm.dev), LBPC, lbpc);
}
- if (IS_DISPLAY_VER(dev_priv, 4)) {
+ if (DISPLAY_VER(dev_priv) == 4) {
mask = BACKLIGHT_DUTY_CYCLE_MASK;
} else {
level <<= 1;
@@ -1040,7 +1041,7 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
* 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
* that has backlight.
*/
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
intel_de_write(dev_priv, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
}
@@ -1372,6 +1373,9 @@ int intel_backlight_device_register(struct intel_connector *connector)
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_panel *panel = &connector->panel;
struct backlight_properties props;
+ struct backlight_device *bd;
+ const char *name;
+ int ret = 0;
if (WARN_ON(panel->backlight.device))
return -ENODEV;
@@ -1398,28 +1402,49 @@ int intel_backlight_device_register(struct intel_connector *connector)
else
props.power = FB_BLANK_POWERDOWN;
+ name = kstrdup("intel_backlight", GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ bd = backlight_device_register(name, connector->base.kdev, connector,
+ &intel_backlight_device_ops, &props);
+
/*
- * Note: using the same name independent of the connector prevents
- * registration of multiple backlight devices in the driver.
+ * Using the same name independent of the drm device or connector
+ * prevents registration of multiple backlight devices in the
+ * driver. However, we need to use the default name for backward
+ * compatibility. Use unique names for subsequent backlight devices as a
+ * fallback when the default name already exists.
*/
- panel->backlight.device =
- backlight_device_register("intel_backlight",
- connector->base.kdev,
- connector,
- &intel_backlight_device_ops, &props);
-
- if (IS_ERR(panel->backlight.device)) {
- drm_err(&i915->drm, "Failed to register backlight: %ld\n",
- PTR_ERR(panel->backlight.device));
- panel->backlight.device = NULL;
- return -ENODEV;
+ if (IS_ERR(bd) && PTR_ERR(bd) == -EEXIST) {
+ kfree(name);
+ name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
+ i915->drm.primary->index, connector->base.name);
+ if (!name)
+ return -ENOMEM;
+
+ bd = backlight_device_register(name, connector->base.kdev, connector,
+ &intel_backlight_device_ops, &props);
}
+ if (IS_ERR(bd)) {
+ drm_err(&i915->drm,
+ "[CONNECTOR:%d:%s] backlight device %s register failed: %ld\n",
+ connector->base.base.id, connector->base.name, name, PTR_ERR(bd));
+ ret = PTR_ERR(bd);
+ goto out;
+ }
+
+ panel->backlight.device = bd;
+
drm_dbg_kms(&i915->drm,
- "Connector %s backlight sysfs interface registered\n",
- connector->base.name);
+ "[CONNECTOR:%d:%s] backlight device %s registered\n",
+ connector->base.base.id, connector->base.name, name);
- return 0;
+out:
+ kfree(name);
+
+ return ret;
}
void intel_backlight_device_unregister(struct intel_connector *connector)
@@ -1728,7 +1753,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu
ctl = intel_de_read(dev_priv, BLC_PWM_CTL);
- if (IS_DISPLAY_VER(dev_priv, 2) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
+ if (DISPLAY_VER(dev_priv) == 2 || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
if (IS_PINEVIEW(dev_priv))
@@ -2161,7 +2186,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
intel_dsi_dcs_init_backlight_funcs(connector) == 0)
return;
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
panel->backlight.pwm_funcs = &bxt_pwm_funcs;
} else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) {
panel->backlight.pwm_funcs = &cnp_pwm_funcs;
@@ -2178,7 +2203,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
} else {
panel->backlight.pwm_funcs = &vlv_pwm_funcs;
}
- } else if (IS_DISPLAY_VER(dev_priv, 4)) {
+ } else if (DISPLAY_VER(dev_priv) == 4) {
panel->backlight.pwm_funcs = &i965_pwm_funcs;
} else {
panel->backlight.pwm_funcs = &i9xx_pwm_funcs;
diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
index 7c8e0d76207f..8ac263f471be 100644
--- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
@@ -30,6 +30,7 @@
#include <linux/seq_file.h>
#include "intel_atomic.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_pipe_crc.h"
@@ -409,7 +410,7 @@ static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv,
enum pipe pipe,
enum intel_pipe_crc_source *source, u32 *val)
{
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
return i8xx_pipe_crc_ctl_reg(source, val);
else if (DISPLAY_VER(dev_priv) < 5)
return i9xx_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
@@ -539,7 +540,7 @@ static int
intel_is_valid_crc_source(struct drm_i915_private *dev_priv,
const enum intel_pipe_crc_source source)
{
- if (IS_DISPLAY_VER(dev_priv, 2))
+ if (DISPLAY_VER(dev_priv) == 2)
return i8xx_crc_source_valid(dev_priv, source);
else if (DISPLAY_VER(dev_priv) < 5)
return i9xx_crc_source_valid(dev_priv, source);
@@ -580,13 +581,14 @@ int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
return -EINVAL;
}
-int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
+int intel_crtc_set_crc_source(struct drm_crtc *_crtc, const char *source_name)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
+ struct intel_crtc *crtc = to_intel_crtc(_crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
enum intel_display_power_domain power_domain;
enum intel_pipe_crc_source source;
+ enum pipe pipe = crtc->pipe;
intel_wakeref_t wakeref;
u32 val = 0; /* shut up gcc */
int ret = 0;
@@ -597,7 +599,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
return -EINVAL;
}
- power_domain = POWER_DOMAIN_PIPE(crtc->index);
+ power_domain = POWER_DOMAIN_PIPE(pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wakeref) {
drm_dbg_kms(&dev_priv->drm,
@@ -607,64 +609,64 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
enable = source != INTEL_PIPE_CRC_SOURCE_NONE;
if (enable)
- intel_crtc_crc_setup_workarounds(to_intel_crtc(crtc), true);
+ intel_crtc_crc_setup_workarounds(crtc, true);
- ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val);
+ ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val);
if (ret != 0)
goto out;
pipe_crc->source = source;
- intel_de_write(dev_priv, PIPE_CRC_CTL(crtc->index), val);
- intel_de_posting_read(dev_priv, PIPE_CRC_CTL(crtc->index));
+ intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val);
+ intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
if (!source) {
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
- vlv_undo_pipe_scramble_reset(dev_priv, crtc->index);
+ vlv_undo_pipe_scramble_reset(dev_priv, pipe);
}
pipe_crc->skipped = 0;
out:
if (!enable)
- intel_crtc_crc_setup_workarounds(to_intel_crtc(crtc), false);
+ intel_crtc_crc_setup_workarounds(crtc, false);
intel_display_power_put(dev_priv, power_domain, wakeref);
return ret;
}
-void intel_crtc_enable_pipe_crc(struct intel_crtc *intel_crtc)
+void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc)
{
- struct drm_crtc *crtc = &intel_crtc->base;
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
+ enum pipe pipe = crtc->pipe;
u32 val = 0;
- if (!crtc->crc.opened)
+ if (!crtc->base.crc.opened)
return;
- if (get_new_crc_ctl_reg(dev_priv, crtc->index, &pipe_crc->source, &val) < 0)
+ if (get_new_crc_ctl_reg(dev_priv, pipe, &pipe_crc->source, &val) < 0)
return;
/* Don't need pipe_crc->lock here, IRQs are not generated. */
pipe_crc->skipped = 0;
- intel_de_write(dev_priv, PIPE_CRC_CTL(crtc->index), val);
- intel_de_posting_read(dev_priv, PIPE_CRC_CTL(crtc->index));
+ intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val);
+ intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
}
-void intel_crtc_disable_pipe_crc(struct intel_crtc *intel_crtc)
+void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc)
{
- struct drm_crtc *crtc = &intel_crtc->base;
- struct drm_i915_private *dev_priv = to_i915(crtc->dev);
- struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
+ enum pipe pipe = crtc->pipe;
/* Swallow crc's until we stop generating them. */
spin_lock_irq(&pipe_crc->lock);
pipe_crc->skipped = INT_MIN;
spin_unlock_irq(&pipe_crc->lock);
- intel_de_write(dev_priv, PIPE_CRC_CTL(crtc->index), 0);
- intel_de_posting_read(dev_priv, PIPE_CRC_CTL(crtc->index));
+ intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), 0);
+ intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
intel_synchronize_irq(dev_priv);
}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index c55da130773b..a36ec4a818ff 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -5,6 +5,7 @@
#include "g4x_dp.h"
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dpll.h"
@@ -313,10 +314,10 @@ void intel_pps_reset_all(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder;
- if (drm_WARN_ON(&dev_priv->drm,
- !(IS_VALLEYVIEW(dev_priv) ||
- IS_CHERRYVIEW(dev_priv) ||
- IS_GEN9_LP(dev_priv))))
+ if (drm_WARN_ON(&dev_priv->drm, !IS_LP(dev_priv)))
+ return;
+
+ if (!HAS_DISPLAY(dev_priv))
return;
/*
@@ -338,7 +339,7 @@ void intel_pps_reset_all(struct drm_i915_private *dev_priv)
if (encoder->type != INTEL_OUTPUT_EDP)
continue;
- if (IS_GEN9_LP(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 9)
intel_dp->pps.pps_reset = true;
else
intel_dp->pps.pps_pipe = INVALID_PIPE;
@@ -361,7 +362,7 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
memset(regs, 0, sizeof(*regs));
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pps_idx = bxt_power_sequencer_idx(intel_dp);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
pps_idx = vlv_power_sequencer_pipe(intel_dp);
@@ -372,7 +373,8 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
regs->pp_off = PP_OFF_DELAYS(pps_idx);
/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
- if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ||
+ INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
regs->pp_div = INVALID_MMIO_REG;
else
regs->pp_div = PP_DIVISOR(pps_idx);
@@ -1378,7 +1380,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
int pps_num;
int pps_idx;
- if (HAS_DDI(dev_priv))
+ if (!HAS_DISPLAY(dev_priv) || HAS_DDI(dev_priv))
return;
/*
* This w/a is needed at least on CPT/PPT, but to be sure apply it
@@ -1399,7 +1401,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
void intel_pps_setup(struct drm_i915_private *i915)
{
- if (HAS_PCH_SPLIT(i915) || IS_GEN9_LP(i915))
+ if (HAS_PCH_SPLIT(i915) || IS_GEMINILAKE(i915) || IS_BROXTON(i915))
i915->pps_mmio_base = PCH_PPS_BASE;
else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
i915->pps_mmio_base = VLV_PPS_BASE;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 8ada4f829cab..77865cf6641f 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -27,6 +27,7 @@
#include "i915_drv.h"
#include "intel_atomic.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp_aux.h"
#include "intel_hdmi.h"
@@ -524,7 +525,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
val = psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT;
val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
- if (DISPLAY_VER(dev_priv) >= 10)
+ if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
val |= EDP_PSR2_FRAME_BEFORE_SU(intel_dp->psr.sink_sync_latency + 1);
@@ -637,7 +638,7 @@ unlock:
static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp)
{
- if (!intel_dp->psr.dc3co_enabled)
+ if (!intel_dp->psr.dc3co_exitline)
return;
cancel_delayed_work(&intel_dp->psr.dc3co_work);
@@ -645,28 +646,47 @@ static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp)
tgl_psr2_disable_dc3co(intel_dp);
}
+static bool
+dc3co_is_pipe_port_compatible(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum port port = dig_port->base.port;
+
+ if (IS_ALDERLAKE_P(dev_priv))
+ return pipe <= PIPE_B && port <= PORT_B;
+ else
+ return pipe == PIPE_A && port == PORT_A;
+}
+
static void
tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
const u32 crtc_vdisplay = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u32 exit_scanlines;
/*
+ * FIXME: Due to the changed sequence of activating/deactivating DC3CO,
+ * disable DC3CO until the changed dc3co activating/deactivating sequence
+ * is applied. B.Specs:49196
+ */
+ return;
+
+ /*
* DMC's DC3CO exit mechanism has an issue with Selective Fecth
* TODO: when the issue is addressed, this restriction should be removed.
*/
if (crtc_state->enable_psr2_sel_fetch)
return;
- if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC3CO))
+ if (!(dev_priv->dmc.allowed_dc_mask & DC_STATE_EN_DC3CO))
return;
- /* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/
- if (to_intel_crtc(crtc_state->uapi.crtc)->pipe != PIPE_A ||
- dig_port->base.port != PORT_A)
+ if (!dc3co_is_pipe_port_compatible(intel_dp, crtc_state))
return;
/*
@@ -712,6 +732,13 @@ static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp,
}
}
+ /* Wa_14010254185 Wa_14010103792 */
+ if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1)) {
+ drm_dbg_kms(&dev_priv->drm,
+ "PSR2 sel fetch not enabled, missing the implementation of WAs\n");
+ return false;
+ }
+
return crtc_state->enable_psr2_sel_fetch = true;
}
@@ -732,6 +759,21 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return false;
}
+ /* Wa_16011181250 */
+ if (IS_ROCKETLAKE(dev_priv) || IS_ALDERLAKE_S(dev_priv)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 is defeatured for this platform\n");
+ return false;
+ }
+
+ /*
+ * We are missing the implementation of some workarounds to enabled PSR2
+ * in Alderlake_P, until ready PSR2 should be kept disabled.
+ */
+ if (IS_ALDERLAKE_P(dev_priv)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 is missing the implementation of workarounds\n");
+ return false;
+ }
+
if (!transcoder_has_psr2(dev_priv, crtc_state->cpu_transcoder)) {
drm_dbg_kms(&dev_priv->drm,
"PSR2 not supported in transcoder %s\n",
@@ -769,7 +811,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
psr_max_h = 4096;
psr_max_v = 2304;
max_bpp = 24;
- } else if (IS_DISPLAY_VER(dev_priv, 9)) {
+ } else if (DISPLAY_VER(dev_priv) == 9) {
psr_max_h = 3640;
psr_max_v = 2304;
max_bpp = 24;
@@ -804,6 +846,13 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
}
}
+ /* Wa_2209313811 */
+ if (!crtc_state->enable_psr2_sel_fetch &&
+ IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B1)) {
+ drm_dbg_kms(&dev_priv->drm, "PSR2 HW tracking is not supported this Display stepping\n");
+ return false;
+ }
+
if (!crtc_state->enable_psr2_sel_fetch &&
(crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) {
drm_dbg_kms(&dev_priv->drm,
@@ -873,6 +922,51 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
}
+void intel_psr_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config)
+{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ struct intel_dp *intel_dp;
+ u32 val;
+
+ if (!dig_port)
+ return;
+
+ intel_dp = &dig_port->dp;
+ if (!CAN_PSR(intel_dp))
+ return;
+
+ mutex_lock(&intel_dp->psr.lock);
+ if (!intel_dp->psr.enabled)
+ goto unlock;
+
+ /*
+ * Not possible to read EDP_PSR/PSR2_CTL registers as it is
+ * enabled/disabled because of frontbuffer tracking and others.
+ */
+ pipe_config->has_psr = true;
+ pipe_config->has_psr2 = intel_dp->psr.psr2_enabled;
+ pipe_config->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_VSC);
+
+ if (!intel_dp->psr.psr2_enabled)
+ goto unlock;
+
+ if (HAS_PSR2_SEL_FETCH(dev_priv)) {
+ val = intel_de_read(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder));
+ if (val & PSR2_MAN_TRK_CTL_ENABLE)
+ pipe_config->enable_psr2_sel_fetch = true;
+ }
+
+ if (DISPLAY_VER(dev_priv) >= 12) {
+ val = intel_de_read(dev_priv, EXITLINE(intel_dp->psr.transcoder));
+ val &= EXITLINE_MASK;
+ pipe_config->dc3co_exitline = val;
+ }
+unlock:
+ mutex_unlock(&intel_dp->psr.lock);
+}
+
static void intel_psr_activate(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -896,11 +990,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
intel_dp->psr.active = true;
}
-static void intel_psr_enable_source(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state)
+static void intel_psr_enable_source(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 mask;
/* Only HSW and BDW have PSR AUX registers that need to be setup. SKL+
@@ -909,7 +1002,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_psr_setup_aux(intel_dp);
- if (intel_dp->psr.psr2_enabled && IS_DISPLAY_VER(dev_priv, 9)) {
+ if (intel_dp->psr.psr2_enabled && DISPLAY_VER(dev_priv) == 9) {
i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
u32 chicken = intel_de_read(dev_priv, reg);
@@ -937,7 +1030,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
psr_irq_control(intel_dp);
- if (crtc_state->dc3co_exitline) {
+ if (intel_dp->psr.dc3co_exitline) {
u32 val;
/*
@@ -946,7 +1039,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
*/
val = intel_de_read(dev_priv, EXITLINE(cpu_transcoder));
val &= ~EXITLINE_MASK;
- val |= crtc_state->dc3co_exitline << EXITLINE_SHIFT;
+ val |= intel_dp->psr.dc3co_exitline << EXITLINE_SHIFT;
val |= EXITLINE_ENABLE;
intel_de_write(dev_priv, EXITLINE(cpu_transcoder), val);
}
@@ -957,27 +1050,11 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
IGNORE_PSR2_HW_TRACKING : 0);
}
-static void intel_psr_enable_locked(struct intel_dp *intel_dp,
- const struct intel_crtc_state *crtc_state,
- const struct drm_connector_state *conn_state)
+static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- struct intel_encoder *encoder = &dig_port->base;
u32 val;
- drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled);
-
- intel_dp->psr.psr2_enabled = crtc_state->has_psr2;
- intel_dp->psr.busy_frontbuffer_bits = 0;
- intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
- intel_dp->psr.dc3co_enabled = !!crtc_state->dc3co_exitline;
- intel_dp->psr.transcoder = crtc_state->cpu_transcoder;
- /* DC5/DC6 requires at least 6 idle frames */
- val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6);
- intel_dp->psr.dc3co_exit_delay = val;
- intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
-
/*
* If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR
* will still keep the error set even after the reset done in the
@@ -998,17 +1075,45 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp->psr.sink_not_reliable = true;
drm_dbg_kms(&dev_priv->drm,
"PSR interruption error set, not enabling PSR\n");
- return;
+ return false;
}
+ return true;
+}
+
+static void intel_psr_enable_locked(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ struct intel_encoder *encoder = &dig_port->base;
+ u32 val;
+
+ drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled);
+
+ intel_dp->psr.psr2_enabled = crtc_state->has_psr2;
+ intel_dp->psr.busy_frontbuffer_bits = 0;
+ intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
+ intel_dp->psr.transcoder = crtc_state->cpu_transcoder;
+ /* DC5/DC6 requires at least 6 idle frames */
+ val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6);
+ intel_dp->psr.dc3co_exit_delay = val;
+ intel_dp->psr.dc3co_exitline = crtc_state->dc3co_exitline;
+ intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
+
+ if (!psr_interrupt_error_check(intel_dp))
+ return;
+
drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n",
intel_dp->psr.psr2_enabled ? "2" : "1");
intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
&intel_dp->psr.vsc);
intel_write_dp_vsc_sdp(encoder, crtc_state, &intel_dp->psr.vsc);
intel_psr_enable_sink(intel_dp);
- intel_psr_enable_source(intel_dp, crtc_state);
+ intel_psr_enable_source(intel_dp);
intel_dp->psr.enabled = true;
+ intel_dp->psr.paused = false;
intel_psr_activate(intel_dp);
}
@@ -1078,22 +1183,12 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
intel_dp->psr.active = false;
}
-static void intel_psr_disable_locked(struct intel_dp *intel_dp)
+static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
i915_reg_t psr_status;
u32 psr_status_mask;
- lockdep_assert_held(&intel_dp->psr.lock);
-
- if (!intel_dp->psr.enabled)
- return;
-
- drm_dbg_kms(&dev_priv->drm, "Disabling PSR%s\n",
- intel_dp->psr.psr2_enabled ? "2" : "1");
-
- intel_psr_exit(intel_dp);
-
if (intel_dp->psr.psr2_enabled) {
psr_status = EDP_PSR2_STATUS(intel_dp->psr.transcoder);
psr_status_mask = EDP_PSR2_STATUS_STATE_MASK;
@@ -1106,6 +1201,22 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
if (intel_de_wait_for_clear(dev_priv, psr_status,
psr_status_mask, 2000))
drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n");
+}
+
+static void intel_psr_disable_locked(struct intel_dp *intel_dp)
+{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+ lockdep_assert_held(&intel_dp->psr.lock);
+
+ if (!intel_dp->psr.enabled)
+ return;
+
+ drm_dbg_kms(&dev_priv->drm, "Disabling PSR%s\n",
+ intel_dp->psr.psr2_enabled ? "2" : "1");
+
+ intel_psr_exit(intel_dp);
+ intel_psr_wait_exit_locked(intel_dp);
/* WA 1408330847 */
if (intel_dp->psr.psr2_sel_fetch_enabled &&
@@ -1150,25 +1261,66 @@ void intel_psr_disable(struct intel_dp *intel_dp,
cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
}
+/**
+ * intel_psr_pause - Pause PSR
+ * @intel_dp: Intel DP
+ *
+ * This function need to be called after enabling psr.
+ */
+void intel_psr_pause(struct intel_dp *intel_dp)
+{
+ struct intel_psr *psr = &intel_dp->psr;
+
+ if (!CAN_PSR(intel_dp))
+ return;
+
+ mutex_lock(&psr->lock);
+
+ if (!psr->enabled) {
+ mutex_unlock(&psr->lock);
+ return;
+ }
+
+ intel_psr_exit(intel_dp);
+ intel_psr_wait_exit_locked(intel_dp);
+ psr->paused = true;
+
+ mutex_unlock(&psr->lock);
+
+ cancel_work_sync(&psr->work);
+ cancel_delayed_work_sync(&psr->dc3co_work);
+}
+
+/**
+ * intel_psr_resume - Resume PSR
+ * @intel_dp: Intel DP
+ *
+ * This function need to be called after pausing psr.
+ */
+void intel_psr_resume(struct intel_dp *intel_dp)
+{
+ struct intel_psr *psr = &intel_dp->psr;
+
+ if (!CAN_PSR(intel_dp))
+ return;
+
+ mutex_lock(&psr->lock);
+
+ if (!psr->paused)
+ goto unlock;
+
+ psr->paused = false;
+ intel_psr_activate(intel_dp);
+
+unlock:
+ mutex_unlock(&psr->lock);
+}
+
static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- if (IS_TIGERLAKE(dev_priv))
- /*
- * Writes to CURSURFLIVE in TGL are causing IOMMU errors and
- * visual glitches that are often reproduced when executing
- * CPU intensive workloads while a eDP 4K panel is attached.
- *
- * Manually exiting PSR causes the frontbuffer to be updated
- * without glitches and the IOMMU errors are also gone but
- * this comes at the cost of less time with PSR active.
- *
- * So using this workaround until this issue is root caused
- * and a better fix is found.
- */
- intel_psr_exit(intel_dp);
- else if (DISPLAY_VER(dev_priv) >= 9)
+ if (DISPLAY_VER(dev_priv) >= 9)
/*
* Display WA #0884: skl+
* This documented WA for bxt can be safely applied
@@ -1759,7 +1911,7 @@ tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
{
mutex_lock(&intel_dp->psr.lock);
- if (!intel_dp->psr.dc3co_enabled)
+ if (!intel_dp->psr.dc3co_exitline)
goto unlock;
if (!intel_dp->psr.psr2_enabled || !intel_dp->psr.active)
@@ -1818,6 +1970,16 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe);
intel_dp->psr.busy_frontbuffer_bits &= ~pipe_frontbuffer_bits;
+ /*
+ * If the PSR is paused by an explicit intel_psr_paused() call,
+ * we have to ensure that the PSR is not activated until
+ * intel_psr_resume() is called.
+ */
+ if (intel_dp->psr.paused) {
+ mutex_unlock(&intel_dp->psr.lock);
+ continue;
+ }
+
/* By definition flush = invalidate + flush */
if (pipe_frontbuffer_bits)
psr_force_hw_tracking_exit(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 0491a49ffd50..641521b101c8 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -17,6 +17,7 @@ struct intel_crtc;
struct intel_atomic_state;
struct intel_plane_state;
struct intel_plane;
+struct intel_encoder;
void intel_psr_init_dpcd(struct intel_dp *intel_dp);
void intel_psr_enable(struct intel_dp *intel_dp,
@@ -37,6 +38,8 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
void intel_psr_init(struct intel_dp *intel_dp);
void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
+void intel_psr_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config);
void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir);
void intel_psr_short_pulse(struct intel_dp *intel_dp);
void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state);
@@ -48,5 +51,7 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
int color_plane);
+void intel_psr_pause(struct intel_dp *intel_dp);
+void intel_psr_resume(struct intel_dp *intel_dp);
#endif /* __INTEL_PSR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.c b/drivers/gpu/drm/i915/display/intel_qp_tables.c
new file mode 100644
index 000000000000..c626a24fe98f
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_qp_tables.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <drm/drm_dsc.h>
+
+#include "i915_utils.h"
+#include "intel_qp_tables.h"
+
+/* from BPP 6 to 24 in steps of 0.5 */
+#define RC_RANGE_QP444_8BPC_MAX_NUM_BPP 37
+
+/* from BPP 6 to 30 in steps of 0.5 */
+#define RC_RANGE_QP444_10BPC_MAX_NUM_BPP 49
+
+/* from BPP 6 to 36 in steps of 0.5 */
+#define RC_RANGE_QP444_12BPC_MAX_NUM_BPP 61
+
+/*
+ * These qp tables are as per the C model
+ * and it has the rows pointing to bpps which increment
+ * in steps of 0.5
+ * We do not support fractional bpps as of today,
+ * hence we would skip the fractional bpps during
+ * our references for qp calclulations.
+ */
+static const u8 rc_range_minqp444_8bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_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, 0, 0, 0 },
+ { 1, 1, 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, 0 },
+ { 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
+ { 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ { 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ { 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
+ 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+ { 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0 },
+ { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4,
+ 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0 },
+ { 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5,
+ 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1 },
+ { 14, 14, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10, 9, 9, 9, 8, 8,
+ 8, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3 }
+};
+
+static const u8 rc_range_maxqp444_8bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_8BPC_MAX_NUM_BPP] = {
+ { 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 6, 6, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
+ { 8, 7, 7, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
+ { 8, 8, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 3, 3, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+ { 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 4, 4, 3, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+ { 9, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 },
+ { 9, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 },
+ { 10, 10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 5, 5, 4, 4, 4, 4, 3,
+ 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 },
+ { 11, 11, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 7, 6, 6, 5, 5, 5, 5, 5,
+ 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 12, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 7, 6, 6, 5, 5, 5,
+ 5, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 12, 12, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6,
+ 5, 5, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7,
+ 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1 },
+ { 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7,
+ 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1 },
+ { 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 8,
+ 8, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 2, 2, 2 },
+ { 15, 15, 14, 14, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 9,
+ 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4 }
+};
+
+static const u8 rc_range_minqp444_10bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_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,
+ 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, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 7, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3,
+ 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 9, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4,
+ 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0 },
+ { 9, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 5, 5,
+ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0 },
+ { 9, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5,
+ 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 0,
+ 0, 0, 0 },
+ { 9, 9, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5,
+ 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1,
+ 1, 0, 0 },
+ { 10, 9, 9, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+ 1, 1, 0 },
+ { 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6,
+ 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1,
+ 1, 1, 1 },
+ { 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2,
+ 2, 1, 1, 1 },
+ { 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
+ 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2,
+ 2, 2, 2, 1 },
+ { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4,
+ 4, 3, 3, 3, 3, 2, 2, 2, 2, 1 },
+ { 18, 18, 17, 17, 16, 16, 16, 16, 15, 15, 14, 14, 14, 14, 13, 13, 13,
+ 12, 12, 12, 11, 11, 11, 11, 10, 10, 9, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7,
+ 7, 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3 }
+};
+
+static const u8 rc_range_maxqp444_10bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_10BPC_MAX_NUM_BPP] = {
+ { 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 10, 10, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0 },
+ { 12, 11, 11, 10, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 6, 6, 5, 5, 5, 4,
+ 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0 },
+ { 12, 12, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 8, 7, 7, 6,
+ 6, 6, 5, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0 },
+ { 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7,
+ 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0 },
+ { 13, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 9, 8, 8,
+ 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2,
+ 2, 2, 1, 1, 1, 1, 0, 0 },
+ { 13, 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8,
+ 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1 },
+ { 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 10, 9, 9,
+ 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3,
+ 3, 2, 2, 2, 1, 1, 1, 1 },
+ { 15, 15, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 10, 10, 9,
+ 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3,
+ 3, 3, 2, 2, 2, 2, 1, 1 },
+ { 16, 15, 15, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 10,
+ 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
+ 4, 3, 3, 3, 2, 2, 2, 2, 1 },
+ { 16, 16, 15, 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11,
+ 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
+ 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 },
+ { 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12,
+ 11, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5,
+ 5, 4, 4, 4, 4, 3, 3, 2, 2, 2 },
+ { 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 13, 13, 13, 12, 12, 12,
+ 11, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5,
+ 5, 4, 4, 4, 4, 3, 3, 3, 3, 2 },
+ { 17, 17, 17, 17, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 12,
+ 12, 12, 12, 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6,
+ 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2 },
+ { 19, 19, 18, 18, 17, 17, 17, 17, 16, 16, 15, 15, 15, 15, 14, 14, 14,
+ 13, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10, 10, 9, 9, 8, 8, 8,
+ 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4 }
+};
+
+static const u8 rc_range_minqp444_12bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_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, 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 },
+ { 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 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 },
+ { 11, 10, 10, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3,
+ 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 11, 11, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 6, 6, 6, 6, 6, 5, 5, 5,
+ 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 8, 7, 7, 7,
+ 7, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 13, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 9, 9, 8, 8,
+ 8, 8, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 13, 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 9, 9, 9, 9,
+ 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 3, 3,
+ 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
+ { 13, 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10,
+ 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4,
+ 4, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 },
+ { 13, 13, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 10, 10, 10, 10, 9, 9, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5,
+ 5, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0 },
+ { 14, 13, 13, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 5,
+ 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 0 },
+ { 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12,
+ 12, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7,
+ 6, 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1 },
+ { 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8,
+ 7, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1 },
+ { 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 12, 12, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8,
+ 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1 },
+ { 17, 17, 17, 17, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 14, 14, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8,
+ 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 1 },
+ { 22, 22, 21, 21, 20, 20, 20, 20, 19, 19, 18, 18, 18, 18, 17, 17, 17, 16, 16,
+ 16, 15, 15, 15, 15, 14, 14, 13, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 11,
+ 10, 10, 9, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 3 }
+};
+
+static const u8 rc_range_maxqp444_12bpc[DSC_NUM_BUF_RANGES][RC_RANGE_QP444_12BPC_MAX_NUM_BPP] = {
+ { 12, 12, 12, 12, 12, 12, 11, 11, 11, 10, 9, 9, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4,
+ 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 9, 9, 9, 8, 8, 7, 7, 7, 7, 5,
+ 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 15, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 11, 10, 10, 9, 9,
+ 9, 7, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 16, 16, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 11, 11, 10,
+ 10, 10, 8, 8, 8, 8, 8, 7, 7, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 2,
+ 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 17, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 13, 12, 12, 11, 10,
+ 10, 10, 10, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+ { 17, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11,
+ 11, 11, 11, 9, 9, 9, 9, 8, 8, 8, 8, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3,
+ 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0 },
+ { 17, 17, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 13, 12, 12, 11,
+ 11, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5,
+ 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0 },
+ { 18, 18, 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 14, 13, 13, 12,
+ 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+ 6, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1 },
+ { 19, 19, 18, 18, 17, 17, 17, 17, 17, 17, 16, 16, 16, 15, 15, 14, 14, 13, 13,
+ 13, 13, 13, 12, 12, 12, 12, 11, 11, 10, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6,
+ 6, 6, 5, 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1 },
+ { 20, 19, 19, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 16, 16, 15, 14, 14, 13,
+ 13, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7,
+ 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 1 },
+ { 20, 20, 19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 16, 16, 15, 15, 14, 14,
+ 14, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9,
+ 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2 },
+ { 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 17, 16, 16, 16, 15, 15,
+ 15, 14, 14, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9,
+ 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 2, 2, 2 },
+ { 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15,
+ 15, 14, 14, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9,
+ 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 2, 2, 2 },
+ { 21, 21, 21, 21, 20, 20, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 16, 16, 16,
+ 16, 15, 15, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10,
+ 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 2 },
+ { 23, 23, 22, 22, 21, 21, 21, 21, 20, 20, 19, 19, 19, 19, 18, 18, 18, 17, 17,
+ 17, 16, 16, 16, 16, 15, 15, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12,
+ 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]; \
+} while (0)
+
+u8 intel_lookup_range_min_qp(int bpc, int buf_i, int bpp_i)
+{
+ PARAM_TABLE(min, 8, buf_i, bpp_i);
+ PARAM_TABLE(min, 10, buf_i, bpp_i);
+ PARAM_TABLE(min, 12, buf_i, bpp_i);
+
+ MISSING_CASE(bpc);
+ return 0;
+}
+
+u8 intel_lookup_range_max_qp(int bpc, int buf_i, int bpp_i)
+{
+ PARAM_TABLE(max, 8, buf_i, bpp_i);
+ PARAM_TABLE(max, 10, buf_i, bpp_i);
+ PARAM_TABLE(max, 12, buf_i, bpp_i);
+
+ 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
new file mode 100644
index 000000000000..9fb3c36bd7c6
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_qp_tables.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef _INTEL_QP_TABLES_H_
+#define _INTEL_QP_TABLES_H_
+
+#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);
+
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index f770d6bcd2c9..e4f91d7a5c60 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -38,6 +38,8 @@
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_connector.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index acbf4e63b245..4ae9a7455b23 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -43,6 +43,7 @@
#include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_atomic_plane.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_frontbuffer.h"
#include "intel_sprite.h"
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 71b8edafb1c3..c23c210a55f5 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -26,9 +26,7 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
static enum intel_display_power_domain
tc_cold_get_power_domain(struct intel_digital_port *dig_port)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-
- if (IS_DISPLAY_VER(i915, 11))
+ if (intel_tc_cold_requires_aux_pw(dig_port))
return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
else
return POWER_DOMAIN_TC_COLD_OFF;
@@ -40,7 +38,7 @@ tc_cold_block(struct intel_digital_port *dig_port)
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
enum intel_display_power_domain domain;
- if (IS_DISPLAY_VER(i915, 11) && !dig_port->tc_legacy_port)
+ if (DISPLAY_VER(i915) == 11 && !dig_port->tc_legacy_port)
return 0;
domain = tc_cold_get_power_domain(dig_port);
@@ -71,7 +69,7 @@ assert_tc_cold_blocked(struct intel_digital_port *dig_port)
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
bool enabled;
- if (IS_DISPLAY_VER(i915, 11) && !dig_port->tc_legacy_port)
+ if (DISPLAY_VER(i915) == 11 && !dig_port->tc_legacy_port)
return;
enabled = intel_display_power_is_enabled(i915,
@@ -205,7 +203,7 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
}
-static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
+static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
@@ -238,6 +236,40 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
return mask;
}
+static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+ u32 isr_bit = i915->hotplug.pch_hpd[dig_port->base.hpd_pin];
+ struct intel_uncore *uncore = &i915->uncore;
+ u32 val, mask = 0;
+
+ val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port));
+ if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT)
+ mask |= BIT(TC_PORT_DP_ALT);
+ if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT)
+ mask |= BIT(TC_PORT_TBT_ALT);
+
+ if (intel_uncore_read(uncore, SDEISR) & isr_bit)
+ 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);
+}
+
static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -256,8 +288,35 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
return val & DP_PHY_MODE_STATUS_COMPLETED(dig_port->tc_phy_fia_idx);
}
-static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
- bool enable)
+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);
+ struct intel_uncore *uncore = &i915->uncore;
+ u32 val;
+
+ val = intel_uncore_read(uncore, TCSS_DDI_STATUS(dig_port->tc_phy_fia_idx));
+ 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 & 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);
+}
+
+static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
+ bool take)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
@@ -267,20 +326,20 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
- "Port %s: PHY in TCCOLD, can't set safe-mode to %s\n",
- dig_port->tc_port_name, enableddisabled(enable));
+ "Port %s: PHY in TCCOLD, can't %s ownership\n",
+ dig_port->tc_port_name, take ? "take" : "release");
return false;
}
val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
- if (!enable)
+ if (take)
val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
intel_uncore_write(uncore,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
- if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
+ if (!take && wait_for(!tc_phy_status_complete(dig_port), 10))
drm_dbg_kms(&i915->drm,
"Port %s: PHY complete clear timed out\n",
dig_port->tc_port_name);
@@ -288,7 +347,35 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
return true;
}
-static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
+static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
+ bool take)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_uncore *uncore = &i915->uncore;
+ enum port port = dig_port->base.port;
+ u32 val;
+
+ val = intel_uncore_read(uncore, DDI_BUF_CTL(port));
+ if (take)
+ val |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+ else
+ val &= ~DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+ intel_uncore_write(uncore, DDI_BUF_CTL(port), val);
+
+ return true;
+}
+
+static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take)
+{
+ 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 intel_uncore *uncore = &i915->uncore;
@@ -303,7 +390,28 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
return true;
}
- return !(val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx));
+ return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
+}
+
+static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_uncore *uncore = &i915->uncore;
+ enum port port = dig_port->base.port;
+ u32 val;
+
+ val = intel_uncore_read(uncore, DDI_BUF_CTL(port));
+ return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+}
+
+static bool tc_phy_is_owned(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_is_owned(dig_port);
+
+ return icl_tc_phy_is_owned(dig_port);
}
/*
@@ -323,13 +431,13 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
int max_lanes;
- if (!icl_tc_phy_status_complete(dig_port)) {
+ if (!tc_phy_status_complete(dig_port)) {
drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n",
dig_port->tc_port_name);
goto out_set_tbt_alt_mode;
}
- if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
+ if (!tc_phy_take_ownership(dig_port, true) &&
!drm_WARN_ON(&i915->drm, dig_port->tc_legacy_port))
goto out_set_tbt_alt_mode;
@@ -348,7 +456,7 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) {
drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n",
dig_port->tc_port_name);
- goto out_set_safe_mode;
+ goto out_release_phy;
}
if (max_lanes < required_lanes) {
@@ -356,15 +464,15 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
"Port %s: PHY max lanes %d < required lanes %d\n",
dig_port->tc_port_name,
max_lanes, required_lanes);
- goto out_set_safe_mode;
+ goto out_release_phy;
}
dig_port->tc_mode = TC_PORT_DP_ALT;
return;
-out_set_safe_mode:
- icl_tc_phy_set_safe_mode(dig_port, true);
+out_release_phy:
+ tc_phy_take_ownership(dig_port, false);
out_set_tbt_alt_mode:
dig_port->tc_mode = TC_PORT_TBT_ALT;
}
@@ -380,7 +488,7 @@ static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
/* Nothing to do, we never disconnect from legacy mode */
break;
case TC_PORT_DP_ALT:
- icl_tc_phy_set_safe_mode(dig_port, true);
+ tc_phy_take_ownership(dig_port, false);
dig_port->tc_mode = TC_PORT_TBT_ALT;
break;
case TC_PORT_TBT_ALT:
@@ -395,14 +503,14 @@ static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- if (!icl_tc_phy_status_complete(dig_port)) {
+ if (!tc_phy_status_complete(dig_port)) {
drm_dbg_kms(&i915->drm, "Port %s: PHY status not complete\n",
dig_port->tc_port_name);
return dig_port->tc_mode == TC_PORT_TBT_ALT;
}
- if (icl_tc_phy_is_in_safe_mode(dig_port)) {
- drm_dbg_kms(&i915->drm, "Port %s: PHY still in safe mode\n",
+ if (!tc_phy_is_owned(dig_port)) {
+ drm_dbg_kms(&i915->drm, "Port %s: PHY not owned\n",
dig_port->tc_port_name);
return false;
@@ -417,11 +525,10 @@ intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
u32 live_status_mask = tc_port_live_status_mask(dig_port);
- bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
enum tc_port_mode mode;
- if (in_safe_mode ||
- drm_WARN_ON(&i915->drm, !icl_tc_phy_status_complete(dig_port)))
+ if (!tc_phy_is_owned(dig_port) ||
+ drm_WARN_ON(&i915->drm, !tc_phy_status_complete(dig_port)))
return TC_PORT_TBT_ALT;
mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
@@ -443,7 +550,7 @@ intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
if (live_status_mask)
return fls(live_status_mask) - 1;
- return icl_tc_phy_status_complete(dig_port) &&
+ return tc_phy_status_complete(dig_port) &&
dig_port->tc_legacy_port ? TC_PORT_LEGACY :
TC_PORT_TBT_ALT;
}
@@ -455,7 +562,7 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
enum tc_port_mode old_tc_mode = dig_port->tc_mode;
intel_display_power_flush_work(i915);
- if (DISPLAY_VER(i915) != 11 || !dig_port->tc_legacy_port) {
+ if (!intel_tc_cold_requires_aux_pw(dig_port)) {
enum intel_display_power_domain aux_domain;
bool aux_powered;
@@ -625,9 +732,11 @@ tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig
if (!INTEL_INFO(i915)->display.has_modular_fia)
return false;
+ mutex_lock(&dig_port->tc_lock);
wakeref = tc_cold_block(dig_port);
val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1));
tc_cold_unblock(dig_port, wakeref);
+ mutex_unlock(&dig_port->tc_lock);
drm_WARN_ON(&i915->drm, val == 0xffffffff);
@@ -670,3 +779,11 @@ void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
dig_port->tc_link_refcount = 0;
tc_port_load_fia_params(i915, dig_port);
}
+
+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);
+
+ return (DISPLAY_VER(i915) == 11 && dig_port->tc_legacy_port) ||
+ IS_ALDERLAKE_P(i915);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index b619e4736f85..0eacbd76ec15 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -29,4 +29,6 @@ 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);
+bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port);
+
#endif /* __INTEL_TC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index e558f121ec4e..aa52af7891f0 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -36,6 +36,7 @@
#include "i915_drv.h"
#include "intel_connector.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_hotplug.h"
#include "intel_tv.h"
@@ -1165,7 +1166,7 @@ intel_tv_get_config(struct intel_encoder *encoder,
static bool intel_tv_source_too_wide(struct drm_i915_private *dev_priv,
int hdisplay)
{
- return IS_DISPLAY_VER(dev_priv, 3) && hdisplay > 1024;
+ return DISPLAY_VER(dev_priv) == 3 && hdisplay > 1024;
}
static bool intel_tv_vert_scaling(const struct drm_display_mode *tv_mode,
@@ -1306,7 +1307,7 @@ intel_tv_compute_config(struct intel_encoder *encoder,
* the active portion. Hence following this formula seems
* more trouble that it's worth.
*
- * if (IS_GEN(dev_priv, 4)) {
+ * if (GRAPHICS_VER(dev_priv) == 4) {
* num = cdclk * (tv_mode->oversample >> !tv_mode->progressive);
* den = tv_mode->clock;
* } else {
@@ -1789,7 +1790,7 @@ intel_tv_get_modes(struct drm_connector *connector)
continue;
/* no vertical scaling with wide sources on gen3 */
- if (IS_DISPLAY_VER(dev_priv, 3) && input->w > 1024 &&
+ if (DISPLAY_VER(dev_priv) == 3 && input->w > 1024 &&
input->h > intel_tv_mode_vdisplay(tv_mode))
continue;
@@ -1978,7 +1979,7 @@ intel_tv_init(struct drm_i915_private *dev_priv)
/* Create TV properties then attach current values */
for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
/* 1080p50/1080p60 not supported on gen3 */
- if (IS_DISPLAY_VER(dev_priv, 3) &&
+ if (DISPLAY_VER(dev_priv) == 3 &&
tv_modes[i].oversample == 1)
break;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 3a21c65ffa85..85749370508c 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -5,11 +5,13 @@
* Author: Gaurav K Singh <gaurav.k.singh@intel.com>
* Manasi Navare <manasi.d.navare@intel.com>
*/
-
+#include <linux/limits.h>
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsi.h"
#include "intel_vdsc.h"
+#include "intel_qp_tables.h"
enum ROW_INDEX_BPP {
ROW_INDEX_6BPP = 0,
@@ -372,12 +374,81 @@ static bool is_pipe_dsc(const struct intel_crtc_state *crtc_state)
return true;
}
+static void
+calculate_rc_params(struct rc_parameters *rc,
+ struct drm_dsc_config *vdsc_cfg)
+{
+ int bpc = vdsc_cfg->bits_per_component;
+ int bpp = vdsc_cfg->bits_per_pixel >> 4;
+ int ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
+ int ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
+ int ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
+ int ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
+ int qp_bpc_modifier = (bpc - 8) * 2;
+ u32 res, buf_i, bpp_i;
+
+ if (vdsc_cfg->slice_height >= 8)
+ rc->first_line_bpg_offset =
+ 12 + DIV_ROUND_UP((9 * min(34, vdsc_cfg->slice_height - 8)), 100);
+ else
+ rc->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
+
+ /* Our hw supports only 444 modes as of today */
+ if (bpp >= 12)
+ rc->initial_offset = 2048;
+ else if (bpp >= 10)
+ rc->initial_offset = 5632 - DIV_ROUND_UP(((bpp - 10) * 3584), 2);
+ else if (bpp >= 8)
+ rc->initial_offset = 6144 - DIV_ROUND_UP(((bpp - 8) * 512), 2);
+ else
+ rc->initial_offset = 6144;
+
+ /* initial_xmit_delay = rc_model_size/2/compression_bpp */
+ rc->initial_xmit_delay = DIV_ROUND_UP(DSC_RC_MODEL_SIZE_CONST, 2 * bpp);
+
+ rc->flatness_min_qp = 3 + qp_bpc_modifier;
+ rc->flatness_max_qp = 12 + qp_bpc_modifier;
+
+ rc->rc_quant_incr_limit0 = 11 + qp_bpc_modifier;
+ rc->rc_quant_incr_limit1 = 11 + qp_bpc_modifier;
+
+ bpp_i = (2 * (bpp - 6));
+ 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);
+ rc->rc_range_params[buf_i].range_max_qp =
+ intel_lookup_range_max_qp(bpc, buf_i, bpp_i);
+
+ /* Calculate range_bgp_offset */
+ if (bpp <= 6) {
+ rc->rc_range_params[buf_i].range_bpg_offset = ofs_und6[buf_i];
+ } else if (bpp <= 8) {
+ res = DIV_ROUND_UP(((bpp - 6) * (ofs_und8[buf_i] - ofs_und6[buf_i])), 2);
+ rc->rc_range_params[buf_i].range_bpg_offset =
+ ofs_und6[buf_i] + res;
+ } else if (bpp <= 12) {
+ rc->rc_range_params[buf_i].range_bpg_offset =
+ ofs_und8[buf_i];
+ } else if (bpp <= 15) {
+ res = DIV_ROUND_UP(((bpp - 12) * (ofs_und15[buf_i] - ofs_und12[buf_i])), 3);
+ rc->rc_range_params[buf_i].range_bpg_offset =
+ ofs_und12[buf_i] + res;
+ } else {
+ rc->rc_range_params[buf_i].range_bpg_offset =
+ ofs_und15[buf_i];
+ }
+ }
+}
+
int intel_dsc_compute_params(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config;
u16 compressed_bpp = pipe_config->dsc.compressed_bpp;
const struct rc_parameters *rc_params;
+ struct rc_parameters *rc = NULL;
u8 i = 0;
vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay;
@@ -412,9 +483,24 @@ int intel_dsc_compute_params(struct intel_encoder *encoder,
vdsc_cfg->rc_buf_thresh[13] = 0x7D;
}
- rc_params = get_rc_params(compressed_bpp, vdsc_cfg->bits_per_component);
- if (!rc_params)
- return -EINVAL;
+ /*
+ * From XE_LPD onwards we supports compression bpps in steps of 1
+ * upto uncompressed bpp-1, hence add calculations for all the rc
+ * parameters
+ */
+ if (DISPLAY_VER(dev_priv) >= 13) {
+ rc = kmalloc(sizeof(*rc), GFP_KERNEL);
+ if (!rc)
+ return -ENOMEM;
+
+ calculate_rc_params(rc, vdsc_cfg);
+ rc_params = rc;
+ } else {
+ rc_params = get_rc_params(compressed_bpp,
+ vdsc_cfg->bits_per_component);
+ if (!rc_params)
+ return -EINVAL;
+ }
vdsc_cfg->first_line_bpg_offset = rc_params->first_line_bpg_offset;
vdsc_cfg->initial_xmit_delay = rc_params->initial_xmit_delay;
@@ -440,20 +526,20 @@ int intel_dsc_compute_params(struct intel_encoder *encoder,
/*
* BitsPerComponent value determines mux_word_size:
- * When BitsPerComponent is 12bpc, muxWordSize will be equal to 64 bits
- * When BitsPerComponent is 8 or 10bpc, muxWordSize will be equal to
- * 48 bits
+ * When BitsPerComponent is less than or 10bpc, muxWordSize will be equal to
+ * 48 bits otherwise 64
*/
- if (vdsc_cfg->bits_per_component == 8 ||
- vdsc_cfg->bits_per_component == 10)
+ if (vdsc_cfg->bits_per_component <= 10)
vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
- else if (vdsc_cfg->bits_per_component == 12)
+ else
vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
/* InitialScaleValue is a 6 bit value with 3 fractional bits (U3.3) */
vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) /
(vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset);
+ kfree(rc);
+
return 0;
}
@@ -469,13 +555,13 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state)
* POWER_DOMAIN_TRANSCODER_VDSC_PW2 power domain in two cases:
*
* - ICL eDP/DSI transcoder
- * - Gen12+ (except RKL) pipe A
+ * - Display version 12 (except RKL) pipe A
*
* For any other pipe, VDSC/joining uses the power well associated with
* the pipe in use. Hence another reference on the pipe power domain
* will suffice. (Except no VDSC/joining on ICL pipe A.)
*/
- if (DISPLAY_VER(i915) >= 12 && !IS_ROCKETLAKE(i915) && pipe == PIPE_A)
+ if (DISPLAY_VER(i915) == 12 && !IS_ROCKETLAKE(i915) && pipe == PIPE_A)
return POWER_DOMAIN_TRANSCODER_VDSC_PW2;
else if (is_pipe_dsc(crtc_state))
return POWER_DOMAIN_PIPE(pipe);
@@ -1020,6 +1106,43 @@ static i915_reg_t dss_ctl2_reg(const struct intel_crtc_state *crtc_state)
return is_pipe_dsc(crtc_state) ? ICL_PIPE_DSS_CTL2(pipe) : DSS_CTL2;
}
+static struct intel_crtc *
+_get_crtc_for_pipe(struct drm_i915_private *i915, enum pipe pipe)
+{
+ if (!intel_pipe_valid(i915, pipe))
+ return NULL;
+
+ return intel_get_crtc_for_pipe(i915, pipe);
+}
+
+struct intel_crtc *
+intel_dsc_get_bigjoiner_secondary(const struct intel_crtc *primary_crtc)
+{
+ return _get_crtc_for_pipe(to_i915(primary_crtc->base.dev), primary_crtc->pipe + 1);
+}
+
+static struct intel_crtc *
+intel_dsc_get_bigjoiner_primary(const struct intel_crtc *secondary_crtc)
+{
+ return _get_crtc_for_pipe(to_i915(secondary_crtc->base.dev), secondary_crtc->pipe - 1);
+}
+
+void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ u32 dss_ctl1_val = 0;
+
+ if (crtc_state->bigjoiner && !crtc_state->dsc.compression_enable) {
+ if (crtc_state->bigjoiner_slave)
+ dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE;
+ else
+ dss_ctl1_val |= UNCOMPRESSED_JOINER_MASTER;
+
+ intel_de_write(dev_priv, dss_ctl1_reg(crtc_state), dss_ctl1_val);
+ }
+}
+
void intel_dsc_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
@@ -1059,11 +1182,31 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- if (!old_crtc_state->dsc.compression_enable)
- return;
+ /* Disable only if either of them is enabled */
+ if (old_crtc_state->dsc.compression_enable ||
+ old_crtc_state->bigjoiner) {
+ intel_de_write(dev_priv, dss_ctl1_reg(old_crtc_state), 0);
+ intel_de_write(dev_priv, dss_ctl2_reg(old_crtc_state), 0);
+ }
+}
+
+void intel_uncompressed_joiner_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ u32 dss_ctl1;
- intel_de_write(dev_priv, dss_ctl1_reg(old_crtc_state), 0);
- intel_de_write(dev_priv, dss_ctl2_reg(old_crtc_state), 0);
+ dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc_state));
+ if (dss_ctl1 & UNCOMPRESSED_JOINER_MASTER) {
+ crtc_state->bigjoiner = true;
+ crtc_state->bigjoiner_linked_crtc = intel_dsc_get_bigjoiner_secondary(crtc);
+ drm_WARN_ON(&dev_priv->drm, !crtc_state->bigjoiner_linked_crtc);
+ } else if (dss_ctl1 & UNCOMPRESSED_JOINER_SLAVE) {
+ crtc_state->bigjoiner = true;
+ crtc_state->bigjoiner_slave = true;
+ crtc_state->bigjoiner_linked_crtc = intel_dsc_get_bigjoiner_primary(crtc);
+ drm_WARN_ON(&dev_priv->drm, !crtc_state->bigjoiner_linked_crtc);
+ }
}
void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
@@ -1100,14 +1243,11 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
if (!(dss_ctl1 & MASTER_BIG_JOINER_ENABLE)) {
crtc_state->bigjoiner_slave = true;
- if (!WARN_ON(crtc->pipe == PIPE_A))
- crtc_state->bigjoiner_linked_crtc =
- intel_get_crtc_for_pipe(dev_priv, crtc->pipe - 1);
+ crtc_state->bigjoiner_linked_crtc = intel_dsc_get_bigjoiner_primary(crtc);
} else {
- if (!WARN_ON(INTEL_NUM_PIPES(dev_priv) == crtc->pipe + 1))
- crtc_state->bigjoiner_linked_crtc =
- intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1);
+ crtc_state->bigjoiner_linked_crtc = intel_dsc_get_bigjoiner_secondary(crtc);
}
+ drm_WARN_ON(&dev_priv->drm, !crtc_state->bigjoiner_linked_crtc);
}
/* FIXME: add more state readout as needed */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
index 65d301c23580..dfb1fd38deb4 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -12,13 +12,16 @@ struct intel_encoder;
struct intel_crtc_state;
bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state);
+void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state);
void intel_dsc_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
int intel_dsc_compute_params(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config);
+void intel_uncompressed_joiner_get_config(struct intel_crtc_state *crtc_state);
void intel_dsc_get_config(struct intel_crtc_state *crtc_state);
enum intel_display_power_domain
intel_dsc_power_domain(const struct intel_crtc_state *crtc_state);
+struct intel_crtc *intel_dsc_get_bigjoiner_secondary(const struct intel_crtc *primary_crtc);
#endif /* __INTEL_VDSC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index a9c2b2fd9252..c335b1dbafcf 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -5,6 +5,7 @@
*/
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_vrr.h"
@@ -67,7 +68,10 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
/* The hw imposes the extra scanline before frame start */
- return crtc_state->vrr.pipeline_full + i915->framestart_delay + 1;
+ if (DISPLAY_VER(i915) >= 13)
+ return crtc_state->vrr.guardband + i915->framestart_delay + 1;
+ else
+ return crtc_state->vrr.pipeline_full + i915->framestart_delay + 1;
}
int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state)
@@ -85,6 +89,8 @@ void
intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
@@ -123,17 +129,26 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1;
/*
- * FIXME: s/4/framestart_delay+1/ to get consistent
- * earliest/latest points for register latching regardless
- * of the framestart_delay used?
- *
- * FIXME: this really needs the extra scanline to provide consistent
- * behaviour for all framestart_delay values. Otherwise with
- * framestart_delay==3 we will end up extending the min vblank by
- * one extra line.
+ * For XE_LPD+, we use guardband and pipeline override
+ * is deprecated.
*/
- crtc_state->vrr.pipeline_full =
- min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1);
+ if (DISPLAY_VER(i915) >= 13)
+ crtc_state->vrr.guardband =
+ crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay -
+ i915->window2_delay;
+ else
+ /*
+ * FIXME: s/4/framestart_delay+1/ to get consistent
+ * earliest/latest points for register latching regardless
+ * of the framestart_delay used?
+ *
+ * FIXME: this really needs the extra scanline to provide consistent
+ * behaviour for all framestart_delay values. Otherwise with
+ * framestart_delay==3 we will end up extending the min vblank by
+ * one extra line.
+ */
+ crtc_state->vrr.pipeline_full =
+ min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1);
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
@@ -148,10 +163,15 @@ void intel_vrr_enable(struct intel_encoder *encoder,
if (!crtc_state->vrr.enable)
return;
- trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
- VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
- VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
- VRR_CTL_PIPELINE_FULL_OVERRIDE;
+ if (DISPLAY_VER(dev_priv) >= 13)
+ trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
+ VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
+ XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
+ else
+ trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
+ VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
+ VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
+ VRR_CTL_PIPELINE_FULL_OVERRIDE;
intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1);
intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1);
@@ -198,8 +218,13 @@ void intel_vrr_get_config(struct intel_crtc *crtc,
if (!crtc_state->vrr.enable)
return;
- if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE)
- crtc_state->vrr.pipeline_full = REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl);
+ if (DISPLAY_VER(dev_priv) >= 13)
+ crtc_state->vrr.guardband =
+ REG_FIELD_GET(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, trans_vrr_ctl);
+ else
+ if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE)
+ crtc_state->vrr.pipeline_full =
+ REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl);
if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN)
crtc_state->vrr.flipline = intel_de_read(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder)) + 1;
crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1;
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index 17a98cb627df..394b7bbf48d8 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -2,6 +2,7 @@
/*
* Copyright © 2020 Intel Corporation
*/
+#include "intel_de.h"
#include "intel_display_types.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 7ffd7b570b54..92a4fd508e92 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -10,6 +10,7 @@
#include "i915_drv.h"
#include "intel_atomic_plane.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_pm.h"
@@ -198,6 +199,13 @@ static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
DRM_FORMAT_MOD_INVALID
};
+static const u64 adlp_step_a_plane_format_modifiers[] = {
+ I915_FORMAT_MOD_Y_TILED,
+ I915_FORMAT_MOD_X_TILED,
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+};
+
int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
{
switch (format) {
@@ -267,7 +275,7 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
{
- if (HAS_D12_PLANE_MINIMIZATION(i915))
+ if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
else
return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
@@ -286,40 +294,64 @@ bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
icl_hdr_plane_mask() & BIT(plane_id);
}
+static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state)
+{
+ unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+
+ /* two pixels per clock */
+ return DIV_ROUND_UP(pixel_rate, 2);
+}
+
static void
-skl_plane_ratio(const struct intel_crtc_state *crtc_state,
- const struct intel_plane_state *plane_state,
+glk_plane_ratio(const struct intel_plane_state *plane_state,
unsigned int *num, unsigned int *den)
{
- struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
if (fb->format->cpp[0] == 8) {
- if (DISPLAY_VER(dev_priv) >= 10) {
- *num = 10;
- *den = 8;
- } else {
- *num = 9;
- *den = 8;
- }
+ *num = 10;
+ *den = 8;
} else {
*num = 1;
*den = 1;
}
}
-static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
- unsigned int num, den;
unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+ unsigned int num, den;
- skl_plane_ratio(crtc_state, plane_state, &num, &den);
+ glk_plane_ratio(plane_state, &num, &den);
- /* two pixels per clock on glk+ */
- if (DISPLAY_VER(dev_priv) >= 10)
- den *= 2;
+ /* two pixels per clock */
+ return DIV_ROUND_UP(pixel_rate * num, 2 * den);
+}
+
+static void
+skl_plane_ratio(const struct intel_plane_state *plane_state,
+ unsigned int *num, unsigned int *den)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+ if (fb->format->cpp[0] == 8) {
+ *num = 9;
+ *den = 8;
+ } else {
+ *num = 1;
+ *den = 1;
+ }
+}
+
+static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state)
+{
+ unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+ unsigned int num, den;
+
+ skl_plane_ratio(plane_state, &num, &den);
return DIV_ROUND_UP(pixel_rate * num, den);
}
@@ -457,17 +489,35 @@ skl_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
+ struct drm_i915_private *i915 = to_i915(plane->base.dev);
const struct drm_format_info *info = drm_format_info(pixel_format);
int cpp = info->cpp[0];
+ int max_horizontal_pixels = 8192;
+ int max_stride_bytes;
+
+ if (DISPLAY_VER(i915) >= 13) {
+ /*
+ * The stride in bytes must not exceed of the size
+ * of 128K bytes. For pixel formats of 64bpp will allow
+ * for a 16K pixel surface.
+ */
+ max_stride_bytes = 131072;
+ if (cpp == 8)
+ max_horizontal_pixels = 16384;
+ else
+ max_horizontal_pixels = 65536;
+ } else {
+ /*
+ * "The stride in bytes must not exceed the
+ * of the size of 8K pixels and 32K bytes."
+ */
+ max_stride_bytes = 32768;
+ }
- /*
- * "The stride in bytes must not exceed the
- * of the size of 8K pixels and 32K bytes."
- */
if (drm_rotation_90_or_270(rotation))
- return min(8192, 32768 / cpp);
+ return min(max_horizontal_pixels, max_stride_bytes / cpp);
else
- return min(8192 * cpp, 32768);
+ return min(max_horizontal_pixels * cpp, max_stride_bytes);
}
@@ -800,6 +850,29 @@ static u32 cnl_plane_ctl_flip(unsigned int reflect)
return 0;
}
+static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+ if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
+ switch (fb->format->cpp[0]) {
+ case 2:
+ return PLANE_CTL_ARB_SLOTS(1);
+ default:
+ return PLANE_CTL_ARB_SLOTS(0);
+ }
+ } else {
+ switch (fb->format->cpp[0]) {
+ case 8:
+ return PLANE_CTL_ARB_SLOTS(3);
+ case 4:
+ return PLANE_CTL_ARB_SLOTS(1);
+ default:
+ return PLANE_CTL_ARB_SLOTS(0);
+ }
+ }
+}
+
static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
@@ -829,7 +902,7 @@ static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
plane_ctl = PLANE_CTL_ENABLE;
- if (DISPLAY_VER(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) < 10) {
plane_ctl |= skl_plane_ctl_alpha(plane_state);
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
@@ -853,6 +926,10 @@ static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
+ /* Wa_22012358565:adlp */
+ if (DISPLAY_VER(dev_priv) == 13)
+ plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
+
return plane_ctl;
}
@@ -909,6 +986,21 @@ static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
return plane_color_ctl;
}
+static u32 skl_surf_address(const struct intel_plane_state *plane_state,
+ int color_plane)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+ u32 offset = plane_state->view.color_plane[color_plane].offset;
+
+ if (intel_fb_uses_dpt(fb)) {
+ WARN_ON(offset & 0x1fffff);
+ return offset >> 9;
+ } else {
+ WARN_ON(offset & 0xfff);
+ return offset;
+ }
+}
+
static void
skl_program_plane(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
@@ -919,7 +1011,7 @@ skl_program_plane(struct intel_plane *plane,
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
- u32 surf_addr = plane_state->view.color_plane[color_plane].offset;
+ u32 surf_addr = skl_surf_address(plane_state, color_plane);
u32 stride = skl_plane_stride(plane_state, color_plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
int aux_plane = skl_main_to_aux_plane(fb, color_plane);
@@ -958,7 +1050,7 @@ skl_program_plane(struct intel_plane *plane,
}
if (aux_plane) {
- aux_dist = plane_state->view.color_plane[aux_plane].offset - surf_addr;
+ aux_dist = skl_surf_address(plane_state, aux_plane) - surf_addr;
if (DISPLAY_VER(dev_priv) < 12)
aux_dist |= skl_plane_stride(plane_state, aux_plane);
@@ -1008,6 +1100,14 @@ skl_program_plane(struct intel_plane *plane,
intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
/*
+ * Enable the scaler before the plane so that we don't
+ * get a catastrophic underrun even if the two operations
+ * end up happening in two different frames.
+ */
+ if (plane_state->scaler_id >= 0)
+ skl_program_plane_scaler(plane, crtc_state, plane_state);
+
+ /*
* The control register self-arms if the plane was previously
* disabled. Try to make the plane enable atomic by writing
* the control register just before the surface register.
@@ -1016,9 +1116,6 @@ skl_program_plane(struct intel_plane *plane,
intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
intel_plane_ggtt_offset(plane_state) + surf_addr);
- if (plane_state->scaler_id >= 0)
- skl_program_plane_scaler(plane, crtc_state, plane_state);
-
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
@@ -1082,7 +1179,6 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
- struct drm_format_name_buf format_name;
if (!fb)
return 0;
@@ -1103,8 +1199,7 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
}
if (drm_rotation_90_or_270(rotation)) {
- if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
- fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
+ if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
drm_dbg_kms(&dev_priv->drm,
"Y/Yf tiling required for 90/270!\n");
return -EINVAL;
@@ -1130,9 +1225,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
case DRM_FORMAT_XVYU12_16161616:
case DRM_FORMAT_XVYU16161616:
drm_dbg_kms(&dev_priv->drm,
- "Unsupported pixel format %s for 90/270!\n",
- drm_get_format_name(fb->format->format,
- &format_name));
+ "Unsupported pixel format %p4cc for 90/270!\n",
+ &fb->format->format);
return -EINVAL;
default:
break;
@@ -1184,7 +1278,7 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s
* than the cursor ending less than 4 pixels from the left edge of the
* screen may cause FIFO underflow and display corruption.
*/
- if (IS_DISPLAY_VER(dev_priv, 10) &&
+ if (DISPLAY_VER(dev_priv) == 10 &&
(crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
drm_dbg_kms(&dev_priv->drm,
"requested plane X %s position %d invalid (valid range %d-%d)\n",
@@ -1412,7 +1506,10 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
}
}
- drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
+ if (DISPLAY_VER(dev_priv) >= 13)
+ drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
+ else
+ drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
plane_state->view.color_plane[0].offset = offset;
plane_state->view.color_plane[0].x = x;
@@ -1486,7 +1583,10 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
}
}
- drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
+ if (DISPLAY_VER(i915) >= 13)
+ drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
+ else
+ drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
plane_state->view.color_plane[uv_plane].offset = offset;
plane_state->view.color_plane[uv_plane].x = x;
@@ -1671,7 +1771,7 @@ static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
return false;
- if (IS_DISPLAY_VER(dev_priv, 9) && pipe == PIPE_C)
+ if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
return false;
if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
@@ -1813,6 +1913,10 @@ static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
return false;
+ /* Wa_22011186057 */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ return false;
+
return plane_id < PLANE_SPRITE4;
}
@@ -1830,8 +1934,12 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
+ break;
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+ /* Wa_22011186057 */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ return false;
break;
default:
return false;
@@ -1886,7 +1994,10 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
enum plane_id plane_id)
{
- if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
+ /* Wa_22011186057 */
+ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_A0))
+ return adlp_step_a_plane_format_modifiers;
+ else if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
return gen12_plane_format_modifiers_mc_ccs;
else
return gen12_plane_format_modifiers_rc_ccs;
@@ -1965,12 +2076,15 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
plane->min_width = icl_plane_min_width;
plane->max_width = icl_plane_max_width;
plane->max_height = icl_plane_max_height;
+ plane->min_cdclk = icl_plane_min_cdclk;
} else if (DISPLAY_VER(dev_priv) >= 10) {
plane->max_width = glk_plane_max_width;
plane->max_height = skl_plane_max_height;
+ plane->min_cdclk = glk_plane_min_cdclk;
} else {
plane->max_width = skl_plane_max_width;
plane->max_height = skl_plane_max_height;
+ plane->min_cdclk = skl_plane_min_cdclk;
}
plane->max_stride = skl_plane_max_stride;
@@ -1978,11 +2092,10 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
plane->disable_plane = skl_disable_plane;
plane->get_hw_state = skl_plane_get_hw_state;
plane->check_plane = skl_plane_check;
- plane->min_cdclk = skl_plane_min_cdclk;
if (plane_id == PLANE_PRIMARY) {
- plane->need_async_flip_disable_wa = IS_DISPLAY_RANGE(dev_priv,
- 9, 10);
+ plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv,
+ 9, 10);
plane->async_flip = skl_plane_async_flip;
plane->enable_flip_done = skl_plane_enable_flip_done;
plane->disable_flip_done = skl_plane_disable_flip_done;
@@ -2024,9 +2137,12 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
if (ret)
goto fail;
- supported_rotations =
- DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
- DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
+ if (DISPLAY_VER(dev_priv) >= 13)
+ supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
+ else
+ supported_rotations =
+ DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
+ DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv))
supported_rotations |= DRM_MODE_REFLECT_X;
@@ -2197,7 +2313,11 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
- fb->pitches[0] = (val & 0x3ff) * stride_mult;
+
+ if (DISPLAY_VER(dev_priv) >= 13)
+ fb->pitches[0] = (val & PLANE_STRIDE_MASK_XELPD) * stride_mult;
+ else
+ fb->pitches[0] = (val & PLANE_STRIDE_MASK) * stride_mult;
aligned_height = intel_fb_align_height(fb, 0, fb->height);
@@ -2215,4 +2335,3 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
error:
kfree(intel_fb);
}
-
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 74a27508759d..084c9c43b2ed 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -33,6 +33,8 @@
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_connector.h"
+#include "intel_crtc.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsi.h"
#include "intel_fifo_underrun.h"
@@ -297,7 +299,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder,
else
pipe_config->pipe_bpp = 18;
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
/* Enable Frame time stamp based scanline reporting */
pipe_config->mode_flags |=
I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
@@ -522,7 +524,7 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
if (IS_GEMINILAKE(dev_priv))
glk_dsi_device_ready(encoder);
- else if (IS_GEN9_LP(dev_priv))
+ else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_dsi_device_ready(encoder);
else
vlv_dsi_device_ready(encoder);
@@ -601,7 +603,7 @@ static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder)
drm_dbg_kms(&dev_priv->drm, "\n");
for_each_dsi_port(port, intel_dsi->ports) {
/* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */
- i915_reg_t port_ctrl = IS_GEN9_LP(dev_priv) ?
+ i915_reg_t port_ctrl = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A);
u32 val;
@@ -621,7 +623,7 @@ static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder)
* On VLV/CHV, wait till Clock lanes are in LP-00 state for MIPI
* Port A only. MIPI Port C has no similar bit for checking.
*/
- if ((IS_GEN9_LP(dev_priv) || port == PORT_A) &&
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) || port == PORT_A) &&
intel_de_wait_for_clear(dev_priv, port_ctrl,
AFE_LATCHOUT, 30))
drm_err(&dev_priv->drm, "DSI LP not going Low\n");
@@ -646,7 +648,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder,
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
u32 temp;
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
for_each_dsi_port(port, intel_dsi->ports) {
temp = intel_de_read(dev_priv,
MIPI_CTRL(port));
@@ -666,7 +668,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder,
}
for_each_dsi_port(port, intel_dsi->ports) {
- i915_reg_t port_ctrl = IS_GEN9_LP(dev_priv) ?
+ i915_reg_t port_ctrl = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
u32 temp;
@@ -703,7 +705,7 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
- i915_reg_t port_ctrl = IS_GEN9_LP(dev_priv) ?
+ i915_reg_t port_ctrl = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
u32 temp;
@@ -714,6 +716,19 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
}
}
+static void intel_dsi_wait_panel_power_cycle(struct intel_dsi *intel_dsi)
+{
+ ktime_t panel_power_on_time;
+ s64 panel_power_off_duration;
+
+ panel_power_on_time = ktime_get_boottime();
+ panel_power_off_duration = ktime_ms_delta(panel_power_on_time,
+ intel_dsi->panel_power_off_time);
+
+ if (panel_power_off_duration < (s64)intel_dsi->panel_pwr_cycle_delay)
+ msleep(intel_dsi->panel_pwr_cycle_delay - panel_power_off_duration);
+}
+
static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
const struct intel_crtc_state *pipe_config);
static void intel_dsi_unprepare(struct intel_encoder *encoder);
@@ -775,13 +790,15 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state,
drm_dbg_kms(&dev_priv->drm, "\n");
+ intel_dsi_wait_panel_power_cycle(intel_dsi);
+
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
/*
* The BIOS may leave the PLL in a wonky state where it doesn't
* lock. It needs to be fully powered down to fix it.
*/
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
bxt_dsi_pll_disable(encoder);
bxt_dsi_pll_enable(encoder, pipe_config);
} else {
@@ -846,8 +863,10 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state,
/* Send initialization commands in LP mode */
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
- /* Enable port in pre-enable phase itself because as per hw team
- * recommendation, port should be enabled befor plane & pipe */
+ /*
+ * Enable port in pre-enable phase itself because as per hw team
+ * recommendation, port should be enabled before plane & pipe
+ */
if (is_cmd_mode(intel_dsi)) {
for_each_dsi_port(port, intel_dsi->ports)
intel_de_write(dev_priv,
@@ -932,7 +951,7 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state,
drm_dbg_kms(&dev_priv->drm, "\n");
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
intel_crtc_vblank_off(old_crtc_state);
skl_scaler_disable(old_crtc_state);
@@ -971,7 +990,7 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state,
val & ~MIPIO_RST_CTRL);
}
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
bxt_dsi_pll_disable(encoder);
} else {
u32 val;
@@ -989,18 +1008,14 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state,
intel_dsi_msleep(intel_dsi, intel_dsi->panel_off_delay);
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF);
- /*
- * FIXME As we do with eDP, just make a note of the time here
- * and perform the wait before the next panel power on.
- */
- msleep(intel_dsi->panel_pwr_cycle_delay);
+ intel_dsi->panel_power_off_time = ktime_get_boottime();
}
static void intel_dsi_shutdown(struct intel_encoder *encoder)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
- msleep(intel_dsi->panel_pwr_cycle_delay);
+ intel_dsi_wait_panel_power_cycle(intel_dsi);
}
static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
@@ -1024,12 +1039,13 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
* configuration, otherwise accessing DSI registers will hang the
* machine. See BSpec North Display Engine registers/MIPI[BXT].
*/
- if (IS_GEN9_LP(dev_priv) && !bxt_dsi_pll_is_enabled(dev_priv))
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ !bxt_dsi_pll_is_enabled(dev_priv))
goto out_put_power;
/* XXX: this only works for one DSI output */
for_each_dsi_port(port, intel_dsi->ports) {
- i915_reg_t ctrl_reg = IS_GEN9_LP(dev_priv) ?
+ i915_reg_t ctrl_reg = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ?
BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
bool enabled = intel_de_read(dev_priv, ctrl_reg) & DPI_ENABLE;
@@ -1055,7 +1071,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
if (!(intel_de_read(dev_priv, MIPI_DEVICE_READY(port)) & DEVICE_READY))
continue;
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
u32 tmp = intel_de_read(dev_priv, MIPI_CTRL(port));
tmp &= BXT_PIPE_SELECT_MASK;
tmp >>= BXT_PIPE_SELECT_SHIFT;
@@ -1251,7 +1267,7 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
bxt_dsi_get_pipe_config(encoder, pipe_config);
pclk = bxt_dsi_get_pclk(encoder, pipe_config);
} else {
@@ -1317,7 +1333,7 @@ static void set_dsi_timings(struct drm_encoder *encoder,
hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio);
for_each_dsi_port(port, intel_dsi->ports) {
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
/*
* Program hdisplay and vdisplay on MIPI transcoder.
* This is different from calculated hactive and
@@ -1407,7 +1423,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
tmp &= ~READ_REQUEST_PRIORITY_MASK;
intel_de_write(dev_priv, MIPI_CTRL(port),
tmp | READ_REQUEST_PRIORITY_HIGH);
- } else if (IS_GEN9_LP(dev_priv)) {
+ } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
enum pipe pipe = intel_crtc->pipe;
tmp = intel_de_read(dev_priv, MIPI_CTRL(port));
@@ -1445,7 +1461,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
if (intel_dsi->clock_stop)
tmp |= CLOCKSTOP;
- if (IS_GEN9_LP(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
tmp |= BXT_DPHY_DEFEATURE_EN;
if (!is_cmd_mode(intel_dsi))
tmp |= BXT_DEFEATURE_DPI_FIFO_CTR;
@@ -1492,7 +1508,8 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
intel_de_write(dev_priv, MIPI_INIT_COUNT(port),
txclkesc(intel_dsi->escape_clk_div, 100));
- if (IS_GEN9_LP(dev_priv) && (!intel_dsi->dual_link)) {
+ if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
+ !intel_dsi->dual_link) {
/*
* BXT spec says write MIPI_INIT_COUNT for
* both the ports, even if only one is
@@ -1570,7 +1587,7 @@ static void intel_dsi_unprepare(struct intel_encoder *encoder)
/* Panel commands can be sent when clock is in LP11 */
intel_de_write(dev_priv, MIPI_DEVICE_READY(port), 0x0);
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_dsi_reset_clocks(encoder, port);
else
vlv_dsi_reset_clocks(encoder, port);
@@ -1828,7 +1845,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
if (!intel_bios_is_dsi_present(dev_priv, &port))
return;
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
else
dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
@@ -1854,7 +1871,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
intel_encoder->compute_config = intel_dsi_compute_config;
intel_encoder->pre_enable = intel_dsi_pre_enable;
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
intel_encoder->enable = bxt_dsi_enable;
intel_encoder->disable = intel_dsi_disable;
intel_encoder->post_disable = intel_dsi_post_disable;
@@ -1874,13 +1891,15 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
* On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
* port C. BXT isn't limited like this.
*/
- if (IS_GEN9_LP(dev_priv))
+ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
intel_encoder->pipe_mask = ~0;
else if (port == PORT_A)
intel_encoder->pipe_mask = BIT(PIPE_A);
else
intel_encoder->pipe_mask = BIT(PIPE_B);
+ intel_dsi->panel_power_off_time = ktime_get_boottime();
+
if (dev_priv->vbt.dsi.config->dual_link)
intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C);
else
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
index 4070b00c3690..90185b219447 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c
@@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include "i915_drv.h"
+#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsi.h"
#include "intel_sideband.h"