From 4b9cc6efeb0684912d518e9953a1d493b2b89a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:17 +0200 Subject: drm/i915/dvo: Remove unused panel_wants_dither MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_dvo.panel_wants_dither is only set but never used. We can't do dithering on the gmch side anyway since the dithering logic is part of the integrated LVDS port and not available for other output types. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index c86f9890754d..94dcc43876c9 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -118,8 +118,6 @@ struct intel_dvo { struct intel_dvo_device dev; struct intel_connector *attached_connector; - - bool panel_wants_dither; }; static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder) @@ -531,8 +529,6 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_encoder); intel_panel_init(intel_connector); - - intel_dvo->panel_wants_dither = true; } return; -- cgit v1.2.3 From 3b5130a68df1a513713b027d03125ba11ebc2975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:18 +0200 Subject: drm/i915/dvo: Don't leak connector state on DVO init failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we can't initialize the DVO encoder also free the connector state allocated by intel_connector_alloc(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 94dcc43876c9..8859e400b860 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -535,5 +535,5 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) } kfree(intel_dvo); - kfree(intel_connector); + intel_connector_free(intel_connector); } -- cgit v1.2.3 From 6ebf5caf1fae75634b0564152958ecb433cfa952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:19 +0200 Subject: drm/i915/dvo: Actually initialize the DVO encoder type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We call drm_encoder_init() before determining the correct encoder type, thus we always end up with DRM_MODE_ENCODER_NONE. Determine the correct encoder type earlier. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 8859e400b860..fe61cb41d83b 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -387,13 +387,26 @@ static enum port intel_dvo_port(i915_reg_t dvo_reg) return PORT_C; } +static int intel_dvo_encoder_type(const struct intel_dvo_device *dvo) +{ + switch (dvo->type) { + case INTEL_DVO_CHIP_TMDS: + return DRM_MODE_ENCODER_TMDS; + case INTEL_DVO_CHIP_LVDS_NO_FIXED: + case INTEL_DVO_CHIP_LVDS: + return DRM_MODE_ENCODER_LVDS; + default: + MISSING_CASE(dvo->type); + return DRM_MODE_ENCODER_NONE; + } +} + void intel_dvo_init(struct drm_i915_private *dev_priv) { struct intel_encoder *intel_encoder; struct intel_dvo *intel_dvo; struct intel_connector *intel_connector; int i; - int encoder_type = DRM_MODE_ENCODER_NONE; intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) @@ -481,7 +494,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) port = intel_dvo_port(dvo->dvo_reg); drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dvo_enc_funcs, encoder_type, + &intel_dvo_enc_funcs, + intel_dvo_encoder_type(dvo), "DVO %c", port_name(port)); intel_encoder->type = INTEL_OUTPUT_DVO; @@ -500,14 +514,12 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) drm_connector_init(&dev_priv->drm, connector, &intel_dvo_connector_funcs, DRM_MODE_CONNECTOR_DVII); - encoder_type = DRM_MODE_ENCODER_TMDS; break; case INTEL_DVO_CHIP_LVDS_NO_FIXED: case INTEL_DVO_CHIP_LVDS: drm_connector_init(&dev_priv->drm, connector, &intel_dvo_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - encoder_type = DRM_MODE_ENCODER_LVDS; break; } -- cgit v1.2.3 From 201ec1bbca03a0c190962626574f8061a84cc9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:20 +0200 Subject: drm/i915/dvo: Introduce intel_dvo_connector_type() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce intel_dvo_connector_type() as a counterpart to intel_dvo_encoder_type(), mainly to declutter intel_dvo_init() a bit. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index fe61cb41d83b..9ce3b4ec6a4d 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -401,6 +401,20 @@ static int intel_dvo_encoder_type(const struct intel_dvo_device *dvo) } } +static int intel_dvo_connector_type(const struct intel_dvo_device *dvo) +{ + switch (dvo->type) { + case INTEL_DVO_CHIP_TMDS: + return DRM_MODE_CONNECTOR_DVII; + case INTEL_DVO_CHIP_LVDS_NO_FIXED: + case INTEL_DVO_CHIP_LVDS: + return DRM_MODE_CONNECTOR_LVDS; + default: + MISSING_CASE(dvo->type); + return DRM_MODE_CONNECTOR_Unknown; + } +} + void intel_dvo_init(struct drm_i915_private *dev_priv) { struct intel_encoder *intel_encoder; @@ -507,21 +521,13 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | BIT(INTEL_OUTPUT_DVO); - switch (dvo->type) { - case INTEL_DVO_CHIP_TMDS: + if (dvo->type == INTEL_DVO_CHIP_TMDS) intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - DRM_MODE_CONNECTOR_DVII); - break; - case INTEL_DVO_CHIP_LVDS_NO_FIXED: - case INTEL_DVO_CHIP_LVDS: - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - break; - } + + drm_connector_init(&dev_priv->drm, connector, + &intel_dvo_connector_funcs, + intel_dvo_connector_type(dvo)); drm_connector_helper_add(connector, &intel_dvo_connector_helper_funcs); -- cgit v1.2.3 From c584f86c6242dff11d3e8f7b1646e5470a132784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:21 +0200 Subject: drm/i915/dvo: Eliminate useless 'port' variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorder the drm_encoder_init() vs. encoder->port assignment so that we don't need the extra 'port' variable. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 9ce3b4ec6a4d..87ee913cf89b 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -453,7 +453,6 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) bool dvoinit; enum pipe pipe; u32 dpll[I915_MAX_PIPES]; - enum port port; /* * Allow the I2C driver info to specify the GPIO to be used in @@ -506,21 +505,20 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) if (!dvoinit) continue; - port = intel_dvo_port(dvo->dvo_reg); - drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dvo_enc_funcs, - intel_dvo_encoder_type(dvo), - "DVO %c", port_name(port)); - intel_encoder->type = INTEL_OUTPUT_DVO; intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - intel_encoder->port = port; + intel_encoder->port = intel_dvo_port(dvo->dvo_reg); intel_encoder->pipe_mask = ~0; if (dvo->type != INTEL_DVO_CHIP_LVDS) intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | BIT(INTEL_OUTPUT_DVO); + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, + &intel_dvo_enc_funcs, + intel_dvo_encoder_type(dvo), + "DVO %c", port_name(intel_encoder->port)); + if (dvo->type == INTEL_DVO_CHIP_TMDS) intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; -- cgit v1.2.3 From d82b9a898d52a30adbedd158222f162489db52ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:22 +0200 Subject: drm/i915/dvo: Flatten intel_dvo_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The loop over intel_dvo_devices[] makes intel_dvo_init() an ugly mess. Pull the i2c device probe out to a separate function so that we can get rid of the loop and flatten the code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 217 +++++++++++++++++-------------- 1 file changed, 117 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 87ee913cf89b..bccbda50113c 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -415,12 +415,88 @@ static int intel_dvo_connector_type(const struct intel_dvo_device *dvo) } } +static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv, + struct intel_dvo *intel_dvo, + const struct intel_dvo_device *dvo) +{ + struct i2c_adapter *i2c; + u32 dpll[I915_MAX_PIPES]; + enum pipe pipe; + int gpio; + bool ret; + + /* + * Allow the I2C driver info to specify the GPIO to be used in + * special cases, but otherwise default to what's defined + * in the spec. + */ + if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) + gpio = dvo->gpio; + else if (dvo->type == INTEL_DVO_CHIP_LVDS) + gpio = GMBUS_PIN_SSC; + else + gpio = GMBUS_PIN_DPB; + + /* + * Set up the I2C bus necessary for the chip we're probing. + * It appears that everything is on GPIOE except for panels + * on i830 laptops, which are on GPIOB (DVOA). + */ + i2c = intel_gmbus_get_adapter(dev_priv, gpio); + + intel_dvo->dev = *dvo; + + /* + * GMBUS NAK handling seems to be unstable, hence let the + * transmitter detection run in bit banging mode for now. + */ + intel_gmbus_force_bit(i2c, true); + + /* + * ns2501 requires the DVO 2x clock before it will + * respond to i2c accesses, so make sure we have + * the clock enabled before we attempt to initialize + * the device. + */ + for_each_pipe(dev_priv, pipe) { + dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); + intel_de_write(dev_priv, DPLL(pipe), + dpll[pipe] | DPLL_DVO_2X_MODE); + } + + ret = dvo->dev_ops->init(&intel_dvo->dev, i2c); + + /* restore the DVO 2x clock state to original */ + for_each_pipe(dev_priv, pipe) { + intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); + } + + intel_gmbus_force_bit(i2c, false); + + return ret; +} + +static bool intel_dvo_probe(struct drm_i915_private *dev_priv, + struct intel_dvo *intel_dvo) +{ + int i; + + /* Now, try to find a controller */ + for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { + if (intel_dvo_init_dev(dev_priv, intel_dvo, + &intel_dvo_devices[i])) + return true; + } + + return false; +} + void intel_dvo_init(struct drm_i915_private *dev_priv) { struct intel_encoder *intel_encoder; struct intel_dvo *intel_dvo; struct intel_connector *intel_connector; - int i; + struct drm_connector *connector; intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) @@ -432,6 +508,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) return; } + connector = &intel_connector->base; + intel_dvo->attached_connector = intel_connector; intel_encoder = &intel_dvo->base; @@ -444,112 +522,51 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_encoder->pre_enable = intel_dvo_pre_enable; intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; - /* Now, try to find a controller */ - for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { - struct drm_connector *connector = &intel_connector->base; - const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; - struct i2c_adapter *i2c; - int gpio; - bool dvoinit; - enum pipe pipe; - u32 dpll[I915_MAX_PIPES]; + if (!intel_dvo_probe(dev_priv, intel_dvo)) { + kfree(intel_dvo); + intel_connector_free(intel_connector); + return; + } - /* - * Allow the I2C driver info to specify the GPIO to be used in - * special cases, but otherwise default to what's defined - * in the spec. - */ - if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) - gpio = dvo->gpio; - else if (dvo->type == INTEL_DVO_CHIP_LVDS) - gpio = GMBUS_PIN_SSC; - else - gpio = GMBUS_PIN_DPB; + intel_encoder->type = INTEL_OUTPUT_DVO; + intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; + intel_encoder->port = intel_dvo_port(intel_dvo->dev.dvo_reg); + intel_encoder->pipe_mask = ~0; - /* - * Set up the I2C bus necessary for the chip we're probing. - * It appears that everything is on GPIOE except for panels - * on i830 laptops, which are on GPIOB (DVOA). - */ - i2c = intel_gmbus_get_adapter(dev_priv, gpio); + if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS) + intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | + BIT(INTEL_OUTPUT_DVO); - intel_dvo->dev = *dvo; + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, + &intel_dvo_enc_funcs, + intel_dvo_encoder_type(&intel_dvo->dev), + "DVO %c", port_name(intel_encoder->port)); - /* - * GMBUS NAK handling seems to be unstable, hence let the - * transmitter detection run in bit banging mode for now. - */ - intel_gmbus_force_bit(i2c, true); + if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS) + intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_init(&dev_priv->drm, connector, + &intel_dvo_connector_funcs, + intel_dvo_connector_type(&intel_dvo->dev)); + drm_connector_helper_add(connector, + &intel_dvo_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + + intel_connector_attach_encoder(intel_connector, intel_encoder); + if (intel_dvo->dev.type == INTEL_DVO_CHIP_LVDS) { /* - * ns2501 requires the DVO 2x clock before it will - * respond to i2c accesses, so make sure we have - * have the clock enabled before we attempt to - * initialize the device. + * For our LVDS chipsets, we should hopefully be able + * to dig the fixed panel mode out of the BIOS data. + * However, it's in a different format from the BIOS + * data on chipsets with integrated LVDS (stored in AIM + * headers, likely), so for now, just get the current + * mode being output through DVO. */ - for_each_pipe(dev_priv, pipe) { - dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe)); - intel_de_write(dev_priv, DPLL(pipe), - dpll[pipe] | DPLL_DVO_2X_MODE); - } - - dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); - - /* restore the DVO 2x clock state to original */ - for_each_pipe(dev_priv, pipe) { - intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]); - } - - intel_gmbus_force_bit(i2c, false); - - if (!dvoinit) - continue; - - intel_encoder->type = INTEL_OUTPUT_DVO; - intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - intel_encoder->port = intel_dvo_port(dvo->dvo_reg); - intel_encoder->pipe_mask = ~0; - - if (dvo->type != INTEL_DVO_CHIP_LVDS) - intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | - BIT(INTEL_OUTPUT_DVO); - - drm_encoder_init(&dev_priv->drm, &intel_encoder->base, - &intel_dvo_enc_funcs, - intel_dvo_encoder_type(dvo), - "DVO %c", port_name(intel_encoder->port)); - - if (dvo->type == INTEL_DVO_CHIP_TMDS) - intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - - drm_connector_init(&dev_priv->drm, connector, - &intel_dvo_connector_funcs, - intel_dvo_connector_type(dvo)); - - drm_connector_helper_add(connector, - &intel_dvo_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - - intel_connector_attach_encoder(intel_connector, intel_encoder); - if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* - * For our LVDS chipsets, we should hopefully be able - * to dig the fixed panel mode out of the BIOS data. - * However, it's in a different format from the BIOS - * data on chipsets with integrated LVDS (stored in AIM - * headers, likely), so for now, just get the current - * mode being output through DVO. - */ - intel_panel_add_encoder_fixed_mode(intel_connector, - intel_encoder); - - intel_panel_init(intel_connector); - } + intel_panel_add_encoder_fixed_mode(intel_connector, + intel_encoder); - return; + intel_panel_init(intel_connector); } - - kfree(intel_dvo); - intel_connector_free(intel_connector); } -- cgit v1.2.3 From 09b350d7b05a62c9a59e201fcad4331ac6ee40c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:23 +0200 Subject: drm/i915/dvo: s/intel_encoder/encoder/ etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the pointless intel_ namespace from our encoder/connector variables. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 91 ++++++++++++++++---------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index bccbda50113c..d078cf0d9765 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -219,14 +219,14 @@ static void intel_enable_dvo(struct intel_atomic_state *state, } static enum drm_mode_status -intel_dvo_mode_valid(struct drm_connector *connector, +intel_dvo_mode_valid(struct drm_connector *_connector, struct drm_display_mode *mode) { - struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_dvo *intel_dvo = intel_attached_dvo(connector); const struct drm_display_mode *fixed_mode = - intel_panel_fixed_mode(intel_connector, mode); - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + intel_panel_fixed_mode(connector, mode); + int max_dotclk = to_i915(connector->base.dev)->max_dotclk_freq; int target_clock = mode->clock; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -237,7 +237,7 @@ intel_dvo_mode_valid(struct drm_connector *connector, if (fixed_mode) { enum drm_mode_status status; - status = intel_panel_mode_valid(intel_connector, mode); + status = intel_panel_mode_valid(connector, mode); if (status != MODE_OK) return status; @@ -315,13 +315,14 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, } static enum drm_connector_status -intel_dvo_detect(struct drm_connector *connector, bool force) +intel_dvo_detect(struct drm_connector *_connector, bool force) { - struct drm_i915_private *i915 = to_i915(connector->dev); - struct intel_dvo *intel_dvo = intel_attached_dvo(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dvo *intel_dvo = intel_attached_dvo(connector); DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + connector->base.base.id, connector->base.name); if (!INTEL_DISPLAY_ENABLED(i915)) return connector_status_disconnected; @@ -329,9 +330,10 @@ intel_dvo_detect(struct drm_connector *connector, bool force) return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); } -static int intel_dvo_get_modes(struct drm_connector *connector) +static int intel_dvo_get_modes(struct drm_connector *_connector) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); int num_modes; /* @@ -340,12 +342,12 @@ static int intel_dvo_get_modes(struct drm_connector *connector) * (TV-out, for example), but for now with just TMDS and LVDS, * that's not the case. */ - num_modes = intel_ddc_get_modes(connector, + num_modes = intel_ddc_get_modes(&connector->base, intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); if (num_modes) return num_modes; - return intel_panel_get_modes(to_intel_connector(connector)); + return intel_panel_get_modes(connector); } static const struct drm_connector_funcs intel_dvo_connector_funcs = { @@ -493,68 +495,66 @@ static bool intel_dvo_probe(struct drm_i915_private *dev_priv, void intel_dvo_init(struct drm_i915_private *dev_priv) { - struct intel_encoder *intel_encoder; + struct intel_connector *connector; + struct intel_encoder *encoder; struct intel_dvo *intel_dvo; - struct intel_connector *intel_connector; - struct drm_connector *connector; intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) return; - intel_connector = intel_connector_alloc(); - if (!intel_connector) { + connector = intel_connector_alloc(); + if (!connector) { kfree(intel_dvo); return; } - connector = &intel_connector->base; + intel_dvo->attached_connector = connector; - intel_dvo->attached_connector = intel_connector; + encoder = &intel_dvo->base; - intel_encoder = &intel_dvo->base; - - intel_encoder->disable = intel_disable_dvo; - intel_encoder->enable = intel_enable_dvo; - intel_encoder->get_hw_state = intel_dvo_get_hw_state; - intel_encoder->get_config = intel_dvo_get_config; - intel_encoder->compute_config = intel_dvo_compute_config; - intel_encoder->pre_enable = intel_dvo_pre_enable; - intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; + encoder->disable = intel_disable_dvo; + encoder->enable = intel_enable_dvo; + encoder->get_hw_state = intel_dvo_get_hw_state; + encoder->get_config = intel_dvo_get_config; + encoder->compute_config = intel_dvo_compute_config; + encoder->pre_enable = intel_dvo_pre_enable; + connector->get_hw_state = intel_dvo_connector_get_hw_state; if (!intel_dvo_probe(dev_priv, intel_dvo)) { kfree(intel_dvo); - intel_connector_free(intel_connector); + intel_connector_free(connector); return; } - intel_encoder->type = INTEL_OUTPUT_DVO; - intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - intel_encoder->port = intel_dvo_port(intel_dvo->dev.dvo_reg); - intel_encoder->pipe_mask = ~0; + encoder->type = INTEL_OUTPUT_DVO; + encoder->power_domain = POWER_DOMAIN_PORT_OTHER; + encoder->port = intel_dvo_port(intel_dvo->dev.dvo_reg); + encoder->pipe_mask = ~0; if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS) - intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | + encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | BIT(INTEL_OUTPUT_DVO); - drm_encoder_init(&dev_priv->drm, &intel_encoder->base, + drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_dvo_enc_funcs, intel_dvo_encoder_type(&intel_dvo->dev), - "DVO %c", port_name(intel_encoder->port)); + "DVO %c", port_name(encoder->port)); if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS) - intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT | + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - drm_connector_init(&dev_priv->drm, connector, + drm_connector_init(&dev_priv->drm, &connector->base, &intel_dvo_connector_funcs, intel_dvo_connector_type(&intel_dvo->dev)); - drm_connector_helper_add(connector, + drm_connector_helper_add(&connector->base, &intel_dvo_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->base.display_info.subpixel_order = SubPixelHorizontalRGB; + + intel_connector_attach_encoder(connector, encoder); - intel_connector_attach_encoder(intel_connector, intel_encoder); if (intel_dvo->dev.type == INTEL_DVO_CHIP_LVDS) { /* * For our LVDS chipsets, we should hopefully be able @@ -564,9 +564,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) * headers, likely), so for now, just get the current * mode being output through DVO. */ - intel_panel_add_encoder_fixed_mode(intel_connector, - intel_encoder); + intel_panel_add_encoder_fixed_mode(connector, encoder); - intel_panel_init(intel_connector); + intel_panel_init(connector); } } -- cgit v1.2.3 From ef228dbfff70ca5823495d78ddb632abe230ce6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:24 +0200 Subject: drm/i915/dvo: s/dev_priv/i915/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the modern style and rename most 'dev_priv' variables to 'i915'. intel_dvo_init_dev() is the sole exception since it needs the magic 'dev_priv' variable for the DPLL register macros. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 53 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index d078cf0d9765..9462b66e5fb4 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -132,12 +132,11 @@ static struct intel_dvo *intel_attached_dvo(struct intel_connector *connector) static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_dvo *intel_dvo = intel_attached_dvo(connector); u32 tmp; - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); if (!(tmp & DVO_ENABLE)) return false; @@ -148,11 +147,11 @@ static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); u32 tmp; - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); *pipe = (tmp & DVO_PIPE_SEL_MASK) >> DVO_PIPE_SEL_SHIFT; @@ -162,13 +161,13 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, static void intel_dvo_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); u32 tmp, flags = 0; pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO); - tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); if (tmp & DVO_HSYNC_ACTIVE_HIGH) flags |= DRM_MODE_FLAG_PHSYNC; else @@ -188,14 +187,14 @@ static void intel_disable_dvo(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(dev_priv, dvo_reg); + u32 temp = intel_de_read(i915, dvo_reg); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); - intel_de_write(dev_priv, dvo_reg, temp & ~DVO_ENABLE); - intel_de_read(dev_priv, dvo_reg); + intel_de_write(i915, dvo_reg, temp & ~DVO_ENABLE); + intel_de_read(i915, dvo_reg); } static void intel_enable_dvo(struct intel_atomic_state *state, @@ -203,17 +202,17 @@ static void intel_enable_dvo(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(dev_priv, dvo_reg); + u32 temp = intel_de_read(i915, dvo_reg); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, &pipe_config->hw.mode, &pipe_config->hw.adjusted_mode); - intel_de_write(dev_priv, dvo_reg, temp | DVO_ENABLE); - intel_de_read(dev_priv, dvo_reg); + intel_de_write(i915, dvo_reg, temp | DVO_ENABLE); + intel_de_read(i915, dvo_reg); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } @@ -287,7 +286,7 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); @@ -297,7 +296,7 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg; /* Save the data order, since I don't know what it should be set to. */ - dvo_val = intel_de_read(dev_priv, dvo_reg) & + dvo_val = intel_de_read(i915, dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; @@ -309,9 +308,9 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) dvo_val |= DVO_VSYNC_ACTIVE_HIGH; - intel_de_write(dev_priv, dvo_srcdim_reg, + intel_de_write(i915, dvo_srcdim_reg, (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); - intel_de_write(dev_priv, dvo_reg, dvo_val); + intel_de_write(i915, dvo_reg, dvo_val); } static enum drm_connector_status @@ -333,7 +332,7 @@ intel_dvo_detect(struct drm_connector *_connector, bool force) static int intel_dvo_get_modes(struct drm_connector *_connector) { struct intel_connector *connector = to_intel_connector(_connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int num_modes; /* @@ -343,7 +342,7 @@ static int intel_dvo_get_modes(struct drm_connector *_connector) * that's not the case. */ num_modes = intel_ddc_get_modes(&connector->base, - intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); + intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC)); if (num_modes) return num_modes; @@ -478,14 +477,14 @@ static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv, return ret; } -static bool intel_dvo_probe(struct drm_i915_private *dev_priv, +static bool intel_dvo_probe(struct drm_i915_private *i915, struct intel_dvo *intel_dvo) { int i; /* Now, try to find a controller */ for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { - if (intel_dvo_init_dev(dev_priv, intel_dvo, + if (intel_dvo_init_dev(i915, intel_dvo, &intel_dvo_devices[i])) return true; } @@ -493,7 +492,7 @@ static bool intel_dvo_probe(struct drm_i915_private *dev_priv, return false; } -void intel_dvo_init(struct drm_i915_private *dev_priv) +void intel_dvo_init(struct drm_i915_private *i915) { struct intel_connector *connector; struct intel_encoder *encoder; @@ -521,7 +520,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) encoder->pre_enable = intel_dvo_pre_enable; connector->get_hw_state = intel_dvo_connector_get_hw_state; - if (!intel_dvo_probe(dev_priv, intel_dvo)) { + if (!intel_dvo_probe(i915, intel_dvo)) { kfree(intel_dvo); intel_connector_free(connector); return; @@ -536,7 +535,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) | BIT(INTEL_OUTPUT_DVO); - drm_encoder_init(&dev_priv->drm, &encoder->base, + drm_encoder_init(&i915->drm, &encoder->base, &intel_dvo_enc_funcs, intel_dvo_encoder_type(&intel_dvo->dev), "DVO %c", port_name(encoder->port)); @@ -545,7 +544,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - drm_connector_init(&dev_priv->drm, &connector->base, + drm_connector_init(&i915->drm, &connector->base, &intel_dvo_connector_funcs, intel_dvo_connector_type(&intel_dvo->dev)); -- cgit v1.2.3 From f322ed0d76ef0c0f2be99780c2a40ac405411cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 12:55:25 +0200 Subject: drm/i915/dvo: Use per device debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the lonely DRM_DEBUG_KMS() to the per-device variant. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118105525.27254-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 9462b66e5fb4..575cb920bd43 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -320,8 +320,8 @@ intel_dvo_detect(struct drm_connector *_connector, bool force) struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.base.id, connector->base.name); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n", + connector->base.base.id, connector->base.name); if (!INTEL_DISPLAY_ENABLED(i915)) return connector_status_disconnected; -- cgit v1.2.3 From 9a0a4ec530a7514ccd6061ecdeaf719a03cb34cd Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Thu, 17 Nov 2022 15:00:00 -0800 Subject: drm/i915/display: Add missing checks for cdclk crawling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cdclk_sanitize() function was written assuming vco was a signed integer. vco gets assigned to -1 (essentially ~0) for the case where PLL might be enabled and vco is not a frequency that will ever get used. In such a scenario the right thing to do is disable the PLL and re-enable it again with a valid frequency. However the vco is declared as a unsigned variable. With the above assumption, driver takes crawl path when not needed. Add explicit check to not crawl in the case of an invalid PLL. v2: Move the check from .h to .c (MattR) - Move check to bxt_set_cdclk() instead of intel_modeset_calc_cdclk() which is directly in the path of the sanitize() function (Ville) v3: remove unwanted parenthesis(Ville) Cc: Ville Syrjälä Cc: Matt Roper Suggested-by: Ville Syrjälä Signed-off-by: Anusha Srivatsa Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221117230002.792096-1-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b74e36d76013..25d01271dc09 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1717,6 +1717,16 @@ static void dg2_cdclk_squash_program(struct drm_i915_private *i915, intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl); } +static bool cdclk_pll_is_unknown(unsigned int vco) +{ + /* + * Ensure driver does not take the crawl path for the + * case when the vco is set to ~0 in the + * sanitize path. + */ + return vco == ~0; +} + static void bxt_set_cdclk(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) @@ -1749,7 +1759,8 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, return; } - if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) { + if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 && + !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) { if (dev_priv->display.cdclk.hw.vco != vco) adlp_cdclk_pll_crawl(dev_priv, vco); } else if (DISPLAY_VER(dev_priv) >= 11) -- cgit v1.2.3 From 25e0e5ae561003817797c23ae3b85cf510be11c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Nov 2022 15:00:01 -0800 Subject: drm/i915/display: Do both crawl and squash when changing cdclk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For MTL, changing cdclk from between certain frequencies has both squash and crawl. Use the current cdclk config and the new(desired) cdclk config to construct a mid cdclk config. Set the cdclk twice: - Current cdclk -> mid cdclk - mid cdclk -> desired cdclk Driver should not take some Pcode mailbox communication in the cdclk path for platforms that are Display version 14 and later. v2: Add check in intel_modeset_calc_cdclk() to avoid cdclk change via modeset for platforms that support squash_crawl sequences(Ville) v3: Add checks for: - scenario where only slow clock is used and cdclk is actually 0 (bringing up display). - PLLs are on before looking up the waveform. - Squash and crawl capability checks.(Ville) v4: Rebase - Move checks to be more consistent (Ville) - Add comments (Bala) v5: - Further small changes. Move checks around. - Make if-else better looking (Ville) v6: MTl should not follow PUnit mailbox communication as the rest of gen11+ platforms.(Anusha) Cc: Clint Taylor Cc: Balasubramani Vivekanandan Signed-off-by: Anusha Srivatsa Signed-off-by: Ville Syrjälä Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221117230002.792096-2-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 181 ++++++++++++++++++++++++----- 1 file changed, 150 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 25d01271dc09..519c1dfd0906 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1727,37 +1727,79 @@ static bool cdclk_pll_is_unknown(unsigned int vco) return vco == ~0; } -static void bxt_set_cdclk(struct drm_i915_private *dev_priv, - const struct intel_cdclk_config *cdclk_config, - enum pipe pipe) +static int cdclk_squash_divider(u16 waveform) +{ + return hweight16(waveform ?: 0xffff); +} + +static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, + const struct intel_cdclk_config *old_cdclk_config, + const struct intel_cdclk_config *new_cdclk_config, + struct intel_cdclk_config *mid_cdclk_config) +{ + u16 old_waveform, new_waveform, mid_waveform; + int size = 16; + int div = 2; + + /* Return if PLL is in an unknown state, force a complete disable and re-enable. */ + if (cdclk_pll_is_unknown(old_cdclk_config->vco)) + return false; + + /* Return if both Squash and Crawl are not present */ + if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915)) + return false; + + old_waveform = cdclk_squash_waveform(i915, old_cdclk_config->cdclk); + new_waveform = cdclk_squash_waveform(i915, new_cdclk_config->cdclk); + + /* Return if Squash only or Crawl only is the desired action */ + if (old_cdclk_config->vco == 0 || new_cdclk_config->vco == 0 || + old_cdclk_config->vco == new_cdclk_config->vco || + old_waveform == new_waveform) + return false; + + *mid_cdclk_config = *new_cdclk_config; + + /* + * Populate the mid_cdclk_config accordingly. + * - If moving to a higher cdclk, the desired action is squashing. + * The mid cdclk config should have the new (squash) waveform. + * - If moving to a lower cdclk, the desired action is crawling. + * The mid cdclk config should have the new vco. + */ + + if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) { + mid_cdclk_config->vco = old_cdclk_config->vco; + mid_waveform = new_waveform; + } else { + mid_cdclk_config->vco = new_cdclk_config->vco; + mid_waveform = old_waveform; + } + + mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) * + mid_cdclk_config->vco, size * div); + + /* make sure the mid clock came out sane */ + + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk < + min(old_cdclk_config->cdclk, new_cdclk_config->cdclk)); + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk > + i915->display.cdclk.max_cdclk_freq); + drm_WARN_ON(&i915->drm, cdclk_squash_waveform(i915, mid_cdclk_config->cdclk) != + mid_waveform); + + return true; +} + +static void _bxt_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_config *cdclk_config, + enum pipe pipe) { int cdclk = cdclk_config->cdclk; int vco = cdclk_config->vco; u32 val; u16 waveform; int clock; - int ret; - - /* Inform power controller of upcoming frequency change. */ - if (DISPLAY_VER(dev_priv) >= 11) - ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, - SKL_CDCLK_PREPARE_FOR_CHANGE, - SKL_CDCLK_READY_FOR_CHANGE, - SKL_CDCLK_READY_FOR_CHANGE, 3); - else - /* - * BSpec requires us to wait up to 150usec, but that leads to - * timeouts; the 2ms used here is based on experiment. - */ - ret = snb_pcode_write_timeout(&dev_priv->uncore, - HSW_PCODE_DE_WRITE_FREQ_REQ, - 0x80000000, 150, 2); - if (ret) { - drm_err(&dev_priv->drm, - "Failed to inform PCU about cdclk change (err %d, freq %d)\n", - ret, cdclk); - return; - } if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 && !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) { @@ -1793,11 +1835,62 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, if (pipe != INVALID_PIPE) intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); +} + +static void bxt_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_config *cdclk_config, + enum pipe pipe) +{ + struct intel_cdclk_config mid_cdclk_config; + int cdclk = cdclk_config->cdclk; + int ret = 0; + + /* + * Inform power controller of upcoming frequency change. + * Display versions 14 and beyond do not follow the PUnit + * mailbox communication, skip + * this step. + */ + if (DISPLAY_VER(dev_priv) >= 14) + /* NOOP */; + else if (DISPLAY_VER(dev_priv) >= 11) + ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, + SKL_CDCLK_PREPARE_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, 3); + else + /* + * BSpec requires us to wait up to 150usec, but that leads to + * timeouts; the 2ms used here is based on experiment. + */ + ret = snb_pcode_write_timeout(&dev_priv->uncore, + HSW_PCODE_DE_WRITE_FREQ_REQ, + 0x80000000, 150, 2); + + if (ret) { + drm_err(&dev_priv->drm, + "Failed to inform PCU about cdclk change (err %d, freq %d)\n", + ret, cdclk); + return; + } - if (DISPLAY_VER(dev_priv) >= 11) { + if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw, + cdclk_config, &mid_cdclk_config)) { + _bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe); + _bxt_set_cdclk(dev_priv, cdclk_config, pipe); + } else { + _bxt_set_cdclk(dev_priv, cdclk_config, pipe); + } + + if (DISPLAY_VER(dev_priv) >= 14) + /* + * NOOP - No Pcode communication needed for + * Display versions 14 and beyond + */; + else if (DISPLAY_VER(dev_priv) >= 11) ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL, cdclk_config->voltage_level); - } else { + else /* * The timeout isn't specified, the 2ms used here is based on * experiment. @@ -1808,7 +1901,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, cdclk_config->voltage_level, 150, 2); - } if (ret) { drm_err(&dev_priv->drm, @@ -1965,6 +2057,28 @@ void intel_cdclk_uninit_hw(struct drm_i915_private *i915) skl_cdclk_uninit_hw(i915); } +static bool intel_cdclk_can_crawl_and_squash(struct drm_i915_private *i915, + const struct intel_cdclk_config *a, + const struct intel_cdclk_config *b) +{ + u16 old_waveform; + u16 new_waveform; + + drm_WARN_ON(&i915->drm, cdclk_pll_is_unknown(a->vco)); + + if (a->vco == 0 || b->vco == 0) + return false; + + if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915)) + return false; + + old_waveform = cdclk_squash_waveform(i915, a->cdclk); + new_waveform = cdclk_squash_waveform(i915, b->cdclk); + + return a->vco != b->vco && + old_waveform != new_waveform; +} + static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *a, const struct intel_cdclk_config *b) @@ -2771,9 +2885,14 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) pipe = INVALID_PIPE; } - if (intel_cdclk_can_squash(dev_priv, - &old_cdclk_state->actual, - &new_cdclk_state->actual)) { + if (intel_cdclk_can_crawl_and_squash(dev_priv, + &old_cdclk_state->actual, + &new_cdclk_state->actual)) { + drm_dbg_kms(&dev_priv->drm, + "Can change cdclk via crawling and squashing\n"); + } else if (intel_cdclk_can_squash(dev_priv, + &old_cdclk_state->actual, + &new_cdclk_state->actual)) { drm_dbg_kms(&dev_priv->drm, "Can change cdclk via squashing\n"); } else if (intel_cdclk_can_crawl(dev_priv, -- cgit v1.2.3 From 86c0ef7234a7c517b010fd5ecf1e176127bce521 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Thu, 17 Nov 2022 15:00:02 -0800 Subject: drm/i915/display: Add CDCLK Support for MTL As per bSpec MTL has 38.4 MHz Reference clock. Adding the cdclk tables and cdclk_funcs that MTL will use. v2: Revert to using bxt_get_cdclk() BSpec: 65243 Cc: Clint Taylor Signed-off-by: Anusha Srivatsa Reviewed-by: Clint Taylor Link: https://patchwork.freedesktop.org/patch/msgid/20221117230002.792096-3-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 519c1dfd0906..0c107a38f9d0 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1346,6 +1346,16 @@ static const struct intel_cdclk_vals dg2_cdclk_table[] = { {} }; +static const struct intel_cdclk_vals mtl_cdclk_table[] = { + { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a }, + { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 }, + { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0x0000 }, + { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0x0000 }, + {} +}; + static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk) { const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table; @@ -3190,6 +3200,13 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) return freq; } +static const struct intel_cdclk_funcs mtl_cdclk_funcs = { + .get_cdclk = bxt_get_cdclk, + .set_cdclk = bxt_set_cdclk, + .modeset_calc_cdclk = bxt_modeset_calc_cdclk, + .calc_voltage_level = tgl_calc_voltage_level, +}; + static const struct intel_cdclk_funcs tgl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, @@ -3325,7 +3342,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { */ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) { - if (IS_DG2(dev_priv)) { + if (IS_METEORLAKE(dev_priv)) { + dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs; + dev_priv->display.cdclk.table = mtl_cdclk_table; + } else if (IS_DG2(dev_priv)) { dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->display.cdclk.table = dg2_cdclk_table; } else if (IS_ALDERLAKE_P(dev_priv)) { -- cgit v1.2.3 From 282e86eaa5d5e032541b5e3c0b9d0a55fe000607 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Fri, 18 Nov 2022 11:00:08 -0800 Subject: drm/i915/display: Add missing CDCLK Squash support for MTL MTL supports both squash and crawl. Cc: Clint Taylor Cc: Lucas De Marchi Signed-off-by: Anusha Srivatsa Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20221118190008.824412-1-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 0866300243aa..389440a99560 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1117,6 +1117,7 @@ static const struct intel_device_info pvc_info = { XE_LPD_FEATURES, \ .__runtime.display.ip.ver = 14, \ .display.has_cdclk_crawl = 1, \ + .display.has_cdclk_squash = 1, \ .__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) static const struct intel_gt_definition xelpmp_extra_gt[] = { -- cgit v1.2.3 From 8853750dbad8f5dbf912a9f13b3fea41965634e1 Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Mon, 21 Nov 2022 17:07:18 +0200 Subject: drm/i915: Enable SDP split for DP2.0 Enable the SDP split configuration for DP2.0. v2: Move the register handling out of compute config function (JaniN) v3: Patch styling and register access based on platform support (JaniN) v4: Rebased v5: Use unconditional clear bit in intel_de_rmw (Jani Nikula) Bspec: 67768 Signed-off-by: Vinod Govindapillai Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221121150718.1117628-1-vinod.govindapillai@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_audio.h | 2 ++ drivers/gpu/drm/i915/display/intel_ddi.c | 3 +++ drivers/gpu/drm/i915/display/intel_display_types.h | 2 ++ drivers/gpu/drm/i915/display/intel_dp.c | 19 +++++++++++++++++++ 5 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 98c3322b4549..626c47e96a6d 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -798,6 +798,17 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&i915->display.audio.mutex); } +void intel_audio_sdp_split_update(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum transcoder trans = crtc_state->cpu_transcoder; + + if (HAS_DP20(i915)) + intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, + crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); +} + /** * intel_audio_codec_enable - Enable the audio codec for HD audio * @encoder: encoder on which to enable audio diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 63b22131dc45..1b87257c6a17 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -22,5 +22,7 @@ void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); void intel_audio_init(struct drm_i915_private *dev_priv); void intel_audio_deinit(struct drm_i915_private *dev_priv); +void intel_audio_sdp_split_update(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); #endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0f1ec2a98cc8..5f9a2410fc4c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2948,6 +2948,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state, intel_vrr_enable(encoder, crtc_state); + /* Enable/Disable DP2.0 SDP split config before transcoder */ + intel_audio_sdp_split_update(encoder, crtc_state); + intel_enable_transcoder(crtc_state); intel_crtc_vblank_on(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f07395065a69..ff3ef37d099e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1295,6 +1295,8 @@ struct intel_crtc_state { /* Forward Error correction State */ bool fec_enable; + bool sdp_split_enable; + /* Pointer to master transcoder in case of tiled displays */ enum transcoder master_transcoder; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 67089711d9e2..cf8a2f644bab 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2009,6 +2009,23 @@ intel_dp_compute_output_format(struct intel_encoder *encoder, return ret; } +static void +intel_dp_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_connector *connector = conn_state->connector; + + pipe_config->sdp_split_enable = + intel_dp_has_audio(encoder, pipe_config, conn_state) && + intel_dp_is_uhbr(pipe_config); + + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDP split enable: %s\n", + connector->base.id, connector->name, + str_yes_no(pipe_config->sdp_split_enable)); +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2092,6 +2109,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, adjusted_mode->crtc_clock /= n; } + intel_dp_audio_compute_config(encoder, pipe_config, conn_state); + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, adjusted_mode->crtc_clock, -- cgit v1.2.3 From f1c87a94a1087a26f41007ee83264033007421b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Nov 2022 20:52:01 +0200 Subject: drm/i915: Remove non-existent pipes from bigjoiner pipe mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bigjoiner_pipes() doesn't consider that: - RKL only has three pipes - some pipes may be fused off This means that intel_atomic_check_bigjoiner() won't reject all configurations that would need a non-existent pipe. Instead we just keep on rolling witout actually having reserved the slave pipe we need. It's possible that we don't outright explode anywhere due to this since eg. for_each_intel_crtc_in_pipe_mask() will only walk the crtcs we've registered even though the passed in pipe_mask asks for more of them. But clearly the thing won't do what is expected of it when the required pipes are not present. Fix the problem by consulting the device info pipe_mask already in bigjoiner_pipes(). Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221118185201.10469-1-ville.syrjala@linux.intel.com Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_display.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b3e23708d194..6c2686ecb62a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3733,12 +3733,16 @@ out: static u8 bigjoiner_pipes(struct drm_i915_private *i915) { + u8 pipes; + if (DISPLAY_VER(i915) >= 12) - return BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D); + pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D); else if (DISPLAY_VER(i915) >= 11) - return BIT(PIPE_B) | BIT(PIPE_C); + pipes = BIT(PIPE_B) | BIT(PIPE_C); else - return 0; + pipes = 0; + + return pipes & RUNTIME_INFO(i915)->pipe_mask; } static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From 397d5c2c38cde286a76fd59a462b0e1cdc6df4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:18 +0200 Subject: drm/i915: Fix adl+ degamma LUT size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The degamma LUT is interpolated so we need the 128th (==1.0) entry to represent the full < 1.0 input range. Only the 129th and 130th entries are strictly for the >=1.0 extended range inputs. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-7-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 389440a99560..24708fc4f386 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -948,7 +948,7 @@ static const struct intel_device_info adl_s_info = { #define XE_LPD_FEATURES \ .display.abox_mask = GENMASK(1, 0), \ .display.color = { \ - .degamma_lut_size = 128, .gamma_lut_size = 1024, \ + .degamma_lut_size = 129, .gamma_lut_size = 1024, \ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \ DRM_COLOR_LUT_EQUAL_CHANNELS, \ }, \ -- cgit v1.2.3 From c9bc8c7fc05e5ce5157c9c0285eba183b6062f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:19 +0200 Subject: drm/i915: s/gamma/post_csc_lut/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename a the LUT state check foo_gamma_precision() functions to foo_post_csc_lut_precision() to make it more clear what they really do. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-8-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 250e83f1f5ac..e1958a1b4dcc 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1792,7 +1792,7 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) return 0; } -static int i9xx_gamma_precision(const struct intel_crtc_state *crtc_state) +static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable) return 0; @@ -1808,7 +1808,7 @@ static int i9xx_gamma_precision(const struct intel_crtc_state *crtc_state) } } -static int ilk_gamma_precision(const struct intel_crtc_state *crtc_state) +static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable) return 0; @@ -1827,15 +1827,15 @@ static int ilk_gamma_precision(const struct intel_crtc_state *crtc_state) } } -static int chv_gamma_precision(const struct intel_crtc_state *crtc_state) +static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) return 10; else - return i9xx_gamma_precision(crtc_state); + return i9xx_post_csc_lut_precision(crtc_state); } -static int glk_gamma_precision(const struct intel_crtc_state *crtc_state) +static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable) return 0; @@ -1851,7 +1851,7 @@ static int glk_gamma_precision(const struct intel_crtc_state *crtc_state) } } -static int icl_gamma_precision(const struct intel_crtc_state *crtc_state) +static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if ((crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE) == 0) return 0; @@ -1876,16 +1876,16 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat if (HAS_GMCH(i915)) { if (IS_CHERRYVIEW(i915)) - return chv_gamma_precision(crtc_state); + return chv_post_csc_lut_precision(crtc_state); else - return i9xx_gamma_precision(crtc_state); + return i9xx_post_csc_lut_precision(crtc_state); } else { if (DISPLAY_VER(i915) >= 11) - return icl_gamma_precision(crtc_state); + return icl_post_csc_lut_precision(crtc_state); else if (DISPLAY_VER(i915) == 10) - return glk_gamma_precision(crtc_state); + return glk_post_csc_lut_precision(crtc_state); else if (IS_IRONLAKE(i915)) - return ilk_gamma_precision(crtc_state); + return ilk_post_csc_lut_precision(crtc_state); } return 0; -- cgit v1.2.3 From aec31331f84b7294f6b94af755ea44a0ed5bdcba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:20 +0200 Subject: drm/i915: Add glk+ degamma readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read out the degamma LUT on glk+. No state cheker as of yet since it requires dealing with the glk csc vs. degamma mess. v2: deal with post_csc_lut v3: add icl_has_{pre,post}_csc_lut(*) helpers Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 58 ++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e1958a1b4dcc..3dd8a4ff0eca 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1851,9 +1851,19 @@ static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) } } +static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE; +} + +static bool icl_has_pre_csc_lut(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->gamma_mode & PRE_CSC_GAMMA_ENABLE; +} + static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if ((crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE) == 0) + if (!icl_has_post_csc_lut(crtc_state)) return 0; switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { @@ -2182,10 +2192,51 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, return blob; } +static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + /* + * When setting the auto-increment bit, the hardware seems to + * ignore the index bits, so we need to reset it to index 0 + * separately. + */ + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT); + + for (i = 0; i < lut_size; i++) { + u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe)); + + lut[i].red = val; + lut[i].green = val; + lut[i].blue = val; + } + + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + + return blob; +} + static void glk_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + if (crtc_state->csc_enable) + crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc); + if (!crtc_state->gamma_enable) return; @@ -2244,7 +2295,10 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if ((crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE) == 0) + if (icl_has_pre_csc_lut(crtc_state)) + crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc); + + if (!icl_has_post_csc_lut(crtc_state)) return; switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { -- cgit v1.2.3 From 5375f433409975c3f967aec88fe3f8ebdce4e436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:21 +0200 Subject: drm/i915: Read out CHV CGM degamma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since CHV has the dedicate CGM degamma unit readout is trivial. Just do it. v2: deal with post_csc_lut Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 3dd8a4ff0eca..430fa23c102f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1087,6 +1087,13 @@ static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color) return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 14)); } +static void chv_cgm_degamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw) +{ + entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, ldw), 14); + entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_BLUE_LDW_MASK, ldw), 14); + entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_RED_UDW_MASK, udw), 14); +} + static void chv_load_cgm_degamma(struct intel_crtc *crtc, const struct drm_property_blob *blob) { @@ -2048,6 +2055,32 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) crtc_state->post_csc_lut = i965_read_lut_10p6(crtc); } +static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size; i++) { + u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0)); + u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1)); + + chv_cgm_degamma_pack(&lut[i], ldw, udw); + } + + return blob; +} + static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); @@ -2078,6 +2111,9 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA) + crtc_state->pre_csc_lut = chv_read_cgm_degamma(crtc); + if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) crtc_state->post_csc_lut = chv_read_cgm_gamma(crtc); else -- cgit v1.2.3 From 36eb28b44bc84a3091bad93f70bbe86746167f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:22 +0200 Subject: drm/i915: Add gamma/degamma readout for bdw+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read out the gamma/degamma LUT on bdw+. Now that the {pre,post}_csc_lut match the hardware LUT size even in split gamma mode this is trivial. v2: deal with {pre,post}_csc_lut split gamma is no longer a problem v3: add ilk_has_post_csc_lut() helper Reviewed-by: Uma Shankar #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 51 ++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 430fa23c102f..bdc218dbc623 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1815,12 +1815,15 @@ static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state } } -static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) - return 0; + return crtc_state->gamma_enable && + (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0; +} - if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0) +static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_has_post_csc_lut(crtc_state)) return 0; switch (crtc_state->gamma_mode) { @@ -2198,14 +2201,11 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, u32 prec_index) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - int i, hw_lut_size = ivb_lut_10_size(prec_index); - int lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; + int i, lut_size = ivb_lut_10_size(prec_index); enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; struct drm_color_lut *lut; - drm_WARN_ON(&i915->drm, lut_size != hw_lut_size); - blob = drm_property_create_blob(&i915->drm, sizeof(lut[0]) * lut_size, NULL); @@ -2228,6 +2228,37 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, return blob; } +static void bdw_read_luts(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; + + if (!crtc_state->gamma_enable) + return; + + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + *blob = ilk_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_SPLIT: + crtc_state->pre_csc_lut = + bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = + bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(512)); + break; + case GAMMA_MODE_MODE_10BIT: + *blob = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } +} + static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -2395,7 +2426,7 @@ static const struct intel_color_funcs skl_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = skl_color_commit_arm, .load_luts = bdw_load_luts, - .read_luts = NULL, + .read_luts = bdw_read_luts, }; static const struct intel_color_funcs bdw_color_funcs = { @@ -2403,7 +2434,7 @@ static const struct intel_color_funcs bdw_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = bdw_load_luts, - .read_luts = NULL, + .read_luts = bdw_read_luts, }; static const struct intel_color_funcs hsw_color_funcs = { -- cgit v1.2.3 From 9f9af566a177689e812557fb1eb08433adcd6951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:23 +0200 Subject: drm/i915: Add gamma/degamma readout for ivb/hsw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have all the code necessary for gamma/degamma readout on ivb/hsw. Plug it all in. As with bdw+ the cooked {pre,post}_csc_lut make this trivial even in split gamma mode. Note that on HSW if IPS is enabled the hardware will hang if you try to access the LUT in split gamma mode. Thus we need to reorder the LUT readout vs. IPS enable steps. v2: deal with {pre,post}_csc_lut split gamma is no longer a problem handle HSW IPS w/a v3: use ilk_has_post_csc_lut() helper Reviewed-by: Uma Shankar #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-12-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 72 +++++++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_display.c | 4 +- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index bdc218dbc623..583a93351c97 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2196,6 +2196,74 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) } } +/* + * IVB/HSW Bspec / PAL_PREC_INDEX: + * "Restriction : Index auto increment mode is not + * supported and must not be enabled." + */ +static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc, + u32 prec_index) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int i, lut_size = ivb_lut_10_size(prec_index); + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + + blob = drm_property_create_blob(&dev_priv->drm, + sizeof(lut[0]) * lut_size, + NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size; i++) { + u32 val; + + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + prec_index + i); + val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe)); + + ilk_lut_10_pack(&lut[i], val); + } + + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); + + return blob; +} + +static void ivb_read_luts(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; + + if (!crtc_state->gamma_enable) + return; + + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + *blob = ilk_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_SPLIT: + crtc_state->pre_csc_lut = + ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(0)); + crtc_state->post_csc_lut = + ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE | + PAL_PREC_INDEX_VALUE(512)); + break; + case GAMMA_MODE_MODE_10BIT: + *blob = ivb_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } +} + /* On BDW+ the index auto increment mode actually works */ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, u32 prec_index) @@ -2442,7 +2510,7 @@ static const struct intel_color_funcs hsw_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = ivb_load_luts, - .read_luts = NULL, + .read_luts = ivb_read_luts, }; static const struct intel_color_funcs ivb_color_funcs = { @@ -2450,7 +2518,7 @@ static const struct intel_color_funcs ivb_color_funcs = { .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = ilk_color_commit_arm, .load_luts = ivb_load_luts, - .read_luts = NULL, + .read_luts = ivb_read_luts, }; static const struct intel_color_funcs ilk_color_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6c2686ecb62a..483aea32c331 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1246,7 +1246,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(dev_priv); - hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); if (needs_async_flip_vtd_wa(old_crtc_state) && @@ -7587,6 +7586,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); + /* Must be done after gamma readout due to HSW split gamma vs. IPS w/a */ + hsw_ips_post_update(state, crtc); + /* * Activate DRRS after state readout to avoid * dp_m_n vs. dp_m2_n2 confusion on BDW+. -- cgit v1.2.3 From d2559299d339a2dfa4d1f14978e629669cf4b1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:24 +0200 Subject: drm/i915: Make ilk_read_luts() capable of degamma readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like ivb+, ilk/snb can select whether the hw lut acts as gamma or degamma. Make the readout cognizant of that fact. v2: deal with pre_csc_lut v3: use ilk_has_post_csc_lut() helper Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-13-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 583a93351c97..ef171837ef45 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -2176,19 +2176,19 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc) static void ilk_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_property_blob **blob = + ilk_has_post_csc_lut(crtc_state) ? + &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; if (!crtc_state->gamma_enable) return; - if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0) - return; - switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - crtc_state->post_csc_lut = ilk_read_lut_8(crtc); + *blob = ilk_read_lut_8(crtc); break; case GAMMA_MODE_MODE_10BIT: - crtc_state->post_csc_lut = ilk_read_lut_10(crtc); + *blob = ilk_read_lut_10(crtc); break; default: MISSING_CASE(crtc_state->gamma_mode); -- cgit v1.2.3 From 298ad1070c315c89977af2cfbce04630853fde21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:25 +0200 Subject: drm/i915: Prep for C8 palette readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the approproate c8_planes checks to make the LUT code ready for C8 palette readout. Note we currently lack the actual c8_planes readout, so this won't work yet. But no harm in making the code somewhat more ready for the day when we do get c8_planes readout. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-14-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index ef171837ef45..ca01b3e6b585 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1801,7 +1801,7 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; switch (crtc_state->gamma_mode) { @@ -1817,6 +1817,9 @@ static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state) { + if (crtc_state->c8_planes) + return true; + return crtc_state->gamma_enable && (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0; } @@ -1847,7 +1850,7 @@ static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; switch (crtc_state->gamma_mode) { @@ -1863,6 +1866,9 @@ static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state) { + if (crtc_state->c8_planes) + return true; + return crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE; } @@ -2009,7 +2015,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); @@ -2049,7 +2055,7 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) @@ -2180,7 +2186,7 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) ilk_has_post_csc_lut(crtc_state) ? &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { @@ -2240,7 +2246,7 @@ static void ivb_read_luts(struct intel_crtc_state *crtc_state) ilk_has_post_csc_lut(crtc_state) ? &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { @@ -2303,7 +2309,7 @@ static void bdw_read_luts(struct intel_crtc_state *crtc_state) ilk_has_post_csc_lut(crtc_state) ? &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut; - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { @@ -2372,7 +2378,7 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state) if (crtc_state->csc_enable) crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc); - if (!crtc_state->gamma_enable) + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; switch (crtc_state->gamma_mode) { -- cgit v1.2.3 From bad2383f05b588e14fdde728299f090b08d3f27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:26 +0200 Subject: drm/i915: Make .read_luts() mandatory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every platform now implements .read_luts(). Make it mandatory. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-15-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index ca01b3e6b585..f0bb4227338c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1231,8 +1231,7 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - if (i915->display.funcs.color->read_luts) - i915->display.funcs.color->read_luts(crtc_state); + i915->display.funcs.color->read_luts(crtc_state); } static bool need_plane_update(struct intel_plane *plane, -- cgit v1.2.3 From 96ffd0cda60abfbb39246ed2fb0d344b57289904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:27 +0200 Subject: drm/i915: Finish the LUT state checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have full readout now for all platforms (sans the icl+ multi-segment readout hw fail), so hook up the LUT state checker for everyone. We add a new vfunc for this since different platforms need to handle the details a bit differently. The implementation is rather repetitive in places. Probably we want to think of a more declarative approach for the LUT precision/etc. stuff in the future... Note that we're currently missing readout for c8_planes, so we'll have to skip the state check in that case. v2: Fix readout for C8 use cases v3: Skip C8 entirely due to lack of c8_planes readout Add ilk_has_pre_csc_lut() helper and use other such helpers Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-16-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 271 +++++++++++++++++++++------ drivers/gpu/drm/i915/display/intel_color.h | 8 +- drivers/gpu/drm/i915/display/intel_display.c | 29 +-- 3 files changed, 223 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index f0bb4227338c..e2bcfbffb298 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -53,7 +53,18 @@ struct intel_color_funcs { * involved with the same commit. */ void (*load_luts)(const struct intel_crtc_state *crtc_state); + /* + * Read out the LUTs from the hardware into the software state. + * Used by eg. the hardware state checker. + */ void (*read_luts)(struct intel_crtc_state *crtc_state); + /* + * Compare the LUTs + */ + bool (*lut_equal)(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut); }; #define CTM_COEFF_SIGN (1ULL << 63) @@ -1234,6 +1245,24 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state) i915->display.funcs.color->read_luts(crtc_state); } +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + /* + * FIXME c8_planes readout missing thus + * .read_luts() doesn't read out post_csc_lut. + */ + if (!is_pre_csc_lut && crtc_state->c8_planes) + return true; + + return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2, + is_pre_csc_lut); +} + static bool need_plane_update(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { @@ -1814,6 +1843,24 @@ static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state } } +static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + return 0; +} + +static int ilk_gamma_mode_precision(u32 gamma_mode) +{ + switch (gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + return 8; + case GAMMA_MODE_MODE_10BIT: + return 10; + default: + MISSING_CASE(gamma_mode); + return 0; + } +} + static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state) { if (crtc_state->c8_planes) @@ -1823,28 +1870,60 @@ static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state) (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0; } +static bool ilk_has_pre_csc_lut(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->gamma_enable && + (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0; +} + static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (!ilk_has_post_csc_lut(crtc_state)) return 0; - switch (crtc_state->gamma_mode) { - case GAMMA_MODE_MODE_8BIT: - return 8; - case GAMMA_MODE_MODE_10BIT: - return 10; - default: - MISSING_CASE(crtc_state->gamma_mode); + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int ilk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_has_pre_csc_lut(crtc_state)) return 0; - } + + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int ivb_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->gamma_enable && + crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) + return 10; + + return ilk_post_csc_lut_precision(crtc_state); +} + +static int ivb_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->gamma_enable && + crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) + return 10; + + return ilk_pre_csc_lut_precision(crtc_state); } static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) { if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) return 10; - else - return i9xx_post_csc_lut_precision(crtc_state); + + return i9xx_post_csc_lut_precision(crtc_state); +} + +static int chv_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA) + return 14; + + return 0; } static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) @@ -1852,15 +1931,15 @@ static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return 0; - switch (crtc_state->gamma_mode) { - case GAMMA_MODE_MODE_8BIT: - return 8; - case GAMMA_MODE_MODE_10BIT: - return 10; - default: - MISSING_CASE(crtc_state->gamma_mode); + return ilk_gamma_mode_precision(crtc_state->gamma_mode); +} + +static int glk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->csc_enable) return 0; - } + + return 16; } static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state) @@ -1894,26 +1973,12 @@ static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) } } -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state) +static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - - if (HAS_GMCH(i915)) { - if (IS_CHERRYVIEW(i915)) - return chv_post_csc_lut_precision(crtc_state); - else - return i9xx_post_csc_lut_precision(crtc_state); - } else { - if (DISPLAY_VER(i915) >= 11) - return icl_post_csc_lut_precision(crtc_state); - else if (DISPLAY_VER(i915) == 10) - return glk_post_csc_lut_precision(crtc_state); - else if (IS_IRONLAKE(i915)) - return ilk_post_csc_lut_precision(crtc_state); - } + if (!icl_has_pre_csc_lut(crtc_state)) + return 0; - return 0; + return 16; } static bool err_check(struct drm_color_lut *lut1, @@ -1924,9 +1989,9 @@ static bool err_check(struct drm_color_lut *lut1, ((abs((long)lut2->green - lut1->green)) <= err); } -static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1, - struct drm_color_lut *lut2, - int lut_size, u32 err) +static bool intel_lut_entries_equal(struct drm_color_lut *lut1, + struct drm_color_lut *lut2, + int lut_size, u32 err) { int i; @@ -1938,9 +2003,9 @@ static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1, return true; } -bool intel_color_lut_equal(struct drm_property_blob *blob1, - struct drm_property_blob *blob2, - u32 gamma_mode, u32 bit_precision) +static bool intel_lut_equal(const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + int check_size, int precision) { struct drm_color_lut *lut1, *lut2; int lut_size1, lut_size2; @@ -1949,40 +2014,112 @@ bool intel_color_lut_equal(struct drm_property_blob *blob1, if (!blob1 != !blob2) return false; + if (!blob1 != !precision) + return false; + if (!blob1) return true; lut_size1 = drm_color_lut_size(blob1); lut_size2 = drm_color_lut_size(blob2); - /* check sw and hw lut size */ if (lut_size1 != lut_size2) return false; lut1 = blob1->data; lut2 = blob2->data; - err = 0xffff >> bit_precision; + err = 0xffff >> precision; - /* check sw and hw lut entry to be equal */ - switch (gamma_mode & GAMMA_MODE_MODE_MASK) { - case GAMMA_MODE_MODE_8BIT: - case GAMMA_MODE_MODE_10BIT: - if (!intel_color_lut_entries_equal(lut1, lut2, - lut_size2, err)) - return false; - break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: - if (!intel_color_lut_entries_equal(lut1, lut2, - 9, err)) - return false; - break; - default: - MISSING_CASE(gamma_mode); - return false; - } + if (!check_size) + check_size = lut_size1; - return true; + return intel_lut_entries_equal(lut1, lut2, check_size, err); +} + +static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + i9xx_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + i9xx_post_csc_lut_precision(crtc_state)); +} + +static bool chv_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + chv_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + chv_post_csc_lut_precision(crtc_state)); +} + +static bool ilk_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + ilk_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + ilk_post_csc_lut_precision(crtc_state)); +} + +static bool ivb_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + ivb_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + ivb_post_csc_lut_precision(crtc_state)); +} + +static bool glk_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + glk_pre_csc_lut_precision(crtc_state)); + else + return intel_lut_equal(blob1, blob2, 0, + glk_post_csc_lut_precision(crtc_state)); +} + +static bool icl_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) +{ + int check_size = 0; + + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + icl_pre_csc_lut_precision(crtc_state)); + + /* hw readout broken except for the super fine segment :( */ + if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) == + GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED) + check_size = 9; + + return intel_lut_equal(blob1, blob2, check_size, + icl_post_csc_lut_precision(crtc_state)); } static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) @@ -2462,6 +2599,7 @@ static const struct intel_color_funcs chv_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = chv_load_luts, .read_luts = chv_read_luts, + .lut_equal = chv_lut_equal, }; static const struct intel_color_funcs i965_color_funcs = { @@ -2469,6 +2607,7 @@ static const struct intel_color_funcs i965_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = i965_load_luts, .read_luts = i965_read_luts, + .lut_equal = i9xx_lut_equal, }; static const struct intel_color_funcs i9xx_color_funcs = { @@ -2476,6 +2615,7 @@ static const struct intel_color_funcs i9xx_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = i9xx_load_luts, .read_luts = i9xx_read_luts, + .lut_equal = i9xx_lut_equal, }; static const struct intel_color_funcs icl_color_funcs = { @@ -2484,6 +2624,7 @@ static const struct intel_color_funcs icl_color_funcs = { .color_commit_arm = skl_color_commit_arm, .load_luts = icl_load_luts, .read_luts = icl_read_luts, + .lut_equal = icl_lut_equal, }; static const struct intel_color_funcs glk_color_funcs = { @@ -2492,6 +2633,7 @@ static const struct intel_color_funcs glk_color_funcs = { .color_commit_arm = skl_color_commit_arm, .load_luts = glk_load_luts, .read_luts = glk_read_luts, + .lut_equal = glk_lut_equal, }; static const struct intel_color_funcs skl_color_funcs = { @@ -2500,6 +2642,7 @@ static const struct intel_color_funcs skl_color_funcs = { .color_commit_arm = skl_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = bdw_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs bdw_color_funcs = { @@ -2508,6 +2651,7 @@ static const struct intel_color_funcs bdw_color_funcs = { .color_commit_arm = hsw_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = bdw_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs hsw_color_funcs = { @@ -2516,6 +2660,7 @@ static const struct intel_color_funcs hsw_color_funcs = { .color_commit_arm = hsw_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = ivb_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs ivb_color_funcs = { @@ -2524,6 +2669,7 @@ static const struct intel_color_funcs ivb_color_funcs = { .color_commit_arm = ilk_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = ivb_read_luts, + .lut_equal = ivb_lut_equal, }; static const struct intel_color_funcs ilk_color_funcs = { @@ -2532,6 +2678,7 @@ static const struct intel_color_funcs ilk_color_funcs = { .color_commit_arm = ilk_color_commit_arm, .load_luts = ilk_load_luts, .read_luts = ilk_read_luts, + .lut_equal = ilk_lut_equal, }; void intel_color_crtc_init(struct intel_crtc *crtc) diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 2a5ada67774d..1c6b1755f6d2 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -21,10 +21,10 @@ void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state); void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); void intel_color_load_luts(const struct intel_crtc_state *crtc_state); void intel_color_get_config(struct intel_crtc_state *crtc_state); -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state); -bool intel_color_lut_equal(struct drm_property_blob *blob1, - struct drm_property_blob *blob2, - u32 gamma_mode, u32 bit_precision); +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut); void intel_color_assert_luts(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 483aea32c331..32b257157186 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5530,7 +5530,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); bool ret = true; - u32 bp_gamma = 0; bool fixup_inherited = fastset && current_config->inherited && !pipe_config->inherited; @@ -5681,21 +5680,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \ - if (current_config->name1 != pipe_config->name1) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name1), \ - "(expected %i, found %i, won't compare lut values)", \ - current_config->name1, \ - pipe_config->name1); \ - ret = false;\ - } else { \ - if (!intel_color_lut_equal(current_config->name2, \ - pipe_config->name2, pipe_config->name1, \ - bit_precision)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name2), \ - "hw_state doesn't match sw_state"); \ - ret = false; \ - } \ +#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \ + if (current_config->gamma_mode == pipe_config->gamma_mode && \ + !intel_color_lut_equal(current_config, \ + current_config->lut, pipe_config->lut, \ + is_pre_csc_lut)) { \ + pipe_config_mismatch(fastset, crtc, __stringify(lut), \ + "hw_state doesn't match sw_state"); \ + ret = false; \ } \ } while (0) @@ -5792,9 +5784,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(linetime); PIPE_CONF_CHECK_I(ips_linetime); - bp_gamma = intel_color_get_gamma_bit_precision(pipe_config); - if (bp_gamma) - PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma); + PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true); + PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false); if (current_config->active_planes) { PIPE_CONF_CHECK_BOOL(has_psr); -- cgit v1.2.3 From e0b10f88ae33f1a5276f552b9d158ae1623c50e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:28 +0200 Subject: drm/i915: Rework legacy LUT handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently crtc_state_is_legacy_gamma() has a very specific set of conditions, not all of which are actually necessary. Also when we detect those conditions check_luts() just skips all the checks. That will no longer work for glk soon when we'll start to use the hw degamma LUT in place of the hw gamma LUT for YCbCr output. So let's rework the logic to only really consider whether the user provided gamma_lut is one that matches the hw legacy LUT capabilities or not. We'll need to reject C8+degamma on ivb+ since the presence of degamma_lut would either mean we have to really use the LUT for degamma as opposed to C8 palette, or we have to enable split gamma mode which also can't work as the C8 palette. Otherwise this will now cause the legacy LUT to go through the regular lut checks as well. As a side effect we also start to allow the use of the legacy LUT with CTM, but that is perfectly fine as far a the hardware is concerned. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-17-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 82 ++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e2bcfbffb298..8bb8983b490c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -154,15 +154,7 @@ static const u16 ilk_csc_postoff_rgb_to_ycbcr[3] = { static bool lut_is_legacy(const struct drm_property_blob *lut) { - return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; -} - -static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state) -{ - return !crtc_state->hw.degamma_lut && - !crtc_state->hw.ctm && - crtc_state->hw.gamma_lut && - lut_is_legacy(crtc_state->hw.gamma_lut); + return lut && drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; } /* @@ -1317,6 +1309,42 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) return 0; } +static u32 intel_gamma_lut_tests(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + + if (lut_is_legacy(gamma_lut)) + return 0; + + return INTEL_INFO(i915)->display.color.gamma_lut_tests; +} + +static u32 intel_degamma_lut_tests(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + return INTEL_INFO(i915)->display.color.degamma_lut_tests; +} + +static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + + if (lut_is_legacy(gamma_lut)) + return LEGACY_LUT_LENGTH; + + return INTEL_INFO(i915)->display.color.gamma_lut_size; +} + +static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + return INTEL_INFO(i915)->display.color.degamma_lut_size; +} + static int check_lut_size(const struct drm_property_blob *lut, int expected) { int len; @@ -1342,21 +1370,17 @@ static int check_luts(const struct intel_crtc_state *crtc_state) int gamma_length, degamma_length; u32 gamma_tests, degamma_tests; - /* Always allow legacy gamma LUT with no further checking. */ - if (crtc_state_is_legacy_gamma(crtc_state)) - return 0; - /* C8 relies on its palette being stored in the legacy LUT */ - if (crtc_state->c8_planes) { + if (crtc_state->c8_planes && !lut_is_legacy(crtc_state->hw.gamma_lut)) { drm_dbg_kms(&i915->drm, "C8 pixelformat requires the legacy LUT\n"); return -EINVAL; } - degamma_length = INTEL_INFO(i915)->display.color.degamma_lut_size; - gamma_length = INTEL_INFO(i915)->display.color.gamma_lut_size; - degamma_tests = INTEL_INFO(i915)->display.color.degamma_lut_tests; - gamma_tests = INTEL_INFO(i915)->display.color.gamma_lut_tests; + degamma_length = intel_degamma_lut_size(crtc_state); + gamma_length = intel_gamma_lut_size(crtc_state); + degamma_tests = intel_degamma_lut_tests(crtc_state); + gamma_tests = intel_gamma_lut_tests(crtc_state); if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) @@ -1372,7 +1396,7 @@ static int check_luts(const struct intel_crtc_state *crtc_state) static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else return GAMMA_MODE_MODE_10BIT; /* i965+ only */ @@ -1441,14 +1465,12 @@ static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state) { u32 cgm_mode = 0; - if (crtc_state_is_legacy_gamma(crtc_state)) - return 0; - if (crtc_state->hw.degamma_lut) cgm_mode |= CGM_PIPE_MODE_DEGAMMA; if (crtc_state->hw.ctm) cgm_mode |= CGM_PIPE_MODE_CSC; - if (crtc_state->hw.gamma_lut) + if (crtc_state->hw.gamma_lut && + !lut_is_legacy(crtc_state->hw.gamma_lut)) cgm_mode |= CGM_PIPE_MODE_GAMMA; return cgm_mode; @@ -1475,7 +1497,7 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) * Otherwise we bypass it and use the CGM gamma instead. */ crtc_state->gamma_enable = - crtc_state_is_legacy_gamma(crtc_state) && + lut_is_legacy(crtc_state->hw.gamma_lut) && !crtc_state->c8_planes; crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT; @@ -1510,7 +1532,7 @@ static bool ilk_csc_enable(const struct intel_crtc_state *crtc_state) static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else return GAMMA_MODE_MODE_10BIT; @@ -1656,6 +1678,12 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + if (crtc_state->c8_planes && crtc_state->hw.degamma_lut) { + drm_dbg_kms(&i915->drm, + "C8 pixelformat and degamma together are not possible\n"); + return -EINVAL; + } + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB && crtc_state->hw.ctm) { drm_dbg_kms(&i915->drm, @@ -1694,7 +1722,7 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else return GAMMA_MODE_MODE_10BIT; @@ -1779,7 +1807,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) gamma_mode |= POST_CSC_GAMMA_ENABLE; if (!crtc_state->hw.gamma_lut || - crtc_state_is_legacy_gamma(crtc_state)) + lut_is_legacy(crtc_state->hw.gamma_lut)) gamma_mode |= GAMMA_MODE_MODE_8BIT; /* * Enable 10bit gamma for D13 -- cgit v1.2.3 From 58765e0c49722adf3f8d2dcd572ef29a58b3629a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:29 +0200 Subject: drm/i915: Use hw degamma LUT for sw gamma on glk with YCbCr output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On glk we can no longer reorder the hw LUTS vs. pipe CSC like we could on earlier platforms, and neither do we have a separate output CSC like on icl+. That means if we use the pipe CSC for YCbCr output we are currently applying the gamma LUT after the RGB->YCbCr conversion, which is just wrong. The further we go from a linear curve the more distorted the resulting colors become. To work around this terrible limitation the best we can do is repurpose the hw degamma LUT as a poor man's gamma LUT. Now that we have the internal pre_csc_lut attachment point that is not particularly hard to do. What makes this less than ideal however is the fact that the hw degamma LUT and gamma LUTs have very different capabilities. The gamma LUT can operate in direct color type modes, whereas the degamma LUT can't and just always operates in interpolated mode. Additionally the degamma LUT is just a single 1D LUT, whereas the gamma LUT is made of three separate 1D LUts (one for each channel). So in order to make this semi-sensible we must also verify the user supplied LUT more less matches the hw degamma LUT capabilities. We still end up losing most of the LUT entries though, so the results might be a bit crap. The other option of flat out rejecting the YCbCr+gamma LUT combo seems extremely likely to just cause a black screen for the user. Eg. pretty sure Xorg always applies some kind of gamma LUT, and if the user then plugs in a display that needs YCbCr output we're toast. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-18-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 61 ++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8bb8983b490c..c336524d9225 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1362,13 +1362,13 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) return 0; } -static int check_luts(const struct intel_crtc_state *crtc_state) +static int _check_luts(const struct intel_crtc_state *crtc_state, + u32 degamma_tests, u32 gamma_tests) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; /* C8 relies on its palette being stored in the legacy LUT */ if (crtc_state->c8_planes && !lut_is_legacy(crtc_state->hw.gamma_lut)) { @@ -1379,8 +1379,6 @@ static int check_luts(const struct intel_crtc_state *crtc_state) degamma_length = intel_degamma_lut_size(crtc_state); gamma_length = intel_gamma_lut_size(crtc_state); - degamma_tests = intel_degamma_lut_tests(crtc_state); - gamma_tests = intel_gamma_lut_tests(crtc_state); if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) @@ -1393,6 +1391,13 @@ static int check_luts(const struct intel_crtc_state *crtc_state) return 0; } +static int check_luts(const struct intel_crtc_state *crtc_state) +{ + return _check_luts(crtc_state, + intel_degamma_lut_tests(crtc_state), + intel_gamma_lut_tests(crtc_state)); +} + static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state) { if (!crtc_state->gamma_enable || @@ -1414,9 +1419,11 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } else if (DISPLAY_VER(i915) == 10) { drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut == crtc_state->hw.gamma_lut && crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut); drm_WARN_ON(&i915->drm, + crtc_state->post_csc_lut != NULL && crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { drm_WARN_ON(&i915->drm, @@ -1728,10 +1735,33 @@ static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state) return GAMMA_MODE_MODE_10BIT; } -static void glk_assign_luts(struct intel_crtc_state *crtc_state) +static bool glk_use_pre_csc_lut_for_gamma(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->hw.gamma_lut && + !crtc_state->c8_planes && + crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB; +} + +static int glk_assign_luts(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + if (glk_use_pre_csc_lut_for_gamma(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + INTEL_INFO(i915)->display.color.degamma_lut_size); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->pre_csc_lut, gamma_lut); + drm_property_replace_blob(&crtc_state->post_csc_lut, NULL); + + drm_property_blob_put(gamma_lut); + + return 0; + } + intel_assign_luts(crtc_state); /* @@ -1743,6 +1773,19 @@ static void glk_assign_luts(struct intel_crtc_state *crtc_state) if (crtc_state->csc_enable && !crtc_state->pre_csc_lut) drm_property_replace_blob(&crtc_state->pre_csc_lut, i915->display.color.glk_linear_degamma_lut); + + return 0; +} + +static int glk_check_luts(const struct intel_crtc_state *crtc_state) +{ + u32 degamma_tests = intel_degamma_lut_tests(crtc_state); + u32 gamma_tests = intel_gamma_lut_tests(crtc_state); + + if (glk_use_pre_csc_lut_for_gamma(crtc_state)) + gamma_tests |= degamma_tests; + + return _check_luts(crtc_state, degamma_tests, gamma_tests); } static int glk_color_check(struct intel_crtc_state *crtc_state) @@ -1750,7 +1793,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; - ret = check_luts(crtc_state); + ret = glk_check_luts(crtc_state); if (ret) return ret; @@ -1769,11 +1812,13 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) } crtc_state->gamma_enable = + !glk_use_pre_csc_lut_for_gamma(crtc_state) && crtc_state->hw.gamma_lut && !crtc_state->c8_planes; /* On GLK+ degamma LUT is controlled by csc_enable */ crtc_state->csc_enable = + glk_use_pre_csc_lut_for_gamma(crtc_state) || crtc_state->hw.degamma_lut || crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || crtc_state->hw.ctm || crtc_state->limited_color_range; @@ -1786,7 +1831,9 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - glk_assign_luts(crtc_state); + ret = glk_assign_luts(crtc_state); + if (ret) + return ret; crtc_state->preload_luts = intel_can_preload_luts(crtc_state); -- cgit v1.2.3 From 07fc6a7b1a03934cd564ce8492bb6e7a49a12751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:30 +0200 Subject: drm/i915: Use gamma LUT for RGB limited range compression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On hsw+ and glk class hardware we current make a mess of things when we have to both generate limited range output and use the hw gamma LUT. Since we do the range compression using the pipe CSC unit (which is situated before the gamma LUT in the pipe) we are in fact applying the gamma to the limited range data instead of the full range data as the user intended. We can work around this by applying the range compression via the gamma LUT instead of using the pipe CSC for it. Fairly easy to do now that we have the internal post_csc_lut attachment point where we can stick our new cooked LUT. On hsw+ this only needs to be done when using the split gamma mode or when the ctm is enabled since otherwise we can simply reorder the LUT vs. CSC. On glk we need to do this any time a gamma LUT is used since no reordering is possible. We do lose a bit of coverage in intel_color_assert_luts(), but so be it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-19-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 133 ++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index c336524d9225..dee0382015a5 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -249,17 +249,44 @@ static void icl_update_output_csc(struct intel_crtc *crtc, intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]); } -static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) +static bool ilk_limited_range(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - /* - * FIXME if there's a gamma LUT after the CSC, we should - * do the range compression using the gamma LUT instead. - */ - return crtc_state->limited_color_range && - (IS_HASWELL(i915) || IS_BROADWELL(i915) || - IS_DISPLAY_VER(i915, 9, 10)); + /* icl+ have dedicated output CSC */ + if (DISPLAY_VER(i915) >= 11) + return false; + + /* pre-hsw have PIPECONF_COLOR_RANGE_SELECT */ + if (DISPLAY_VER(i915) < 7 || IS_IVYBRIDGE(i915)) + return false; + + return crtc_state->limited_color_range; +} + +static bool ilk_lut_limited_range(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (!ilk_limited_range(crtc_state)) + return false; + + if (crtc_state->c8_planes) + return false; + + if (DISPLAY_VER(i915) == 10) + return crtc_state->hw.gamma_lut; + else + return crtc_state->hw.gamma_lut && + (crtc_state->hw.degamma_lut || crtc_state->hw.ctm); +} + +static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) +{ + if (!ilk_limited_range(crtc_state)) + return false; + + return !ilk_lut_limited_range(crtc_state); } static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, @@ -603,9 +630,18 @@ create_linear_lut(struct drm_i915_private *i915, int lut_size) return blob; } +static u16 lut_limited_range(unsigned int value) +{ + unsigned int min = 16 << 8; + unsigned int max = 235 << 8; + + return value * (max - min) / 0xffff + min; +} + static struct drm_property_blob * create_resized_lut(struct drm_i915_private *i915, - const struct drm_property_blob *blob_in, int lut_out_size) + const struct drm_property_blob *blob_in, int lut_out_size, + bool limited_color_range) { int i, lut_in_size = drm_color_lut_size(blob_in); struct drm_property_blob *blob_out; @@ -621,8 +657,18 @@ create_resized_lut(struct drm_i915_private *i915, lut_in = blob_in->data; lut_out = blob_out->data; - for (i = 0; i < lut_out_size; i++) - lut_out[i] = lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)]; + for (i = 0; i < lut_out_size; i++) { + const struct drm_color_lut *entry = + &lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)]; + + if (limited_color_range) { + lut_out[i].red = lut_limited_range(entry->red); + lut_out[i].green = lut_limited_range(entry->green); + lut_out[i].blue = lut_limited_range(entry->blue); + } else { + lut_out[i] = *entry; + } + } return blob_out; } @@ -1423,6 +1469,7 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut); drm_WARN_ON(&i915->drm, + !ilk_lut_limited_range(crtc_state) && crtc_state->post_csc_lut != NULL && crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { @@ -1430,6 +1477,7 @@ void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut && crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut); drm_WARN_ON(&i915->drm, + !ilk_lut_limited_range(crtc_state) && crtc_state->post_csc_lut != crtc_state->hw.degamma_lut && crtc_state->post_csc_lut != crtc_state->hw.gamma_lut); } @@ -1563,8 +1611,28 @@ static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state) CSC_POSITION_BEFORE_GAMMA; } -static void ilk_assign_luts(struct intel_crtc_state *crtc_state) +static int ilk_assign_luts(struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (ilk_lut_limited_range(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + drm_color_lut_size(crtc_state->hw.gamma_lut), + true); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut); + + drm_property_blob_put(gamma_lut); + + drm_property_replace_blob(&crtc_state->pre_csc_lut, crtc_state->hw.degamma_lut); + + return 0; + } + if (crtc_state->hw.degamma_lut || crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) { drm_property_replace_blob(&crtc_state->pre_csc_lut, @@ -1577,6 +1645,8 @@ static void ilk_assign_luts(struct intel_crtc_state *crtc_state) drm_property_replace_blob(&crtc_state->post_csc_lut, NULL); } + + return 0; } static int ilk_color_check(struct intel_crtc_state *crtc_state) @@ -1613,7 +1683,9 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; - ilk_assign_luts(crtc_state); + ret = ilk_assign_luts(crtc_state); + if (ret) + return ret; crtc_state->preload_luts = intel_can_preload_luts(crtc_state); @@ -1649,19 +1721,19 @@ static int ivb_assign_luts(struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); struct drm_property_blob *degamma_lut, *gamma_lut; - if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) { - ilk_assign_luts(crtc_state); - return 0; - } + if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) + return ilk_assign_luts(crtc_state); drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024); drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024); - degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512); + degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512, + false); if (IS_ERR(degamma_lut)) return PTR_ERR(degamma_lut); - gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512); + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512, + ilk_lut_limited_range(crtc_state)); if (IS_ERR(gamma_lut)) { drm_property_blob_put(degamma_lut); return PTR_ERR(gamma_lut); @@ -1750,7 +1822,8 @@ static int glk_assign_luts(struct intel_crtc_state *crtc_state) struct drm_property_blob *gamma_lut; gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, - INTEL_INFO(i915)->display.color.degamma_lut_size); + INTEL_INFO(i915)->display.color.degamma_lut_size, + false); if (IS_ERR(gamma_lut)) return PTR_ERR(gamma_lut); @@ -1762,7 +1835,23 @@ static int glk_assign_luts(struct intel_crtc_state *crtc_state) return 0; } - intel_assign_luts(crtc_state); + if (ilk_lut_limited_range(crtc_state)) { + struct drm_property_blob *gamma_lut; + + gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, + drm_color_lut_size(crtc_state->hw.gamma_lut), + true); + if (IS_ERR(gamma_lut)) + return PTR_ERR(gamma_lut); + + drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut); + + drm_property_blob_put(gamma_lut); + } else { + drm_property_replace_blob(&crtc_state->post_csc_lut, crtc_state->hw.gamma_lut); + } + + drm_property_replace_blob(&crtc_state->pre_csc_lut, crtc_state->hw.degamma_lut); /* * On GLK+ both pipe CSC and degamma LUT are controlled @@ -1821,7 +1910,7 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) glk_use_pre_csc_lut_for_gamma(crtc_state) || crtc_state->hw.degamma_lut || crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || - crtc_state->hw.ctm || crtc_state->limited_color_range; + crtc_state->hw.ctm || ilk_csc_limited_range(crtc_state); crtc_state->gamma_mode = glk_gamma_mode(crtc_state); -- cgit v1.2.3 From 67630bacae2354c3ae20b10cf25bc7e274882200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2022 17:37:31 +0200 Subject: drm/i915: Add 10bit gamma mode for gen2/3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some gen2/gen3 parts have a 10bit gamma mode, on some pipes. Expose it. The format is different to the later i965+ style in that we store a 10bit value and a 6 bit floating point slope for each entry. Ie. the hardware extrapolates the intermediate steps from the current LUT entry, instead of interpolating between the current and next LUT entries. This also means we don't store the last LUT entry in any register as it is defined by the previous LUT entry's value+slope. The slope has limited precision though (2 bit exponent + 4 bit mantissa), so we'd have to allow for more error in the state checker for the last entry and we have to make sure userspace doesn't pass in something where the slope is simply to steep. In theory we should perhaps check the slope for every interval, but we don't do that for any other interpolated gamma mode and I suspect they may also have some internal limit on the slope. I haven't confirmed that theory though. Anyways, for ease of implementation we shall just ignore the last entry in the state checker. If all the other entries match anyway then that seems like a good indication that the hardware was programmed as expected. v2: Redo the state checker logic a bit Rebase due to other changes v3: Fix C8 readout v4: Use REG_FIELD_PREP() Acked-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221114153732.11773-20-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 268 +++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_pci.c | 10 +- drivers/gpu/drm/i915/i915_reg.h | 14 ++ 3 files changed, 271 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dee0382015a5..842d58da3128 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -467,6 +467,79 @@ static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val) entry->blue = intel_color_lut_pack(REG_FIELD_GET(PALETTE_BLUE_MASK, val), 8); } +/* i8xx/i9xx+ 10bit slope format "even DW" (low 8 bits) */ +static u32 _i9xx_lut_10_ldw(u16 a) +{ + return drm_color_lut_extract(a, 10) & 0xff; +} + +static u32 i9xx_lut_10_ldw(const struct drm_color_lut *color) +{ + return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_ldw(color[0].red)) | + REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_ldw(color[0].green)) | + REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_ldw(color[0].blue)); +} + +/* i8xx/i9xx+ 10bit slope format "odd DW" (high 2 bits + slope) */ +static u32 _i9xx_lut_10_udw(u16 a, u16 b) +{ + unsigned int mantissa, exponent; + + a = drm_color_lut_extract(a, 10); + b = drm_color_lut_extract(b, 10); + + /* b = a + 8 * m * 2 ^ -e */ + mantissa = clamp(b - a, 0, 0x7f); + exponent = 3; + while (mantissa > 0xf) { + mantissa >>= 1; + exponent--; + } + + return (exponent << 6) | + (mantissa << 2) | + (a >> 8); +} + +static u32 i9xx_lut_10_udw(const struct drm_color_lut *color) +{ + return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_udw(color[0].red, color[1].red)) | + REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_udw(color[0].green, color[1].green)) | + REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_udw(color[0].blue, color[1].blue)); +} + +static void i9xx_lut_10_pack(struct drm_color_lut *color, + u32 ldw, u32 udw) +{ + u16 red = REG_FIELD_GET(PALETTE_10BIT_RED_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_RED_UDW_MASK, udw) << 8; + u16 green = REG_FIELD_GET(PALETTE_10BIT_GREEN_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_GREEN_UDW_MASK, udw) << 8; + u16 blue = REG_FIELD_GET(PALETTE_10BIT_BLUE_LDW_MASK, ldw) | + REG_FIELD_GET(PALETTE_10BIT_BLUE_UDW_MASK, udw) << 8; + + color->red = intel_color_lut_pack(red, 10); + color->green = intel_color_lut_pack(green, 10); + color->blue = intel_color_lut_pack(blue, 10); +} + +static void i9xx_lut_10_pack_slope(struct drm_color_lut *color, + u32 ldw, u32 udw) +{ + int r_exp = REG_FIELD_GET(PALETTE_10BIT_RED_EXP_MASK, udw); + int r_mant = REG_FIELD_GET(PALETTE_10BIT_RED_MANT_MASK, udw); + int g_exp = REG_FIELD_GET(PALETTE_10BIT_GREEN_EXP_MASK, udw); + int g_mant = REG_FIELD_GET(PALETTE_10BIT_GREEN_MANT_MASK, udw); + int b_exp = REG_FIELD_GET(PALETTE_10BIT_BLUE_EXP_MASK, udw); + int b_mant = REG_FIELD_GET(PALETTE_10BIT_BLUE_MANT_MASK, udw); + + i9xx_lut_10_pack(color, ldw, udw); + + color->red += r_mant << (3 - r_exp); + color->green += g_mant << (3 - g_exp); + color->blue += b_mant << (3 - b_exp); +} + /* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */ static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color) { @@ -691,12 +764,38 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc, i9xx_lut_8(&lut[i])); } +static void i9xx_load_lut_10(struct intel_crtc *crtc, + const struct drm_property_blob *blob) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct drm_color_lut *lut = blob->data; + int i, lut_size = drm_color_lut_size(blob); + enum pipe pipe = crtc->pipe; + + for (i = 0; i < lut_size - 1; i++) { + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 0), + i9xx_lut_10_ldw(&lut[i])); + intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 1), + i9xx_lut_10_udw(&lut[i])); + } +} + static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - i9xx_load_lut_8(crtc, post_csc_lut); + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + i9xx_load_lut_8(crtc, post_csc_lut); + break; + case GAMMA_MODE_MODE_10BIT: + i9xx_load_lut_10(crtc, post_csc_lut); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static void i965_load_lut_10p6(struct intel_crtc *crtc, @@ -724,10 +823,17 @@ static void i965_load_luts(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: i9xx_load_lut_8(crtc, post_csc_lut); - else + break; + case GAMMA_MODE_MODE_10BIT: i965_load_lut_10p6(crtc, post_csc_lut); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static void ilk_load_lut_8(struct intel_crtc *crtc, @@ -1450,7 +1556,31 @@ static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state) lut_is_legacy(crtc_state->hw.gamma_lut)) return GAMMA_MODE_MODE_8BIT; else - return GAMMA_MODE_MODE_10BIT; /* i965+ only */ + return GAMMA_MODE_MODE_10BIT; +} + +static int i9xx_lut_10_diff(u16 a, u16 b) +{ + return drm_color_lut_extract(a, 10) - + drm_color_lut_extract(b, 10); +} + +static int i9xx_check_lut_10(struct drm_i915_private *dev_priv, + const struct drm_property_blob *blob) +{ + const struct drm_color_lut *lut = blob->data; + int lut_size = drm_color_lut_size(blob); + const struct drm_color_lut *a = &lut[lut_size - 2]; + const struct drm_color_lut *b = &lut[lut_size - 1]; + + if (i9xx_lut_10_diff(b->red, a->red) > 0x7f || + i9xx_lut_10_diff(b->green, a->green) > 0x7f || + i9xx_lut_10_diff(b->blue, a->blue) > 0x7f) { + drm_dbg_kms(&dev_priv->drm, "Last gamma LUT entry exceeds max slope\n"); + return -EINVAL; + } + + return 0; } void intel_color_assert_luts(const struct intel_crtc_state *crtc_state) @@ -1493,6 +1623,7 @@ static void intel_assign_luts(struct intel_crtc_state *crtc_state) static int i9xx_color_check(struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int ret; ret = check_luts(crtc_state); @@ -1505,6 +1636,13 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state); + if (DISPLAY_VER(i915) < 4 && + crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) { + ret = i9xx_check_lut_10(i915, crtc_state->hw.gamma_lut); + if (ret) + return ret; + } + ret = intel_color_add_affected_planes(crtc_state); if (ret) return ret; @@ -2000,7 +2138,7 @@ static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state case GAMMA_MODE_MODE_8BIT: return 8; case GAMMA_MODE_MODE_10BIT: - return 16; + return 10; default: MISSING_CASE(crtc_state->gamma_mode); return 0; @@ -2012,6 +2150,22 @@ static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) return 0; } +static int i965_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) +{ + if (!crtc_state->gamma_enable && !crtc_state->c8_planes) + return 0; + + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + return 8; + case GAMMA_MODE_MODE_10BIT: + return 16; + default: + MISSING_CASE(crtc_state->gamma_mode); + return 0; + } +} + static int ilk_gamma_mode_precision(u32 gamma_mode) { switch (gamma_mode) { @@ -2079,7 +2233,7 @@ static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) return 10; - return i9xx_post_csc_lut_precision(crtc_state); + return i965_post_csc_lut_precision(crtc_state); } static int chv_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state) @@ -2190,6 +2344,9 @@ static bool intel_lut_equal(const struct drm_property_blob *blob1, if (lut_size1 != lut_size2) return false; + if (check_size > lut_size1) + return false; + lut1 = blob1->data; lut2 = blob2->data; @@ -2205,13 +2362,32 @@ static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob1, const struct drm_property_blob *blob2, bool is_pre_csc_lut) +{ + int check_size = 0; + + if (is_pre_csc_lut) + return intel_lut_equal(blob1, blob2, 0, + i9xx_pre_csc_lut_precision(crtc_state)); + + /* 10bit mode last entry is implicit, just skip it */ + if (crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) + check_size = 128; + + return intel_lut_equal(blob1, blob2, check_size, + i9xx_post_csc_lut_precision(crtc_state)); +} + +static bool i965_lut_equal(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob1, + const struct drm_property_blob *blob2, + bool is_pre_csc_lut) { if (is_pre_csc_lut) return intel_lut_equal(blob1, blob2, 0, i9xx_pre_csc_lut_precision(crtc_state)); else return intel_lut_equal(blob1, blob2, 0, - i9xx_post_csc_lut_precision(crtc_state)); + i965_post_csc_lut_precision(crtc_state)); } static bool chv_lut_equal(const struct intel_crtc_state *crtc_state, @@ -2311,6 +2487,35 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) return blob; } +static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob; + struct drm_color_lut *lut; + u32 ldw, udw; + int i; + + blob = drm_property_create_blob(&dev_priv->drm, + lut_size * sizeof(lut[0]), NULL); + if (IS_ERR(blob)) + return NULL; + + lut = blob->data; + + for (i = 0; i < lut_size - 1; i++) { + ldw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 0)); + udw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 1)); + + i9xx_lut_10_pack(&lut[i], ldw, udw); + } + + i9xx_lut_10_pack_slope(&lut[i], ldw, udw); + + return blob; +} + static void i9xx_read_luts(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -2318,7 +2523,17 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; - crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: + crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); + break; + case GAMMA_MODE_MODE_10BIT: + crtc_state->post_csc_lut = i9xx_read_lut_10(crtc); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc) @@ -2358,10 +2573,17 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable && !crtc_state->c8_planes) return; - if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) + switch (crtc_state->gamma_mode) { + case GAMMA_MODE_MODE_8BIT: crtc_state->post_csc_lut = i9xx_read_lut_8(crtc); - else + break; + case GAMMA_MODE_MODE_10BIT: crtc_state->post_csc_lut = i965_read_lut_10p6(crtc); + break; + default: + MISSING_CASE(crtc_state->gamma_mode); + break; + } } static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc) @@ -2771,7 +2993,7 @@ static const struct intel_color_funcs i965_color_funcs = { .color_commit_arm = i9xx_color_commit_arm, .load_luts = i965_load_luts, .read_luts = i965_read_luts, - .lut_equal = i9xx_lut_equal, + .lut_equal = i965_lut_equal, }; static const struct intel_color_funcs i9xx_color_funcs = { @@ -2848,14 +3070,28 @@ static const struct intel_color_funcs ilk_color_funcs = { void intel_color_crtc_init(struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - bool has_ctm = INTEL_INFO(i915)->display.color.degamma_lut_size != 0; + int degamma_lut_size, gamma_lut_size; + bool has_ctm; drm_mode_crtc_set_gamma_size(&crtc->base, 256); - drm_crtc_enable_color_mgmt(&crtc->base, - INTEL_INFO(i915)->display.color.degamma_lut_size, - has_ctm, - INTEL_INFO(i915)->display.color.gamma_lut_size); + gamma_lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size; + degamma_lut_size = INTEL_INFO(i915)->display.color.degamma_lut_size; + has_ctm = degamma_lut_size != 0; + + /* + * "DPALETTE_A: NOTE: The 8-bit (non-10-bit) mode is the + * only mode supported by Alviso and Grantsdale." + * + * Actually looks like this affects all of gen3. + * Confirmed on alv,cst,pnv. Mobile gen2 parts (alm,mgm) + * are confirmed not to suffer from this restriction. + */ + if (DISPLAY_VER(i915) == 3 && crtc->pipe == PIPE_A) + gamma_lut_size = 256; + + drm_crtc_enable_color_mgmt(&crtc->base, degamma_lut_size, + has_ctm, gamma_lut_size); } int intel_color_init(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 24708fc4f386..161e9ad47cbe 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -132,9 +132,9 @@ [PIPE_D] = TGL_CURSOR_D_OFFSET, \ } -#define I9XX_COLORS \ +#define I845_COLORS \ .display.color = { .gamma_lut_size = 256 } -#define I965_COLORS \ +#define I9XX_COLORS \ .display.color = { .gamma_lut_size = 129, \ .gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \ } @@ -210,7 +210,7 @@ .dma_mask_size = 32, \ I845_PIPE_OFFSETS, \ I845_CURSOR_OFFSETS, \ - I9XX_COLORS, \ + I845_COLORS, \ GEN_DEFAULT_PAGE_SIZES, \ GEN_DEFAULT_REGIONS @@ -341,7 +341,7 @@ static const struct intel_device_info pnv_m_info = { .dma_mask_size = 36, \ I9XX_PIPE_OFFSETS, \ I9XX_CURSOR_OFFSETS, \ - I965_COLORS, \ + I9XX_COLORS, \ GEN_DEFAULT_PAGE_SIZES, \ GEN_DEFAULT_REGIONS @@ -547,7 +547,7 @@ static const struct intel_device_info vlv_info = { .display.mmio_offset = VLV_DISPLAY_BASE, I9XX_PIPE_OFFSETS, I9XX_CURSOR_OFFSETS, - I965_COLORS, + I9XX_COLORS, GEN_DEFAULT_PAGE_SIZES, GEN_DEFAULT_REGIONS, }; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9ae8772283f6..0be66eec49c9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1712,6 +1712,20 @@ #define PALETTE_RED_MASK REG_GENMASK(23, 16) #define PALETTE_GREEN_MASK REG_GENMASK(15, 8) #define PALETTE_BLUE_MASK REG_GENMASK(7, 0) +/* pre-i965 10bit interpolated mode ldw */ +#define PALETTE_10BIT_RED_LDW_MASK REG_GENMASK(23, 16) +#define PALETTE_10BIT_GREEN_LDW_MASK REG_GENMASK(15, 8) +#define PALETTE_10BIT_BLUE_LDW_MASK REG_GENMASK(7, 0) +/* pre-i965 10bit interpolated mode udw */ +#define PALETTE_10BIT_RED_EXP_MASK REG_GENMASK(23, 22) +#define PALETTE_10BIT_RED_MANT_MASK REG_GENMASK(21, 18) +#define PALETTE_10BIT_RED_UDW_MASK REG_GENMASK(17, 16) +#define PALETTE_10BIT_GREEN_EXP_MASK REG_GENMASK(15, 14) +#define PALETTE_10BIT_GREEN_MANT_MASK REG_GENMASK(13, 10) +#define PALETTE_10BIT_GREEN_UDW_MASK REG_GENMASK(9, 8) +#define PALETTE_10BIT_BLUE_EXP_MASK REG_GENMASK(7, 6) +#define PALETTE_10BIT_BLUE_MANT_MASK REG_GENMASK(5, 2) +#define PALETTE_10BIT_BLUE_UDW_MASK REG_GENMASK(1, 0) #define PALETTE(pipe, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + \ _PICK((pipe), _PALETTE_A, \ _PALETTE_B, _CHV_PALETTE_C) + \ -- cgit v1.2.3 From d1dd99083d187f64e5f4e507dcebf0d6228b901a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 22 Nov 2022 14:09:48 +0200 Subject: drm/i915/hti: avoid theoretically possible negative shift If phy is PHY_NONE, the shift to register bits becomes negative. Check and warn about this. Reported-by: coverity-bot References: https://lore.kernel.org/r/202211180848.D39006C@keescook Signed-off-by: Jani Nikula Reviewed-by: Kees Cook Link: https://patchwork.freedesktop.org/patch/msgid/20221122120948.3436180-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_hti.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hti.c b/drivers/gpu/drm/i915/display/intel_hti.c index 12a1f4ce1a77..c518efebdf77 100644 --- a/drivers/gpu/drm/i915/display/intel_hti.c +++ b/drivers/gpu/drm/i915/display/intel_hti.c @@ -21,6 +21,9 @@ void intel_hti_init(struct drm_i915_private *i915) bool intel_hti_uses_phy(struct drm_i915_private *i915, enum phy phy) { + if (drm_WARN_ON(&i915->drm, phy == PHY_NONE)) + return false; + return i915->display.hti.state & HDPORT_ENABLED && i915->display.hti.state & HDPORT_DDI_USED(phy); } -- cgit v1.2.3 From 6ad0571b58f9ad6c85306e6115353b8034d77ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:16 +0200 Subject: drm/i915/dvo/ch7xxx: Fix suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Poke a few more bits into the ch7xxx to make it output a picture after being reset during S3. In particular we need to set the input buffer select (IBS), and enable VGA vsync output on the BCO pin. Selecting VGA hsync on the c/h sync pin doesn't actually seem necessary on my ADD card at least, but the BIOS selects it so why not. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-2-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_ch7xxx.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c index 54f58ba44b9f..6d948520e9a6 100644 --- a/drivers/gpu/drm/i915/display/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/display/dvo_ch7xxx.c @@ -50,15 +50,26 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define CH7xxx_INPUT_CLOCK 0x1d #define CH7xxx_GPIO 0x1e #define CH7xxx_GPIO_HPIR (1<<3) -#define CH7xxx_IDF 0x1f +#define CH7xxx_IDF 0x1f +#define CH7xxx_IDF_IBS (1<<7) +#define CH7xxx_IDF_DES (1<<6) #define CH7xxx_IDF_HSP (1<<3) #define CH7xxx_IDF_VSP (1<<4) #define CH7xxx_CONNECTION_DETECT 0x20 #define CH7xxx_CDET_DVI (1<<5) -#define CH7301_DAC_CNTL 0x21 +#define CH7xxx_DAC_CNTL 0x21 +#define CH7xxx_SYNCO_MASK (3 << 3) +#define CH7xxx_SYNCO_VGA_HSYNC (1 << 3) + +#define CH7xxx_CLOCK_OUTPUT 0x22 +#define CH7xxx_BCOEN (1 << 4) +#define CH7xxx_BCOP (1 << 3) +#define CH7xxx_BCO_MASK (7 << 0) +#define CH7xxx_BCO_VGA_VSYNC (6 << 0) + #define CH7301_HOTPLUG 0x23 #define CH7xxx_TCTL 0x31 #define CH7xxx_TVCO 0x32 @@ -301,6 +312,8 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo, ch7xxx_readb(dvo, CH7xxx_IDF, &idf); + idf |= CH7xxx_IDF_IBS; + idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP); if (mode->flags & DRM_MODE_FLAG_PHSYNC) idf |= CH7xxx_IDF_HSP; @@ -309,6 +322,11 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo, idf |= CH7xxx_IDF_VSP; ch7xxx_writeb(dvo, CH7xxx_IDF, idf); + + ch7xxx_writeb(dvo, CH7xxx_DAC_CNTL, + CH7xxx_SYNCO_VGA_HSYNC); + ch7xxx_writeb(dvo, CH7xxx_CLOCK_OUTPUT, + CH7xxx_BCOEN | CH7xxx_BCO_VGA_VSYNC); } /* set the CH7xxx power state */ -- cgit v1.2.3 From 49908b743f6ede9157771130ef24bc13389c9f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:17 +0200 Subject: drm/i915/dvo/sil164: Nuke pointless return statements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the pointless return statements at the end of void functions. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_sil164.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index 0dfa0a0209ff..32dd3b969946 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -205,7 +205,6 @@ static void sil164_mode_set(struct intel_dvo_device *dvo, sil164_writeb(sil, 0x0c, 0x89); sil164_writeb(sil, 0x08, 0x31);*/ /* don't do much */ - return; } /* set the SIL164 power state */ @@ -224,7 +223,6 @@ static void sil164_dpms(struct intel_dvo_device *dvo, bool enable) ch &= ~SIL164_8_PD; sil164_writeb(dvo, SIL164_REG8, ch); - return; } static bool sil164_get_hw_state(struct intel_dvo_device *dvo) -- cgit v1.2.3 From bf590368e540f87983769e7b9d4a5275f1edb81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:18 +0200 Subject: drm/i915/dvo/sil164: Fix suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Poke a few more bits into the SiI164 to make it recover after S3. HEN/VEN are the important bits, the rest PLL filter/HPD detection I just did for good measure to match the BIOS programming. Note that the spec recommended SCNT bit in REGC isn't set by the BIOS at least for me, so I left it out. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-4-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/dvo_sil164.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/dvo_sil164.c b/drivers/gpu/drm/i915/display/dvo_sil164.c index 32dd3b969946..4acc8ce29c0b 100644 --- a/drivers/gpu/drm/i915/display/dvo_sil164.c +++ b/drivers/gpu/drm/i915/display/dvo_sil164.c @@ -58,6 +58,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SIL164_9_MDI (1<<0) #define SIL164_REGC 0x0c +#define SIL164_C_SCNT (1<<7) +#define SIL164_C_PLLF_MASK (0xf<<1) +#define SIL164_C_PLLF_REC (4<<1) +#define SIL164_C_PFEN (1<<0) struct sil164_priv { //I2CDevRec d; @@ -205,6 +209,13 @@ static void sil164_mode_set(struct intel_dvo_device *dvo, sil164_writeb(sil, 0x0c, 0x89); sil164_writeb(sil, 0x08, 0x31);*/ /* don't do much */ + + sil164_writeb(dvo, SIL164_REG8, + SIL164_8_VEN | SIL164_8_HEN); + sil164_writeb(dvo, SIL164_REG9, + SIL164_9_TSEL); + sil164_writeb(dvo, SIL164_REGC, + SIL164_C_PLLF_REC | SIL164_C_PFEN); } /* set the SIL164 power state */ -- cgit v1.2.3 From a8d9a13d24af4555d211680d50af44a79e799c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:19 +0200 Subject: drm/i915/dvo: Parametrize DVO/DVO_SRCDIM registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the dvo_reg/dvo_srcdim_reg stuff by parametrizing the DVO port registers. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 73 +++++++++++----------------- drivers/gpu/drm/i915/display/intel_dvo_dev.h | 7 +-- drivers/gpu/drm/i915/i915_reg.h | 11 ++--- 3 files changed, 37 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 575cb920bd43..d20334d3394c 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -56,48 +56,42 @@ static const struct intel_dvo_device intel_dvo_devices[] = { { .type = INTEL_DVO_CHIP_TMDS, .name = "sil164", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = SIL164_ADDR, .dev_ops = &sil164_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = CH7xxx_ADDR, .dev_ops = &ch7xxx_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = 0x75, /* For some ch7010 */ .dev_ops = &ch7xxx_ops, }, { .type = INTEL_DVO_CHIP_LVDS, .name = "ivch", - .dvo_reg = DVOA, - .dvo_srcdim_reg = DVOA_SRCDIM, + .port = PORT_A, .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ .dev_ops = &ivch_ops, }, { .type = INTEL_DVO_CHIP_TMDS, .name = "tfp410", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = TFP410_ADDR, .dev_ops = &tfp410_ops, }, { .type = INTEL_DVO_CHIP_LVDS, .name = "ch7017", - .dvo_reg = DVOC, - .dvo_srcdim_reg = DVOC_SRCDIM, + .port = PORT_C, .slave_addr = 0x75, .gpio = GMBUS_PIN_DPB, .dev_ops = &ch7017_ops, @@ -105,8 +99,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { { .type = INTEL_DVO_CHIP_LVDS_NO_FIXED, .name = "ns2501", - .dvo_reg = DVOB, - .dvo_srcdim_reg = DVOB_SRCDIM, + .port = PORT_B, .slave_addr = NS2501_ADDR, .dev_ops = &ns2501_ops, }, @@ -133,10 +126,12 @@ static struct intel_dvo *intel_attached_dvo(struct intel_connector *connector) static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct intel_dvo *intel_dvo = intel_attached_dvo(connector); + struct intel_encoder *encoder = intel_attached_encoder(connector); + struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; u32 tmp; - tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); if (!(tmp & DVO_ENABLE)) return false; @@ -148,10 +143,10 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; u32 tmp; - tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); *pipe = (tmp & DVO_PIPE_SEL_MASK) >> DVO_PIPE_SEL_SHIFT; @@ -162,12 +157,12 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; u32 tmp, flags = 0; pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO); - tmp = intel_de_read(i915, intel_dvo->dev.dvo_reg); + tmp = intel_de_read(i915, DVO(port)); if (tmp & DVO_HSYNC_ACTIVE_HIGH) flags |= DRM_MODE_FLAG_PHSYNC; else @@ -189,12 +184,12 @@ static void intel_disable_dvo(struct intel_atomic_state *state, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(i915, dvo_reg); + enum port port = encoder->port; + u32 temp = intel_de_read(i915, DVO(port)); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); - intel_de_write(i915, dvo_reg, temp & ~DVO_ENABLE); - intel_de_read(i915, dvo_reg); + intel_de_write(i915, DVO(port), temp & ~DVO_ENABLE); + intel_de_read(i915, DVO(port)); } static void intel_enable_dvo(struct intel_atomic_state *state, @@ -204,15 +199,15 @@ static void intel_enable_dvo(struct intel_atomic_state *state, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - u32 temp = intel_de_read(i915, dvo_reg); + enum port port = encoder->port; + u32 temp = intel_de_read(i915, DVO(port)); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, &pipe_config->hw.mode, &pipe_config->hw.adjusted_mode); - intel_de_write(i915, dvo_reg, temp | DVO_ENABLE); - intel_de_read(i915, dvo_reg); + intel_de_write(i915, DVO(port), temp | DVO_ENABLE); + intel_de_read(i915, DVO(port)); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } @@ -289,14 +284,12 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + enum port port = encoder->port; enum pipe pipe = crtc->pipe; u32 dvo_val; - i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; - i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg; /* Save the data order, since I don't know what it should be set to. */ - dvo_val = intel_de_read(i915, dvo_reg) & + dvo_val = intel_de_read(i915, DVO(port)) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; @@ -308,9 +301,9 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) dvo_val |= DVO_VSYNC_ACTIVE_HIGH; - intel_de_write(i915, dvo_srcdim_reg, + intel_de_write(i915, DVO_SRCDIM(port), (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); - intel_de_write(i915, dvo_reg, dvo_val); + intel_de_write(i915, DVO(port), dvo_val); } static enum drm_connector_status @@ -378,16 +371,6 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { .destroy = intel_dvo_enc_destroy, }; -static enum port intel_dvo_port(i915_reg_t dvo_reg) -{ - if (i915_mmio_reg_equal(dvo_reg, DVOA)) - return PORT_A; - else if (i915_mmio_reg_equal(dvo_reg, DVOB)) - return PORT_B; - else - return PORT_C; -} - static int intel_dvo_encoder_type(const struct intel_dvo_device *dvo) { switch (dvo->type) { @@ -528,7 +511,7 @@ void intel_dvo_init(struct drm_i915_private *i915) encoder->type = INTEL_OUTPUT_DVO; encoder->power_domain = POWER_DOMAIN_PORT_OTHER; - encoder->port = intel_dvo_port(intel_dvo->dev.dvo_reg); + encoder->port = intel_dvo->dev.port; encoder->pipe_mask = ~0; if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS) diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h index ecff7b190856..ea8eb7dcee38 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h +++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h @@ -25,6 +25,8 @@ #include "i915_reg_defs.h" +#include "intel_display.h" + enum drm_connector_status; struct drm_display_mode; struct i2c_adapter; @@ -32,9 +34,8 @@ struct i2c_adapter; struct intel_dvo_device { const char *name; int type; - /* DVOA/B/C output register */ - i915_reg_t dvo_reg; - i915_reg_t dvo_srcdim_reg; + /* DVOA/B/C */ + enum port port; /* GPIO register used for i2c bus to control this device */ u32 gpio; int slave_addr; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0be66eec49c9..87f60b9fd01a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2591,11 +2591,9 @@ /* DVO port control */ #define _DVOA 0x61120 -#define DVOA _MMIO(_DVOA) #define _DVOB 0x61140 -#define DVOB _MMIO(_DVOB) #define _DVOC 0x61160 -#define DVOC _MMIO(_DVOC) +#define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB) #define DVO_ENABLE (1 << 31) #define DVO_PIPE_SEL_SHIFT 30 #define DVO_PIPE_SEL_MASK (1 << 30) @@ -2622,9 +2620,10 @@ #define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ #define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ #define DVO_PRESERVE_MASK (0x7 << 24) -#define DVOA_SRCDIM _MMIO(0x61124) -#define DVOB_SRCDIM _MMIO(0x61144) -#define DVOC_SRCDIM _MMIO(0x61164) +#define _DVOA_SRCDIM 0x61124 +#define _DVOB_SRCDIM 0x61144 +#define _DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM) #define DVO_SRCDIM_HORIZONTAL_SHIFT 12 #define DVO_SRCDIM_VERTICAL_SHIFT 0 -- cgit v1.2.3 From 5abd7d8d0e47ef9bfe7016489d4acf75ac2eccc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:20 +0200 Subject: drm/i915/dvo: Define a few more DVO register bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define a few extra interrupt related bits on the DVO register. One of these we included in the DVO_PRESERVE_MASK already. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-6-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 3 ++- drivers/gpu/drm/i915/i915_reg.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index d20334d3394c..255deb55b932 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -290,7 +290,8 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, /* Save the data order, since I don't know what it should be set to. */ dvo_val = intel_de_read(i915, DVO(port)) & - (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + (DVO_DEDICATED_INT_ENABLE | + DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 87f60b9fd01a..e77aeb0a379f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2602,6 +2602,9 @@ #define DVO_PIPE_STALL (1 << 28) #define DVO_PIPE_STALL_TV (2 << 28) #define DVO_PIPE_STALL_MASK (3 << 28) +#define DVO_INTERRUPT_SELECT (1 << 27) +#define DVO_DEDICATED_INT_ENABLE (1 << 26) +#define DVO_PRESERVE_MASK (0x3 << 24) #define DVO_USE_VGA_SYNC (1 << 15) #define DVO_DATA_ORDER_I740 (0 << 14) #define DVO_DATA_ORDER_FP (1 << 14) @@ -2619,7 +2622,6 @@ #define DVO_BLANK_ACTIVE_HIGH (1 << 2) #define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ #define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ -#define DVO_PRESERVE_MASK (0x7 << 24) #define _DVOA_SRCDIM 0x61124 #define _DVOB_SRCDIM 0x61144 #define _DVOC_SRCDIM 0x61164 -- cgit v1.2.3 From 9710a5c14ede96628595d7105faeb0e9b94f1ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:21 +0200 Subject: drm/i915/dvo: Rename the "active data order" bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have two sets of bits for DVO "data order" stuff. Rename one set to ACT_DATA_ORDER to make it clear they are separate bitfields. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 255deb55b932..b36c3a620250 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -288,10 +288,10 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, enum pipe pipe = crtc->pipe; u32 dvo_val; - /* Save the data order, since I don't know what it should be set to. */ + /* Save the active data order, since I don't know what it should be set to. */ dvo_val = intel_de_read(i915, DVO(port)) & (DVO_DEDICATED_INT_ENABLE | - DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); + DVO_PRESERVE_MASK | DVO_ACT_DATA_ORDER_GBRG); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e77aeb0a379f..e06c98fd923e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2613,10 +2613,10 @@ #define DVO_VSYNC_TRISTATE (1 << 9) #define DVO_HSYNC_TRISTATE (1 << 8) #define DVO_BORDER_ENABLE (1 << 7) -#define DVO_DATA_ORDER_GBRG (1 << 6) -#define DVO_DATA_ORDER_RGGB (0 << 6) -#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) -#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) +#define DVO_ACT_DATA_ORDER_GBRG (1 << 6) +#define DVO_ACT_DATA_ORDER_RGGB (0 << 6) +#define DVO_ACT_DATA_ORDER_GBRG_ERRATA (0 << 6) +#define DVO_ACT_DATA_ORDER_RGGB_ERRATA (1 << 6) #define DVO_VSYNC_ACTIVE_HIGH (1 << 4) #define DVO_HSYNC_ACTIVE_HIGH (1 << 3) #define DVO_BLANK_ACTIVE_HIGH (1 << 2) -- cgit v1.2.3 From 7ce5b3a7048cd73cff83ab12d62c6e9d53028b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:22 +0200 Subject: drm/i915/dvo: Use REG_BIT() & co. for DVO registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Polish the DVO port registers with REG_BIT()/etc. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 7 ++-- drivers/gpu/drm/i915/i915_reg.h | 63 +++++++++++++++++--------------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index b36c3a620250..a5c464c82e5c 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -148,7 +148,7 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, tmp = intel_de_read(i915, DVO(port)); - *pipe = (tmp & DVO_PIPE_SEL_MASK) >> DVO_PIPE_SEL_SHIFT; + *pipe = REG_FIELD_GET(DVO_PIPE_SEL_MASK, tmp); return tmp & DVO_ENABLE; } @@ -291,7 +291,7 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, /* Save the active data order, since I don't know what it should be set to. */ dvo_val = intel_de_read(i915, DVO(port)) & (DVO_DEDICATED_INT_ENABLE | - DVO_PRESERVE_MASK | DVO_ACT_DATA_ORDER_GBRG); + DVO_PRESERVE_MASK | DVO_ACT_DATA_ORDER_MASK); dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; @@ -303,7 +303,8 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, dvo_val |= DVO_VSYNC_ACTIVE_HIGH; intel_de_write(i915, DVO_SRCDIM(port), - (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); + DVO_SRCDIM_HORIZONTAL(adjusted_mode->crtc_hdisplay) | + DVO_SRCDIM_VERTICAL(adjusted_mode->crtc_vdisplay)); intel_de_write(i915, DVO(port), dvo_val); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e06c98fd923e..1a7de9c8309d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2594,40 +2594,43 @@ #define _DVOB 0x61140 #define _DVOC 0x61160 #define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB) -#define DVO_ENABLE (1 << 31) -#define DVO_PIPE_SEL_SHIFT 30 -#define DVO_PIPE_SEL_MASK (1 << 30) -#define DVO_PIPE_SEL(pipe) ((pipe) << 30) -#define DVO_PIPE_STALL_UNUSED (0 << 28) -#define DVO_PIPE_STALL (1 << 28) -#define DVO_PIPE_STALL_TV (2 << 28) -#define DVO_PIPE_STALL_MASK (3 << 28) -#define DVO_INTERRUPT_SELECT (1 << 27) -#define DVO_DEDICATED_INT_ENABLE (1 << 26) -#define DVO_PRESERVE_MASK (0x3 << 24) -#define DVO_USE_VGA_SYNC (1 << 15) -#define DVO_DATA_ORDER_I740 (0 << 14) -#define DVO_DATA_ORDER_FP (1 << 14) -#define DVO_VSYNC_DISABLE (1 << 11) -#define DVO_HSYNC_DISABLE (1 << 10) -#define DVO_VSYNC_TRISTATE (1 << 9) -#define DVO_HSYNC_TRISTATE (1 << 8) -#define DVO_BORDER_ENABLE (1 << 7) -#define DVO_ACT_DATA_ORDER_GBRG (1 << 6) -#define DVO_ACT_DATA_ORDER_RGGB (0 << 6) -#define DVO_ACT_DATA_ORDER_GBRG_ERRATA (0 << 6) -#define DVO_ACT_DATA_ORDER_RGGB_ERRATA (1 << 6) -#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) -#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) -#define DVO_BLANK_ACTIVE_HIGH (1 << 2) -#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ -#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ +#define DVO_ENABLE REG_BIT(31) +#define DVO_PIPE_SEL_MASK REG_BIT(30) +#define DVO_PIPE_SEL(pipe) REG_FIELD_PREP(DVO_PIPE_SEL_MASK, (pipe)) +#define DVO_PIPE_STALL_MASK REG_GENMASK(29, 28) +#define DVO_PIPE_STALL_UNUSED REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 0) +#define DVO_PIPE_STALL REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 1) +#define DVO_PIPE_STALL_TV REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 2) +#define DVO_INTERRUPT_SELECT REG_BIT(27) +#define DVO_DEDICATED_INT_ENABLE REG_BIT(26) +#define DVO_PRESERVE_MASK REG_GENMASK(25, 24) +#define DVO_USE_VGA_SYNC REG_BIT(15) +#define DVO_DATA_ORDER_MASK REG_BIT(14) +#define DVO_DATA_ORDER_I740 REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 0) +#define DVO_DATA_ORDER_FP REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_DISABLE REG_BIT(11) +#define DVO_HSYNC_DISABLE REG_BIT(10) +#define DVO_VSYNC_TRISTATE REG_BIT(9) +#define DVO_HSYNC_TRISTATE REG_BIT(8) +#define DVO_BORDER_ENABLE REG_BIT(7) +#define DVO_ACT_DATA_ORDER_MASK REG_BIT(6) +#define DVO_ACT_DATA_ORDER_RGGB REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_GBRG REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_ACT_DATA_ORDER_GBRG_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_RGGB_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_ACTIVE_HIGH REG_BIT(4) +#define DVO_HSYNC_ACTIVE_HIGH REG_BIT(3) +#define DVO_BLANK_ACTIVE_HIGH REG_BIT(2) +#define DVO_OUTPUT_CSTATE_PIXELS REG_BIT(1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS REG_BIT(0) /* SDG only */ #define _DVOA_SRCDIM 0x61124 #define _DVOB_SRCDIM 0x61144 #define _DVOC_SRCDIM 0x61164 #define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM) -#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 -#define DVO_SRCDIM_VERTICAL_SHIFT 0 +#define DVO_SRCDIM_HORIZONTAL_MASK REG_GENMASK(22, 12) +#define DVO_SRCDIM_HORIZONTAL(x) REG_FIELD_PREP(DVO_SRCDIM_HORIZONTAL_MASK, (x)) +#define DVO_SRCDIM_VERTICAL_MASK REG_GENMASK(10, 0) +#define DVO_SRCDIM_VERTICAL(x) REG_FIELD_PREP(DVO_SRCDIM_VERTICAL_MASK, (x)) /* LVDS port control */ #define LVDS _MMIO(0x61180) -- cgit v1.2.3 From 079c4c0c6c48506bb657e67fdbe14ee9d7d683e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:23 +0200 Subject: drm/i915/dvo: Use intel_de_rmw() for DVO enable/disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hand rolled RMW with intel_de_rmw() in the DVO port enable/disable functions. Also switch to intel_de_posting_read() for the posting read (though maybe it should be just be nuked...). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index a5c464c82e5c..c590a92205f0 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -185,11 +185,11 @@ static void intel_disable_dvo(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); enum port port = encoder->port; - u32 temp = intel_de_read(i915, DVO(port)); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); - intel_de_write(i915, DVO(port), temp & ~DVO_ENABLE); - intel_de_read(i915, DVO(port)); + + intel_de_rmw(i915, DVO(port), DVO_ENABLE, 0); + intel_de_posting_read(i915, DVO(port)); } static void intel_enable_dvo(struct intel_atomic_state *state, @@ -200,14 +200,13 @@ static void intel_enable_dvo(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); enum port port = encoder->port; - u32 temp = intel_de_read(i915, DVO(port)); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, &pipe_config->hw.mode, &pipe_config->hw.adjusted_mode); - intel_de_write(i915, DVO(port), temp | DVO_ENABLE); - intel_de_read(i915, DVO(port)); + intel_de_rmw(i915, DVO(port), 0, DVO_ENABLE); + intel_de_posting_read(i915, DVO(port)); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } -- cgit v1.2.3 From df9f0ebe87912bd9d3c82b45fecd6d6fa9874cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:24 +0200 Subject: drm/i915/dvo: Extract intel_dvo_regs.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the DVO port register definitons into their own header to declutter i915_reg.h a bit. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 1 + drivers/gpu/drm/i915/display/intel_dvo_regs.h | 54 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 44 ---------------------- 3 files changed, 55 insertions(+), 44 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dvo_regs.h diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index c590a92205f0..4a4b98bfce29 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -38,6 +38,7 @@ #include "intel_display_types.h" #include "intel_dvo.h" #include "intel_dvo_dev.h" +#include "intel_dvo_regs.h" #include "intel_gmbus.h" #include "intel_panel.h" diff --git a/drivers/gpu/drm/i915/display/intel_dvo_regs.h b/drivers/gpu/drm/i915/display/intel_dvo_regs.h new file mode 100644 index 000000000000..6f9058462850 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dvo_regs.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DVO_REGS_H__ +#define __INTEL_DVO_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define _DVOA 0x61120 +#define _DVOB 0x61140 +#define _DVOC 0x61160 +#define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB) +#define DVO_ENABLE REG_BIT(31) +#define DVO_PIPE_SEL_MASK REG_BIT(30) +#define DVO_PIPE_SEL(pipe) REG_FIELD_PREP(DVO_PIPE_SEL_MASK, (pipe)) +#define DVO_PIPE_STALL_MASK REG_GENMASK(29, 28) +#define DVO_PIPE_STALL_UNUSED REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 0) +#define DVO_PIPE_STALL REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 1) +#define DVO_PIPE_STALL_TV REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 2) +#define DVO_INTERRUPT_SELECT REG_BIT(27) +#define DVO_DEDICATED_INT_ENABLE REG_BIT(26) +#define DVO_PRESERVE_MASK REG_GENMASK(25, 24) +#define DVO_USE_VGA_SYNC REG_BIT(15) +#define DVO_DATA_ORDER_MASK REG_BIT(14) +#define DVO_DATA_ORDER_I740 REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 0) +#define DVO_DATA_ORDER_FP REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_DISABLE REG_BIT(11) +#define DVO_HSYNC_DISABLE REG_BIT(10) +#define DVO_VSYNC_TRISTATE REG_BIT(9) +#define DVO_HSYNC_TRISTATE REG_BIT(8) +#define DVO_BORDER_ENABLE REG_BIT(7) +#define DVO_ACT_DATA_ORDER_MASK REG_BIT(6) +#define DVO_ACT_DATA_ORDER_RGGB REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_GBRG REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_ACT_DATA_ORDER_GBRG_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) +#define DVO_ACT_DATA_ORDER_RGGB_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) +#define DVO_VSYNC_ACTIVE_HIGH REG_BIT(4) +#define DVO_HSYNC_ACTIVE_HIGH REG_BIT(3) +#define DVO_BLANK_ACTIVE_HIGH REG_BIT(2) +#define DVO_OUTPUT_CSTATE_PIXELS REG_BIT(1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS REG_BIT(0) /* SDG only */ + +#define _DVOA_SRCDIM 0x61124 +#define _DVOB_SRCDIM 0x61144 +#define _DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM) +#define DVO_SRCDIM_HORIZONTAL_MASK REG_GENMASK(22, 12) +#define DVO_SRCDIM_HORIZONTAL(x) REG_FIELD_PREP(DVO_SRCDIM_HORIZONTAL_MASK, (x)) +#define DVO_SRCDIM_VERTICAL_MASK REG_GENMASK(10, 0) +#define DVO_SRCDIM_VERTICAL(x) REG_FIELD_PREP(DVO_SRCDIM_VERTICAL_MASK, (x)) + +#endif /* __INTEL_DVO_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1a7de9c8309d..0fa86da12af1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2588,50 +2588,6 @@ #define SDVO_PIPE_SEL_MASK_CHV (3 << 24) #define SDVO_PIPE_SEL_CHV(pipe) ((pipe) << 24) - -/* DVO port control */ -#define _DVOA 0x61120 -#define _DVOB 0x61140 -#define _DVOC 0x61160 -#define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB) -#define DVO_ENABLE REG_BIT(31) -#define DVO_PIPE_SEL_MASK REG_BIT(30) -#define DVO_PIPE_SEL(pipe) REG_FIELD_PREP(DVO_PIPE_SEL_MASK, (pipe)) -#define DVO_PIPE_STALL_MASK REG_GENMASK(29, 28) -#define DVO_PIPE_STALL_UNUSED REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 0) -#define DVO_PIPE_STALL REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 1) -#define DVO_PIPE_STALL_TV REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 2) -#define DVO_INTERRUPT_SELECT REG_BIT(27) -#define DVO_DEDICATED_INT_ENABLE REG_BIT(26) -#define DVO_PRESERVE_MASK REG_GENMASK(25, 24) -#define DVO_USE_VGA_SYNC REG_BIT(15) -#define DVO_DATA_ORDER_MASK REG_BIT(14) -#define DVO_DATA_ORDER_I740 REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 0) -#define DVO_DATA_ORDER_FP REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 1) -#define DVO_VSYNC_DISABLE REG_BIT(11) -#define DVO_HSYNC_DISABLE REG_BIT(10) -#define DVO_VSYNC_TRISTATE REG_BIT(9) -#define DVO_HSYNC_TRISTATE REG_BIT(8) -#define DVO_BORDER_ENABLE REG_BIT(7) -#define DVO_ACT_DATA_ORDER_MASK REG_BIT(6) -#define DVO_ACT_DATA_ORDER_RGGB REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) -#define DVO_ACT_DATA_ORDER_GBRG REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) -#define DVO_ACT_DATA_ORDER_GBRG_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0) -#define DVO_ACT_DATA_ORDER_RGGB_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1) -#define DVO_VSYNC_ACTIVE_HIGH REG_BIT(4) -#define DVO_HSYNC_ACTIVE_HIGH REG_BIT(3) -#define DVO_BLANK_ACTIVE_HIGH REG_BIT(2) -#define DVO_OUTPUT_CSTATE_PIXELS REG_BIT(1) /* SDG only */ -#define DVO_OUTPUT_SOURCE_SIZE_PIXELS REG_BIT(0) /* SDG only */ -#define _DVOA_SRCDIM 0x61124 -#define _DVOB_SRCDIM 0x61144 -#define _DVOC_SRCDIM 0x61164 -#define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM) -#define DVO_SRCDIM_HORIZONTAL_MASK REG_GENMASK(22, 12) -#define DVO_SRCDIM_HORIZONTAL(x) REG_FIELD_PREP(DVO_SRCDIM_HORIZONTAL_MASK, (x)) -#define DVO_SRCDIM_VERTICAL_MASK REG_GENMASK(10, 0) -#define DVO_SRCDIM_VERTICAL(x) REG_FIELD_PREP(DVO_SRCDIM_VERTICAL_MASK, (x)) - /* LVDS port control */ #define LVDS _MMIO(0x61180) /* -- cgit v1.2.3 From af2c3b557e2e66b91ea76f39d110b6023574ded4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2022 14:08:25 +0200 Subject: drm/i915/dvo: Log about what was detected on which DVO port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently it's not 100% obvious which DVO encoder chip was found on which port. Leave a slightly better trace in log. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221122120825.26338-11-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 4a4b98bfce29..4aeae0f3ac91 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -525,6 +525,10 @@ void intel_dvo_init(struct drm_i915_private *i915) intel_dvo_encoder_type(&intel_dvo->dev), "DVO %c", port_name(encoder->port)); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] detected %s\n", + encoder->base.base.id, encoder->base.name, + intel_dvo->dev.name); + if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS) connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; -- cgit v1.2.3 From 7674cd0b7d28b952151c3df26bbfa7e07eb2b4ec Mon Sep 17 00:00:00 2001 From: Xia Fukun Date: Fri, 25 Nov 2022 14:34:28 +0800 Subject: drm/i915/bios: fix a memory leak in generate_lfp_data_ptrs When (size != 0 || ptrs->lvds_ entries != 3), the program tries to free() the ptrs. However, the ptrs is not created by calling kzmalloc(), but is obtained by pointer offset operation. This may lead to memory leaks or undefined behavior. Fix this by replacing the arguments of kfree() with ptrs_block. Fixes: a87d0a847607 ("drm/i915/bios: Generate LFP data table pointers if the VBT lacks them") Signed-off-by: Xia Fukun Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221125063428.69486-1-xiafukun@huawei.com --- drivers/gpu/drm/i915/display/intel_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index c2987f2c2b2e..572a4e3769f3 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -414,7 +414,7 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915, ptrs->lvds_entries++; if (size != 0 || ptrs->lvds_entries != 3) { - kfree(ptrs); + kfree(ptrs_block); return NULL; } -- cgit v1.2.3 From 8d58bb7991c45f6b60710cc04c9498c6ea96db90 Mon Sep 17 00:00:00 2001 From: Mikko Kovanen Date: Sat, 26 Nov 2022 13:27:13 +0000 Subject: drm/i915/dsi: fix VBT send packet port selection for dual link DSI intel_dsi->ports contains bitmask of enabled ports and correspondingly logic for selecting port for VBT packet sending must use port specific bitmask when deciding appropriate port. Fixes: 08c59dde71b7 ("drm/i915/dsi: fix VBT send packet port selection for ICL+") Cc: stable@vger.kernel.org Signed-off-by: Mikko Kovanen Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/DBBPR09MB466592B16885D99ABBF2393A91119@DBBPR09MB4665.eurprd09.prod.outlook.com --- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 75e8cc4337c9..fce69fa446d5 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -137,9 +137,9 @@ static enum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi, return ffs(intel_dsi->ports) - 1; if (seq_port) { - if (intel_dsi->ports & PORT_B) + if (intel_dsi->ports & BIT(PORT_B)) return PORT_B; - else if (intel_dsi->ports & PORT_C) + else if (intel_dsi->ports & BIT(PORT_C)) return PORT_C; } -- cgit v1.2.3 From 8f5c2f6eda4fc7d078a9a1cfddda46ef686c502b Mon Sep 17 00:00:00 2001 From: Swati Sharma Date: Thu, 10 Nov 2022 15:03:12 +0530 Subject: drm/i915/dsc: Refactor dsc gen checks Use HAS_DSC(__i915) wrapper containing runtime info of has_dsc member. Platforms supporting dsc has this flag enabled; no need of DISPLAY_VER() check. Also, simplified intel_dsc_source_support() based on above changes. Suggested-by: Jani Nikula Signed-off-by: Swati Sharma Reviewed-by: Jani Nikula Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20221110093312.13932-1-swati2.sharma@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- drivers/gpu/drm/i915/display/intel_vdsc.c | 11 ++++------- drivers/gpu/drm/i915/i915_drv.h | 1 + 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cf8a2f644bab..1607c86af025 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1013,7 +1013,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, * Output bpp is stored in 6.4 format so right shift by 4 to get the * integer value since we support only integer values of bpp. */ - if (DISPLAY_VER(dev_priv) >= 10 && + if (HAS_DSC(dev_priv) && drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) { /* * TBD pass the connector BPC, @@ -2926,7 +2926,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_max_sink_lane_count(intel_dp); /* Read the eDP DSC DPCD registers */ - if (DISPLAY_VER(dev_priv) >= 10) + if (HAS_DSC(dev_priv)) intel_dp_get_dsc_sink_cap(intel_dp); /* @@ -4711,7 +4711,7 @@ intel_dp_detect(struct drm_connector *connector, } /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */ - if (DISPLAY_VER(dev_priv) >= 11) + if (HAS_DSC(dev_priv)) intel_dp_get_dsc_sink_cap(intel_dp); intel_dp_configure_mst(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 9d3b77b41b5c..207b2a648d32 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -345,16 +345,13 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - if (!RUNTIME_INFO(i915)->has_dsc) + if (!HAS_DSC(i915)) return false; - if (DISPLAY_VER(i915) >= 12) - return true; - - if (DISPLAY_VER(i915) >= 11 && cpu_transcoder != TRANSCODER_A) - return true; + if (DISPLAY_VER(i915) == 11 && cpu_transcoder == TRANSCODER_A) + return false; - return false; + return true; } static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2f074d7e0d31..d2b9981d736e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -469,6 +469,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision) #define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) +#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step) #define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step) -- cgit v1.2.3 From 6ee6692520133a14b0d0f3ddddf8c44783cfee06 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 24 Nov 2022 13:21:23 -0300 Subject: drm/i915/dmc: Update DG2 DMC version to v2.08 Release notes: 1. Fixes for Register noclaims and few restore. Fixes: c4cf059d9c2c ("drm/i915/dmc: Update DG2 DMC firmware to v2.07") Signed-off-by: Gustavo Sousa Reviewed-by: Anusha Srivatsa Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20221124162123.16870-1-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 081a4d0083b1..eff3add70611 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -52,8 +52,8 @@ #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define DG2_DMC_PATH DMC_PATH(dg2, 2, 07) -#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 07) +#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) +#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 8) MODULE_FIRMWARE(DG2_DMC_PATH); #define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) -- cgit v1.2.3 From 7d1675dcb5a16c83c60863af3cd26837750cd538 Mon Sep 17 00:00:00 2001 From: "Taylor, Clinton A" Date: Tue, 29 Nov 2022 12:33:43 -0800 Subject: drm/i915/hdmi: SPD infoframe update for discrete Replace integrated with discrete for dgfx platforms. v2: commit title reword (Jani) v3: use variable name i915 (Jani) v4: commit message reword (MattR) Cc: Jani Nikula Reviewed-by: Matt Roper Signed-off-by: Taylor, Clinton A Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221129203343.720860-1-clinton.a.taylor@intel.com --- drivers/gpu/drm/i915/display/intel_hdmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index bac85d88054f..e82f8a07e2b0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -767,6 +767,7 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd; int ret; @@ -776,7 +777,11 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD); - ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); + if (IS_DGFX(i915)) + ret = hdmi_spd_infoframe_init(frame, "Intel", "Discrete gfx"); + else + ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); + if (drm_WARN_ON(encoder->base.dev, ret)) return false; -- cgit v1.2.3 From 8ca57e4fc9aa068264ce1267c4ac51c1bca5864d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 5 Dec 2022 14:29:18 +0200 Subject: drm/i915/fbc: drop uncore locking around i8xx/i965 fbc nuke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The locking should not be needed after commits de5bd083d247 ("drm/i915/fbc: Skip nuke when flip is pending") and 7cfd1a18c5f9 ("drm/i915: Remove remaining locks from i9xx plane udpates"). Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221205122918.3092092-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index b5ee5ea0d010..deba0c49c827 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -323,10 +323,8 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); } static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) @@ -359,10 +357,8 @@ static void i965_fbc_nuke(struct intel_fbc *fbc) enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane; struct drm_i915_private *dev_priv = fbc->i915; - spin_lock_irq(&dev_priv->uncore.lock); intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane))); - spin_unlock_irq(&dev_priv->uncore.lock); } static const struct intel_fbc_funcs i965_fbc_funcs = { -- cgit v1.2.3 From 955f4d7176eb154db587ae162ec2b392dc8d5f27 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Wed, 7 Dec 2022 15:29:09 +0400 Subject: drm/i915: Fix documentation for intel_uncore_forcewake_put__locked intel_uncore_forcewake_put__locked() is used to release a reference. Fixes: a6111f7b6604 ("drm/i915: Reduce locking in execlist command submission") Signed-off-by: Miaoqian Lin Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20221207112909.2655251-1-linmq006@gmail.com --- drivers/gpu/drm/i915/intel_uncore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 92e6f03f18af..9995f478152c 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -821,9 +821,9 @@ void intel_uncore_forcewake_flush(struct intel_uncore *uncore, } /** - * intel_uncore_forcewake_put__locked - grab forcewake domain references + * intel_uncore_forcewake_put__locked - release forcewake domain references * @uncore: the intel_uncore structure - * @fw_domains: forcewake domains to get reference on + * @fw_domains: forcewake domains to put references * * See intel_uncore_forcewake_put(). This variant places the onus * on the caller to explicitly handle the dev_priv->uncore.lock spinlock. -- cgit v1.2.3 From 9e9caa4bebec167b50fc3a0e5c410194aae9ed23 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 11:34:42 +0200 Subject: drm/i915/backlight: use VLV_DISPLAY_BASE for VLV/CHV backlight registers Since the VLV/CHV backlight registers are only used on VLV/CHV, there's no need to dynamically look up DISPLAY_MMIO_BASE(). We know it's VLV_DISPLAY_BASE. Use it statically, reducing the implicit dev_priv references. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/eb252083a56ec64b4fdb58d4d30abcf305a3a9c2.1670405587.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_backlight_regs.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h index 344eb8096bd2..02bd1f8201bf 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight_regs.h +++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h @@ -8,20 +8,17 @@ #include "intel_display_reg_defs.h" -#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250) -#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350) -#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ - _VLV_BLC_PWM_CTL2_B) +#define _VLV_BLC_PWM_CTL2_A (VLV_DISPLAY_BASE + 0x61250) +#define _VLV_BLC_PWM_CTL2_B (VLV_DISPLAY_BASE + 0x61350) +#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, _VLV_BLC_PWM_CTL2_B) -#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254) -#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354) -#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ - _VLV_BLC_PWM_CTL_B) +#define _VLV_BLC_PWM_CTL_A (VLV_DISPLAY_BASE + 0x61254) +#define _VLV_BLC_PWM_CTL_B (VLV_DISPLAY_BASE + 0x61354) +#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, _VLV_BLC_PWM_CTL_B) -#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260) -#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360) -#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ - _VLV_BLC_HIST_CTL_B) +#define _VLV_BLC_HIST_CTL_A (VLV_DISPLAY_BASE + 0x61260) +#define _VLV_BLC_HIST_CTL_B (VLV_DISPLAY_BASE + 0x61360) +#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, _VLV_BLC_HIST_CTL_B) /* Backlight control */ #define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */ -- cgit v1.2.3 From bf3753d1bbcbf99a4aa7ce5b5c92242aa42e2bde Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 11:34:43 +0200 Subject: drm/i915/backlight: drop DISPLAY_MMIO_BASE() use from backlight registers None of the remaining backlight registers that use DISPLAY_MMIO_BASE() are used on VLV/CHV, which are the only platforms that have non-zero base. Just drop the DISPLAY_MMIO_BASE() use, reducing the implicit dev_priv references. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/75ae3f2945912f908df2444d4f0ab97a23b89897.1670405587.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_backlight_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h index 02bd1f8201bf..d0cdfd631d75 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight_regs.h +++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h @@ -21,7 +21,7 @@ #define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, _VLV_BLC_HIST_CTL_B) /* Backlight control */ -#define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */ +#define BLC_PWM_CTL2 _MMIO(0x61250) /* 965+ only */ #define BLM_PWM_ENABLE (1 << 31) #define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ #define BLM_PIPE_SELECT (1 << 29) @@ -44,7 +44,7 @@ #define BLM_PHASE_IN_COUNT_MASK (0xff << 8) #define BLM_PHASE_IN_INCR_SHIFT (0) #define BLM_PHASE_IN_INCR_MASK (0xff << 0) -#define BLC_PWM_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254) +#define BLC_PWM_CTL _MMIO(0x61254) /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. @@ -66,7 +66,7 @@ #define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) #define BLM_POLARITY_PNV (1 << 0) /* pnv only */ -#define BLC_HIST_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260) +#define BLC_HIST_CTL _MMIO(0x61260) #define BLM_HISTOGRAM_ENABLE (1 << 31) /* New registers for PCH-split platforms. Safe where new bits show up, the -- cgit v1.2.3 From 7177935c7d30dd50d9d03edc5d587ac0084e0a31 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 11:34:44 +0200 Subject: drm/i915/backlight: mass rename dev_priv to i915 With the implicit dev_priv usage gone, we can rename dev_priv to i915 throughout. Do some drive-by whitespace cleanups while at it. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/fc8b260bd8fa338edb312637f18ca7e6550d820d.1670405587.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_backlight.c | 517 ++++++++++++------------- 1 file changed, 248 insertions(+), 269 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 71af88a70461..c34bb34ede3e 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -83,16 +83,16 @@ static u32 scale_hw_to_user(struct intel_connector *connector, u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); - if (dev_priv->params.invert_brightness < 0) + if (i915->params.invert_brightness < 0) return val; - if (dev_priv->params.invert_brightness > 0 || - intel_has_quirk(dev_priv, QUIRK_INVERT_BRIGHTNESS)) { + if (i915->params.invert_brightness > 0 || + intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS)) { return panel->backlight.pwm_level_max - val + panel->backlight.pwm_level_min; } @@ -111,10 +111,10 @@ void intel_backlight_set_pwm_level(const struct drm_connector_state *conn_state, u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&dev_priv->drm, + drm_WARN_ON_ONCE(&i915->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); val = scale(val, panel->backlight.min, panel->backlight.max, @@ -125,14 +125,14 @@ u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&dev_priv->drm, + drm_WARN_ON_ONCE(&i915->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); - if (dev_priv->params.invert_brightness > 0 || - (dev_priv->params.invert_brightness == 0 && intel_has_quirk(dev_priv, QUIRK_INVERT_BRIGHTNESS))) + if (i915->params.invert_brightness > 0 || + (i915->params.invert_brightness == 0 && intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS))) val = panel->backlight.pwm_level_max - (val - panel->backlight.pwm_level_min); return scale(val, panel->backlight.pwm_level_min, panel->backlight.pwm_level_max, @@ -141,32 +141,32 @@ u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) static u32 lpt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return intel_de_read(dev_priv, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 pch_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return intel_de_read(dev_priv, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val; - val = intel_de_read(dev_priv, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (DISPLAY_VER(dev_priv) < 4) + val = intel_de_read(i915, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (DISPLAY_VER(i915) < 4) val >>= 1; if (panel->backlight.combination_mode) { u8 lbpc; - pci_read_config_byte(to_pci_dev(dev_priv->drm.dev), LBPC, &lbpc); + pci_read_config_byte(to_pci_dev(i915->drm.dev), LBPC, &lbpc); val *= lbpc; } @@ -175,21 +175,20 @@ static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unuse static u32 vlv_get_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) return 0; - return intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; + return intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 bxt_get_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - return intel_de_read(dev_priv, - BXT_BLC_PWM_DUTY(panel->backlight.controller)); + return intel_de_read(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller)); } static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe unused) @@ -204,69 +203,69 @@ static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe un static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + u32 val; - u32 val = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, val | level); + val = intel_de_read(i915, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, BLC_PWM_PCH_CTL2, val | level); } static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, BLC_PWM_CPU_CTL, tmp | level); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, BLC_PWM_CPU_CTL, tmp | level); } static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp, mask; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); if (panel->backlight.combination_mode) { u8 lbpc; lbpc = level * 0xfe / panel->backlight.pwm_level_max + 1; level /= lbpc; - pci_write_config_byte(to_pci_dev(dev_priv->drm.dev), LBPC, lbpc); + pci_write_config_byte(to_pci_dev(i915->drm.dev), LBPC, lbpc); } - if (DISPLAY_VER(dev_priv) == 4) { + if (DISPLAY_VER(i915) == 4) { mask = BACKLIGHT_DUTY_CYCLE_MASK; } else { level <<= 1; mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; } - tmp = intel_de_read(dev_priv, BLC_PWM_CTL) & ~mask; - intel_de_write(dev_priv, BLC_PWM_CTL, tmp | level); + tmp = intel_de_read(i915, BLC_PWM_CTL) & ~mask; + intel_de_write(i915, BLC_PWM_CTL, tmp | level); } static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 tmp; - tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe), tmp | level); + tmp = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; + intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), tmp | level); } static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - intel_de_write(dev_priv, - BXT_BLC_PWM_DUTY(panel->backlight.controller), level); + intel_de_write(i915, BXT_BLC_PWM_DUTY(panel->backlight.controller), level); } static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -296,7 +295,7 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 hw_level; @@ -309,9 +308,9 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (!panel->backlight.present || !conn_state->crtc) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); - drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.max == 0); hw_level = clamp_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -325,13 +324,13 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state, if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, level); @@ -344,31 +343,29 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta * This needs rework if we need to add support for CPU PWM on PCH split * platforms. */ - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (tmp & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, - "cpu backlight was enabled, disabling\n"); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, - tmp & ~BLM_PWM_ENABLE); + drm_dbg_kms(&i915->drm, "cpu backlight was enabled, disabling\n"); + intel_de_write(i915, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); } - tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); } static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_CPU_CTL2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); - tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); } static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) @@ -378,62 +375,59 @@ static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_st static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { - struct drm_i915_private *dev_priv = to_i915(old_conn_state->connector->dev); + struct drm_i915_private *i915 = to_i915(old_conn_state->connector->dev); u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, BLC_PWM_CTL2); - intel_de_write(dev_priv, BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, BLC_PWM_CTL2); + intel_de_write(i915, BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); } static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), - tmp & ~BLM_PWM_ENABLE); + tmp = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); } static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + tmp = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), tmp & ~BXT_BLC_PWM_ENABLE); if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); val &= ~UTIL_PIN_ENABLE; - intel_de_write(dev_priv, UTIL_PIN_CTL, val); + intel_de_write(i915, UTIL_PIN_CTL, val); } } static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp; intel_backlight_set_pwm_level(old_conn_state, val); - tmp = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + tmp = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), tmp & ~BXT_BLC_PWM_ENABLE); } @@ -451,7 +445,7 @@ static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn void intel_backlight_disable(const struct drm_connector_state *old_conn_state) { struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) @@ -463,68 +457,66 @@ void intel_backlight_disable(const struct drm_connector_state *old_conn_state) * backlight. This will leave the backlight on unnecessarily when * another client is not activated. */ - if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { - drm_dbg_kms(&dev_priv->drm, - "Skipping backlight disable on vga switch\n"); + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { + drm_dbg_kms(&i915->drm, "Skipping backlight disable on vga switch\n"); return; } - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (panel->backlight.device) panel->backlight.device->props.power = FB_BLANK_POWERDOWN; panel->backlight.enabled = false; panel->backlight.funcs->disable(old_conn_state, 0); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2, schicken; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "pch backlight already enabled\n"); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); } - if (HAS_PCH_LPT(dev_priv)) { - schicken = intel_de_read(dev_priv, SOUTH_CHICKEN2); + if (HAS_PCH_LPT(i915)) { + schicken = intel_de_read(i915, SOUTH_CHICKEN2); if (panel->backlight.alternate_pwm_increment) schicken |= LPT_PWM_GRANULARITY; else schicken &= ~LPT_PWM_GRANULARITY; - intel_de_write(dev_priv, SOUTH_CHICKEN2, schicken); + intel_de_write(i915, SOUTH_CHICKEN2, schicken); } else { - schicken = intel_de_read(dev_priv, SOUTH_CHICKEN1); + schicken = intel_de_read(i915, SOUTH_CHICKEN1); if (panel->backlight.alternate_pwm_increment) schicken |= SPT_PWM_GRANULARITY; else schicken &= ~SPT_PWM_GRANULARITY; - intel_de_write(dev_priv, SOUTH_CHICKEN1, schicken); + intel_de_write(i915, SOUTH_CHICKEN1, schicken); } pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; /* After LPT, override is the default. */ - if (HAS_PCH_LPT(dev_priv)) + if (HAS_PCH_LPT(i915)) pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, - pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); @@ -534,61 +526,60 @@ static void pch_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (cpu_ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "cpu backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "cpu backlight already enabled\n"); cpu_ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); } - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "pch backlight already enabled\n"); pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); } if (cpu_transcoder == TRANSCODER_EDP) cpu_ctl2 = BLM_TRANSCODER_EDP; else cpu_ctl2 = BLM_PIPE(cpu_transcoder); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2); - intel_de_posting_read(dev_priv, BLC_PWM_CPU_CTL2); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2); + intel_de_posting_read(i915, BLC_PWM_CPU_CTL2); + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); /* This won't stick until the above enable. */ intel_backlight_set_pwm_level(conn_state, level); pch_ctl2 = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, pch_ctl2); + intel_de_write(i915, BLC_PWM_PCH_CTL2, pch_ctl2); pch_ctl1 = 0; if (panel->backlight.active_low_pwm) pch_ctl1 |= BLM_PCH_POLARITY; - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, pch_ctl1); - intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, - pch_ctl1 | BLM_PCH_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1); + intel_de_posting_read(i915, BLC_PWM_PCH_CTL1); + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); } static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, freq; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); - intel_de_write(dev_priv, BLC_PWM_CTL, 0); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); + intel_de_write(i915, BLC_PWM_CTL, 0); } freq = panel->backlight.pwm_level_max; @@ -598,11 +589,11 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, ctl = freq << 17; if (panel->backlight.combination_mode) ctl |= BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm) + if (IS_PINEVIEW(i915) && panel->backlight.active_low_pwm) ctl |= BLM_POLARITY_PNV; - intel_de_write(dev_priv, BLC_PWM_CTL, ctl); - intel_de_posting_read(dev_priv, BLC_PWM_CTL); + intel_de_write(i915, BLC_PWM_CTL, ctl); + intel_de_posting_read(i915, BLC_PWM_CTL); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -612,24 +603,24 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 * that has backlight. */ - if (DISPLAY_VER(dev_priv) == 2) - intel_de_write(dev_priv, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); + if (DISPLAY_VER(i915) == 2) + intel_de_write(i915, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); } static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe; u32 ctl, ctl2, freq; - ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2); + ctl2 = intel_de_read(i915, BLC_PWM_CTL2); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2); + intel_de_write(i915, BLC_PWM_CTL2, ctl2); } freq = panel->backlight.pwm_level_max; @@ -637,16 +628,16 @@ static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, freq /= 0xff; ctl = freq << 16; - intel_de_write(dev_priv, BLC_PWM_CTL, ctl); + intel_de_write(i915, BLC_PWM_CTL, ctl); ctl2 = BLM_PIPE(pipe); if (panel->backlight.combination_mode) ctl2 |= BLM_COMBINATION_MODE; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2); - intel_de_posting_read(dev_priv, BLC_PWM_CTL2); - intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, BLC_PWM_CTL2, ctl2); + intel_de_posting_read(i915, BLC_PWM_CTL2); + intel_de_write(i915, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); intel_backlight_set_pwm_level(conn_state, level); } @@ -655,20 +646,20 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 ctl, ctl2; - ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); if (ctl2 & BLM_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); ctl2 &= ~BLM_PWM_ENABLE; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); } ctl = panel->backlight.pwm_level_max << 16; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe), ctl); + intel_de_write(i915, VLV_BLC_PWM_CTL(pipe), ctl); /* XXX: combine this into above write? */ intel_backlight_set_pwm_level(conn_state, level); @@ -676,50 +667,45 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, ctl2 = 0; if (panel->backlight.active_low_pwm) ctl2 |= BLM_POLARITY_I965; - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), ctl2); - intel_de_posting_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); - intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe), - ctl2 | BLM_PWM_ENABLE); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2); + intel_de_posting_read(i915, VLV_BLC_PWM_CTL2(pipe)); + intel_de_write(i915, VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); } static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 pwm_ctl, val; /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); if (val & UTIL_PIN_ENABLE) { - drm_dbg_kms(&dev_priv->drm, - "util pin already enabled\n"); + drm_dbg_kms(&i915->drm, "util pin already enabled\n"); val &= ~UTIL_PIN_ENABLE; - intel_de_write(dev_priv, UTIL_PIN_CTL, val); + intel_de_write(i915, UTIL_PIN_CTL, val); } val = 0; if (panel->backlight.util_pin_active_low) val |= UTIL_PIN_POLARITY; - intel_de_write(dev_priv, UTIL_PIN_CTL, + intel_de_write(i915, UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); } - pwm_ctl = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(dev_priv, - BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -728,11 +714,9 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), - pwm_ctl); - intel_de_posting_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -740,22 +724,19 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; - pwm_ctl = intel_de_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { - drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n"); + drm_dbg_kms(&i915->drm, "backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - intel_de_write(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); } - intel_de_write(dev_priv, - BXT_BLC_PWM_FREQ(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller), panel->backlight.pwm_level_max); intel_backlight_set_pwm_level(conn_state, level); @@ -764,11 +745,9 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), - pwm_ctl); - intel_de_posting_read(dev_priv, - BXT_BLC_PWM_CTL(panel->backlight.controller)); - intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller), + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + intel_de_posting_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); + intel_de_write(i915, BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl | BXT_BLC_PWM_ENABLE); } @@ -810,37 +789,37 @@ void intel_backlight_enable(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; if (!panel->backlight.present) return; - drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(pipe)); + drm_dbg_kms(&i915->drm, "pipe %c\n", pipe_name(pipe)); - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) static u32 intel_panel_get_backlight(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val = 0; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (panel->backlight.enabled) val = panel->backlight.funcs->get(connector, intel_connector_get_pipe(connector)); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); - drm_dbg_kms(&dev_priv->drm, "get backlight PWM = %d\n", val); + drm_dbg_kms(&i915->drm, "get backlight PWM = %d\n", val); return val; } @@ -859,16 +838,16 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta u32 user_level, u32 user_max) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 hw_level; if (!panel->backlight.present) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); - drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.max == 0); hw_level = scale_user_to_hw(connector, user_level, user_max); panel->backlight.level = hw_level; @@ -876,7 +855,7 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta if (panel->backlight.enabled) intel_panel_actually_set_backlight(conn_state, hw_level); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } static int intel_backlight_device_update_status(struct backlight_device *bd) @@ -915,11 +894,11 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); intel_wakeref_t wakeref; int ret = 0; - with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) { + with_intel_runtime_pm(&i915->runtime_pm, wakeref) { u32 hw_level; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); @@ -1038,9 +1017,9 @@ void intel_backlight_device_unregister(struct intel_connector *connector) */ static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(i915)->rawclk_freq), pwm_freq_hz); } @@ -1077,7 +1056,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 mul, clock; @@ -1086,7 +1065,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else mul = 128; - if (HAS_PCH_LPT_H(dev_priv)) + if (HAS_PCH_LPT_H(i915)) clock = MHz(135); /* LPT:H */ else clock = MHz(24); /* LPT:LP */ @@ -1100,9 +1079,9 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); - return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq), + return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(i915)->rawclk_freq), pwm_freq_hz * 128); } @@ -1116,13 +1095,13 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int clock; - if (IS_PINEVIEW(dev_priv)) - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + if (IS_PINEVIEW(i915)) + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); else - clock = KHz(dev_priv->display.cdclk.hw.cdclk); + clock = KHz(i915->display.cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); } @@ -1134,13 +1113,13 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int clock; - if (IS_G4X(dev_priv)) - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + if (IS_G4X(i915)) + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); else - clock = KHz(dev_priv->display.cdclk.hw.cdclk); + clock = KHz(i915->display.cdclk.hw.cdclk); return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); } @@ -1152,17 +1131,17 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); int mul, clock; - if ((intel_de_read(dev_priv, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { - if (IS_CHERRYVIEW(dev_priv)) + if ((intel_de_read(i915, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { + if (IS_CHERRYVIEW(i915)) clock = KHz(19200); else clock = MHz(25); mul = 16; } else { - clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq); + clock = KHz(RUNTIME_INFO(i915)->rawclk_freq); mul = 128; } @@ -1171,16 +1150,16 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u16 get_vbt_pwm_freq(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); u16 pwm_freq_hz = connector->panel.vbt.backlight.pwm_freq_hz; if (pwm_freq_hz) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "VBT defined backlight frequency %u Hz\n", pwm_freq_hz); } else { pwm_freq_hz = 200; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "default backlight frequency %u Hz\n", pwm_freq_hz); } @@ -1190,20 +1169,20 @@ static u16 get_vbt_pwm_freq(struct intel_connector *connector) static u32 get_backlight_max_vbt(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u16 pwm_freq_hz = get_vbt_pwm_freq(connector); u32 pwm; if (!panel->backlight.pwm_funcs->hz_to_pwm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "backlight frequency conversion not supported\n"); return 0; } pwm = panel->backlight.pwm_funcs->hz_to_pwm(connector, pwm_freq_hz); if (!pwm) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "backlight frequency conversion failed\n"); return 0; } @@ -1216,11 +1195,11 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) */ static u32 get_backlight_min_vbt(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; int min; - drm_WARN_ON(&dev_priv->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); /* * XXX: If the vbt value is 255, it makes min equal to max, which leads @@ -1231,7 +1210,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) */ min = clamp_t(int, connector->panel.vbt.backlight.min_brightness, 0, 64); if (min != connector->panel.vbt.backlight.min_brightness) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "clamping VBT min backlight %d/255 to %d/255\n", connector->panel.vbt.backlight.min_brightness, min); } @@ -1242,24 +1221,24 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; bool alt, cpu_mode; - if (HAS_PCH_LPT(dev_priv)) - alt = intel_de_read(dev_priv, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; + if (HAS_PCH_LPT(i915)) + alt = intel_de_read(i915, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; else - alt = intel_de_read(dev_priv, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; + alt = intel_de_read(i915, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; panel->backlight.alternate_pwm_increment = alt; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1271,22 +1250,22 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.pwm_enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE; - cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(dev_priv) && + cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(i915) && !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) && (cpu_ctl2 & BLM_PWM_ENABLE); if (cpu_mode) { val = pch_get_backlight(connector, unused); - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "CPU backlight register was enabled, switching to PCH override\n"); /* Write converted CPU PWM value to PCH override register */ lpt_set_backlight(connector->base.state, val); - intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, + intel_de_write(i915, BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE); - intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, + intel_de_write(i915, BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE); } @@ -1295,14 +1274,14 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2; - pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1); + pch_ctl1 = intel_de_read(i915, BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; - pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2); + pch_ctl2 = intel_de_read(i915, BLC_PWM_PCH_CTL2); panel->backlight.pwm_level_max = pch_ctl2 >> 16; if (!panel->backlight.pwm_level_max) @@ -1313,7 +1292,7 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.pwm_level_min = get_backlight_min_vbt(connector); - cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2); + cpu_ctl2 = intel_de_read(i915, BLC_PWM_CPU_CTL2); panel->backlight.pwm_enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && (pch_ctl1 & BLM_PCH_PWM_ENABLE); @@ -1322,16 +1301,16 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, val; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); - if (DISPLAY_VER(dev_priv) == 2 || IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) + if (DISPLAY_VER(i915) == 2 || IS_I915GM(i915) || IS_I945GM(i915)) panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev_priv)) + if (IS_PINEVIEW(i915)) panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.pwm_level_max = ctl >> 17; @@ -1360,15 +1339,15 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2); + ctl2 = intel_de_read(i915, BLC_PWM_CTL2); panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(dev_priv, BLC_PWM_CTL); + ctl = intel_de_read(i915, BLC_PWM_CTL); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1389,17 +1368,17 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2; - if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)) + if (drm_WARN_ON(&i915->drm, pipe != PIPE_A && pipe != PIPE_B)) return -ENODEV; - ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)); + ctl2 = intel_de_read(i915, VLV_BLC_PWM_CTL2(pipe)); panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)); + ctl = intel_de_read(i915, VLV_BLC_PWM_CTL(pipe)); panel->backlight.pwm_level_max = ctl >> 16; if (!panel->backlight.pwm_level_max) @@ -1418,25 +1397,25 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe static int bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; panel->backlight.controller = connector->panel.vbt.backlight.controller; - pwm_ctl = intel_de_read(dev_priv, + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); /* Controller 1 uses the utility pin. */ if (panel->backlight.controller == 1) { - val = intel_de_read(dev_priv, UTIL_PIN_CTL); + val = intel_de_read(i915, UTIL_PIN_CTL); panel->backlight.util_pin_active_low = val & UTIL_PIN_POLARITY; } panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(dev_priv, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1454,7 +1433,7 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) static int cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl; @@ -1465,12 +1444,12 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) */ panel->backlight.controller = 0; - pwm_ctl = intel_de_read(dev_priv, + pwm_ctl = intel_de_read(i915, BXT_BLC_PWM_CTL(panel->backlight.controller)); panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; panel->backlight.pwm_level_max = - intel_de_read(dev_priv, BXT_BLC_PWM_FREQ(panel->backlight.controller)); + intel_de_read(i915, BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.pwm_level_max) panel->backlight.pwm_level_max = get_backlight_max_vbt(connector); @@ -1489,7 +1468,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct intel_panel *panel = &connector->panel; const char *desc; u32 level; @@ -1504,7 +1483,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, } if (IS_ERR(panel->backlight.pwm)) { - drm_err(&dev_priv->drm, "Failed to get the %s PWM chip\n", + drm_err(&i915->drm, "Failed to get the %s PWM chip\n", desc); panel->backlight.pwm = NULL; return -ENODEV; @@ -1522,7 +1501,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, level = intel_backlight_invert_pwm_level(connector, level); panel->backlight.pwm_enabled = true; - drm_dbg_kms(&dev_priv->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", + drm_dbg_kms(&i915->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period, get_vbt_pwm_freq(connector), level); } else { @@ -1531,7 +1510,7 @@ static int ext_pwm_setup_backlight(struct intel_connector *connector, NSEC_PER_SEC / get_vbt_pwm_freq(connector); } - drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", + drm_info(&i915->drm, "Using %s PWM for LCD backlight control\n", desc); return 0; } @@ -1594,47 +1573,47 @@ void intel_backlight_update(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) return; - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); if (!panel->backlight.enabled) __intel_backlight_enable(crtc_state, conn_state); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); } int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; int ret; if (!connector->panel.vbt.backlight.present) { - if (intel_has_quirk(dev_priv, QUIRK_BACKLIGHT_PRESENT)) { - drm_dbg_kms(&dev_priv->drm, + if (intel_has_quirk(i915, QUIRK_BACKLIGHT_PRESENT)) { + drm_dbg_kms(&i915->drm, "no backlight present per VBT, but present per quirk\n"); } else { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "no backlight present per VBT\n"); return 0; } } /* ensure intel_panel has been initialized first */ - if (drm_WARN_ON(&dev_priv->drm, !panel->backlight.funcs)) + if (drm_WARN_ON(&i915->drm, !panel->backlight.funcs)) return -ENODEV; /* set level and max in panel struct */ - mutex_lock(&dev_priv->display.backlight.lock); + mutex_lock(&i915->display.backlight.lock); ret = panel->backlight.funcs->setup(connector, pipe); - mutex_unlock(&dev_priv->display.backlight.lock); + mutex_unlock(&i915->display.backlight.lock); if (ret) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "failed to setup backlight for connector %s\n", connector->base.name); return ret; @@ -1642,7 +1621,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) panel->backlight.present = true; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "Connector %s backlight initialized, %s, brightness %u/%u\n", connector->base.name, str_enabled_disabled(panel->backlight.enabled), @@ -1753,30 +1732,30 @@ void intel_backlight_init_funcs(struct intel_panel *panel) { struct intel_connector *connector = container_of(panel, struct intel_connector, panel); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI && intel_dsi_dcs_init_backlight_funcs(connector) == 0) return; - if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { + if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { panel->backlight.pwm_funcs = &bxt_pwm_funcs; - } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) { + } else if (INTEL_PCH_TYPE(i915) >= PCH_CNP) { panel->backlight.pwm_funcs = &cnp_pwm_funcs; - } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_LPT) { - if (HAS_PCH_LPT(dev_priv)) + } else if (INTEL_PCH_TYPE(i915) >= PCH_LPT) { + if (HAS_PCH_LPT(i915)) panel->backlight.pwm_funcs = &lpt_pwm_funcs; else panel->backlight.pwm_funcs = &spt_pwm_funcs; - } else if (HAS_PCH_SPLIT(dev_priv)) { + } else if (HAS_PCH_SPLIT(i915)) { panel->backlight.pwm_funcs = &pch_pwm_funcs; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) { panel->backlight.pwm_funcs = &ext_pwm_funcs; } else { panel->backlight.pwm_funcs = &vlv_pwm_funcs; } - } else if (DISPLAY_VER(dev_priv) == 4) { + } else if (DISPLAY_VER(i915) == 4) { panel->backlight.pwm_funcs = &i965_pwm_funcs; } else { panel->backlight.pwm_funcs = &i9xx_pwm_funcs; @@ -1786,7 +1765,7 @@ void intel_backlight_init_funcs(struct intel_panel *panel) if (intel_dp_aux_init_backlight_funcs(connector) == 0) return; - if (!intel_has_quirk(dev_priv, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) + if (!intel_has_quirk(i915, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) connector->panel.backlight.power = intel_pps_backlight_power; } -- cgit v1.2.3 From 02c77424bcb35eefbdb6660571d232ff17470080 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 11:34:45 +0200 Subject: drm/i915/backlight: drop drm_device local variables in favor of i915 Prefer only having struct drm_i915_private *i915 around. Drop the drm_device *dev locals. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/6a791b06ab84bb8fb719cd46934eb09644e3edc7.1670405587.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_backlight.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index c34bb34ede3e..3ed5c64c3816 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -861,10 +861,11 @@ static void intel_panel_set_backlight(const struct drm_connector_state *conn_sta static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - struct drm_device *dev = connector->base.dev; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); + DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", bd->props.brightness, bd->props.max_brightness); intel_panel_set_backlight(connector->base.state, bd->props.brightness, @@ -886,28 +887,28 @@ static int intel_backlight_device_update_status(struct backlight_device *bd) bd->props.power = FB_BLANK_POWERDOWN; } - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + return 0; } static int intel_backlight_device_get_brightness(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *i915 = to_i915(dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); intel_wakeref_t wakeref; int ret = 0; with_intel_runtime_pm(&i915->runtime_pm, wakeref) { u32 hw_level; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); hw_level = intel_panel_get_backlight(connector); ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); } return ret; @@ -1467,18 +1468,17 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) static int ext_pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *i915 = to_i915(dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; const char *desc; u32 level; /* Get the right PWM chip for DSI backlight according to VBT */ if (connector->panel.vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { - panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight"); + panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_pmic_backlight"); desc = "PMIC"; } else { - panel->backlight.pwm = pwm_get(dev->dev, "pwm_soc_backlight"); + panel->backlight.pwm = pwm_get(i915->drm.dev, "pwm_soc_backlight"); desc = "SoC"; } -- cgit v1.2.3 From 40c3012205b68b53f20d20b9c34b570094d083f4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 11:34:46 +0200 Subject: drm/i915/backlight: convert DRM_DEBUG_KMS() to drm_dbg_kms() Fix the final straggler. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/4769f8377be11536bd19840a2e59ef9f8c0a558c.1670405587.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_backlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 3ed5c64c3816..5b7da72c95b8 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -866,8 +866,8 @@ static int intel_backlight_device_update_status(struct backlight_device *bd) drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL); - DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", - bd->props.brightness, bd->props.max_brightness); + drm_dbg_kms(&i915->drm, "updating intel_backlight, brightness=%d/%d\n", + bd->props.brightness, bd->props.max_brightness); intel_panel_set_backlight(connector->base.state, bd->props.brightness, bd->props.max_brightness); -- cgit v1.2.3 From 93b3c44d6f760e5df3680d9fa08093675f1cf116 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 7 Dec 2022 19:17:18 +0200 Subject: drm/i915/de: Add more macros to remove all direct calls to uncore Add more de helpers to be able to avoid direct calls to uncore. v3 by Jani: - drop intel_de_write_samevalue/intel_de_rewrite_fw altogether v2 by Jani: - drop pcode stuff for now - rename intel_de_write_samevalue -> intel_de_rewrite_fw Signed-off-by: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/0d051554dfeeb4d8aa3bc9136ed111fa35f647d8.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_de.h | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 9c104f65e4c8..004f01906fd7 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -16,6 +16,12 @@ intel_de_read(struct drm_i915_private *i915, i915_reg_t reg) return intel_uncore_read(&i915->uncore, reg); } +static inline u8 +intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) +{ + return intel_uncore_read8(&i915->uncore, reg); +} + static inline void intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) { @@ -41,6 +47,23 @@ intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, return intel_wait_for_register(&i915->uncore, reg, mask, value, timeout); } +static inline int +intel_de_wait_for_register_fw(struct drm_i915_private *i915, i915_reg_t reg, + u32 mask, u32 value, unsigned int timeout) +{ + return intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout); +} + +static inline int +__intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, + u32 mask, u32 value, + unsigned int fast_timeout_us, + unsigned int slow_timeout_ms, u32 *out_value) +{ + return __intel_wait_for_register(&i915->uncore, reg, mask, value, + fast_timeout_us, slow_timeout_ms, out_value); +} + static inline int intel_de_wait_for_set(struct drm_i915_private *i915, i915_reg_t reg, u32 mask, unsigned int timeout) @@ -81,4 +104,16 @@ intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val) intel_uncore_write_fw(&i915->uncore, reg, val); } +static inline u32 +intel_de_read_notrace(struct drm_i915_private *i915, i915_reg_t reg) +{ + return intel_uncore_read_notrace(&i915->uncore, reg); +} + +static inline void +intel_de_write_notrace(struct drm_i915_private *i915, i915_reg_t reg, u32 val) +{ + intel_uncore_write_notrace(&i915->uncore, reg, val); +} + #endif /* __INTEL_DE_H__ */ -- cgit v1.2.3 From 4fa9fc424ac97ce5ea1a7bbd49524d26ede2c0be Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:19 +0200 Subject: drm/i915/de: return the old register value from intel_de_rmw() A similar thing was added in intel_uncore_rmw(). Make it available for display too. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/b82cb29e8ece63e68499307f9e3e83139e590d23.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_de.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 004f01906fd7..3dbd76fdabd6 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -34,10 +34,10 @@ intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val) intel_uncore_write(&i915->uncore, reg, val); } -static inline void +static inline u32 intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set) { - intel_uncore_rmw(&i915->uncore, reg, clear, set); + return intel_uncore_rmw(&i915->uncore, reg, clear, set); } static inline int -- cgit v1.2.3 From 330bdd964da888525c72a5f971afadaa44e4221c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:20 +0200 Subject: drm/i915/crt: drop a bunch of unnecessary register variables There's no need to save the register offsets. Drop the variables. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/3493286ecd1ae166e1e15235d31115f766f7c878.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_crt.c | 39 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 797ad9489f7e..ed94ba5c0302 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -689,23 +689,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) u32 vsample; u32 vblank, vblank_start, vblank_end; u32 dsl; - i915_reg_t bclrpat_reg, vtotal_reg, - vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg; u8 st00; enum drm_connector_status status; drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n"); - bclrpat_reg = BCLRPAT(pipe); - vtotal_reg = VTOTAL(pipe); - vblank_reg = VBLANK(pipe); - vsync_reg = VSYNC(pipe); - pipeconf_reg = PIPECONF(pipe); - pipe_dsl_reg = PIPEDSL(pipe); - - save_bclrpat = intel_uncore_read(uncore, bclrpat_reg); - save_vtotal = intel_uncore_read(uncore, vtotal_reg); - vblank = intel_uncore_read(uncore, vblank_reg); + save_bclrpat = intel_uncore_read(uncore, BCLRPAT(pipe)); + save_vtotal = intel_uncore_read(uncore, VTOTAL(pipe)); + vblank = intel_uncore_read(uncore, VBLANK(pipe)); vtotal = ((save_vtotal >> 16) & 0xfff) + 1; vactive = (save_vtotal & 0x7ff) + 1; @@ -714,14 +705,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) vblank_end = ((vblank >> 16) & 0xfff) + 1; /* Set the border color to purple. */ - intel_uncore_write(uncore, bclrpat_reg, 0x500050); + intel_uncore_write(uncore, BCLRPAT(pipe), 0x500050); if (DISPLAY_VER(dev_priv) != 2) { - u32 pipeconf = intel_uncore_read(uncore, pipeconf_reg); + u32 pipeconf = intel_uncore_read(uncore, PIPECONF(pipe)); intel_uncore_write(uncore, - pipeconf_reg, + PIPECONF(pipe), pipeconf | PIPECONF_FORCE_BORDER); - intel_uncore_posting_read(uncore, pipeconf_reg); + intel_uncore_posting_read(uncore, PIPECONF(pipe)); /* Wait for next Vblank to substitue * border color for Color info */ intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); @@ -730,7 +721,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) connector_status_connected : connector_status_disconnected; - intel_uncore_write(uncore, pipeconf_reg, pipeconf); + intel_uncore_write(uncore, PIPECONF(pipe), pipeconf); } else { bool restore_vblank = false; int count, detect; @@ -740,12 +731,12 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) * Yes, this will flicker */ if (vblank_start <= vactive && vblank_end >= vtotal) { - u32 vsync = intel_de_read(dev_priv, vsync_reg); + u32 vsync = intel_de_read(dev_priv, VSYNC(pipe)); u32 vsync_start = (vsync & 0xffff) + 1; vblank_start = vsync_start; intel_uncore_write(uncore, - vblank_reg, + VBLANK(pipe), (vblank_start - 1) | ((vblank_end - 1) << 16)); restore_vblank = true; @@ -759,9 +750,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) /* * Wait for the border to be displayed */ - while (intel_uncore_read(uncore, pipe_dsl_reg) >= vactive) + while (intel_uncore_read(uncore, PIPEDSL(pipe)) >= vactive) ; - while ((dsl = intel_uncore_read(uncore, pipe_dsl_reg)) <= + while ((dsl = intel_uncore_read(uncore, PIPEDSL(pipe))) <= vsample) ; /* @@ -775,11 +766,11 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE); if (st00 & (1 << 4)) detect++; - } while ((intel_uncore_read(uncore, pipe_dsl_reg) == dsl)); + } while ((intel_uncore_read(uncore, PIPEDSL(pipe)) == dsl)); /* restore vblank if necessary */ if (restore_vblank) - intel_uncore_write(uncore, vblank_reg, vblank); + intel_uncore_write(uncore, VBLANK(pipe), vblank); /* * If more than 3/4 of the scanline detected a monitor, * then it is assumed to be present. This works even on i830, @@ -792,7 +783,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) } /* Restore previous settings */ - intel_uncore_write(uncore, bclrpat_reg, save_bclrpat); + intel_uncore_write(uncore, BCLRPAT(pipe), save_bclrpat); return status; } -- cgit v1.2.3 From f0798d8f723d1d394a0edcd883eb4d2852499fb2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:21 +0200 Subject: drm/i915/crt: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/39c198439be580052d1f78a44c96df7ba8ffd56d.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_crt.c | 42 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index ed94ba5c0302..7267ffc7f539 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -682,7 +682,6 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) { struct drm_device *dev = crt->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_uncore *uncore = &dev_priv->uncore; u32 save_bclrpat; u32 save_vtotal; u32 vtotal, vactive; @@ -694,9 +693,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n"); - save_bclrpat = intel_uncore_read(uncore, BCLRPAT(pipe)); - save_vtotal = intel_uncore_read(uncore, VTOTAL(pipe)); - vblank = intel_uncore_read(uncore, VBLANK(pipe)); + save_bclrpat = intel_de_read(dev_priv, BCLRPAT(pipe)); + save_vtotal = intel_de_read(dev_priv, VTOTAL(pipe)); + vblank = intel_de_read(dev_priv, VBLANK(pipe)); vtotal = ((save_vtotal >> 16) & 0xfff) + 1; vactive = (save_vtotal & 0x7ff) + 1; @@ -705,23 +704,23 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) vblank_end = ((vblank >> 16) & 0xfff) + 1; /* Set the border color to purple. */ - intel_uncore_write(uncore, BCLRPAT(pipe), 0x500050); + intel_de_write(dev_priv, BCLRPAT(pipe), 0x500050); if (DISPLAY_VER(dev_priv) != 2) { - u32 pipeconf = intel_uncore_read(uncore, PIPECONF(pipe)); - intel_uncore_write(uncore, - PIPECONF(pipe), - pipeconf | PIPECONF_FORCE_BORDER); - intel_uncore_posting_read(uncore, PIPECONF(pipe)); + u32 pipeconf = intel_de_read(dev_priv, PIPECONF(pipe)); + + intel_de_write(dev_priv, PIPECONF(pipe), + pipeconf | PIPECONF_FORCE_BORDER); + intel_de_posting_read(dev_priv, PIPECONF(pipe)); /* Wait for next Vblank to substitue * border color for Color info */ intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe)); - st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE); + st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? connector_status_connected : connector_status_disconnected; - intel_uncore_write(uncore, PIPECONF(pipe), pipeconf); + intel_de_write(dev_priv, PIPECONF(pipe), pipeconf); } else { bool restore_vblank = false; int count, detect; @@ -735,10 +734,8 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) u32 vsync_start = (vsync & 0xffff) + 1; vblank_start = vsync_start; - intel_uncore_write(uncore, - VBLANK(pipe), - (vblank_start - 1) | - ((vblank_end - 1) << 16)); + intel_de_write(dev_priv, VBLANK(pipe), + (vblank_start - 1) | ((vblank_end - 1) << 16)); restore_vblank = true; } /* sample in the vertical border, selecting the larger one */ @@ -750,10 +747,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) /* * Wait for the border to be displayed */ - while (intel_uncore_read(uncore, PIPEDSL(pipe)) >= vactive) + while (intel_de_read(dev_priv, PIPEDSL(pipe)) >= vactive) ; - while ((dsl = intel_uncore_read(uncore, PIPEDSL(pipe))) <= - vsample) + while ((dsl = intel_de_read(dev_priv, PIPEDSL(pipe))) <= vsample) ; /* * Watch ST00 for an entire scanline @@ -763,14 +759,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) do { count++; /* Read the ST00 VGA status register */ - st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE); + st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE); if (st00 & (1 << 4)) detect++; - } while ((intel_uncore_read(uncore, PIPEDSL(pipe)) == dsl)); + } while ((intel_de_read(dev_priv, PIPEDSL(pipe)) == dsl)); /* restore vblank if necessary */ if (restore_vblank) - intel_uncore_write(uncore, VBLANK(pipe), vblank); + intel_de_write(dev_priv, VBLANK(pipe), vblank); /* * If more than 3/4 of the scanline detected a monitor, * then it is assumed to be present. This works even on i830, @@ -783,7 +779,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe) } /* Restore previous settings */ - intel_uncore_write(uncore, BCLRPAT(pipe), save_bclrpat); + intel_de_write(dev_priv, BCLRPAT(pipe), save_bclrpat); return status; } -- cgit v1.2.3 From a0c51490885f608fad3821fb1010ac78fa77f41d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:22 +0200 Subject: drm/i915/power: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/21ea52a7c4fd400c256316143e3a2c9106c554d9.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 3adba64937de..1a23ecd4623a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1673,7 +1673,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, if (DISPLAY_VER(dev_priv) >= 12) { val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM | DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR; - intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val); + intel_de_rmw(dev_priv, GEN11_CHICKEN_DCPR_2, 0, val); } /* Wa_14011503030:xelpd */ -- cgit v1.2.3 From 2c035d759f5f26f9aa1caec703d956d0cb446528 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:23 +0200 Subject: drm/i915/dmc: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/bc144ab3565b10e71244cd09f72ce7df86f4b5c6.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index eff3add70611..f107b8cd3c9e 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -433,9 +433,9 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv) for (id = 0; id < DMC_FW_MAX; id++) { for (i = 0; i < dmc->dmc_info[id].dmc_fw_size; i++) { - intel_uncore_write_fw(&dev_priv->uncore, - DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i), - dmc->dmc_info[id].payload[i]); + intel_de_write_fw(dev_priv, + DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i), + dmc->dmc_info[id].payload[i]); } } -- cgit v1.2.3 From ec2593e3075b13335fc1f862f395c2dd3258176f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:24 +0200 Subject: drm/i915/dp-aux: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/262a0cf647b37e27a1c7776d3816e1b4ef959a91.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 664bebdecea7..91c93c93e5fc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -6,6 +6,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "i915_trace.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dp_aux.h" #include "intel_pps.h" @@ -42,7 +43,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp) u32 status; bool done; -#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) +#define C (((status = intel_de_read_notrace(i915, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) done = wait_event_timeout(i915->display.gmbus.wait_queue, C, msecs_to_jiffies_timeout(timeout_ms)); @@ -191,7 +192,6 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum phy phy = intel_port_to_phy(i915, dig_port->base.port); bool is_tc_port = intel_phy_is_tc(i915, phy); i915_reg_t ch_ctl, ch_data[5]; @@ -235,7 +235,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, /* Try to wait for any previous AUX channel activity */ for (try = 0; try < 3; try++) { - status = intel_uncore_read_notrace(uncore, ch_ctl); + status = intel_de_read_notrace(i915, ch_ctl); if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) break; msleep(1); @@ -244,7 +244,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); if (try == 3) { - const u32 status = intel_uncore_read(uncore, ch_ctl); + const u32 status = intel_de_read(i915, ch_ctl); if (status != intel_dp->aux_busy_last_status) { drm_WARN(&i915->drm, 1, @@ -274,23 +274,20 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ for (i = 0; i < send_bytes; i += 4) - intel_uncore_write(uncore, - ch_data[i >> 2], - intel_dp_aux_pack(send + i, - send_bytes - i)); + intel_de_write(i915, ch_data[i >> 2], + intel_dp_aux_pack(send + i, + send_bytes - i)); /* Send the command and wait for it to complete */ - intel_uncore_write(uncore, ch_ctl, send_ctl); + intel_de_write(i915, ch_ctl, send_ctl); status = intel_dp_aux_wait_done(intel_dp); /* Clear done status and any errors */ - intel_uncore_write(uncore, - ch_ctl, - status | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); + intel_de_write(i915, ch_ctl, + status | DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); /* * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 @@ -361,7 +358,7 @@ done: recv_bytes = recv_size; for (i = 0; i < recv_bytes; i += 4) - intel_dp_aux_unpack(intel_uncore_read(uncore, ch_data[i >> 2]), + intel_dp_aux_unpack(intel_de_read(i915, ch_data[i >> 2]), recv + i, recv_bytes - i); ret = recv_bytes; -- cgit v1.2.3 From 01f84f742121024b3af290934bda8a4e81932297 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:25 +0200 Subject: drm/i915/gmbus: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/05690286d1521ec9c82d680122cca9a90a75b8dd.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 46 +++++++++++------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index a5840a28a69d..0bc4f6b48e80 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -255,14 +255,12 @@ static void bxt_gmbus_clock_gating(struct drm_i915_private *i915, static u32 get_reserved(struct intel_gmbus *bus) { struct drm_i915_private *i915 = bus->i915; - struct intel_uncore *uncore = &i915->uncore; u32 reserved = 0; /* On most chips, these bits must be preserved in software. */ if (!IS_I830(i915) && !IS_I845G(i915)) - reserved = intel_uncore_read_notrace(uncore, bus->gpio_reg) & - (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); + reserved = intel_de_read_notrace(i915, bus->gpio_reg) & + (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); return reserved; } @@ -270,37 +268,31 @@ static u32 get_reserved(struct intel_gmbus *bus) static int get_clock(void *data) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | GPIO_CLOCK_DIR_MASK); - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK); + intel_de_write_notrace(i915, bus->gpio_reg, reserved); - return (intel_uncore_read_notrace(uncore, bus->gpio_reg) & - GPIO_CLOCK_VAL_IN) != 0; + return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0; } static int get_data(void *data) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | GPIO_DATA_DIR_MASK); - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK); + intel_de_write_notrace(i915, bus->gpio_reg, reserved); - return (intel_uncore_read_notrace(uncore, bus->gpio_reg) & - GPIO_DATA_VAL_IN) != 0; + return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0; } static void set_clock(void *data, int state_high) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); u32 clock_bits; @@ -310,16 +302,14 @@ static void set_clock(void *data, int state_high) clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; - intel_uncore_write_notrace(uncore, - bus->gpio_reg, - reserved | clock_bits); - intel_uncore_posting_read(uncore, bus->gpio_reg); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | clock_bits); + intel_de_posting_read(i915, bus->gpio_reg); } static void set_data(void *data, int state_high) { struct intel_gmbus *bus = data; - struct intel_uncore *uncore = &bus->i915->uncore; + struct drm_i915_private *i915 = bus->i915; u32 reserved = get_reserved(bus); u32 data_bits; @@ -329,8 +319,8 @@ static void set_data(void *data, int state_high) data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK; - intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved | data_bits); - intel_uncore_posting_read(uncore, bus->gpio_reg); + intel_de_write_notrace(i915, bus->gpio_reg, reserved | data_bits); + intel_de_posting_read(i915, bus->gpio_reg); } static int @@ -439,9 +429,7 @@ gmbus_wait_idle(struct drm_i915_private *i915) add_wait_queue(&i915->display.gmbus.wait_queue, &wait); intel_de_write_fw(i915, GMBUS4(i915), irq_enable); - ret = intel_wait_for_register_fw(&i915->uncore, - GMBUS2(i915), GMBUS_ACTIVE, 0, - 10); + ret = intel_de_wait_for_register_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10); intel_de_write_fw(i915, GMBUS4(i915), 0); remove_wait_queue(&i915->display.gmbus.wait_queue, &wait); -- cgit v1.2.3 From 00136429f72164bb6da00eba61ac36b822a30414 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:26 +0200 Subject: drm/i915/wm: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/588815fc60752b6470ee4067246698d478309fa1.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/skl_watermark.c | 42 ++++++++++++---------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index e0766d1be966..ae4e9e680c2e 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -45,8 +45,7 @@ u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *i915) enum dbuf_slice slice; for_each_dbuf_slice(i915, slice) { - if (intel_uncore_read(&i915->uncore, - DBUF_CTL_S(slice)) & DBUF_POWER_STATE) + if (intel_de_read(i915, DBUF_CTL_S(slice)) & DBUF_POWER_STATE) enabled_slices |= BIT(slice); } @@ -75,7 +74,7 @@ intel_sagv_block_time(struct drm_i915_private *i915) if (DISPLAY_VER(i915) >= 14) { u32 val; - val = intel_uncore_read(&i915->uncore, MTL_LATENCY_SAGV); + val = intel_de_read(i915, MTL_LATENCY_SAGV); return REG_FIELD_GET(MTL_LATENCY_QCLK_SAGV, val); } else if (DISPLAY_VER(i915) >= 12) { @@ -756,18 +755,18 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *i915, /* Cursor doesn't support NV12/planar, so no extra calculation needed */ if (plane_id == PLANE_CURSOR) { - val = intel_uncore_read(&i915->uncore, CUR_BUF_CFG(pipe)); + val = intel_de_read(i915, CUR_BUF_CFG(pipe)); skl_ddb_entry_init_from_hw(ddb, val); return; } - val = intel_uncore_read(&i915->uncore, PLANE_BUF_CFG(pipe, plane_id)); + val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id)); skl_ddb_entry_init_from_hw(ddb, val); if (DISPLAY_VER(i915) >= 11) return; - val = intel_uncore_read(&i915->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id)); + val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id)); skl_ddb_entry_init_from_hw(ddb_y, val); } @@ -2821,36 +2820,32 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, for (level = 0; level <= max_level; level++) { if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, PLANE_WM(pipe, plane_id, level)); + val = intel_de_read(i915, PLANE_WM(pipe, plane_id, level)); else - val = intel_uncore_read(&i915->uncore, CUR_WM(pipe, level)); + val = intel_de_read(i915, CUR_WM(pipe, level)); skl_wm_level_from_reg_val(val, &wm->wm[level]); } if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, PLANE_WM_TRANS(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_TRANS(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, CUR_WM_TRANS(pipe)); + val = intel_de_read(i915, CUR_WM_TRANS(pipe)); skl_wm_level_from_reg_val(val, &wm->trans_wm); if (HAS_HW_SAGV_WM(i915)) { if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, - PLANE_WM_SAGV(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, - CUR_WM_SAGV(pipe)); + val = intel_de_read(i915, CUR_WM_SAGV(pipe)); skl_wm_level_from_reg_val(val, &wm->sagv.wm0); if (plane_id != PLANE_CURSOR) - val = intel_uncore_read(&i915->uncore, - PLANE_WM_SAGV_TRANS(pipe, plane_id)); + val = intel_de_read(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id)); else - val = intel_uncore_read(&i915->uncore, - CUR_WM_SAGV_TRANS(pipe)); + val = intel_de_read(i915, CUR_WM_SAGV_TRANS(pipe)); skl_wm_level_from_reg_val(val, &wm->sagv.trans_wm); } else if (DISPLAY_VER(i915) >= 12) { @@ -3126,8 +3121,8 @@ void skl_watermark_ipc_update(struct drm_i915_private *i915) if (!HAS_IPC(i915)) return; - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL2, DISP_IPC_ENABLE, - skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); + intel_de_rmw(i915, DISP_ARB_CTL2, DISP_IPC_ENABLE, + skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); } static bool skl_watermark_ipc_can_enable(struct drm_i915_private *i915) @@ -3201,19 +3196,18 @@ adjust_wm_latency(struct drm_i915_private *i915, static void mtl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) { - struct intel_uncore *uncore = &i915->uncore; int max_level = ilk_wm_max_level(i915); u32 val; - val = intel_uncore_read(uncore, MTL_LATENCY_LP0_LP1); + val = intel_de_read(i915, MTL_LATENCY_LP0_LP1); wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); - val = intel_uncore_read(uncore, MTL_LATENCY_LP2_LP3); + val = intel_de_read(i915, MTL_LATENCY_LP2_LP3); wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); - val = intel_uncore_read(uncore, MTL_LATENCY_LP4_LP5); + val = intel_de_read(i915, MTL_LATENCY_LP4_LP5); wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); -- cgit v1.2.3 From 5544d5e49bc880e3e6be0fc49a4c4c971bb2b065 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:27 +0200 Subject: drm/i915/snps: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/4992661d93f8d5744e19408dc60ae49a5f2d597a.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_snps_phy.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index c799e891f8b5..9494cfd45519 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -44,18 +44,18 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) } } -void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv, +void intel_snps_phy_update_psr_power_state(struct drm_i915_private *i915, enum phy phy, bool enable) { u32 val; - if (!intel_phy_is_snps(dev_priv, phy)) + if (!intel_phy_is_snps(i915, phy)) return; val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, enable ? 2 : 3); - intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_TX_REQ(phy), - SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val); + intel_de_rmw(i915, SNPS_PHY_TX_REQ(phy), + SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val); } void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, @@ -1785,7 +1785,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder, */ /* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */ - intel_uncore_rmw(&dev_priv->uncore, enable_reg, 0, PLL_ENABLE); + intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE); /* * 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This @@ -1830,14 +1830,13 @@ void intel_mpllb_disable(struct intel_encoder *encoder) */ /* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */ - intel_uncore_rmw(&i915->uncore, enable_reg, PLL_ENABLE, 0); + intel_de_rmw(i915, enable_reg, PLL_ENABLE, 0); /* * 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0". * This will allow the PLL to stop running. */ - intel_uncore_rmw(&i915->uncore, SNPS_PHY_MPLLB_DIV(phy), - SNPS_PHY_MPLLB_FORCE_EN, 0); + intel_de_rmw(i915, SNPS_PHY_MPLLB_DIV(phy), SNPS_PHY_MPLLB_FORCE_EN, 0); /* * 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment -- cgit v1.2.3 From 42bbdb81965606a270ec05165bf2b6d074686332 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 Dec 2022 19:17:28 +0200 Subject: drm/i915/tc: switch to intel_de_* register accessors in display code Avoid direct uncore use in display code. Cc: Maarten Lankhorst Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/8c29f4f76c2163da309ead0bf48652024f134f11.1670433372.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_tc.c | 55 +++++++++++---------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 70624b4b2d38..f45328712bff 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -5,6 +5,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_de.h" #include "intel_display.h" #include "intel_display_power_map.h" #include "intel_display_types.h" @@ -120,11 +121,9 @@ assert_tc_cold_blocked(struct intel_digital_port *dig_port) u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 lane_mask; - lane_mask = intel_uncore_read(uncore, - PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); assert_tc_cold_blocked(dig_port); @@ -136,11 +135,9 @@ u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 pin_mask; - pin_mask = intel_uncore_read(uncore, - PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); + pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); assert_tc_cold_blocked(dig_port); @@ -186,7 +183,6 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; - struct intel_uncore *uncore = &i915->uncore; u32 val; drm_WARN_ON(&i915->drm, @@ -194,8 +190,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, assert_tc_cold_blocked(dig_port); - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx); switch (required_lanes) { @@ -216,8 +211,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, MISSING_CASE(required_lanes); } - intel_uncore_write(uncore, - PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); + intel_de_write(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); } static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, @@ -246,13 +240,11 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; u32 mask = 0; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, @@ -266,7 +258,7 @@ static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx)) mask |= BIT(TC_PORT_DP_ALT); - if (intel_uncore_read(uncore, SDEISR) & isr_bit) + if (intel_de_read(i915, SDEISR) & isr_bit) mask |= BIT(TC_PORT_LEGACY); /* The sink can be connected only in a single mode. */ @@ -281,7 +273,6 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; - struct intel_uncore *uncore = &i915->uncore; u32 val, mask = 0; /* @@ -289,13 +280,13 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) * registers in IOM. Note that this doesn't apply to PHY and FIA * registers. */ - val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); + val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port)); if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT) mask |= BIT(TC_PORT_DP_ALT); if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT) mask |= BIT(TC_PORT_TBT_ALT); - if (intel_uncore_read(uncore, SDEISR) & isr_bit) + if (intel_de_read(i915, SDEISR) & isr_bit) mask |= BIT(TC_PORT_LEGACY); /* The sink can be connected only in a single mode. */ @@ -326,11 +317,9 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port) static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assuming not complete\n", @@ -352,10 +341,9 @@ static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); + val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assuming not complete\n", @@ -380,11 +368,9 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, can't %s ownership\n", @@ -397,8 +383,7 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, if (take) val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); - intel_uncore_write(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); + intel_de_write(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); return true; } @@ -407,11 +392,10 @@ static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum port port = dig_port->base.port; - intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, - take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); + intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, + take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); return true; } @@ -429,11 +413,9 @@ static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; u32 val; - val = intel_uncore_read(uncore, - PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); + val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); if (val == 0xffffffff) { drm_dbg_kms(&i915->drm, "Port %s: PHY in TCCOLD, assume safe mode\n", @@ -447,11 +429,10 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port) static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_uncore *uncore = &i915->uncore; enum port port = dig_port->base.port; u32 val; - val = intel_uncore_read(uncore, DDI_BUF_CTL(port)); + val = intel_de_read(i915, DDI_BUF_CTL(port)); return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP; } @@ -907,7 +888,7 @@ tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig mutex_lock(&dig_port->tc_lock); wakeref = tc_cold_block(dig_port, &domain); - val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1)); + val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1)); tc_cold_unblock(dig_port, domain, wakeref); mutex_unlock(&dig_port->tc_lock); -- cgit v1.2.3 From a467a243554a64b418c14d7531a3b18c03d53bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 8 Dec 2022 00:52:19 +0200 Subject: drm/i915: Fix VLV/CHV HDMI/DP audio enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Despite what I claimed in commit c3c5dc1d9224 ("drm/i915/audio: Do the vblank waits") the vblank interrupts are in fact not enabled yet when we do the audio enable sequence on VLV/CHV (all other platforms are fine). Reorder the enable sequence on VLV/CHV to match that of the other platforms so that the audio enable happens after the pipe has been enabled. Fixes: c3c5dc1d9224 ("drm/i915/audio: Do the vblank waits") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221207225219.29060-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/g4x_dp.c | 4 ++-- drivers/gpu/drm/i915/display/g4x_hdmi.c | 25 +++++++++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 3593938dcd87..24ef36ec2d3d 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -673,8 +673,6 @@ static void intel_enable_dp(struct intel_atomic_state *state, intel_dp_pcon_dsc_configure(intel_dp, pipe_config); intel_dp_start_link_train(intel_dp, pipe_config); intel_dp_stop_link_train(intel_dp, pipe_config); - - intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void g4x_enable_dp(struct intel_atomic_state *state, @@ -683,6 +681,7 @@ static void g4x_enable_dp(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { intel_enable_dp(state, encoder, pipe_config, conn_state); + intel_audio_codec_enable(encoder, pipe_config, conn_state); intel_edp_backlight_on(pipe_config, conn_state); } @@ -691,6 +690,7 @@ static void vlv_enable_dp(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { + intel_audio_codec_enable(encoder, pipe_config, conn_state); intel_edp_backlight_on(pipe_config, conn_state); } diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 121caeaa409b..c3580d96765c 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -157,10 +157,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, &pipe_config->infoframes.hdmi); } -static void g4x_enable_hdmi(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) +static void g4x_hdmi_enable_port(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -175,6 +173,16 @@ static void g4x_enable_hdmi(struct intel_atomic_state *state, intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp); intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg); +} + +static void g4x_enable_hdmi(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + g4x_hdmi_enable_port(encoder, pipe_config); drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio && !pipe_config->has_hdmi_sink); @@ -294,6 +302,11 @@ static void vlv_enable_hdmi(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio && + !pipe_config->has_hdmi_sink); + intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void intel_disable_hdmi(struct intel_atomic_state *state, @@ -415,7 +428,7 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state, pipe_config->has_infoframe, pipe_config, conn_state); - g4x_enable_hdmi(state, encoder, pipe_config, conn_state); + g4x_hdmi_enable_port(encoder, pipe_config); vlv_wait_port_ready(dev_priv, dig_port, 0x0); } @@ -492,7 +505,7 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state, pipe_config->has_infoframe, pipe_config, conn_state); - g4x_enable_hdmi(state, encoder, pipe_config, conn_state); + g4x_hdmi_enable_port(encoder, pipe_config); vlv_wait_port_ready(dev_priv, dig_port, 0x0); -- cgit v1.2.3 From 98f974aa3c43f862826d2c05e3844536d0972ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 2 Dec 2022 15:44:09 +0200 Subject: drm/i915/vrr: Make registers latch in a consitent place on icl/tgl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Account for the framestart delay when calculating the "pipeline full" value for icl/tgl vrr. This puts the start of vblank (ie. where the double bufferd registers get latched) to a consistent place regardless of what framestart delay value is used. framestart delay does not change where start of vblank occurs in non-vrr mode and I can't see any reason why we'd want different behaviour in vrr mode. Currently framestart delay is always set to 1, and the hardcoded 4 scanlines in the code means we're currently delaying the start of vblank by three extra lines. And with framestart delay set to 4 we'd have no extra delay. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221202134412.21943-2-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_vrr.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 7b1357e82b69..6655dd2c1684 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -153,18 +153,9 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, crtc_state->vrr.guardband = crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay; } else { - /* - * FIXME: s/4/framestart_delay/ to get consistent - * earliest/latest points for register latching regardless - * of the framestart_delay used? - * - * FIXME: this really needs the extra scanline to provide consistent - * behaviour for all framestart_delay values. Otherwise with - * framestart_delay==4 we will end up extending the min vblank by - * one extra line. - */ crtc_state->vrr.pipeline_full = - min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1); + min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - + crtc_state->framestart_delay - 1); } crtc_state->mode_flags |= I915_MODE_FLAG_VRR; -- cgit v1.2.3 From 944bda740fc953d37d8a8a5506193c6031ecd2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 2 Dec 2022 15:44:10 +0200 Subject: drm/i915/vrr: Fix guardband/vblank exit length calculation for adl+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are miscalculating both the guardband value, and the resulting vblank exit length on adl+. This means that our start of vblank (double buffered register latch point) is incorrect, and we also think that it's not where it actually is (hence vblank evasion/etc. may not work properly). Fix up the calculations to match the real hardware behaviour (as reverse engineered by intel_display_poller). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221202134412.21943-3-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_vrr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 6655dd2c1684..753e7b211708 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -78,10 +78,10 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - /* The hw imposes the extra scanline before frame start */ if (DISPLAY_VER(i915) >= 13) - return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1; + return crtc_state->vrr.guardband; else + /* The hw imposes the extra scanline before frame start */ return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; } @@ -151,7 +151,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, * number of scan lines. Assuming 0 for no DSB. */ crtc_state->vrr.guardband = - crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay; + crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vdisplay; } else { crtc_state->vrr.pipeline_full = min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - -- cgit v1.2.3 From 0504d0acc282fe99cf4bd0cdc5551b352357142f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 2 Dec 2022 15:44:11 +0200 Subject: drm/i915/vrr: Reorder transcoder vs. vrr enable/disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On mtl it looks like disabling VRR after the transcoder has been disabled can cause the pipe/transcoder to get stuck when re-enabled in non-vrr mode. Reversing the order seems to help. Bspec is extremely confused about the VRR enable/disable sequence anyway, and this now more closely matches the non-modeset VRR sequence, whereas the full modeset sequence still claims that the original order is fine. But since we eventually want to toggle VRR without a full modeset anyway this seems like the better order to follow. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221202134412.21943-4-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 5f9a2410fc4c..69595cbb2766 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2726,10 +2726,10 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) { intel_crtc_vblank_off(old_crtc_state); - intel_disable_transcoder(old_crtc_state); - intel_vrr_disable(old_crtc_state); + intel_disable_transcoder(old_crtc_state); + intel_ddi_disable_transcoder_func(old_crtc_state); intel_dsc_disable(old_crtc_state); @@ -2946,13 +2946,13 @@ static void intel_enable_ddi(struct intel_atomic_state *state, if (!intel_crtc_is_bigjoiner_slave(crtc_state)) intel_ddi_enable_transcoder_func(encoder, crtc_state); - intel_vrr_enable(encoder, crtc_state); - /* Enable/Disable DP2.0 SDP split config before transcoder */ intel_audio_sdp_split_update(encoder, crtc_state); intel_enable_transcoder(crtc_state); + intel_vrr_enable(encoder, crtc_state); + intel_crtc_vblank_on(crtc_state); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) -- cgit v1.2.3 From 2ac5438ca9226c70ef37e81bd6b6c997017ae081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 2 Dec 2022 15:44:12 +0200 Subject: drm/i915/vrr: Be more careful with the bits in TRANS_VRR_CTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On mtl (at least) clearing the guardband bits in the same write as the enable bit gets cleared seems to cause an immediate FIFO underrun. Thus is seems that we need to first clear just the enable bit, then wait for the VRR live status to indicate the transcoder has exited VRR mode (this step is documented in Bspec as well), and finally we can clear out the rest of the TRANS_VRR_CTL for good measure. I did this without any RMWs in case we want to toggle VRR on/off via DSB in the future, and as we know DSB can't read registers. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221202134412.21943-5-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_vrr.c | 36 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 753e7b211708..5ff6aed9575e 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -161,31 +161,36 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, crtc_state->mode_flags |= I915_MODE_FLAG_VRR; } +static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (DISPLAY_VER(i915) >= 13) + return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | + XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband); + else + return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | + VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) | + VRR_CTL_PIPELINE_FULL_OVERRIDE; +} + void intel_vrr_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 trans_vrr_ctl; if (!crtc_state->vrr.enable) return; - if (DISPLAY_VER(dev_priv) >= 13) - trans_vrr_ctl = VRR_CTL_VRR_ENABLE | - VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | - XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband); - else - trans_vrr_ctl = VRR_CTL_VRR_ENABLE | - VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | - VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) | - VRR_CTL_PIPELINE_FULL_OVERRIDE; - intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1); intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1); - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state)); intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1); intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN); + + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), + VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); } void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) @@ -222,8 +227,13 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->vrr.enable) return; - intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), + trans_vrr_ctl(old_crtc_state)); + intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder), + VRR_STATUS_VRR_EN_LIVE, 1000); + intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); } void intel_vrr_get_config(struct intel_crtc *crtc, -- cgit v1.2.3 From be4a847652056b067d6dc6fe0fc024a9e2e987ca Mon Sep 17 00:00:00 2001 From: Khaled Almahallawy Date: Wed, 23 Nov 2022 14:09:26 -0800 Subject: drm/i915/display: Don't disable DDI/Transcoder when setting phy test pattern Bspecs has updated recently to remove the restriction to disable DDI/Transcoder before setting PHY test pattern. This update is to address PHY compliance test failures observed on a port with LTTPR. The issue is that when Transc. is disabled, the main link signals fed to LTTPR will be dropped invalidating link training, which will affect the quality of the phy test pattern when the transcoder is enabled again. v2: Update commit message (Clint) v3: Add missing Signed-off in v2 v4: Update Bspec and commit message for pre-gen12 (Jani) Bspec: 50482, 7555 Fixes: 8cdf72711928 ("drm/i915/dp: Program vswing, pre-emphasis, test-pattern") Cc: Imre Deak Cc: Clint Taylor CC: Jani Nikula Tested-by: Khaled Almahallawy Reviewed-by: Clint Taylor Signed-off-by: Khaled Almahallawy Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221123220926.170034-1-khaled.almahallawy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 59 --------------------------------- 1 file changed, 59 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 1607c86af025..0820e58cb6b8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3698,61 +3698,6 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp, } } -static void -intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); - enum pipe pipe = crtc->pipe; - u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; - - trans_ddi_func_ctl_value = intel_de_read(dev_priv, - TRANS_DDI_FUNC_CTL(pipe)); - trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe)); - dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe)); - - trans_ddi_func_ctl_value &= ~(TRANS_DDI_FUNC_ENABLE | - TGL_TRANS_DDI_PORT_MASK); - trans_conf_value &= ~PIPECONF_ENABLE; - dp_tp_ctl_value &= ~DP_TP_CTL_ENABLE; - - intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value); - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), - trans_ddi_func_ctl_value); - intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value); -} - -static void -intel_dp_autotest_phy_ddi_enable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - enum port port = dig_port->base.port; - struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); - enum pipe pipe = crtc->pipe; - u32 trans_ddi_func_ctl_value, trans_conf_value, dp_tp_ctl_value; - - trans_ddi_func_ctl_value = intel_de_read(dev_priv, - TRANS_DDI_FUNC_CTL(pipe)); - trans_conf_value = intel_de_read(dev_priv, PIPECONF(pipe)); - dp_tp_ctl_value = intel_de_read(dev_priv, TGL_DP_TP_CTL(pipe)); - - trans_ddi_func_ctl_value |= TRANS_DDI_FUNC_ENABLE | - TGL_TRANS_DDI_SELECT_PORT(port); - trans_conf_value |= PIPECONF_ENABLE; - dp_tp_ctl_value |= DP_TP_CTL_ENABLE; - - intel_de_write(dev_priv, PIPECONF(pipe), trans_conf_value); - intel_de_write(dev_priv, TGL_DP_TP_CTL(pipe), dp_tp_ctl_value); - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), - trans_ddi_func_ctl_value); -} - static void intel_dp_process_phy_request(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -3771,14 +3716,10 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp, intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status); - intel_dp_autotest_phy_ddi_disable(intel_dp, crtc_state); - intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX); intel_dp_phy_pattern_update(intel_dp, crtc_state); - intel_dp_autotest_phy_ddi_enable(intel_dp, crtc_state); - drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, intel_dp->train_set, crtc_state->lane_count); -- cgit v1.2.3 From af9339788966f42b2b5917bc4bc1fdef9e35dff8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 8 Dec 2022 15:36:38 +0200 Subject: drm/i915/display: no need for gt/gen8_ppgtt.h Remove an unnecessary include. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20221208133638.478024-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 32b257157186..6cdfdae2c712 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -70,8 +70,6 @@ #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" -#include "gt/gen8_ppgtt.h" - #include "g4x_dp.h" #include "g4x_hdmi.h" #include "hsw_ips.h" -- cgit v1.2.3 From f70f8153e3642337b444fbc0c64d546a46bbcd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:48 +0200 Subject: drm/i915: Introduce intel_panel_init_alloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a place where we can initialize connector->panel after it's been allocated. We already have a intel_panel_init() so had to get creative with the name and came up with intel_panel_init_alloc(). Cc: Animesh Manna Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_connector.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.c | 7 +++++++ drivers/gpu/drm/i915/display/intel_panel.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index 6205ddd3ded0..562da3b741e2 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -54,7 +54,7 @@ int intel_connector_init(struct intel_connector *connector) __drm_atomic_helper_connector_reset(&connector->base, &conn_state->base); - INIT_LIST_HEAD(&connector->panel.fixed_modes); + intel_panel_init_alloc(connector); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 1640726bfbf6..b49228eb79e7 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -661,6 +661,13 @@ intel_panel_mode_valid(struct intel_connector *connector, return MODE_OK; } +void intel_panel_init_alloc(struct intel_connector *connector) +{ + struct intel_panel *panel = &connector->panel; + + INIT_LIST_HEAD(&panel->fixed_modes); +} + int intel_panel_init(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 5c5b5b7f95b6..4b51e1c51da6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -18,6 +18,7 @@ struct intel_connector; struct intel_crtc_state; struct intel_encoder; +void intel_panel_init_alloc(struct intel_connector *connector); int intel_panel_init(struct intel_connector *connector); void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status -- cgit v1.2.3 From 3f9ffce5765d68775163b8b134c4d7f156b48eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:49 +0200 Subject: drm/i915: Do panel VBT init early if the VBT declares an explicit panel type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lots of ADL machines out there with bogus VBTs that declare two eDP child devices. In order for those to work we need to figure out which power sequencer to use before we try the EDID read. So let's do the panel VBT init early if we can, falling back to the post-EDID init otherwise. The post-EDID init panel_type=0xff approach of assuming the power sequencer should already be enabled doesn't really work with multiple eDP panels, and currently we just end up using the same power sequencer for both eDP ports, which at least confuses the wakeref tracking, and potentially also causes us to toggle the VDD for the panel when we should not. Cc: Animesh Manna Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_bios.c | 56 ++++++++++++++++------ drivers/gpu/drm/i915/display/intel_bios.h | 11 +++-- drivers/gpu/drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++- drivers/gpu/drm/i915/display/intel_lvds.c | 4 +- drivers/gpu/drm/i915/display/intel_panel.c | 1 + drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- 9 files changed, 61 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index d16b30a2dded..ae14c794c4bc 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -2043,7 +2043,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) /* attach connector to encoder */ intel_connector_attach_encoder(intel_connector, encoder); - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL); mutex_lock(&dev_priv->drm.mode_config.mutex); intel_panel_add_vbt_lfp_fixed_mode(intel_connector); diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 572a4e3769f3..55544d484318 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -620,14 +620,14 @@ static void dump_pnp_id(struct drm_i915_private *i915, static int opregion_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { return intel_opregion_get_panel_type(i915); } static int vbt_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { const struct bdb_lvds_options *lvds_options; @@ -652,7 +652,7 @@ static int vbt_get_panel_type(struct drm_i915_private *i915, static int pnpid_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_ptrs *ptrs; @@ -701,9 +701,9 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, static int fallback_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { - return 0; + return use_fallback ? 0 : -1; } enum panel_type { @@ -715,13 +715,13 @@ enum panel_type { static int get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid) + const struct edid *edid, bool use_fallback) { struct { const char *name; int (*get_panel_type)(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, - const struct edid *edid); + const struct edid *edid, bool use_fallback); int panel_type; } panel_types[] = { [PANEL_TYPE_OPREGION] = { @@ -744,7 +744,8 @@ static int get_panel_type(struct drm_i915_private *i915, int i; for (i = 0; i < ARRAY_SIZE(panel_types); i++) { - panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, edid); + panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, + edid, use_fallback); drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf && panel_types[i].panel_type != 0xff); @@ -3183,14 +3184,26 @@ out: kfree(oprom_vbt); } -void intel_bios_init_panel(struct drm_i915_private *i915, - struct intel_panel *panel, - const struct intel_bios_encoder_data *devdata, - const struct edid *edid) +static void intel_bios_init_panel(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid, + bool use_fallback) { - init_vbt_panel_defaults(panel); + /* already have it? */ + if (panel->vbt.panel_type >= 0) { + drm_WARN_ON(&i915->drm, !use_fallback); + return; + } - panel->vbt.panel_type = get_panel_type(i915, devdata, edid); + panel->vbt.panel_type = get_panel_type(i915, devdata, + edid, use_fallback); + if (panel->vbt.panel_type < 0) { + drm_WARN_ON(&i915->drm, use_fallback); + return; + } + + init_vbt_panel_defaults(panel); parse_panel_options(i915, panel); parse_generic_dtd(i915, panel); @@ -3205,6 +3218,21 @@ void intel_bios_init_panel(struct drm_i915_private *i915, parse_mipi_sequence(i915, panel); } +void intel_bios_init_panel_early(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata) +{ + intel_bios_init_panel(i915, panel, devdata, NULL, false); +} + +void intel_bios_init_panel_late(struct drm_i915_private *i915, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid) +{ + intel_bios_init_panel(i915, panel, devdata, edid, true); +} + /** * intel_bios_driver_remove - Free any resources allocated by intel_bios_init() * @i915: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index e375405a7828..ff1fdd2e0c1c 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -232,10 +232,13 @@ struct mipi_pps_data { } __packed; void intel_bios_init(struct drm_i915_private *dev_priv); -void intel_bios_init_panel(struct drm_i915_private *dev_priv, - struct intel_panel *panel, - const struct intel_bios_encoder_data *devdata, - const struct edid *edid); +void intel_bios_init_panel_early(struct drm_i915_private *dev_priv, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata); +void intel_bios_init_panel_late(struct drm_i915_private *dev_priv, + struct intel_panel *panel, + const struct intel_bios_encoder_data *devdata, + const struct edid *edid); void intel_bios_fini_panel(struct intel_panel *panel); void intel_bios_driver_remove(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ff3ef37d099e..cc64e787e401 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -291,7 +291,7 @@ struct intel_vbt_panel_data { struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ /* Feature bits */ - unsigned int panel_type:4; + int panel_type; unsigned int lvds_dither:1; unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0820e58cb6b8..06844f45df41 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5221,6 +5221,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, return false; } + intel_bios_init_panel_early(dev_priv, &intel_connector->panel, + encoder->devdata); + intel_pps_init(intel_dp); /* Cache DPCD and EDID for edp. */ @@ -5256,8 +5259,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; - intel_bios_init_panel(dev_priv, &intel_connector->panel, - encoder->devdata, IS_ERR(edid) ? NULL : edid); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, + encoder->devdata, IS_ERR(edid) ? NULL : edid); intel_panel_add_edid_fixed_modes(intel_connector, true); diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 7bf1bdfd03ec..aecec992cd0d 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -964,8 +964,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) } intel_connector->edid = edid; - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, - IS_ERR(edid) ? NULL : edid); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, + IS_ERR(edid) ? NULL : edid); /* Try EDID first */ intel_panel_add_edid_fixed_modes(intel_connector, true); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index b49228eb79e7..609fcdbd7d58 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -665,6 +665,7 @@ void intel_panel_init_alloc(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; + connector->panel.vbt.panel_type = -1; INIT_LIST_HEAD(&panel->fixed_modes); } diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 329b9d9af667..21805c15d5eb 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2886,7 +2886,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type) if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; - intel_bios_init_panel(i915, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(i915, &intel_connector->panel, NULL, NULL); /* * Fetch modes from VBT. For SDVO prefer the VBT mode since some diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 84481030883a..662bdb656aa3 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1916,7 +1916,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_dsi->panel_power_off_time = ktime_get_boottime(); - intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL); if (intel_connector->panel.vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); -- cgit v1.2.3 From 209074fd5a8217688b9ee5c200d470df3e32dee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:50 +0200 Subject: drm/i915: Generalize the PPS vlv_pipe_check() stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restate the vlv_pipe_check() stuff in terms of PPS index (rather than pipe, which it is on VLV/CHV) so that we can reuse this same mechanim on other platforms as well. Cc: Animesh Manna Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_pps.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 9bbf41a076f7..41ab12fcce0e 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -234,31 +234,26 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) return backlight_controller; } -typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv, - enum pipe pipe); +typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx); -static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_has_pp_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON; + return intel_de_read(dev_priv, PP_STATUS(pps_idx)) & PP_ON; } -static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_has_vdd_on(struct drm_i915_private *dev_priv, int pps_idx) { - return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD; + return intel_de_read(dev_priv, PP_CONTROL(pps_idx)) & EDP_FORCE_VDD; } -static bool vlv_pipe_any(struct drm_i915_private *dev_priv, - enum pipe pipe) +static bool pps_any(struct drm_i915_private *dev_priv, int pps_idx) { return true; } static enum pipe vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, - enum port port, - vlv_pipe_check pipe_check) + enum port port, pps_check check) { enum pipe pipe; @@ -269,7 +264,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv, if (port_sel != PANEL_PORT_SELECT_VLV(port)) continue; - if (!pipe_check(dev_priv, pipe)) + if (!check(dev_priv, pipe)) continue; return pipe; @@ -290,15 +285,15 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) /* try to find a pipe with this port selected */ /* first pick one where the panel is on */ intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_has_pp_on); + pps_has_pp_on); /* didn't find one? pick one where vdd is on */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_has_vdd_on); + pps_has_vdd_on); /* didn't find one? pick one with just the correct port */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port, - vlv_pipe_any); + pps_any); /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) { -- cgit v1.2.3 From bf38bba3e7d635ff1b6abc097f50094d100e90e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:51 +0200 Subject: drm/i915: Try to use the correct power sequencer intiially on bxt/glk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently on bxt/glk we just grab the power sequencer index from the VBT data even though it may not have been parsed yet. That could lead us to using the incorrect power sequencer during the initial panel probe. To avoid that let's try to read out the current state of the power sequencer from the hardware. Unfortunately the power sequencer no longer has anything in its registers to associate it with the port, so the best we can do is just iterate through the power sequencers and pick the first one. This should be sufficient for single panel cases. For the dual panel cases we probably need to go back to parsing the VBT before the panel probe (and hope that panel_type=0xff is never a thing in those cases). To that end the code always prefers the VBT panel sequencer, if available. v2: Restructure a bit for upcoming icp+ dual PPS support Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-5-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_display_types.h | 22 +++-- drivers/gpu/drm/i915/display/intel_panel.c | 1 + drivers/gpu/drm/i915/display/intel_pps.c | 96 +++++++++++++++++++--- 3 files changed, 102 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index cc64e787e401..32e8b2fc3cc6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -330,7 +330,7 @@ struct intel_vbt_panel_data { bool present; bool active_low_pwm; u8 min_brightness; /* min_brightness/255 of max */ - u8 controller; /* brightness controller number */ + s8 controller; /* brightness controller number */ enum intel_backlight_type type; } backlight; @@ -1570,11 +1570,19 @@ struct intel_pps { ktime_t panel_power_off_time; intel_wakeref_t vdd_wakeref; - /* - * Pipe whose power sequencer is currently locked into - * this port. Only relevant on VLV/CHV. - */ - enum pipe pps_pipe; + union { + /* + * Pipe whose power sequencer is currently locked into + * this port. Only relevant on VLV/CHV. + */ + enum pipe pps_pipe; + + /* + * Power sequencer index. Only relevant on BXT+. + */ + int pps_idx; + }; + /* * Pipe currently driving the port. Used for preventing * the use of the PPS for any pipe currentrly driving @@ -1583,7 +1591,7 @@ struct intel_pps { enum pipe active_pipe; /* * Set if the sequencer may be reset due to a power transition, - * requiring a reinitialization. Only relevant on BXT. + * requiring a reinitialization. Only relevant on BXT+. */ bool pps_reset; struct edp_power_seq pps_delays; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 609fcdbd7d58..3b1004b019a8 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -666,6 +666,7 @@ void intel_panel_init_alloc(struct intel_connector *connector) struct intel_panel *panel = &connector->panel; connector->panel.vbt.panel_type = -1; + connector->panel.vbt.backlight.controller = -1; INIT_LIST_HEAD(&panel->fixed_modes); } diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 41ab12fcce0e..d8d2f22f3e0c 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -212,8 +212,7 @@ static int bxt_power_sequencer_idx(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct intel_connector *connector = intel_dp->attached_connector; - int backlight_controller = connector->panel.vbt.backlight.controller; + int pps_idx = intel_dp->pps.pps_idx; lockdep_assert_held(&dev_priv->display.pps.mutex); @@ -221,7 +220,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp)); if (!intel_dp->pps.pps_reset) - return backlight_controller; + return pps_idx; intel_dp->pps.pps_reset = false; @@ -231,7 +230,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) */ pps_init_registers(intel_dp, false); - return backlight_controller; + return pps_idx; } typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx); @@ -311,6 +310,64 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) pipe_name(intel_dp->pps.pps_pipe)); } +static int +bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) +{ + int pps_idx, pps_num = 2; + + for (pps_idx = 0; pps_idx < pps_num; pps_idx++) { + if (check(i915, pps_idx)) + return pps_idx; + } + + return -1; +} + +static void +pps_initial_setup(struct intel_dp *intel_dp) +{ + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct intel_connector *connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + lockdep_assert_held(&i915->display.pps.mutex); + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + vlv_initial_power_sequencer_setup(intel_dp); + return; + } + + if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915)) + return; + + /* first ask the VBT */ + intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; + if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= 2)) + intel_dp->pps.pps_idx = -1; + + /* VBT wasn't parsed yet? pick one where the panel is on */ + if (intel_dp->pps.pps_idx < 0) + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_pp_on); + /* didn't find one? pick one where vdd is on */ + if (intel_dp->pps.pps_idx < 0) + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_vdd_on); + /* didn't find one? pick any */ + if (intel_dp->pps.pps_idx < 0) { + intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_any); + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] no initial power sequencer, assuming %d\n", + encoder->base.base.id, encoder->base.name, + intel_dp->pps.pps_idx); + return; + } + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] initial power sequencer: %d\n", + encoder->base.base.id, encoder->base.name, + intel_dp->pps.pps_idx); +} + void intel_pps_reset_all(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; @@ -363,10 +420,10 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, memset(regs, 0, sizeof(*regs)); - if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - pps_idx = bxt_power_sequencer_idx(intel_dp); - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) pps_idx = vlv_power_sequencer_pipe(intel_dp); + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) + pps_idx = bxt_power_sequencer_idx(intel_dp); regs->pp_ctrl = PP_CONTROL(pps_idx); regs->pp_stat = PP_STATUS(pps_idx); @@ -1429,7 +1486,6 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp) void intel_pps_init(struct intel_dp *intel_dp) { - struct drm_i915_private *i915 = dp_to_i915(intel_dp); intel_wakeref_t wakeref; intel_dp->pps.initializing = true; @@ -1438,8 +1494,7 @@ void intel_pps_init(struct intel_dp *intel_dp) pps_init_timestamps(intel_dp); with_intel_pps_lock(intel_dp, wakeref) { - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - vlv_initial_power_sequencer_setup(intel_dp); + pps_initial_setup(intel_dp); pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); @@ -1447,12 +1502,33 @@ void intel_pps_init(struct intel_dp *intel_dp) } } +static void pps_init_late(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct intel_connector *connector = intel_dp->attached_connector; + + if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915)) + return; + + drm_WARN(&i915->drm, connector->panel.vbt.backlight.controller >= 0 && + intel_dp->pps.pps_idx != connector->panel.vbt.backlight.controller, + "[ENCODER:%d:%s] power sequencer mismatch: %d (initial) vs. %d (VBT)\n", + encoder->base.base.id, encoder->base.name, + intel_dp->pps.pps_idx, connector->panel.vbt.backlight.controller); + + if (connector->panel.vbt.backlight.controller >= 0) + intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; +} + void intel_pps_init_late(struct intel_dp *intel_dp) { intel_wakeref_t wakeref; with_intel_pps_lock(intel_dp, wakeref) { /* Reinit delays after per-panel info has been parsed from VBT */ + pps_init_late(intel_dp); + memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp->pps.pps_delays)); pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); -- cgit v1.2.3 From d83804f22d8532a8feb49ee5f552b41f3df41008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:52 +0200 Subject: drm/i915: Extend dual PPS handlind for ICP+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the PCH side the second PPS was introduced in ICP. Let's make sure we examine both power sequencer on ICP+ as well. Note that DG1/2 south block only has the single PPS, so need to exclude the fake DG1/2 PCHs. Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-6-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_pps.c | 44 +++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index d8d2f22f3e0c..77b0a4f27abc 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -310,10 +310,27 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) pipe_name(intel_dp->pps.pps_pipe)); } +static int intel_num_pps(struct drm_i915_private *i915) +{ + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return 2; + + if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) + return 2; + + if (INTEL_PCH_TYPE(i915) >= PCH_DG1) + return 1; + + if (INTEL_PCH_TYPE(i915) >= PCH_ICP) + return 2; + + return 1; +} + static int bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) { - int pps_idx, pps_num = 2; + int pps_idx, pps_num = intel_num_pps(i915); for (pps_idx = 0; pps_idx < pps_num; pps_idx++) { if (check(i915, pps_idx)) @@ -337,12 +354,13 @@ pps_initial_setup(struct intel_dp *intel_dp) return; } - if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915)) - return; - /* first ask the VBT */ - intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; - if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= 2)) + if (intel_num_pps(i915) > 1) + intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller; + else + intel_dp->pps.pps_idx = 0; + + if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= intel_num_pps(i915))) intel_dp->pps.pps_idx = -1; /* VBT wasn't parsed yet? pick one where the panel is on */ @@ -416,7 +434,7 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, struct pps_registers *regs) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - int pps_idx = 0; + int pps_idx; memset(regs, 0, sizeof(*regs)); @@ -424,6 +442,8 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, pps_idx = vlv_power_sequencer_pipe(intel_dp); else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pps_idx = bxt_power_sequencer_idx(intel_dp); + else + pps_idx = intel_dp->pps.pps_idx; regs->pp_ctrl = PP_CONTROL(pps_idx); regs->pp_stat = PP_STATUS(pps_idx); @@ -1508,7 +1528,10 @@ static void pps_init_late(struct intel_dp *intel_dp) struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct intel_connector *connector = intel_dp->attached_connector; - if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915)) + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return; + + if (intel_num_pps(i915) < 2) return; drm_WARN(&i915->drm, connector->panel.vbt.backlight.controller >= 0 && @@ -1551,10 +1574,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) * This w/a is needed at least on CPT/PPT, but to be sure apply it * everywhere where registers can be write protected. */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - pps_num = 2; - else - pps_num = 1; + pps_num = intel_num_pps(dev_priv); for (pps_idx = 0; pps_idx < pps_num; pps_idx++) { u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx)); -- cgit v1.2.3 From ba21bb24810f8b49b83ee3f49b60953445e79f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:53 +0200 Subject: drm/i915: Reject unusable power sequencers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ICP-ADP the pins used by the second PPS can be alternatively muxed to some other function. In that case the second power sequencer is unusable. Unfortunately (on my ADL Thinkpad T14 gen3 at least) the BIOS still likes to enable the VDD on the second PPS (due to the VBT declaring the second bogus eDP panel) even when not correctly muxed, so we need to deal with it somehow. For now let's just initialize the PPS as normal, and then use the normal eDP probe failure VDD off path to turn it off (and release the wakeref the PPS init grabbed). The alternative of just declaring that the platform has a single PPS doesn't really work since it would cause the second eDP probe to also try to use the first PPS and thus clobber the state for the first (real) eDP panel. Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-7-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dp.c | 12 ++++++++++- drivers/gpu/drm/i915/display/intel_pps.c | 34 +++++++++++++++++++++++--------- drivers/gpu/drm/i915/display/intel_pps.h | 2 +- drivers/gpu/drm/i915/i915_reg.h | 1 + 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 06844f45df41..72cf83a27405 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5224,7 +5224,17 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_bios_init_panel_early(dev_priv, &intel_connector->panel, encoder->devdata); - intel_pps_init(intel_dp); + if (!intel_pps_init(intel_dp)) { + drm_info(&dev_priv->drm, + "[ENCODER:%d:%s] unusable PPS, disabling eDP\n", + encoder->base.base.id, encoder->base.name); + /* + * The BIOS may have still enabled VDD on the PPS even + * though it's unusable. Make sure we turn it back off + * and to release the power domain references/etc. + */ + goto out_vdd_off; + } /* Cache DPCD and EDID for edp. */ has_dpcd = intel_edp_init_dpcd(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 77b0a4f27abc..d18c1c58dfcf 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -327,6 +327,18 @@ static int intel_num_pps(struct drm_i915_private *i915) return 1; } +static bool intel_pps_is_valid(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (intel_dp->pps.pps_idx == 1 && + INTEL_PCH_TYPE(i915) >= PCH_ICP && + INTEL_PCH_TYPE(i915) < PCH_MTP) + return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT; + + return true; +} + static int bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) { @@ -340,7 +352,7 @@ bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check) return -1; } -static void +static bool pps_initial_setup(struct intel_dp *intel_dp) { struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; @@ -351,7 +363,7 @@ pps_initial_setup(struct intel_dp *intel_dp) if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { vlv_initial_power_sequencer_setup(intel_dp); - return; + return true; } /* first ask the VBT */ @@ -377,13 +389,14 @@ pps_initial_setup(struct intel_dp *intel_dp) "[ENCODER:%d:%s] no initial power sequencer, assuming %d\n", encoder->base.base.id, encoder->base.name, intel_dp->pps.pps_idx); - return; + } else { + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] initial power sequencer: %d\n", + encoder->base.base.id, encoder->base.name, + intel_dp->pps.pps_idx); } - drm_dbg_kms(&i915->drm, - "[ENCODER:%d:%s] initial power sequencer: %d\n", - encoder->base.base.id, encoder->base.name, - intel_dp->pps.pps_idx); + return intel_pps_is_valid(intel_dp); } void intel_pps_reset_all(struct drm_i915_private *dev_priv) @@ -1504,9 +1517,10 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp) } } -void intel_pps_init(struct intel_dp *intel_dp) +bool intel_pps_init(struct intel_dp *intel_dp) { intel_wakeref_t wakeref; + bool ret; intel_dp->pps.initializing = true; INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work); @@ -1514,12 +1528,14 @@ void intel_pps_init(struct intel_dp *intel_dp) pps_init_timestamps(intel_dp); with_intel_pps_lock(intel_dp, wakeref) { - pps_initial_setup(intel_dp); + ret = pps_initial_setup(intel_dp); pps_init_delays(intel_dp); pps_init_registers(intel_dp, false); pps_vdd_init(intel_dp); } + + return ret; } static void pps_init_late(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h index a3a56f903f26..a2c2467e3c22 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.h +++ b/drivers/gpu/drm/i915/display/intel_pps.h @@ -40,7 +40,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp); bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp); void intel_pps_wait_power_cycle(struct intel_dp *intel_dp); -void intel_pps_init(struct intel_dp *intel_dp); +bool intel_pps_init(struct intel_dp *intel_dp); void intel_pps_init_late(struct intel_dp *intel_dp); void intel_pps_encoder_reset(struct intel_dp *intel_dp); void intel_pps_reset_all(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0fa86da12af1..168ef34d110b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6241,6 +6241,7 @@ #define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8) #define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8) #define SBCLK_RUN_REFCLK_DIS (1 << 7) +#define ICP_SECOND_PPS_IO_SELECT REG_BIT(2) #define SPT_PWM_GRANULARITY (1 << 0) #define SOUTH_CHICKEN2 _MMIO(0xc2004) #define FDI_MPHY_IOSFSB_RESET_STATUS (1 << 13) -- cgit v1.2.3 From 1e47e035bb733476128a5281bdd29ac27c91c603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:54 +0200 Subject: drm/i915: Print the PPS registers using consistent format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the consistent format when dumping out the PPS control/status registers. Helps with pattern matching. Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-8-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_pps.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index d18c1c58dfcf..f6bc896338de 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -527,7 +527,8 @@ void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) { drm_WARN(&dev_priv->drm, 1, "eDP powered off while attempting aux channel communication.\n"); - drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n", + drm_dbg_kms(&dev_priv->drm, + "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", intel_de_read(dev_priv, _pp_stat_reg(intel_dp)), intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp))); } @@ -559,7 +560,7 @@ static void wait_panel_status(struct intel_dp *intel_dp, pp_ctrl_reg = _pp_ctrl_reg(intel_dp); drm_dbg_kms(&dev_priv->drm, - "mask %08x value %08x status %08x control %08x\n", + "mask: 0x%08x value: 0x%08x PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", mask, value, intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -567,7 +568,7 @@ static void wait_panel_status(struct intel_dp *intel_dp, if (intel_de_wait_for_register(dev_priv, pp_stat_reg, mask, value, 5000)) drm_err(&dev_priv->drm, - "Panel status timeout: status %08x control %08x\n", + "Panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); -- cgit v1.2.3 From ed5509d1d45102fd82d2d870616ceb48fcc474aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 25 Nov 2022 19:31:55 +0200 Subject: drm/i915: Fix whitespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stray spaces have snuck in where everything else uses tabs. Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-9-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_pps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index f6bc896338de..880c530d5832 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -535,7 +535,7 @@ void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) } #define IDLE_ON_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) -#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) +#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) #define IDLE_OFF_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | 0) #define IDLE_OFF_VALUE (0 | PP_SEQUENCE_NONE | 0 | 0) -- cgit v1.2.3 From 4c0eb35fc103eb71e9b842270f449b79b1cf69b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Sun, 27 Nov 2022 17:52:39 +0200 Subject: drm/i915: Improve PPS debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always include both the encoder and PPS instance information in the debug prints so that we know what piece of hardware we're actually dealing with. v2: Make sure pps is selected before debug prints/etc. in intel_pps_vdd_on_unlocked() on vlv/chv There is no pps on pipe C on chv v3: Allow PPS=INVALID_PIPE for vlv/chv Cc: Animesh Manna Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221127155239.26973-1-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_pps.c | 194 ++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 880c530d5832..7b21438edd9b 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -22,6 +22,40 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, static void pps_init_delays(struct intel_dp *intel_dp); static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd); +static const char *pps_name(struct drm_i915_private *i915, + struct intel_pps *pps) +{ + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + switch (pps->pps_pipe) { + case INVALID_PIPE: + /* + * FIXME would be nice if we can guarantee + * to always have a valid PPS when calling this. + */ + return "PPS "; + case PIPE_A: + return "PPS A"; + case PIPE_B: + return "PPS B"; + default: + MISSING_CASE(pps->pps_pipe); + break; + } + } else { + switch (pps->pps_idx) { + case 0: + return "PPS 0"; + case 1: + return "PPS 1"; + default: + MISSING_CASE(pps->pps_idx); + break; + } + } + + return "PPS "; +} + intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -60,15 +94,15 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) if (drm_WARN(&dev_priv->drm, intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN, - "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name)) + "skipping %s kick due to [ENCODER:%d:%s] being active\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name)) return; drm_dbg_kms(&dev_priv->drm, - "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name); + "kicking %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); /* Preserve the BIOS-computed detected bit. This is * supposed to be read-only. @@ -95,7 +129,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) { drm_err(&dev_priv->drm, - "Failed to force on pll for pipe %c!\n", + "Failed to force on PLL for pipe %c!\n", pipe_name(pipe)); return; } @@ -190,10 +224,9 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) intel_dp->pps.pps_pipe = pipe; drm_dbg_kms(&dev_priv->drm, - "picked pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(intel_dp->pps.pps_pipe), - dig_port->base.base.base.id, - dig_port->base.base.name); + "picked %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); /* init power sequencer on this pipe and port */ pps_init_delays(intel_dp); @@ -297,17 +330,15 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */ if (intel_dp->pps.pps_pipe == INVALID_PIPE) { drm_dbg_kms(&dev_priv->drm, - "no initial power sequencer for [ENCODER:%d:%s]\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + "[ENCODER:%d:%s] no initial power sequencer\n", + dig_port->base.base.base.id, dig_port->base.base.name); return; } drm_dbg_kms(&dev_priv->drm, - "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n", - dig_port->base.base.base.id, - dig_port->base.base.name, - pipe_name(intel_dp->pps.pps_pipe)); + "[ENCODER:%d:%s] initial power sequencer: %s\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); } static int intel_num_pps(struct drm_i915_private *i915) @@ -386,14 +417,14 @@ pps_initial_setup(struct intel_dp *intel_dp) intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_any); drm_dbg_kms(&i915->drm, - "[ENCODER:%d:%s] no initial power sequencer, assuming %d\n", + "[ENCODER:%d:%s] no initial power sequencer, assuming %s\n", encoder->base.base.id, encoder->base.name, - intel_dp->pps.pps_idx); + pps_name(i915, &intel_dp->pps)); } else { drm_dbg_kms(&i915->drm, - "[ENCODER:%d:%s] initial power sequencer: %d\n", + "[ENCODER:%d:%s] initial power sequencer: %s\n", encoder->base.base.id, encoder->base.name, - intel_dp->pps.pps_idx); + pps_name(i915, &intel_dp->pps)); } return intel_pps_is_valid(intel_dp); @@ -520,15 +551,20 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); if (!intel_dp_is_edp(intel_dp)) return; if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) { drm_WARN(&dev_priv->drm, 1, - "eDP powered off while attempting aux channel communication.\n"); + "[ENCODER:%d:%s] %s powered off while attempting AUX CH communication.\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); drm_dbg_kms(&dev_priv->drm, - "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, _pp_stat_reg(intel_dp)), intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp))); } @@ -546,10 +582,10 @@ void intel_pps_check_power_unlocked(struct intel_dp *intel_dp) static void intel_pps_verify_state(struct intel_dp *intel_dp); static void wait_panel_status(struct intel_dp *intel_dp, - u32 mask, - u32 value) + u32 mask, u32 value) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); i915_reg_t pp_stat_reg, pp_ctrl_reg; lockdep_assert_held(&dev_priv->display.pps.mutex); @@ -560,7 +596,9 @@ static void wait_panel_status(struct intel_dp *intel_dp, pp_ctrl_reg = _pp_ctrl_reg(intel_dp); drm_dbg_kms(&dev_priv->drm, - "mask: 0x%08x value: 0x%08x PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + "[ENCODER:%d:%s] %s mask: 0x%08x value: 0x%08x PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), mask, value, intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -568,7 +606,9 @@ static void wait_panel_status(struct intel_dp *intel_dp, if (intel_de_wait_for_register(dev_priv, pp_stat_reg, mask, value, 5000)) drm_err(&dev_priv->drm, - "Panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + "[ENCODER:%d:%s] %s panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -578,26 +618,35 @@ static void wait_panel_status(struct intel_dp *intel_dp, static void wait_panel_on(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - drm_dbg_kms(&i915->drm, "Wait for panel power on\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power on\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE); } static void wait_panel_off(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - drm_dbg_kms(&i915->drm, "Wait for panel power off time\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power off time\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE); } static void wait_panel_power_cycle(struct intel_dp *intel_dp) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); ktime_t panel_power_on_time; s64 panel_power_off_duration; - drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n"); + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power cycle\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(i915, &intel_dp->pps)); /* take the difference of current time and panel power off time * and then make panel wait for t11_t12 if needed. */ @@ -684,9 +733,12 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port)); - drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + pp_stat_reg = _pp_stat_reg(intel_dp); + pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD on\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); if (!edp_have_panel_power(intel_dp)) wait_panel_power_cycle(intel_dp); @@ -694,12 +746,11 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) pp = ilk_get_pp_control(intel_dp); pp |= EDP_FORCE_VDD; - pp_stat_reg = _pp_stat_reg(intel_dp); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); - intel_de_write(dev_priv, pp_ctrl_reg, pp); intel_de_posting_read(dev_priv, pp_ctrl_reg); - drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); /* @@ -707,9 +758,9 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) */ if (!edp_have_panel_power(intel_dp)) { drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] panel power wasn't enabled\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + "[ENCODER:%d:%s] %s panel power wasn't enabled\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); msleep(intel_dp->pps.panel_power_up_delay); } @@ -724,6 +775,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) */ void intel_pps_vdd_on(struct intel_dp *intel_dp) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); intel_wakeref_t wakeref; bool vdd; @@ -733,9 +785,10 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp) vdd = false; with_intel_pps_lock(intel_dp, wakeref) vdd = intel_pps_vdd_on_unlocked(intel_dp); - I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n", + I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] %s VDD already requested on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(i915, &intel_dp->pps)); } static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) @@ -753,9 +806,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) if (!edp_have_panel_vdd(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n", - dig_port->base.base.base.id, - dig_port->base.base.name); + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD off\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); pp = ilk_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; @@ -767,7 +820,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) intel_de_posting_read(dev_priv, pp_ctrl_reg); /* Make sure sequencer is idle before allowing subsequent activity */ - drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps), intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); @@ -842,9 +897,10 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync) if (!intel_dp_is_edp(intel_dp)) return; - I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on", + I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] %s VDD not forced on", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); intel_dp->pps.want_panel_vdd = false; @@ -865,14 +921,16 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) if (!intel_dp_is_edp(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n", + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name); + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp), - "[ENCODER:%d:%s] panel power already on\n", + "[ENCODER:%d:%s] %s panel power already on\n", dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name)) + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(dev_priv, &intel_dp->pps))) return; wait_panel_power_cycle(intel_dp); @@ -926,12 +984,14 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp) if (!intel_dp_is_edp(intel_dp)) return; - drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n", - dig_port->base.base.base.id, dig_port->base.base.name); + drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power off\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); drm_WARN(&dev_priv->drm, !intel_dp->pps.want_panel_vdd, - "Need [ENCODER:%d:%s] VDD to turn off panel\n", - dig_port->base.base.base.id, dig_port->base.base.name); + "[ENCODER:%d:%s] %s need VDD to turn off panel\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); pp = ilk_get_pp_control(intel_dp); /* We need to switch off panel power _and_ force vdd, for otherwise some @@ -1066,9 +1126,9 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) * from a port. */ drm_dbg_kms(&dev_priv->drm, - "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n", - pipe_name(pipe), dig_port->base.base.base.id, - dig_port->base.base.name); + "detaching %s from [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + dig_port->base.base.base.id, dig_port->base.base.name); intel_de_write(dev_priv, pp_on_reg, 0); intel_de_posting_read(dev_priv, pp_on_reg); @@ -1086,7 +1146,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); drm_WARN(&dev_priv->drm, intel_dp->pps.active_pipe == pipe, - "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n", + "stealing PPS %c from active [ENCODER:%d:%s]\n", pipe_name(pipe), encoder->base.base.id, encoder->base.name); @@ -1094,7 +1154,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv, continue; drm_dbg_kms(&dev_priv->drm, - "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n", + "stealing PPS %c from [ENCODER:%d:%s]\n", pipe_name(pipe), encoder->base.base.id, encoder->base.name); @@ -1139,9 +1199,9 @@ void vlv_pps_init(struct intel_encoder *encoder, intel_dp->pps.pps_pipe = crtc->pipe; drm_dbg_kms(&dev_priv->drm, - "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n", - pipe_name(intel_dp->pps.pps_pipe), encoder->base.base.id, - encoder->base.name); + "initializing %s for [ENCODER:%d:%s]\n", + pps_name(dev_priv, &intel_dp->pps), + encoder->base.base.id, encoder->base.name); /* init power sequencer on this pipe and port */ pps_init_delays(intel_dp); @@ -1165,7 +1225,9 @@ static void pps_vdd_init(struct intel_dp *intel_dp) * indefinitely. */ drm_dbg_kms(&dev_priv->drm, - "VDD left on by BIOS, adjusting state tracking\n"); + "[ENCODER:%d:%s] %s VDD left on by BIOS, adjusting state tracking\n", + dig_port->base.base.base.id, dig_port->base.base.name, + pps_name(dev_priv, &intel_dp->pps)); drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref); intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port)); -- cgit v1.2.3 From 2357f2b271adf61e47426c7e5a94de1b65a51e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 9 Dec 2022 14:05:43 -0800 Subject: drm/i915/mtl: Initial display workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces initial workarounds for mtl platform v2: switch IS_MTL_DISPLAY_STEP to use IS_METEORLAKE from testing display ver. (Tvrtko) v3: clerical issues, extend 16015201720 to mtl. (MattR) v4: make sure 16015201720 includes display 13. (MattR) Bspec: 66624 Signed-off-by: Matt Atwood Signed-off-by: Jouni Högander Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20221209220543.502047-1-matthew.s.atwood@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++-- drivers/gpu/drm/i915/display/intel_fbc.c | 6 ++++-- drivers/gpu/drm/i915/display/intel_hdmi.c | 3 ++- drivers/gpu/drm/i915/display/intel_psr.c | 27 +++++++++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index f107b8cd3c9e..905b5dcdca14 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -387,11 +387,11 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) { enum pipe pipe; - if (DISPLAY_VER(i915) != 13) + if (DISPLAY_VER(i915) < 13) return; /* - * Wa_16015201720:adl-p,dg2 + * Wa_16015201720:adl-p,dg2, mtl * The WA requires clock gating to be disabled all the time * for pipe A and B. * For pipe C and D clock gating needs to be disabled only diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index deba0c49c827..5e69d3c11d21 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -811,7 +811,7 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc) static void intel_fbc_program_workarounds(struct intel_fbc *fbc) { - /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp */ + /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915)) intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); @@ -1091,7 +1091,9 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, } /* Wa_14016291713 */ - if (IS_DISPLAY_VER(i915, 12, 13) && crtc_state->has_psr) { + if ((IS_DISPLAY_VER(i915, 12, 13) || + IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0)) && + crtc_state->has_psr) { plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)"; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index e82f8a07e2b0..efa2da080f62 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -537,7 +537,8 @@ void hsw_write_infoframe(struct intel_encoder *encoder, 0); /* Wa_14013475917 */ - if (DISPLAY_VER(dev_priv) == 13 && crtc_state->has_psr && + if ((DISPLAY_VER(dev_priv) == 13 || + IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) && crtc_state->has_psr && type == DP_SDP_VSC) return; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 5b678916e6db..9820e5fdd087 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -797,7 +797,7 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp, return intel_dp->psr.su_y_granularity == 4; /* - * adl_p and display 14+ platforms has 1 line granularity. + * adl_p and mtl platforms have 1 line granularity. * For other platforms with SW tracking we can adjust the y coordinates * to match sink requirement if multiple of 4. */ @@ -1170,11 +1170,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, PSR2_ADD_VERTICAL_LINE_COUNT); /* - * Wa_16014451276:adlp + * Wa_16014451276:adlp,mtl[a0,b0] * All supported adlp panels have 1-based X granularity, this may * cause issues if non-supported panels are used. */ - if (IS_ALDERLAKE_P(dev_priv)) + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), 0, + ADLP_1_BASED_X_GRANULARITY); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, ADLP_1_BASED_X_GRANULARITY); @@ -1185,8 +1188,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, TRANS_SET_CONTEXT_LATENCY_MASK, TRANS_SET_CONTEXT_LATENCY_VALUE(1)); - /* Wa_16012604467:adlp */ - if (IS_ALDERLAKE_P(dev_priv)) + /* Wa_16012604467:adlp,mtl[a0,b0] */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, + MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0, + MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, CLKGATE_DIS_MISC_DMASC_GATING_DIS); @@ -1362,8 +1369,12 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) TRANS_SET_CONTEXT_LATENCY(intel_dp->psr.transcoder), TRANS_SET_CONTEXT_LATENCY_MASK, 0); - /* Wa_16012604467:adlp */ - if (IS_ALDERLAKE_P(dev_priv)) + /* Wa_16012604467:adlp,mtl[a0,b0] */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + intel_de_rmw(dev_priv, + MTL_CLKGATE_DIS_TRANS(intel_dp->psr.transcoder), + MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0); + else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); @@ -1625,7 +1636,7 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, if (full_update) { /* - * Not applying Wa_14014971508:adlp as we do not support the + * Not applying Wa_14014971508:adlp,mtl as we do not support the * feature that requires this workaround. */ val |= man_trk_ctl_single_full_frame_bit_get(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d2b9981d736e..5d2c54456cc1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -726,6 +726,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_XEHPSDV_GRAPHICS_STEP(__i915, since, until) \ (IS_XEHPSDV(__i915) && IS_GRAPHICS_STEP(__i915, since, until)) +#define IS_MTL_DISPLAY_STEP(__i915, since, until) \ + (IS_METEORLAKE(__i915) && \ + IS_DISPLAY_STEP(__i915, since, until)) + /* * DG2 hardware steppings are a bit unusual. The hardware design was forked to * create three variants (G10, G11, and G12) which each have distinct -- cgit v1.2.3 From 07e176f2ad357a9371b9e9a80fc1c77016399ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:26 +0200 Subject: drm/i915: Shorten GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s/GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED/GAMMA_MODE_MODE_12BIT_MULTI_SEG/ to make this thing slightly shorter. Also fix up the platform comment while at it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-2-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 10 +++++----- drivers/gpu/drm/i915/i915_reg.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 842d58da3128..956b221860e6 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1212,7 +1212,7 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) case GAMMA_MODE_MODE_8BIT: ilk_load_lut_8(crtc, post_csc_lut); break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: icl_program_gamma_superfine_segment(crtc_state); icl_program_gamma_multi_segment(crtc_state); ivb_load_lut_ext_max(crtc_state); @@ -2091,7 +2091,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) else if (DISPLAY_VER(i915) >= 13) gamma_mode |= GAMMA_MODE_MODE_10BIT; else - gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED; + gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEG; return gamma_mode; } @@ -2283,7 +2283,7 @@ static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) return 8; case GAMMA_MODE_MODE_10BIT: return 10; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: return 16; default: MISSING_CASE(crtc_state->gamma_mode); @@ -2455,7 +2455,7 @@ static bool icl_lut_equal(const struct intel_crtc_state *crtc_state, /* hw readout broken except for the super fine segment :( */ if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) == - GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED) + GAMMA_MODE_MODE_12BIT_MULTI_SEG) check_size = 9; return intel_lut_equal(blob1, blob2, check_size, @@ -2971,7 +2971,7 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) case GAMMA_MODE_MODE_10BIT: crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0)); break; - case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: + case GAMMA_MODE_MODE_12BIT_MULTI_SEG: crtc_state->post_csc_lut = icl_read_lut_multi_segment(crtc); break; default: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 168ef34d110b..ab39cfb14a19 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5315,7 +5315,7 @@ #define GAMMA_MODE_MODE_10BIT (1 << 0) #define GAMMA_MODE_MODE_12BIT (2 << 0) #define GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */ -#define GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */ +#define GAMMA_MODE_MODE_12BIT_MULTI_SEG (3 << 0) /* icl-tgl */ /* Display Internal Timeout Register */ #define RM_TIMEOUT _MMIO(0x42060) -- cgit v1.2.3 From 1867fcebd7a728d15a5c2352933d5731b0eca7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:27 +0200 Subject: drm/i915: Clean up GAMMA_MODE defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for GAMMA_MODE bits. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-3-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/i915_reg.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ab39cfb14a19..6c91e42540cb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5308,14 +5308,14 @@ #define _GAMMA_MODE_A 0x4a480 #define _GAMMA_MODE_B 0x4ac80 #define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) -#define PRE_CSC_GAMMA_ENABLE (1 << 31) -#define POST_CSC_GAMMA_ENABLE (1 << 30) -#define GAMMA_MODE_MODE_MASK (3 << 0) -#define GAMMA_MODE_MODE_8BIT (0 << 0) -#define GAMMA_MODE_MODE_10BIT (1 << 0) -#define GAMMA_MODE_MODE_12BIT (2 << 0) -#define GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */ -#define GAMMA_MODE_MODE_12BIT_MULTI_SEG (3 << 0) /* icl-tgl */ +#define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */ +#define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */ +#define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0) +#define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0) +#define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1) +#define GAMMA_MODE_MODE_12BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 2) +#define GAMMA_MODE_MODE_SPLIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* ivb-bdw */ +#define GAMMA_MODE_MODE_12BIT_MULTI_SEG REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* icl-tgl */ /* Display Internal Timeout Register */ #define RM_TIMEOUT _MMIO(0x42060) -- cgit v1.2.3 From 67eab12b8bcc80ec7b6f27a71bce82f9d706d109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:28 +0200 Subject: drm/i915: Define skl+ palette anti-collision bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've been frobbing the palette anti-collision logic bit while playing around with DSB. Not sure we'll have real use for this but let's define the bit anyways so I don't have to carry it around locally. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-4-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6c91e42540cb..8685f3f4a213 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5310,6 +5310,7 @@ #define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) #define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */ #define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */ +#define PALETTE_ANTICOL_DISABLE REG_BIT(15) /* skl+ */ #define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0) #define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0) #define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1) -- cgit v1.2.3 From bb0409f40ffab331f660a742c59953f5ae7698a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:29 +0200 Subject: drm/i915: Clean up various indexed LUT registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for the LUT index registers, and also use the REG_FIELD_PREP() stuff a bit more consistently when generating the values for said registers. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-5-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 46 ++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_reg.h | 18 ++++++------ 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 956b221860e6..c960c2aaf328 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -910,7 +910,8 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index++); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + prec_index + i); intel_de_write_fw(i915, PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i])); } @@ -919,7 +920,8 @@ static void ivb_load_lut_10(struct intel_crtc *crtc, * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } /* On BDW+ the index auto increment mode actually works */ @@ -933,7 +935,8 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, enum pipe pipe = crtc->pipe; intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + PAL_PREC_AUTO_INCREMENT | + prec_index); for (i = 0; i < lut_size; i++) intel_de_write_fw(i915, PREC_PAL_DATA(pipe), @@ -943,7 +946,8 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) @@ -1049,9 +1053,11 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); + PRE_CSC_GAMC_INDEX_VALUE(0)); + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT | + PRE_CSC_GAMC_INDEX_VALUE(0)); for (i = 0; i < lut_size; i++) { /* @@ -1165,7 +1171,9 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) * seg2[0] being unused by the hardware. */ intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_INDEX_VALUE(0)); + for (i = 1; i < 257; i++) { entry = &lut[i * 8]; intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), @@ -2756,7 +2764,8 @@ static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc, ilk_lut_10_pack(&lut[i], val); } - intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); return blob; } @@ -2811,7 +2820,8 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, lut = blob->data; intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index | PAL_PREC_AUTO_INCREMENT); + PAL_PREC_AUTO_INCREMENT | + prec_index); for (i = 0; i < lut_size; i++) { u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe)); @@ -2819,7 +2829,8 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, ilk_lut_10_pack(&lut[i], val); } - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); return blob; } @@ -2876,9 +2887,11 @@ static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT); + PRE_CSC_GAMC_INDEX_VALUE(0)); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT | + PRE_CSC_GAMC_INDEX_VALUE(0)); for (i = 0; i < lut_size; i++) { u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe)); @@ -2888,7 +2901,8 @@ static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) lut[i].blue = val; } - intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_INDEX_VALUE(0)); return blob; } @@ -2934,7 +2948,8 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) lut = blob->data; intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + PAL_PREC_MULTI_SEG_AUTO_INCREMENT | + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); for (i = 0; i < 9; i++) { u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe)); @@ -2943,7 +2958,8 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) ilk_lut_12p4_pack(&lut[i], ldw, udw); } - intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), 0); + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); /* * FIXME readouts from PAL_PREC_DATA register aren't giving diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8685f3f4a213..619f11d31b11 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7522,11 +7522,10 @@ enum skl_power_gate { #define _PAL_PREC_INDEX_A 0x4A400 #define _PAL_PREC_INDEX_B 0x4AC00 #define _PAL_PREC_INDEX_C 0x4B400 -#define PAL_PREC_10_12_BIT (0 << 31) -#define PAL_PREC_SPLIT_MODE (1 << 31) -#define PAL_PREC_AUTO_INCREMENT (1 << 15) -#define PAL_PREC_INDEX_VALUE_MASK (0x3ff << 0) -#define PAL_PREC_INDEX_VALUE(x) ((x) << 0) +#define PAL_PREC_SPLIT_MODE REG_BIT(31) +#define PAL_PREC_AUTO_INCREMENT REG_BIT(15) +#define PAL_PREC_INDEX_VALUE_MASK REG_GENMASK(9, 0) +#define PAL_PREC_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_INDEX_VALUE_MASK, (x)) #define _PAL_PREC_DATA_A 0x4A404 #define _PAL_PREC_DATA_B 0x4AC04 #define _PAL_PREC_DATA_C 0x4B404 @@ -7550,7 +7549,9 @@ enum skl_power_gate { #define _PRE_CSC_GAMC_INDEX_A 0x4A484 #define _PRE_CSC_GAMC_INDEX_B 0x4AC84 #define _PRE_CSC_GAMC_INDEX_C 0x4B484 -#define PRE_CSC_GAMC_AUTO_INCREMENT (1 << 10) +#define PRE_CSC_GAMC_AUTO_INCREMENT REG_BIT(10) +#define PRE_CSC_GAMC_INDEX_VALUE_MASK REG_GENMASK(7, 0) +#define PRE_CSC_GAMC_INDEX_VALUE(x) REG_FIELD_PREP(PRE_CSC_GAMC_INDEX_VALUE_MASK, (x)) #define _PRE_CSC_GAMC_DATA_A 0x4A488 #define _PRE_CSC_GAMC_DATA_B 0x4AC88 #define _PRE_CSC_GAMC_DATA_C 0x4B488 @@ -7561,8 +7562,9 @@ enum skl_power_gate { /* ICL Multi segmented gamma */ #define _PAL_PREC_MULTI_SEG_INDEX_A 0x4A408 #define _PAL_PREC_MULTI_SEG_INDEX_B 0x4AC08 -#define PAL_PREC_MULTI_SEGMENT_AUTO_INCREMENT REG_BIT(15) -#define PAL_PREC_MULTI_SEGMENT_INDEX_VALUE_MASK REG_GENMASK(4, 0) +#define PAL_PREC_MULTI_SEG_AUTO_INCREMENT REG_BIT(15) +#define PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK REG_GENMASK(4, 0) +#define PAL_PREC_MULTI_SEG_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK, (x)) #define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C #define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C -- cgit v1.2.3 From 26886082fbba1c438f88b1efed2f4dfd5612fefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:30 +0200 Subject: drm/i915: Standardize auto-increment LUT load procedure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various gamma units on various platforms have some problems loading the LUT index and auto-increment bit at the same time. We have to do this in two steps. The first known case was the glk degamma LUT, but at least ADL has another known case. We're not going to suffer too badly from a couple of extra register writes here, so let's just standardize on this practice for all auto-increment LUT loads/reads. This way we never have to worry about this specific issue again. And for good measure always reset the index back to zero at the end (we already did this in a few places). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-6-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index c960c2aaf328..bd7e781d9d07 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -934,6 +934,8 @@ static void bdw_load_lut_10(struct intel_crtc *crtc, int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + prec_index); intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT | prec_index); @@ -1138,7 +1140,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256). */ intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT); + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; @@ -1148,6 +1153,9 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), ilk_lut_12p4_udw(entry)); } + + intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); } static void @@ -1170,6 +1178,8 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1], * seg2[0] being unused by the hardware. */ + intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT | PAL_PREC_INDEX_VALUE(0)); @@ -1202,6 +1212,9 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) ilk_lut_12p4_udw(entry)); } + intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; ivb_load_lut_max(crtc_state, entry); @@ -2819,6 +2832,8 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc, lut = blob->data; + intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), + prec_index); intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT | prec_index); @@ -2947,6 +2962,8 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc) lut = blob->data; + intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), PAL_PREC_MULTI_SEG_AUTO_INCREMENT | PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); -- cgit v1.2.3 From 413352f47189955a7a1600336bf757846f642a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:31 +0200 Subject: drm/i915: Document LUT "max" register precision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the precision of the LUT "max" registers, just so we don't have to dig through the spec so much. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-7-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_reg.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 619f11d31b11..7ca676a9c50c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3619,7 +3619,7 @@ #define _PIPEAGCMAX 0x70010 #define _PIPEBGCMAX 0x71010 -#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4) +#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4) /* u1.16 */ #define _PIPE_ARB_CTL_A 0x70028 /* icl+ */ #define PIPE_ARB_CTL(pipe) _MMIO_PIPE2(pipe, _PIPE_ARB_CTL_A) @@ -5303,7 +5303,7 @@ #define _PREC_PIPEAGCMAX 0x4d000 #define _PREC_PIPEBGCMAX 0x4d010 -#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) +#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) /* u1.16 */ #define _GAMMA_MODE_A 0x4a480 #define _GAMMA_MODE_B 0x4ac80 @@ -7542,9 +7542,9 @@ enum skl_power_gate { #define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B) #define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B) -#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) -#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) -#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) +#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) /* u1.16 */ +#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) /* u3.16 */ +#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) /* glk+, u3.16 */ #define _PRE_CSC_GAMC_INDEX_A 0x4A484 #define _PRE_CSC_GAMC_INDEX_B 0x4AC84 -- cgit v1.2.3 From 75b5fef1aa228d14af189bf5e5e960d8e7a7b0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:32 +0200 Subject: drm/i915: Move the DSB->mmio fallback into the LUT code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of DSB has to be done differently on a case by case basis. So no way this kind of blind mmio fallback in the guts of the DSB code will work properly. Move it at least one level up into the LUT loading code. Not sure if this is the way we want do the DSB vs. mmio handling in the end, but at least it's a bit closer than what we had before. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-8-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 94 +++++++++++++++++++----------- drivers/gpu/drm/i915/display/intel_dsb.c | 18 +----- 2 files changed, 62 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index bd7e781d9d07..5a4f794e1d08 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -836,6 +836,28 @@ static void i965_load_luts(const struct intel_crtc_state *crtc_state) } } +static void ilk_lut_write(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (crtc_state->dsb) + intel_dsb_reg_write(crtc_state, reg, val); + else + intel_de_write_fw(i915, reg, val); +} + +static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, + i915_reg_t reg, u32 val) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (crtc_state->dsb) + intel_dsb_indexed_reg_write(crtc_state, reg, val); + else + intel_de_write_fw(i915, reg, val); +} + static void ilk_load_lut_8(struct intel_crtc *crtc, const struct drm_property_blob *blob) { @@ -958,9 +980,9 @@ static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16); } static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) @@ -969,9 +991,9 @@ static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; /* Program the max register to clamp values > 1.0. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); - intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16); + ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16); } static void ivb_load_luts(const struct intel_crtc_state *crtc_state) @@ -1118,9 +1140,9 @@ ivb_load_lut_max(const struct intel_crtc_state *crtc_state, enum pipe pipe = crtc->pipe; /* FIXME LUT entries are 16 bit only, so we can prog 0xFFFF max */ - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), color->red); - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), color->green); - intel_dsb_reg_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), color->blue); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), color->red); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), color->green); + ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), color->blue); } static void @@ -1139,23 +1161,23 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) * 9 entries, corresponding to values 0, 1/(8 * 128 * 256), * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256). */ - intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); - intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT | - PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_udw(entry)); } - intel_dsb_reg_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), - PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), + PAL_PREC_MULTI_SEG_INDEX_VALUE(0)); } static void @@ -1178,18 +1200,19 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1], * seg2[0] being unused by the hardware. */ - intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), - PAL_PREC_INDEX_VALUE(0)); - intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT | - PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + PAL_PREC_INDEX_VALUE(0)); for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } /* @@ -1206,14 +1229,15 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) */ for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - intel_dsb_indexed_reg_write(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } - intel_dsb_reg_write(crtc_state, PREC_PAL_INDEX(pipe), - PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); /* The last entry in the LUT is to be programmed in GCMAX */ entry = &lut[256 * 8 * 128]; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 1e1c6107d51b..b4f0356c2463 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -129,14 +129,9 @@ void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, struct intel_dsb *dsb = crtc_state->dsb; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 *buf; + u32 *buf = dsb->cmd_buf; u32 reg_val; - if (!dsb) { - intel_de_write_fw(dev_priv, reg, val); - return; - } - buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; @@ -205,16 +200,9 @@ void intel_dsb_reg_write(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); - struct intel_dsb *dsb; - u32 *buf; - - dsb = crtc_state->dsb; - if (!dsb) { - intel_de_write_fw(dev_priv, reg, val); - return; - } + struct intel_dsb *dsb = crtc_state->dsb; + u32 *buf = dsb->cmd_buf; - buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; -- cgit v1.2.3 From efb2b57edf20c32b08eee4ce8b436c459fe4caea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:33 +0200 Subject: drm/i915: Move the DSB setup/cleaup into the color code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the color management code is the only user of the DSB at the moment move the DSB prepare/cleanup there too. The code has to anyway make decisions on whether to use the DSB or not (and how to use it). Also we'll need a place where we actually generate the DSB command buffer ahead of time rather than the current situation where it gets generated too late during the mmio programming of the hardware. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-9-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_color.h | 2 ++ drivers/gpu/drm/i915/display/intel_display.c | 25 ++++++++++--------------- drivers/gpu/drm/i915/display/intel_display.h | 8 ++++++++ 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 5a4f794e1d08..5a8652407f30 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1389,6 +1389,16 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) i915->display.funcs.color->color_commit_arm(crtc_state); } +void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) +{ + intel_dsb_prepare(crtc_state); +} + +void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) +{ + intel_dsb_cleanup(crtc_state); +} + static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 1c6b1755f6d2..d620b5b1e2a6 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -17,6 +17,8 @@ void intel_color_init_hooks(struct drm_i915_private *i915); int intel_color_init(struct drm_i915_private *i915); void intel_color_crtc_init(struct intel_crtc *crtc); int intel_color_check(struct intel_crtc_state *crtc_state); +void intel_color_prepare_commit(struct intel_crtc_state *crtc_state); +void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state); void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state); void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); void intel_color_load_luts(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6cdfdae2c712..e75b9b2a0e01 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -91,7 +91,6 @@ #include "intel_dp_link_training.h" #include "intel_dpio_phy.h" #include "intel_dpt.h" -#include "intel_dsb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" @@ -6929,7 +6928,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { if (intel_crtc_needs_color_update(crtc_state)) - intel_dsb_prepare(crtc_state); + intel_color_prepare_commit(crtc_state); } return 0; @@ -7380,24 +7379,18 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat &wait_reset); } -static void intel_cleanup_dsbs(struct intel_atomic_state *state) -{ - struct intel_crtc_state *old_crtc_state, *new_crtc_state; - struct intel_crtc *crtc; - int i; - - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) - intel_dsb_cleanup(old_crtc_state); -} - static void intel_atomic_cleanup_work(struct work_struct *work) { struct intel_atomic_state *state = container_of(work, struct intel_atomic_state, base.commit_work); struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *old_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) + intel_color_cleanup_commit(old_crtc_state); - intel_cleanup_dsbs(state); drm_atomic_helper_cleanup_planes(&i915->drm, &state->base); drm_atomic_helper_commit_cleanup_done(&state->base); drm_atomic_state_put(&state->base); @@ -7588,6 +7581,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * DSB cleanup is done in cleanup_work aligning with framebuffer * cleanup. So copy and reset the dsb structure to sync with * commit_done and later do dsb cleanup in cleanup_work. + * + * FIXME get rid of this funny new->old swapping */ old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb); } @@ -7738,7 +7733,7 @@ static int intel_atomic_commit(struct drm_device *dev, i915_sw_fence_commit(&state->commit_ready); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) - intel_dsb_cleanup(new_crtc_state); + intel_color_cleanup_commit(new_crtc_state); drm_atomic_helper_cleanup_planes(dev, &state->base); intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 714030136b7f..ef73730f32b0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -440,6 +440,14 @@ enum hpd_pin { (__i)++) \ for_each_if(plane) +#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->base.dev->mode_config.num_crtc && \ + ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ + (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \ + (__i)++) \ + for_each_if(crtc) + #define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ -- cgit v1.2.3 From b358c3b98813b1557588a11c894b22915251a2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:34 +0200 Subject: drm/i915: Make DSB lower level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We could have many different uses for the DSB(s) during a single commit, so the current approach of passing the whole crtc_state to the DSB functions is far too high level. Lower the abstraction a little bit so each DSB user can decide where to stick the command buffer/etc. v2: Document the intel_dsb_prepare() return value (Ankit) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-10-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 17 +++++-- drivers/gpu/drm/i915/display/intel_dsb.c | 82 ++++++++++++++---------------- drivers/gpu/drm/i915/display/intel_dsb.h | 13 ++--- 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 5a8652407f30..2715f1b617e1 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -842,7 +842,7 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state, struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); if (crtc_state->dsb) - intel_dsb_reg_write(crtc_state, reg, val); + intel_dsb_reg_write(crtc_state->dsb, reg, val); else intel_de_write_fw(i915, reg, val); } @@ -853,7 +853,7 @@ static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); if (crtc_state->dsb) - intel_dsb_indexed_reg_write(crtc_state, reg, val); + intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val); else intel_de_write_fw(i915, reg, val); } @@ -1273,7 +1273,8 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) break; } - intel_dsb_commit(crtc_state); + if (crtc_state->dsb) + intel_dsb_commit(crtc_state->dsb); } static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color) @@ -1391,12 +1392,18 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) { - intel_dsb_prepare(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + crtc_state->dsb = intel_dsb_prepare(crtc); } void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) { - intel_dsb_cleanup(crtc_state); + if (!crtc_state->dsb) + return; + + intel_dsb_cleanup(crtc_state->dsb); + crtc_state->dsb = NULL; } static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index b4f0356c2463..3d63c1bf1e4f 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -24,8 +24,10 @@ enum dsb_id { struct intel_dsb { enum dsb_id id; + u32 *cmd_buf; struct i915_vma *vma; + struct intel_crtc *crtc; /* * free_pos will point the first free entry position @@ -113,7 +115,7 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915, /** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. - * @crtc_state: intel_crtc_state structure + * @dsb: DSB context * @reg: register address. * @val: value. * @@ -123,11 +125,10 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915, * is done through mmio write. */ -void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_dsb *dsb = crtc_state->dsb; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *crtc = dsb->crtc; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 *buf = dsb->cmd_buf; u32 reg_val; @@ -195,12 +196,11 @@ void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, * and rest all erroneous condition register programming is done * through mmio write. */ -void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc *crtc = dsb->crtc; struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_dsb *dsb = crtc_state->dsb; u32 *buf = dsb->cmd_buf; if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { @@ -217,17 +217,14 @@ void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, /** * intel_dsb_commit() - Trigger workload execution of DSB. - * @crtc_state: intel_crtc_state structure + * @dsb: DSB context * * This function is used to do actual write to hardware using DSB. - * On errors, fall back to MMIO. Also this function help to reset the context. */ -void intel_dsb_commit(const struct intel_crtc_state *crtc_state) +void intel_dsb_commit(struct intel_dsb *dsb) { - struct intel_dsb *dsb = crtc_state->dsb; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = dsb->crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 tail; @@ -274,14 +271,16 @@ reset: /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. - * @crtc_state: intel_crtc_state structure to prepare associated dsb instance. + * @crtc: the CRTC * * This function prepare the command buffer which is used to store dsb * instructions with data. + * + * Returns: + * DSB context, NULL on failure */ -void intel_dsb_prepare(struct intel_crtc_state *crtc_state) +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_dsb *dsb; struct drm_i915_gem_object *obj; @@ -290,63 +289,60 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state) intel_wakeref_t wakeref; if (!HAS_DSB(i915)) - return; + return NULL; dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); - if (!dsb) { - drm_err(&i915->drm, "DSB object creation failed\n"); - return; - } + if (!dsb) + goto out; wakeref = intel_runtime_pm_get(&i915->runtime_pm); obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); - if (IS_ERR(obj)) { - kfree(dsb); - goto out; - } + if (IS_ERR(obj)) + goto out_put_rpm; vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { i915_gem_object_put(obj); - kfree(dsb); - goto out; + goto out_put_rpm; } buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC); if (IS_ERR(buf)) { i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); - kfree(dsb); - goto out; + goto out_put_rpm; } + intel_runtime_pm_put(&i915->runtime_pm, wakeref); + dsb->id = DSB1; dsb->vma = vma; + dsb->crtc = crtc; dsb->cmd_buf = buf; dsb->free_pos = 0; dsb->ins_start_offset = 0; - crtc_state->dsb = dsb; -out: - if (!crtc_state->dsb) - drm_info(&i915->drm, - "DSB queue setup failed, will fallback to MMIO for display HW programming\n"); + return dsb; + +out_put_rpm: intel_runtime_pm_put(&i915->runtime_pm, wakeref); + kfree(dsb); +out: + drm_info_once(&i915->drm, + "DSB queue setup failed, will fallback to MMIO for display HW programming\n"); + + return NULL; } /** * intel_dsb_cleanup() - To cleanup DSB context. - * @crtc_state: intel_crtc_state structure to cleanup associated dsb instance. + * @dsb: DSB context * * This function cleanup the DSB context by unpinning and releasing * the VMA object associated with it. */ -void intel_dsb_cleanup(struct intel_crtc_state *crtc_state) +void intel_dsb_cleanup(struct intel_dsb *dsb) { - if (!crtc_state->dsb) - return; - - i915_vma_unpin_and_release(&crtc_state->dsb->vma, I915_VMA_RELEASE_MAP); - kfree(crtc_state->dsb); - crtc_state->dsb = NULL; + i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); + kfree(dsb); } diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 74dd2b3343bb..25f13c4d5389 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -10,14 +10,15 @@ #include "i915_reg_defs.h" -struct intel_crtc_state; +struct intel_crtc; +struct intel_dsb; -void intel_dsb_prepare(struct intel_crtc_state *crtc_state); -void intel_dsb_cleanup(struct intel_crtc_state *crtc_state); -void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state, +struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); +void intel_dsb_cleanup(struct intel_dsb *dsb); +void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state, +void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_commit(const struct intel_crtc_state *crtc_state); +void intel_dsb_commit(struct intel_dsb *dsb); #endif -- cgit v1.2.3 From 2487ae0bcb53a7d4180c551c02b1f318ea590c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:35 +0200 Subject: drm/i915: Disable DSB usage specifically for LUTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DSB has problem loading the LUTs at the moment. Some of that is due to the palette anti collision logic, some due to what seem real hw issues. Disable it the whole thing locally in the color management code for now. Note that we currently have this weird situation where on adl+ we load parts of the LUT with DSB and parts with mmio. That is due to the fact that only some parts of the LUT code are using the DSB register write functions (ivb_load_lut_ext*()), while the rest is using pure mmio (bdw_load_lut_10()). So now we'll go back to pure mmio temporarily, until the DSB issues get fixed (at which point we should be going for pure DSB). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-11-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 2715f1b617e1..9978d21f1634 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1394,6 +1394,9 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + /* FIXME DSB has issues loading LUTs, disable it for now */ + return; + crtc_state->dsb = intel_dsb_prepare(crtc); } -- cgit v1.2.3 From 048ed577a327143f5bdb30299bffdafc0a6a34bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:36 +0200 Subject: Revert "drm/i915: Disable DSB usage for now" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 99510e1afb4863a225207146bd988064c5fd0629. DSB is now getting disabled locally in the color management code so we don't need to apply this big hammer via the device info (not that we have other DSB users at the moment). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-12-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/i915_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 161e9ad47cbe..6fc4711ea632 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -889,7 +889,7 @@ static const struct intel_device_info jsl_info = { TGL_CURSOR_OFFSETS, \ .has_global_mocs = 1, \ .has_pxp = 1, \ - .display.has_dsb = 0 /* FIXME: LUT load is broken with DSB */ + .display.has_dsb = 1 static const struct intel_device_info tgl_info = { GEN12_FEATURES, -- cgit v1.2.3 From aeb0351e825a2f8eaaabb89f7012ee099fc306a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Nov 2022 17:26:37 +0200 Subject: drm/i915: Use ilk_lut_write*() for all ilk+ gamma modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We could use the dsb to load the LUT in any gamma mode, not just when using the multi-segment mode. So replace the direct mmio on all ilk+ paths with the wrapper. There are a few functions (ilk_load_lut_10(), ivb_load_lut_10()) that would never be used on a platform with dsb so we could skip those, but probably better to keep all this 100% consistent to avoid people getting confused and copy pasting the wrong thing when adding a new gamma mode. The gmch stuff I left with direct mmio since those are fairly distinct and shouldn't cause too much confusion. Although I've also pondered about converting everything over to dsb command buffers and just executing it on the CPU when the real hw is not available. But dunno if that would actually be a good idea or not... Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123152638.20622-13-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_color.c | 106 ++++++++++++++--------------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 9978d21f1634..d57631b0bb9a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -858,10 +858,10 @@ static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, intel_de_write_fw(i915, reg, val); } -static void ilk_load_lut_8(struct intel_crtc *crtc, +static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut; enum pipe pipe = crtc->pipe; int i; @@ -872,36 +872,35 @@ static void ilk_load_lut_8(struct intel_crtc *crtc, lut = blob->data; for (i = 0; i < 256; i++) - intel_de_write_fw(i915, LGC_PALETTE(pipe, i), - i9xx_lut_8(&lut[i])); + ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i), + i9xx_lut_8(&lut[i])); } -static void ilk_load_lut_10(struct intel_crtc *crtc, +static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) - intel_de_write_fw(i915, PREC_PALETTE(pipe, i), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PALETTE(pipe, i), + ilk_lut_10(&lut[i])); } static void ilk_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_10BIT: - ilk_load_lut_10(crtc, blob); + ilk_load_lut_10(crtc_state, blob); break; default: MISSING_CASE(crtc_state->gamma_mode); @@ -922,56 +921,56 @@ static int ivb_lut_10_size(u32 prec_index) * "Restriction : Index auto increment mode is not * supported and must not be enabled." */ -static void ivb_load_lut_10(struct intel_crtc *crtc, +static void ivb_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; for (i = 0; i < lut_size; i++) { - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index + i); - intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + prec_index + i); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); } /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } /* On BDW+ the index auto increment mode actually works */ -static void bdw_load_lut_10(struct intel_crtc *crtc, +static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob, u32 prec_index) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_color_lut *lut = blob->data; int i, lut_size = drm_color_lut_size(blob); enum pipe pipe = crtc->pipe; - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - prec_index); - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - PAL_PREC_AUTO_INCREMENT | - prec_index); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + prec_index); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_AUTO_INCREMENT | + prec_index); for (i = 0; i < lut_size; i++) - intel_de_write_fw(i915, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be * written properly. */ - intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), - PAL_PREC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), + PAL_PREC_INDEX_VALUE(0)); } static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state) @@ -998,24 +997,23 @@ static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state) static void ivb_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_SPLIT: - ivb_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc_state, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - ivb_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | + ivb_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: - ivb_load_lut_10(crtc, blob, + ivb_load_lut_10(crtc_state, blob, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; @@ -1027,25 +1025,23 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) static void bdw_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut; switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, blob); + ilk_load_lut_8(crtc_state, blob); break; case GAMMA_MODE_MODE_SPLIT: - bdw_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc_state, pre_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE | + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_SPLIT_MODE | PAL_PREC_INDEX_VALUE(512)); break; case GAMMA_MODE_MODE_10BIT: - - bdw_load_lut_10(crtc, blob, + bdw_load_lut_10(crtc_state, blob, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); break; @@ -1077,11 +1073,11 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ignore the index bits, so we need to reset it to index 0 * separately. */ - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_INDEX_VALUE(0)); - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), - PRE_CSC_GAMC_AUTO_INCREMENT | - PRE_CSC_GAMC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_INDEX_VALUE(0)); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT | + PRE_CSC_GAMC_INDEX_VALUE(0)); for (i = 0; i < lut_size; i++) { /* @@ -1097,32 +1093,31 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < glk_degamma_lut_size(i915)) - intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); - intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } static void glk_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (pre_csc_lut) glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, post_csc_lut); + ilk_load_lut_8(crtc_state, post_csc_lut); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); glk_load_lut_ext2_max(crtc_state); break; @@ -1248,14 +1243,13 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (pre_csc_lut) glk_load_degamma_lut(crtc_state, pre_csc_lut); switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { case GAMMA_MODE_MODE_8BIT: - ilk_load_lut_8(crtc, post_csc_lut); + ilk_load_lut_8(crtc_state, post_csc_lut); break; case GAMMA_MODE_MODE_12BIT_MULTI_SEG: icl_program_gamma_superfine_segment(crtc_state); @@ -1264,7 +1258,7 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state) glk_load_lut_ext2_max(crtc_state); break; case GAMMA_MODE_MODE_10BIT: - bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); + bdw_load_lut_10(crtc_state, post_csc_lut, PAL_PREC_INDEX_VALUE(0)); ivb_load_lut_ext_max(crtc_state); glk_load_lut_ext2_max(crtc_state); break; -- cgit v1.2.3 From f052febd24f1117de0929c141d9ee63941720cf9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 8 Dec 2022 16:23:47 +0200 Subject: drm/i915: add new "soc" sub-directory and move PCH and DRAM code there MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new sub-directory for things that aren't specifically about the GPU and don't really belong in the i915 driver top level, but also don't belong under any of the existing sub-directories either. Name it "soc", and move the PCH and DRAM code there. Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Ville Syrjälä Acked-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221208142347.602726-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/Makefile | 7 +- drivers/gpu/drm/i915/i915_driver.c | 3 +- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_dram.c | 572 ---------------------------------- drivers/gpu/drm/i915/intel_dram.h | 14 - drivers/gpu/drm/i915/intel_pch.c | 279 ----------------- drivers/gpu/drm/i915/intel_pch.h | 91 ------ drivers/gpu/drm/i915/soc/intel_dram.c | 572 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/soc/intel_dram.h | 14 + drivers/gpu/drm/i915/soc/intel_pch.c | 279 +++++++++++++++++ drivers/gpu/drm/i915/soc/intel_pch.h | 91 ++++++ 11 files changed, 965 insertions(+), 960 deletions(-) delete mode 100644 drivers/gpu/drm/i915/intel_dram.c delete mode 100644 drivers/gpu/drm/i915/intel_dram.h delete mode 100644 drivers/gpu/drm/i915/intel_pch.c delete mode 100644 drivers/gpu/drm/i915/intel_pch.h create mode 100644 drivers/gpu/drm/i915/soc/intel_dram.c create mode 100644 drivers/gpu/drm/i915/soc/intel_dram.h create mode 100644 drivers/gpu/drm/i915/soc/intel_pch.c create mode 100644 drivers/gpu/drm/i915/soc/intel_pch.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index cb8232bd315b..0ed5985c03b5 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -48,9 +48,7 @@ i915-y += i915_driver.o \ i915_sysfs.o \ i915_utils.o \ intel_device_info.o \ - intel_dram.o \ intel_memory_region.o \ - intel_pch.o \ intel_pcode.o \ intel_pm.o \ intel_region_ttm.o \ @@ -62,6 +60,11 @@ i915-y += i915_driver.o \ vlv_sideband.o \ vlv_suspend.o +# core peripheral code +i915-y += \ + soc/intel_dram.o \ + soc/intel_pch.o + # core library code i915-y += \ i915_memcpy.o \ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c3d43f9b1e45..9ceea52ad9db 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -75,6 +75,8 @@ #include "pxp/intel_pxp_pm.h" +#include "soc/intel_dram.h" + #include "i915_file_private.h" #include "i915_debugfs.h" #include "i915_driver.h" @@ -93,7 +95,6 @@ #include "i915_sysfs.h" #include "i915_utils.h" #include "i915_vgpu.h" -#include "intel_dram.h" #include "intel_gvt.h" #include "intel_memory_region.h" #include "intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5d2c54456cc1..05b84196216c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -49,6 +49,8 @@ #include "gt/intel_workarounds.h" #include "gt/uc/intel_uc.h" +#include "soc/intel_pch.h" + #include "i915_drm_client.h" #include "i915_gem.h" #include "i915_gpu_error.h" @@ -58,7 +60,6 @@ #include "i915_utils.h" #include "intel_device_info.h" #include "intel_memory_region.h" -#include "intel_pch.h" #include "intel_runtime_pm.h" #include "intel_step.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/i915/intel_dram.c b/drivers/gpu/drm/i915/intel_dram.c deleted file mode 100644 index bba8cb6e8ae4..000000000000 --- a/drivers/gpu/drm/i915/intel_dram.c +++ /dev/null @@ -1,572 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2020 Intel Corporation - */ - -#include - -#include "i915_drv.h" -#include "i915_reg.h" -#include "intel_dram.h" -#include "intel_mchbar_regs.h" -#include "intel_pcode.h" - -struct dram_dimm_info { - u16 size; - u8 width, ranks; -}; - -struct dram_channel_info { - struct dram_dimm_info dimm_l, dimm_s; - u8 ranks; - bool is_16gb_dimm; -}; - -#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type - -static const char *intel_dram_type_str(enum intel_dram_type type) -{ - static const char * const str[] = { - DRAM_TYPE_STR(UNKNOWN), - DRAM_TYPE_STR(DDR3), - DRAM_TYPE_STR(DDR4), - DRAM_TYPE_STR(LPDDR3), - DRAM_TYPE_STR(LPDDR4), - }; - - if (type >= ARRAY_SIZE(str)) - type = INTEL_DRAM_UNKNOWN; - - return str[type]; -} - -#undef DRAM_TYPE_STR - -static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) -{ - return dimm->ranks * 64 / (dimm->width ?: 1); -} - -/* Returns total Gb for the whole DIMM */ -static int skl_get_dimm_size(u16 val) -{ - return (val & SKL_DRAM_SIZE_MASK) * 8; -} - -static int skl_get_dimm_width(u16 val) -{ - if (skl_get_dimm_size(val) == 0) - return 0; - - switch (val & SKL_DRAM_WIDTH_MASK) { - case SKL_DRAM_WIDTH_X8: - case SKL_DRAM_WIDTH_X16: - case SKL_DRAM_WIDTH_X32: - val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; - return 8 << val; - default: - MISSING_CASE(val); - return 0; - } -} - -static int skl_get_dimm_ranks(u16 val) -{ - if (skl_get_dimm_size(val) == 0) - return 0; - - val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT; - - return val + 1; -} - -/* Returns total Gb for the whole DIMM */ -static int icl_get_dimm_size(u16 val) -{ - return (val & ICL_DRAM_SIZE_MASK) * 8 / 2; -} - -static int icl_get_dimm_width(u16 val) -{ - if (icl_get_dimm_size(val) == 0) - return 0; - - switch (val & ICL_DRAM_WIDTH_MASK) { - case ICL_DRAM_WIDTH_X8: - case ICL_DRAM_WIDTH_X16: - case ICL_DRAM_WIDTH_X32: - val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT; - return 8 << val; - default: - MISSING_CASE(val); - return 0; - } -} - -static int icl_get_dimm_ranks(u16 val) -{ - if (icl_get_dimm_size(val) == 0) - return 0; - - val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT; - - return val + 1; -} - -static bool -skl_is_16gb_dimm(const struct dram_dimm_info *dimm) -{ - /* Convert total Gb to Gb per DRAM device */ - return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) == 16; -} - -static void -skl_dram_get_dimm_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, char dimm_name, u16 val) -{ - if (GRAPHICS_VER(i915) >= 11) { - dimm->size = icl_get_dimm_size(val); - dimm->width = icl_get_dimm_width(val); - dimm->ranks = icl_get_dimm_ranks(val); - } else { - dimm->size = skl_get_dimm_size(val); - dimm->width = skl_get_dimm_width(val); - dimm->ranks = skl_get_dimm_ranks(val); - } - - drm_dbg_kms(&i915->drm, - "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n", - channel, dimm_name, dimm->size, dimm->width, dimm->ranks, - str_yes_no(skl_is_16gb_dimm(dimm))); -} - -static int -skl_dram_get_channel_info(struct drm_i915_private *i915, - struct dram_channel_info *ch, - int channel, u32 val) -{ - skl_dram_get_dimm_info(i915, &ch->dimm_l, - channel, 'L', val & 0xffff); - skl_dram_get_dimm_info(i915, &ch->dimm_s, - channel, 'S', val >> 16); - - if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { - drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); - return -EINVAL; - } - - if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2) - ch->ranks = 2; - else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1) - ch->ranks = 2; - else - ch->ranks = 1; - - ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || - skl_is_16gb_dimm(&ch->dimm_s); - - drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n", - channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); - - return 0; -} - -static bool -intel_is_dram_symmetric(const struct dram_channel_info *ch0, - const struct dram_channel_info *ch1) -{ - return !memcmp(ch0, ch1, sizeof(*ch0)) && - (ch0->dimm_s.size == 0 || - !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l))); -} - -static int -skl_dram_get_channels_info(struct drm_i915_private *i915) -{ - struct dram_info *dram_info = &i915->dram_info; - struct dram_channel_info ch0 = {}, ch1 = {}; - u32 val; - int ret; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch0, 0, val); - if (ret == 0) - dram_info->num_channels++; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch1, 1, val); - if (ret == 0) - dram_info->num_channels++; - - if (dram_info->num_channels == 0) { - drm_info(&i915->drm, "Number of memory channels is zero\n"); - return -EINVAL; - } - - if (ch0.ranks == 0 && ch1.ranks == 0) { - drm_info(&i915->drm, "couldn't get memory rank information\n"); - return -EINVAL; - } - - dram_info->wm_lv_0_adjust_needed = ch0.is_16gb_dimm || ch1.is_16gb_dimm; - - dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); - - drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", - str_yes_no(dram_info->symmetric_memory)); - - return 0; -} - -static enum intel_dram_type -skl_get_dram_type(struct drm_i915_private *i915) -{ - u32 val; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); - - switch (val & SKL_DRAM_DDR_TYPE_MASK) { - case SKL_DRAM_DDR_TYPE_DDR3: - return INTEL_DRAM_DDR3; - case SKL_DRAM_DDR_TYPE_DDR4: - return INTEL_DRAM_DDR4; - case SKL_DRAM_DDR_TYPE_LPDDR3: - return INTEL_DRAM_LPDDR3; - case SKL_DRAM_DDR_TYPE_LPDDR4: - return INTEL_DRAM_LPDDR4; - default: - MISSING_CASE(val); - return INTEL_DRAM_UNKNOWN; - } -} - -static int -skl_get_dram_info(struct drm_i915_private *i915) -{ - struct dram_info *dram_info = &i915->dram_info; - int ret; - - dram_info->type = skl_get_dram_type(i915); - drm_dbg_kms(&i915->drm, "DRAM type: %s\n", - intel_dram_type_str(dram_info->type)); - - ret = skl_dram_get_channels_info(i915); - if (ret) - return ret; - - return 0; -} - -/* Returns Gb per DRAM device */ -static int bxt_get_dimm_size(u32 val) -{ - switch (val & BXT_DRAM_SIZE_MASK) { - case BXT_DRAM_SIZE_4GBIT: - return 4; - case BXT_DRAM_SIZE_6GBIT: - return 6; - case BXT_DRAM_SIZE_8GBIT: - return 8; - case BXT_DRAM_SIZE_12GBIT: - return 12; - case BXT_DRAM_SIZE_16GBIT: - return 16; - default: - MISSING_CASE(val); - return 0; - } -} - -static int bxt_get_dimm_width(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return 0; - - val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT; - - return 8 << val; -} - -static int bxt_get_dimm_ranks(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return 0; - - switch (val & BXT_DRAM_RANK_MASK) { - case BXT_DRAM_RANK_SINGLE: - return 1; - case BXT_DRAM_RANK_DUAL: - return 2; - default: - MISSING_CASE(val); - return 0; - } -} - -static enum intel_dram_type bxt_get_dimm_type(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return INTEL_DRAM_UNKNOWN; - - switch (val & BXT_DRAM_TYPE_MASK) { - case BXT_DRAM_TYPE_DDR3: - return INTEL_DRAM_DDR3; - case BXT_DRAM_TYPE_LPDDR3: - return INTEL_DRAM_LPDDR3; - case BXT_DRAM_TYPE_DDR4: - return INTEL_DRAM_DDR4; - case BXT_DRAM_TYPE_LPDDR4: - return INTEL_DRAM_LPDDR4; - default: - MISSING_CASE(val); - return INTEL_DRAM_UNKNOWN; - } -} - -static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) -{ - dimm->width = bxt_get_dimm_width(val); - dimm->ranks = bxt_get_dimm_ranks(val); - - /* - * Size in register is Gb per DRAM device. Convert to total - * Gb to match the way we report this for non-LP platforms. - */ - dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); -} - -static int bxt_get_dram_info(struct drm_i915_private *i915) -{ - struct dram_info *dram_info = &i915->dram_info; - u32 val; - u8 valid_ranks = 0; - int i; - - /* - * Now read each DUNIT8/9/10/11 to check the rank of each dimms. - */ - for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { - struct dram_dimm_info dimm; - enum intel_dram_type type; - - val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i)); - if (val == 0xFFFFFFFF) - continue; - - dram_info->num_channels++; - - bxt_get_dimm_info(&dimm, val); - type = bxt_get_dimm_type(val); - - drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && - dram_info->type != INTEL_DRAM_UNKNOWN && - dram_info->type != type); - - drm_dbg_kms(&i915->drm, - "CH%u DIMM size: %u Gb, width: X%u, ranks: %u, type: %s\n", - i - BXT_D_CR_DRP0_DUNIT_START, - dimm.size, dimm.width, dimm.ranks, - intel_dram_type_str(type)); - - if (valid_ranks == 0) - valid_ranks = dimm.ranks; - - if (type != INTEL_DRAM_UNKNOWN) - dram_info->type = type; - } - - if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { - drm_info(&i915->drm, "couldn't get memory information\n"); - return -EINVAL; - } - - return 0; -} - -static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv) -{ - struct dram_info *dram_info = &dev_priv->dram_info; - u32 val = 0; - int ret; - - ret = snb_pcode_read(&dev_priv->uncore, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | - ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); - if (ret) - return ret; - - if (GRAPHICS_VER(dev_priv) == 12) { - switch (val & 0xf) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR5; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR5; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - case 4: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 5: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - default: - MISSING_CASE(val & 0xf); - return -EINVAL; - } - } else { - switch (val & 0xf) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - default: - MISSING_CASE(val & 0xf); - return -EINVAL; - } - } - - dram_info->num_channels = (val & 0xf0) >> 4; - dram_info->num_qgv_points = (val & 0xf00) >> 8; - dram_info->num_psf_gv_points = (val & 0x3000) >> 12; - - return 0; -} - -static int gen11_get_dram_info(struct drm_i915_private *i915) -{ - int ret = skl_get_dram_info(i915); - - if (ret) - return ret; - - return icl_pcode_read_mem_global_info(i915); -} - -static int gen12_get_dram_info(struct drm_i915_private *i915) -{ - i915->dram_info.wm_lv_0_adjust_needed = false; - - return icl_pcode_read_mem_global_info(i915); -} - -static int xelpdp_get_dram_info(struct drm_i915_private *i915) -{ - u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); - struct dram_info *dram_info = &i915->dram_info; - - switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR5; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR5; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - case 4: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 5: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - default: - MISSING_CASE(val); - return -EINVAL; - } - - dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val); - dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val); - /* PSF GV points not supported in D14+ */ - - return 0; -} - -void intel_dram_detect(struct drm_i915_private *i915) -{ - struct dram_info *dram_info = &i915->dram_info; - int ret; - - if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) - return; - - /* - * Assume level 0 watermark latency adjustment is needed until proven - * otherwise, this w/a is not needed by bxt/glk. - */ - dram_info->wm_lv_0_adjust_needed = !IS_GEN9_LP(i915); - - if (DISPLAY_VER(i915) >= 14) - ret = xelpdp_get_dram_info(i915); - else if (GRAPHICS_VER(i915) >= 12) - ret = gen12_get_dram_info(i915); - else if (GRAPHICS_VER(i915) >= 11) - ret = gen11_get_dram_info(i915); - else if (IS_GEN9_LP(i915)) - ret = bxt_get_dram_info(i915); - else - ret = skl_get_dram_info(i915); - if (ret) - return; - - drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); - - drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n", - str_yes_no(dram_info->wm_lv_0_adjust_needed)); -} - -static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) -{ - static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; - static const u8 sets[4] = { 1, 1, 2, 2 }; - - return EDRAM_NUM_BANKS(cap) * - ways[EDRAM_WAYS_IDX(cap)] * - sets[EDRAM_SETS_IDX(cap)]; -} - -void intel_dram_edram_detect(struct drm_i915_private *i915) -{ - u32 edram_cap = 0; - - if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) - return; - - edram_cap = __raw_uncore_read32(&i915->uncore, HSW_EDRAM_CAP); - - /* NB: We can't write IDICR yet because we don't have gt funcs set up */ - - if (!(edram_cap & EDRAM_ENABLED)) - return; - - /* - * The needed capability bits for size calculation are not there with - * pre gen9 so return 128MB always. - */ - if (GRAPHICS_VER(i915) < 9) - i915->edram_size_mb = 128; - else - i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); - - drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); -} diff --git a/drivers/gpu/drm/i915/intel_dram.h b/drivers/gpu/drm/i915/intel_dram.h deleted file mode 100644 index 4ba13c13162c..000000000000 --- a/drivers/gpu/drm/i915/intel_dram.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2020 Intel Corporation - */ - -#ifndef __INTEL_DRAM_H__ -#define __INTEL_DRAM_H__ - -struct drm_i915_private; - -void intel_dram_edram_detect(struct drm_i915_private *i915); -void intel_dram_detect(struct drm_i915_private *i915); - -#endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c deleted file mode 100644 index ba9843cb1b13..000000000000 --- a/drivers/gpu/drm/i915/intel_pch.c +++ /dev/null @@ -1,279 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright 2019 Intel Corporation. - */ - -#include "i915_drv.h" -#include "i915_utils.h" -#include "intel_pch.h" - -/* Map PCH device id to PCH type, or PCH_NONE if unknown. */ -static enum intel_pch -intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) -{ - switch (id) { - case INTEL_PCH_IBX_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n"); - drm_WARN_ON(&dev_priv->drm, GRAPHICS_VER(dev_priv) != 5); - return PCH_IBX; - case INTEL_PCH_CPT_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n"); - drm_WARN_ON(&dev_priv->drm, - GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv)); - return PCH_CPT; - case INTEL_PCH_PPT_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n"); - drm_WARN_ON(&dev_priv->drm, - GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv)); - /* PPT is CPT compatible */ - return PCH_CPT; - case INTEL_PCH_LPT_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); - drm_WARN_ON(&dev_priv->drm, - IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); - return PCH_LPT; - case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); - drm_WARN_ON(&dev_priv->drm, - !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); - return PCH_LPT; - case INTEL_PCH_WPT_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); - drm_WARN_ON(&dev_priv->drm, - IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); - /* WPT is LPT compatible */ - return PCH_LPT; - case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); - drm_WARN_ON(&dev_priv->drm, - !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); - /* WPT is LPT compatible */ - return PCH_LPT; - case INTEL_PCH_SPT_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); - return PCH_SPT; - case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv)); - return PCH_SPT; - case INTEL_PCH_KBP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv)); - /* KBP is SPT compatible */ - return PCH_SPT; - case INTEL_PCH_CNP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv)); - return PCH_CNP; - case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, - "Found Cannon Lake LP PCH (CNP-LP)\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv)); - return PCH_CNP; - case INTEL_PCH_CMP_DEVICE_ID_TYPE: - case INTEL_PCH_CMP2_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv) && - !IS_ROCKETLAKE(dev_priv)); - /* CMP is CNP compatible */ - return PCH_CNP; - case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n"); - drm_WARN_ON(&dev_priv->drm, - !IS_COFFEELAKE(dev_priv) && - !IS_COMETLAKE(dev_priv)); - /* CMP-V is based on KBP, which is SPT compatible */ - return PCH_SPT; - case INTEL_PCH_ICP_DEVICE_ID_TYPE: - case INTEL_PCH_ICP2_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); - return PCH_ICP; - case INTEL_PCH_MCC_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); - /* MCC is TGP compatible */ - return PCH_TGP; - case INTEL_PCH_TGP_DEVICE_ID_TYPE: - case INTEL_PCH_TGP2_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) && - !IS_ROCKETLAKE(dev_priv) && - !IS_GEN9_BC(dev_priv)); - return PCH_TGP; - case INTEL_PCH_JSP_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); - /* JSP is ICP compatible */ - return PCH_ICP; - case INTEL_PCH_ADP_DEVICE_ID_TYPE: - case INTEL_PCH_ADP2_DEVICE_ID_TYPE: - case INTEL_PCH_ADP3_DEVICE_ID_TYPE: - case INTEL_PCH_ADP4_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Alder Lake PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) && - !IS_ALDERLAKE_P(dev_priv)); - return PCH_ADP; - case INTEL_PCH_MTP_DEVICE_ID_TYPE: - case INTEL_PCH_MTP2_DEVICE_ID_TYPE: - drm_dbg_kms(&dev_priv->drm, "Found Meteor Lake PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_METEORLAKE(dev_priv)); - return PCH_MTP; - default: - return PCH_NONE; - } -} - -static bool intel_is_virt_pch(unsigned short id, - unsigned short svendor, unsigned short sdevice) -{ - return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || - id == INTEL_PCH_P3X_DEVICE_ID_TYPE || - (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && - svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && - sdevice == PCI_SUBDEVICE_ID_QEMU)); -} - -static void -intel_virt_detect_pch(const struct drm_i915_private *dev_priv, - unsigned short *pch_id, enum intel_pch *pch_type) -{ - unsigned short id = 0; - - /* - * In a virtualized passthrough environment we can be in a - * setup where the ISA bridge is not able to be passed through. - * In this case, a south bridge can be emulated and we have to - * make an educated guess as to which PCH is really there. - */ - - if (IS_METEORLAKE(dev_priv)) - id = INTEL_PCH_MTP_DEVICE_ID_TYPE; - else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) - id = INTEL_PCH_ADP_DEVICE_ID_TYPE; - else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) - id = INTEL_PCH_TGP_DEVICE_ID_TYPE; - else if (IS_JSL_EHL(dev_priv)) - id = INTEL_PCH_MCC_DEVICE_ID_TYPE; - else if (IS_ICELAKE(dev_priv)) - id = INTEL_PCH_ICP_DEVICE_ID_TYPE; - else if (IS_COFFEELAKE(dev_priv) || - IS_COMETLAKE(dev_priv)) - id = INTEL_PCH_CNP_DEVICE_ID_TYPE; - else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv)) - id = INTEL_PCH_SPT_DEVICE_ID_TYPE; - else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) - id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; - else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) - id = INTEL_PCH_LPT_DEVICE_ID_TYPE; - else if (GRAPHICS_VER(dev_priv) == 6 || IS_IVYBRIDGE(dev_priv)) - id = INTEL_PCH_CPT_DEVICE_ID_TYPE; - else if (GRAPHICS_VER(dev_priv) == 5) - id = INTEL_PCH_IBX_DEVICE_ID_TYPE; - - if (id) - drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id); - else - drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n"); - - *pch_type = intel_pch_type(dev_priv, id); - - /* Sanity check virtual PCH id */ - if (drm_WARN_ON(&dev_priv->drm, - id && *pch_type == PCH_NONE)) - id = 0; - - *pch_id = id; -} - -void intel_detect_pch(struct drm_i915_private *dev_priv) -{ - struct pci_dev *pch = NULL; - unsigned short id; - enum intel_pch pch_type; - - /* DG1 has south engine display on the same PCI device */ - if (IS_DG1(dev_priv)) { - dev_priv->pch_type = PCH_DG1; - return; - } else if (IS_DG2(dev_priv)) { - dev_priv->pch_type = PCH_DG2; - return; - } - - /* - * The reason to probe ISA bridge instead of Dev31:Fun0 is to - * make graphics device passthrough work easy for VMM, that only - * need to expose ISA bridge to let driver know the real hardware - * underneath. This is a requirement from virtualization team. - * - * In some virtualized environments (e.g. XEN), there is irrelevant - * ISA bridge in the system. To work reliably, we should scan trhough - * all the ISA bridge devices and check for the first match, instead - * of only checking the first one. - */ - while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { - if (pch->vendor != PCI_VENDOR_ID_INTEL) - continue; - - id = pch->device & INTEL_PCH_DEVICE_ID_MASK; - - pch_type = intel_pch_type(dev_priv, id); - if (pch_type != PCH_NONE) { - dev_priv->pch_type = pch_type; - dev_priv->pch_id = id; - break; - } else if (intel_is_virt_pch(id, pch->subsystem_vendor, - pch->subsystem_device)) { - intel_virt_detect_pch(dev_priv, &id, &pch_type); - dev_priv->pch_type = pch_type; - dev_priv->pch_id = id; - break; - } - } - - /* - * Use PCH_NOP (PCH but no South Display) for PCH platforms without - * display. - */ - if (pch && !HAS_DISPLAY(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "Display disabled, reverting to NOP PCH\n"); - dev_priv->pch_type = PCH_NOP; - dev_priv->pch_id = 0; - } else if (!pch) { - if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) { - intel_virt_detect_pch(dev_priv, &id, &pch_type); - dev_priv->pch_type = pch_type; - dev_priv->pch_id = id; - } else { - drm_dbg_kms(&dev_priv->drm, "No PCH found.\n"); - } - } - - pci_dev_put(pch); -} diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h deleted file mode 100644 index 32aff5a70d04..000000000000 --- a/drivers/gpu/drm/i915/intel_pch.h +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2019 Intel Corporation. - */ - -#ifndef __INTEL_PCH__ -#define __INTEL_PCH__ - -struct drm_i915_private; - -/* - * Sorted by south display engine compatibility. - * If the new PCH comes with a south display engine that is not - * inherited from the latest item, please do not add it to the - * end. Instead, add it right after its "parent" PCH. - */ -enum intel_pch { - PCH_NOP = -1, /* PCH without south display */ - PCH_NONE = 0, /* No PCH present */ - PCH_IBX, /* Ibexpeak PCH */ - PCH_CPT, /* Cougarpoint/Pantherpoint PCH */ - PCH_LPT, /* Lynxpoint/Wildcatpoint PCH */ - PCH_SPT, /* Sunrisepoint/Kaby Lake PCH */ - PCH_CNP, /* Cannon/Comet Lake PCH */ - PCH_ICP, /* Ice Lake/Jasper Lake PCH */ - PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */ - PCH_ADP, /* Alder Lake PCH */ - PCH_MTP, /* Meteor Lake PCH */ - - /* Fake PCHs, functionality handled on the same PCI dev */ - PCH_DG1 = 1024, - PCH_DG2, -}; - -#define INTEL_PCH_DEVICE_ID_MASK 0xff80 -#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 -#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 -#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00 -#define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00 -#define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00 -#define INTEL_PCH_WPT_DEVICE_ID_TYPE 0x8c80 -#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE 0x9c80 -#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100 -#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 -#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280 -#define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300 -#define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80 -#define INTEL_PCH_CMP_DEVICE_ID_TYPE 0x0280 -#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 -#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 -#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 -#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 -#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 -#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 -#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 -#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 -#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 -#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 -#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 -#define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480 -#define INTEL_PCH_MTP_DEVICE_ID_TYPE 0x7E00 -#define INTEL_PCH_MTP2_DEVICE_ID_TYPE 0xAE00 -#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 -#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 -#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ - -#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) -#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id) -#define HAS_PCH_MTP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_MTP) -#define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2) -#define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP) -#define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1) -#define HAS_PCH_TGP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_TGP) -#define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP) -#define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP) -#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) -#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) -#define HAS_PCH_LPT_LP(dev_priv) \ - (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ - INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) -#define HAS_PCH_LPT_H(dev_priv) \ - (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ - INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_DEVICE_ID_TYPE) -#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) -#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) -#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) -#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE) - -void intel_detect_pch(struct drm_i915_private *dev_priv); - -#endif /* __INTEL_PCH__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c new file mode 100644 index 000000000000..bba8cb6e8ae4 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ + +#include + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_dram.h" +#include "intel_mchbar_regs.h" +#include "intel_pcode.h" + +struct dram_dimm_info { + u16 size; + u8 width, ranks; +}; + +struct dram_channel_info { + struct dram_dimm_info dimm_l, dimm_s; + u8 ranks; + bool is_16gb_dimm; +}; + +#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type + +static const char *intel_dram_type_str(enum intel_dram_type type) +{ + static const char * const str[] = { + DRAM_TYPE_STR(UNKNOWN), + DRAM_TYPE_STR(DDR3), + DRAM_TYPE_STR(DDR4), + DRAM_TYPE_STR(LPDDR3), + DRAM_TYPE_STR(LPDDR4), + }; + + if (type >= ARRAY_SIZE(str)) + type = INTEL_DRAM_UNKNOWN; + + return str[type]; +} + +#undef DRAM_TYPE_STR + +static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) +{ + return dimm->ranks * 64 / (dimm->width ?: 1); +} + +/* Returns total Gb for the whole DIMM */ +static int skl_get_dimm_size(u16 val) +{ + return (val & SKL_DRAM_SIZE_MASK) * 8; +} + +static int skl_get_dimm_width(u16 val) +{ + if (skl_get_dimm_size(val) == 0) + return 0; + + switch (val & SKL_DRAM_WIDTH_MASK) { + case SKL_DRAM_WIDTH_X8: + case SKL_DRAM_WIDTH_X16: + case SKL_DRAM_WIDTH_X32: + val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; + return 8 << val; + default: + MISSING_CASE(val); + return 0; + } +} + +static int skl_get_dimm_ranks(u16 val) +{ + if (skl_get_dimm_size(val) == 0) + return 0; + + val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT; + + return val + 1; +} + +/* Returns total Gb for the whole DIMM */ +static int icl_get_dimm_size(u16 val) +{ + return (val & ICL_DRAM_SIZE_MASK) * 8 / 2; +} + +static int icl_get_dimm_width(u16 val) +{ + if (icl_get_dimm_size(val) == 0) + return 0; + + switch (val & ICL_DRAM_WIDTH_MASK) { + case ICL_DRAM_WIDTH_X8: + case ICL_DRAM_WIDTH_X16: + case ICL_DRAM_WIDTH_X32: + val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT; + return 8 << val; + default: + MISSING_CASE(val); + return 0; + } +} + +static int icl_get_dimm_ranks(u16 val) +{ + if (icl_get_dimm_size(val) == 0) + return 0; + + val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT; + + return val + 1; +} + +static bool +skl_is_16gb_dimm(const struct dram_dimm_info *dimm) +{ + /* Convert total Gb to Gb per DRAM device */ + return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) == 16; +} + +static void +skl_dram_get_dimm_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, char dimm_name, u16 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_size(val); + dimm->width = icl_get_dimm_width(val); + dimm->ranks = icl_get_dimm_ranks(val); + } else { + dimm->size = skl_get_dimm_size(val); + dimm->width = skl_get_dimm_width(val); + dimm->ranks = skl_get_dimm_ranks(val); + } + + drm_dbg_kms(&i915->drm, + "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n", + channel, dimm_name, dimm->size, dimm->width, dimm->ranks, + str_yes_no(skl_is_16gb_dimm(dimm))); +} + +static int +skl_dram_get_channel_info(struct drm_i915_private *i915, + struct dram_channel_info *ch, + int channel, u32 val) +{ + skl_dram_get_dimm_info(i915, &ch->dimm_l, + channel, 'L', val & 0xffff); + skl_dram_get_dimm_info(i915, &ch->dimm_s, + channel, 'S', val >> 16); + + if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { + drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); + return -EINVAL; + } + + if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2) + ch->ranks = 2; + else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1) + ch->ranks = 2; + else + ch->ranks = 1; + + ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || + skl_is_16gb_dimm(&ch->dimm_s); + + drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n", + channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); + + return 0; +} + +static bool +intel_is_dram_symmetric(const struct dram_channel_info *ch0, + const struct dram_channel_info *ch1) +{ + return !memcmp(ch0, ch1, sizeof(*ch0)) && + (ch0->dimm_s.size == 0 || + !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l))); +} + +static int +skl_dram_get_channels_info(struct drm_i915_private *i915) +{ + struct dram_info *dram_info = &i915->dram_info; + struct dram_channel_info ch0 = {}, ch1 = {}; + u32 val; + int ret; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(i915, &ch0, 0, val); + if (ret == 0) + dram_info->num_channels++; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(i915, &ch1, 1, val); + if (ret == 0) + dram_info->num_channels++; + + if (dram_info->num_channels == 0) { + drm_info(&i915->drm, "Number of memory channels is zero\n"); + return -EINVAL; + } + + if (ch0.ranks == 0 && ch1.ranks == 0) { + drm_info(&i915->drm, "couldn't get memory rank information\n"); + return -EINVAL; + } + + dram_info->wm_lv_0_adjust_needed = ch0.is_16gb_dimm || ch1.is_16gb_dimm; + + dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); + + drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", + str_yes_no(dram_info->symmetric_memory)); + + return 0; +} + +static enum intel_dram_type +skl_get_dram_type(struct drm_i915_private *i915) +{ + u32 val; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); + + switch (val & SKL_DRAM_DDR_TYPE_MASK) { + case SKL_DRAM_DDR_TYPE_DDR3: + return INTEL_DRAM_DDR3; + case SKL_DRAM_DDR_TYPE_DDR4: + return INTEL_DRAM_DDR4; + case SKL_DRAM_DDR_TYPE_LPDDR3: + return INTEL_DRAM_LPDDR3; + case SKL_DRAM_DDR_TYPE_LPDDR4: + return INTEL_DRAM_LPDDR4; + default: + MISSING_CASE(val); + return INTEL_DRAM_UNKNOWN; + } +} + +static int +skl_get_dram_info(struct drm_i915_private *i915) +{ + struct dram_info *dram_info = &i915->dram_info; + int ret; + + dram_info->type = skl_get_dram_type(i915); + drm_dbg_kms(&i915->drm, "DRAM type: %s\n", + intel_dram_type_str(dram_info->type)); + + ret = skl_dram_get_channels_info(i915); + if (ret) + return ret; + + return 0; +} + +/* Returns Gb per DRAM device */ +static int bxt_get_dimm_size(u32 val) +{ + switch (val & BXT_DRAM_SIZE_MASK) { + case BXT_DRAM_SIZE_4GBIT: + return 4; + case BXT_DRAM_SIZE_6GBIT: + return 6; + case BXT_DRAM_SIZE_8GBIT: + return 8; + case BXT_DRAM_SIZE_12GBIT: + return 12; + case BXT_DRAM_SIZE_16GBIT: + return 16; + default: + MISSING_CASE(val); + return 0; + } +} + +static int bxt_get_dimm_width(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return 0; + + val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT; + + return 8 << val; +} + +static int bxt_get_dimm_ranks(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return 0; + + switch (val & BXT_DRAM_RANK_MASK) { + case BXT_DRAM_RANK_SINGLE: + return 1; + case BXT_DRAM_RANK_DUAL: + return 2; + default: + MISSING_CASE(val); + return 0; + } +} + +static enum intel_dram_type bxt_get_dimm_type(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return INTEL_DRAM_UNKNOWN; + + switch (val & BXT_DRAM_TYPE_MASK) { + case BXT_DRAM_TYPE_DDR3: + return INTEL_DRAM_DDR3; + case BXT_DRAM_TYPE_LPDDR3: + return INTEL_DRAM_LPDDR3; + case BXT_DRAM_TYPE_DDR4: + return INTEL_DRAM_DDR4; + case BXT_DRAM_TYPE_LPDDR4: + return INTEL_DRAM_LPDDR4; + default: + MISSING_CASE(val); + return INTEL_DRAM_UNKNOWN; + } +} + +static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) +{ + dimm->width = bxt_get_dimm_width(val); + dimm->ranks = bxt_get_dimm_ranks(val); + + /* + * Size in register is Gb per DRAM device. Convert to total + * Gb to match the way we report this for non-LP platforms. + */ + dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); +} + +static int bxt_get_dram_info(struct drm_i915_private *i915) +{ + struct dram_info *dram_info = &i915->dram_info; + u32 val; + u8 valid_ranks = 0; + int i; + + /* + * Now read each DUNIT8/9/10/11 to check the rank of each dimms. + */ + for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { + struct dram_dimm_info dimm; + enum intel_dram_type type; + + val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i)); + if (val == 0xFFFFFFFF) + continue; + + dram_info->num_channels++; + + bxt_get_dimm_info(&dimm, val); + type = bxt_get_dimm_type(val); + + drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && + dram_info->type != INTEL_DRAM_UNKNOWN && + dram_info->type != type); + + drm_dbg_kms(&i915->drm, + "CH%u DIMM size: %u Gb, width: X%u, ranks: %u, type: %s\n", + i - BXT_D_CR_DRP0_DUNIT_START, + dimm.size, dimm.width, dimm.ranks, + intel_dram_type_str(type)); + + if (valid_ranks == 0) + valid_ranks = dimm.ranks; + + if (type != INTEL_DRAM_UNKNOWN) + dram_info->type = type; + } + + if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { + drm_info(&i915->drm, "couldn't get memory information\n"); + return -EINVAL; + } + + return 0; +} + +static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = &dev_priv->dram_info; + u32 val = 0; + int ret; + + ret = snb_pcode_read(&dev_priv->uncore, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | + ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); + if (ret) + return ret; + + if (GRAPHICS_VER(dev_priv) == 12) { + switch (val & 0xf) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR5; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR5; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + case 4: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 5: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + default: + MISSING_CASE(val & 0xf); + return -EINVAL; + } + } else { + switch (val & 0xf) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + default: + MISSING_CASE(val & 0xf); + return -EINVAL; + } + } + + dram_info->num_channels = (val & 0xf0) >> 4; + dram_info->num_qgv_points = (val & 0xf00) >> 8; + dram_info->num_psf_gv_points = (val & 0x3000) >> 12; + + return 0; +} + +static int gen11_get_dram_info(struct drm_i915_private *i915) +{ + int ret = skl_get_dram_info(i915); + + if (ret) + return ret; + + return icl_pcode_read_mem_global_info(i915); +} + +static int gen12_get_dram_info(struct drm_i915_private *i915) +{ + i915->dram_info.wm_lv_0_adjust_needed = false; + + return icl_pcode_read_mem_global_info(i915); +} + +static int xelpdp_get_dram_info(struct drm_i915_private *i915) +{ + u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); + struct dram_info *dram_info = &i915->dram_info; + + switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR5; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR5; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + case 4: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 5: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + default: + MISSING_CASE(val); + return -EINVAL; + } + + dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val); + dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val); + /* PSF GV points not supported in D14+ */ + + return 0; +} + +void intel_dram_detect(struct drm_i915_private *i915) +{ + struct dram_info *dram_info = &i915->dram_info; + int ret; + + if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) + return; + + /* + * Assume level 0 watermark latency adjustment is needed until proven + * otherwise, this w/a is not needed by bxt/glk. + */ + dram_info->wm_lv_0_adjust_needed = !IS_GEN9_LP(i915); + + if (DISPLAY_VER(i915) >= 14) + ret = xelpdp_get_dram_info(i915); + else if (GRAPHICS_VER(i915) >= 12) + ret = gen12_get_dram_info(i915); + else if (GRAPHICS_VER(i915) >= 11) + ret = gen11_get_dram_info(i915); + else if (IS_GEN9_LP(i915)) + ret = bxt_get_dram_info(i915); + else + ret = skl_get_dram_info(i915); + if (ret) + return; + + drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); + + drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n", + str_yes_no(dram_info->wm_lv_0_adjust_needed)); +} + +static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) +{ + static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; + static const u8 sets[4] = { 1, 1, 2, 2 }; + + return EDRAM_NUM_BANKS(cap) * + ways[EDRAM_WAYS_IDX(cap)] * + sets[EDRAM_SETS_IDX(cap)]; +} + +void intel_dram_edram_detect(struct drm_i915_private *i915) +{ + u32 edram_cap = 0; + + if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) + return; + + edram_cap = __raw_uncore_read32(&i915->uncore, HSW_EDRAM_CAP); + + /* NB: We can't write IDICR yet because we don't have gt funcs set up */ + + if (!(edram_cap & EDRAM_ENABLED)) + return; + + /* + * The needed capability bits for size calculation are not there with + * pre gen9 so return 128MB always. + */ + if (GRAPHICS_VER(i915) < 9) + i915->edram_size_mb = 128; + else + i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); + + drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); +} diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h new file mode 100644 index 000000000000..4ba13c13162c --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2020 Intel Corporation + */ + +#ifndef __INTEL_DRAM_H__ +#define __INTEL_DRAM_H__ + +struct drm_i915_private; + +void intel_dram_edram_detect(struct drm_i915_private *i915); +void intel_dram_detect(struct drm_i915_private *i915); + +#endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c new file mode 100644 index 000000000000..ba9843cb1b13 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_pch.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2019 Intel Corporation. + */ + +#include "i915_drv.h" +#include "i915_utils.h" +#include "intel_pch.h" + +/* Map PCH device id to PCH type, or PCH_NONE if unknown. */ +static enum intel_pch +intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) +{ + switch (id) { + case INTEL_PCH_IBX_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n"); + drm_WARN_ON(&dev_priv->drm, GRAPHICS_VER(dev_priv) != 5); + return PCH_IBX; + case INTEL_PCH_CPT_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n"); + drm_WARN_ON(&dev_priv->drm, + GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv)); + return PCH_CPT; + case INTEL_PCH_PPT_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n"); + drm_WARN_ON(&dev_priv->drm, + GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv)); + /* PPT is CPT compatible */ + return PCH_CPT; + case INTEL_PCH_LPT_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, + IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, + !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_WPT_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, + IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + /* WPT is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, + !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + /* WPT is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_SPT_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_SKYLAKE(dev_priv) && + !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_KBP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_SKYLAKE(dev_priv) && + !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv)); + /* KBP is SPT compatible */ + return PCH_SPT; + case INTEL_PCH_CNP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, + "Found Cannon Lake LP PCH (CNP-LP)\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_CMP_DEVICE_ID_TYPE: + case INTEL_PCH_CMP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv) && + !IS_ROCKETLAKE(dev_priv)); + /* CMP is CNP compatible */ + return PCH_CNP; + case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n"); + drm_WARN_ON(&dev_priv->drm, + !IS_COFFEELAKE(dev_priv) && + !IS_COMETLAKE(dev_priv)); + /* CMP-V is based on KBP, which is SPT compatible */ + return PCH_SPT; + case INTEL_PCH_ICP_DEVICE_ID_TYPE: + case INTEL_PCH_ICP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); + return PCH_ICP; + case INTEL_PCH_MCC_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); + /* MCC is TGP compatible */ + return PCH_TGP; + case INTEL_PCH_TGP_DEVICE_ID_TYPE: + case INTEL_PCH_TGP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) && + !IS_ROCKETLAKE(dev_priv) && + !IS_GEN9_BC(dev_priv)); + return PCH_TGP; + case INTEL_PCH_JSP_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); + /* JSP is ICP compatible */ + return PCH_ICP; + case INTEL_PCH_ADP_DEVICE_ID_TYPE: + case INTEL_PCH_ADP2_DEVICE_ID_TYPE: + case INTEL_PCH_ADP3_DEVICE_ID_TYPE: + case INTEL_PCH_ADP4_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Alder Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) && + !IS_ALDERLAKE_P(dev_priv)); + return PCH_ADP; + case INTEL_PCH_MTP_DEVICE_ID_TYPE: + case INTEL_PCH_MTP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Meteor Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_METEORLAKE(dev_priv)); + return PCH_MTP; + default: + return PCH_NONE; + } +} + +static bool intel_is_virt_pch(unsigned short id, + unsigned short svendor, unsigned short sdevice) +{ + return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || + id == INTEL_PCH_P3X_DEVICE_ID_TYPE || + (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && + svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && + sdevice == PCI_SUBDEVICE_ID_QEMU)); +} + +static void +intel_virt_detect_pch(const struct drm_i915_private *dev_priv, + unsigned short *pch_id, enum intel_pch *pch_type) +{ + unsigned short id = 0; + + /* + * In a virtualized passthrough environment we can be in a + * setup where the ISA bridge is not able to be passed through. + * In this case, a south bridge can be emulated and we have to + * make an educated guess as to which PCH is really there. + */ + + if (IS_METEORLAKE(dev_priv)) + id = INTEL_PCH_MTP_DEVICE_ID_TYPE; + else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) + id = INTEL_PCH_ADP_DEVICE_ID_TYPE; + else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) + id = INTEL_PCH_TGP_DEVICE_ID_TYPE; + else if (IS_JSL_EHL(dev_priv)) + id = INTEL_PCH_MCC_DEVICE_ID_TYPE; + else if (IS_ICELAKE(dev_priv)) + id = INTEL_PCH_ICP_DEVICE_ID_TYPE; + else if (IS_COFFEELAKE(dev_priv) || + IS_COMETLAKE(dev_priv)) + id = INTEL_PCH_CNP_DEVICE_ID_TYPE; + else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv)) + id = INTEL_PCH_SPT_DEVICE_ID_TYPE; + else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + id = INTEL_PCH_LPT_DEVICE_ID_TYPE; + else if (GRAPHICS_VER(dev_priv) == 6 || IS_IVYBRIDGE(dev_priv)) + id = INTEL_PCH_CPT_DEVICE_ID_TYPE; + else if (GRAPHICS_VER(dev_priv) == 5) + id = INTEL_PCH_IBX_DEVICE_ID_TYPE; + + if (id) + drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id); + else + drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n"); + + *pch_type = intel_pch_type(dev_priv, id); + + /* Sanity check virtual PCH id */ + if (drm_WARN_ON(&dev_priv->drm, + id && *pch_type == PCH_NONE)) + id = 0; + + *pch_id = id; +} + +void intel_detect_pch(struct drm_i915_private *dev_priv) +{ + struct pci_dev *pch = NULL; + unsigned short id; + enum intel_pch pch_type; + + /* DG1 has south engine display on the same PCI device */ + if (IS_DG1(dev_priv)) { + dev_priv->pch_type = PCH_DG1; + return; + } else if (IS_DG2(dev_priv)) { + dev_priv->pch_type = PCH_DG2; + return; + } + + /* + * The reason to probe ISA bridge instead of Dev31:Fun0 is to + * make graphics device passthrough work easy for VMM, that only + * need to expose ISA bridge to let driver know the real hardware + * underneath. This is a requirement from virtualization team. + * + * In some virtualized environments (e.g. XEN), there is irrelevant + * ISA bridge in the system. To work reliably, we should scan trhough + * all the ISA bridge devices and check for the first match, instead + * of only checking the first one. + */ + while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { + if (pch->vendor != PCI_VENDOR_ID_INTEL) + continue; + + id = pch->device & INTEL_PCH_DEVICE_ID_MASK; + + pch_type = intel_pch_type(dev_priv, id); + if (pch_type != PCH_NONE) { + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; + } else if (intel_is_virt_pch(id, pch->subsystem_vendor, + pch->subsystem_device)) { + intel_virt_detect_pch(dev_priv, &id, &pch_type); + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; + } + } + + /* + * Use PCH_NOP (PCH but no South Display) for PCH platforms without + * display. + */ + if (pch && !HAS_DISPLAY(dev_priv)) { + drm_dbg_kms(&dev_priv->drm, + "Display disabled, reverting to NOP PCH\n"); + dev_priv->pch_type = PCH_NOP; + dev_priv->pch_id = 0; + } else if (!pch) { + if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) { + intel_virt_detect_pch(dev_priv, &id, &pch_type); + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + } else { + drm_dbg_kms(&dev_priv->drm, "No PCH found.\n"); + } + } + + pci_dev_put(pch); +} diff --git a/drivers/gpu/drm/i915/soc/intel_pch.h b/drivers/gpu/drm/i915/soc/intel_pch.h new file mode 100644 index 000000000000..32aff5a70d04 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_pch.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2019 Intel Corporation. + */ + +#ifndef __INTEL_PCH__ +#define __INTEL_PCH__ + +struct drm_i915_private; + +/* + * Sorted by south display engine compatibility. + * If the new PCH comes with a south display engine that is not + * inherited from the latest item, please do not add it to the + * end. Instead, add it right after its "parent" PCH. + */ +enum intel_pch { + PCH_NOP = -1, /* PCH without south display */ + PCH_NONE = 0, /* No PCH present */ + PCH_IBX, /* Ibexpeak PCH */ + PCH_CPT, /* Cougarpoint/Pantherpoint PCH */ + PCH_LPT, /* Lynxpoint/Wildcatpoint PCH */ + PCH_SPT, /* Sunrisepoint/Kaby Lake PCH */ + PCH_CNP, /* Cannon/Comet Lake PCH */ + PCH_ICP, /* Ice Lake/Jasper Lake PCH */ + PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */ + PCH_ADP, /* Alder Lake PCH */ + PCH_MTP, /* Meteor Lake PCH */ + + /* Fake PCHs, functionality handled on the same PCI dev */ + PCH_DG1 = 1024, + PCH_DG2, +}; + +#define INTEL_PCH_DEVICE_ID_MASK 0xff80 +#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 +#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 +#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00 +#define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00 +#define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00 +#define INTEL_PCH_WPT_DEVICE_ID_TYPE 0x8c80 +#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE 0x9c80 +#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100 +#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 +#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280 +#define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300 +#define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80 +#define INTEL_PCH_CMP_DEVICE_ID_TYPE 0x0280 +#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 +#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 +#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 +#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 +#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 +#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 +#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 +#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 +#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 +#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 +#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 +#define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480 +#define INTEL_PCH_MTP_DEVICE_ID_TYPE 0x7E00 +#define INTEL_PCH_MTP2_DEVICE_ID_TYPE 0xAE00 +#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 +#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 +#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ + +#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) +#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id) +#define HAS_PCH_MTP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_MTP) +#define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2) +#define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP) +#define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1) +#define HAS_PCH_TGP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_TGP) +#define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP) +#define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP) +#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) +#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) +#define HAS_PCH_LPT_LP(dev_priv) \ + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) +#define HAS_PCH_LPT_H(dev_priv) \ + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_DEVICE_ID_TYPE) +#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) +#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) +#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) +#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE) + +void intel_detect_pch(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_PCH__ */ -- cgit v1.2.3 From 1482ec00be4a3634aeffbcc799791a723df69339 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 1 Nov 2022 11:42:17 +0200 Subject: drm: Add missing DP DSC extended capability definitions. Adding DP DSC register definitions, we might need for further DSC implementation, supporting MST and DP branch pass-through mode. v2: - Fixed checkpatch comment warning v3: - Removed function which is not yet used(Jani Nikula) Reviewed-by: Vinod Govindapillai Acked-by: Maarten Lankhorst Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221101094222.22091-2-stanislav.lisovskiy@intel.com --- include/drm/display/drm_dp.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index e934aab357be..9bc22a02874d 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -240,6 +240,8 @@ #define DP_DSC_SUPPORT 0x060 /* DP 1.4 */ # define DP_DSC_DECOMPRESSION_IS_SUPPORTED (1 << 0) # define DP_DSC_PASSTHROUGH_IS_SUPPORTED (1 << 1) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_COMP_TO_COMP (1 << 2) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_UNCOMP_TO_COMP (1 << 3) #define DP_DSC_REV 0x061 # define DP_DSC_MAJOR_MASK (0xf << 0) @@ -278,12 +280,15 @@ #define DP_DSC_BLK_PREDICTION_SUPPORT 0x066 # define DP_DSC_BLK_PREDICTION_IS_SUPPORTED (1 << 0) +# define DP_DSC_RGB_COLOR_CONV_BYPASS_SUPPORT (1 << 1) #define DP_DSC_MAX_BITS_PER_PIXEL_LOW 0x067 /* eDP 1.4 */ #define DP_DSC_MAX_BITS_PER_PIXEL_HI 0x068 /* eDP 1.4 */ # define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK (0x3 << 0) # define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8 +# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK 0x06 +# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY 0x08 #define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069 # define DP_DSC_RGB (1 << 0) @@ -345,11 +350,13 @@ # define DP_DSC_24_PER_DP_DSC_SINK (1 << 2) #define DP_DSC_BITS_PER_PIXEL_INC 0x06F +# define DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK 0x1f +# define DP_DSC_RGB_YCbCr420_MAX_BPP_DELTA_MASK 0xe0 # define DP_DSC_BITS_PER_PIXEL_1_16 0x0 # define DP_DSC_BITS_PER_PIXEL_1_8 0x1 # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 -# define DP_DSC_BITS_PER_PIXEL_1 0x4 +# define DP_DSC_BITS_PER_PIXEL_1_1 0x4 #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ # define DP_PSR_IS_SUPPORTED 1 -- cgit v1.2.3 From 9096e36d5ba6a7662b75eb02038dc4cd46ba47b4 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 1 Nov 2022 11:42:18 +0200 Subject: drm/i915: Fix intel_dp_mst_compute_link_config We currently always exit that bpp loop because drm_dp_atomic_find_vcpi_slots doesn't care if we actually can fit those or not. I think that wasn't the initial intention here, especially when we keep trying with lower bpps, we are supposed to keep trying until we actually find some _working_ configuration, which isn't the case here. So added that drm_dp_mst_check here, so that we can make sure that try all the bpps before we fail. Reviewed-by: Vinod Govindapillai Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221101094222.22091-3-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 4077a979a924..823dfceefd90 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -60,6 +60,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int bpp, slots = -EINVAL; + int ret = 0; mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); if (IS_ERR(mst_state)) @@ -85,10 +86,21 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, connector->port, crtc_state->pbn); if (slots == -EDEADLK) return slots; - if (slots >= 0) - break; + if (slots >= 0) { + ret = drm_dp_mst_atomic_check(state); + /* + * If we got slots >= 0 and we can fit those based on check + * then we can exit the loop. Otherwise keep trying. + */ + if (!ret) + break; + } } + /* Despite slots are non-zero, we still failed the atomic check */ + if (ret && slots >= 0) + slots = ret; + if (slots < 0) { drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n", slots); -- cgit v1.2.3 From 7971aacf6e2d5ee508f63bc3707766f27c0f3e2b Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 1 Nov 2022 11:42:19 +0200 Subject: drm/i915: Extract drm_dp_atomic_find_vcpi_slots cycle to separate function We would be using almost same code to loop through bpps while calling drm_dp_atomic_find_vcpi_slots - lets remove this duplication by introducing a new function intel_dp_mst_find_vcpi_slots_for_bpp v2: Fix pbn_div calculation - shouldn't matter if its DSC or not. v3: FIx rebase conflict, constant_n no longer needed. Reviewed-by: Vinod Govindapillai Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221101094222.22091-4-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 48 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 823dfceefd90..1cdcde56f966 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -45,10 +45,14 @@ #include "intel_hotplug.h" #include "skl_scaler.h" -static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - struct link_config_limits *limits) +static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int max_bpp, + int min_bpp, + struct link_config_limits *limits, + struct drm_connector_state *conn_state, + int step, + bool dsc) { struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); @@ -72,18 +76,20 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, // TODO: Handle pbn_div changes by adding a new MST helper if (!mst_state->pbn_div) { mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr, - limits->max_rate, - limits->max_lane_count); + crtc_state->port_clock, + crtc_state->lane_count); } - for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { + for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { crtc_state->pipe_bpp = bpp; crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, - crtc_state->pipe_bpp, - false); + dsc ? bpp << 4 : crtc_state->pipe_bpp, + dsc); + slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, - connector->port, crtc_state->pbn); + connector->port, + crtc_state->pbn); if (slots == -EDEADLK) return slots; if (slots >= 0) { @@ -101,11 +107,29 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, if (ret && slots >= 0) slots = ret; - if (slots < 0) { + if (slots < 0) drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n", slots); + + return slots; +} + + +static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + struct link_config_limits *limits) +{ + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int slots = -EINVAL; + + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp, + limits->min_bpp, limits, + conn_state, 2 * 3, false); + + if (slots < 0) return slots; - } intel_link_compute_m_n(crtc_state->pipe_bpp, crtc_state->lane_count, -- cgit v1.2.3 From d51f25eb479aeb61c194089f66261be67ff9237a Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 1 Nov 2022 11:42:20 +0200 Subject: drm/i915: Add DSC support to MST path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever we are not able to get enough timeslots for required PBN, let's try to allocate those using DSC, just same way as we do for SST. v2: Removed intel_dp_mst_dsc_compute_config and refactored intel_dp_dsc_compute_config to support timeslots as a parameter(Ville Syrjälä) v3: - Rebased - Added a debug to see that we at least try reserving VCPI slots using DSC, because currently its not visible from the logs, thus making debugging more tricky. - Moved timeslots to numerator, where it should be. v4: - Call drm_dp_mst_atomic_check already during link config computation, because we need to know already by this moment if uncompressed amount of VCPI slots needed can fit, otherwise we need to use DSC. (thanks to Vinod Govindapillai for pointing this out) v5: - Put pipe_config->bigjoiner_pipes back to original condition in intel_dp_dsc_compute_config (don't remember when I lost it) v6: - Removed unnecessary drm_dp_mst_atomic_check as it is now always called in a newly introduced intel_dp_mst_find_vcpi_slots_for_bpp function (Vinod Govindapillai) Reviewed-by: Vinod Govindapillai Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221101094222.22091-5-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 57 +++++++------ drivers/gpu/drm/i915/display/intel_dp.h | 17 ++++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 125 ++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 72cf83a27405..6a95c0f5aa4b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -117,7 +117,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) } static void intel_dp_unset_edid(struct intel_dp *intel_dp); -static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); /* Is link rate UHBR and thus 128b/132b? */ bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state) @@ -673,11 +672,12 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915) return 6144 * 8; } -static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, - u32 link_clock, u32 lane_count, - u32 mode_clock, u32 mode_hdisplay, - bool bigjoiner, - u32 pipe_bpp) +u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, + u32 link_clock, u32 lane_count, + u32 mode_clock, u32 mode_hdisplay, + bool bigjoiner, + u32 pipe_bpp, + u32 timeslots) { u32 bits_per_pixel, max_bpp_small_joiner_ram; int i; @@ -688,8 +688,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, * for SST -> TimeSlotsPerMTP is 1, * for MST -> TimeSlotsPerMTP has to be calculated */ - bits_per_pixel = (link_clock * lane_count * 8) / + bits_per_pixel = (link_clock * lane_count * 8) * timeslots / intel_dp_mode_to_fec_clock(mode_clock); + drm_dbg_kms(&i915->drm, "Max link bpp: %u\n", bits_per_pixel); /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / @@ -738,9 +739,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, return bits_per_pixel << 4; } -static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, - int mode_clock, int mode_hdisplay, - bool bigjoiner) +u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, + int mode_clock, int mode_hdisplay, + bool bigjoiner) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 min_slice_count, i; @@ -947,8 +948,8 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_OK; } -static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, - int hdisplay, int clock) +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -1035,7 +1036,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock, mode->hdisplay, bigjoiner, - pipe_bpp) >> 4; + pipe_bpp, 1) >> 4; dsc_slice_count = intel_dp_dsc_get_slice_count(intel_dp, target_clock, @@ -1364,7 +1365,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, return -EINVAL; } -static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc) +int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); int i, num_bpc; @@ -1465,10 +1466,11 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, return drm_dsc_compute_rc_parameters(vdsc_cfg); } -static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state, - struct link_config_limits *limits) +int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, + struct link_config_limits *limits, + int timeslots) { 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); @@ -1524,7 +1526,8 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, pipe_config->bigjoiner_pipes, - pipe_bpp); + pipe_bpp, + timeslots); dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, @@ -1536,11 +1539,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, return -EINVAL; } pipe_config->dsc.compressed_bpp = min_t(u16, - dsc_max_output_bpp >> 4, - pipe_config->pipe_bpp); + dsc_max_output_bpp >> 4, + pipe_config->pipe_bpp); pipe_config->dsc.slice_count = dsc_dp_slice_count; + drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n", + pipe_config->dsc.compressed_bpp, + pipe_config->dsc.slice_count); } - /* * VDSC engine operates at 1 Pixel per clock, so if peak pixel rate * is greater than the maximum Cdclock and if slice count is even @@ -1548,13 +1553,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, */ if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_cdclk_freq || pipe_config->bigjoiner_pipes) { - if (pipe_config->dsc.slice_count < 2) { + if (pipe_config->dsc.slice_count > 1) { + pipe_config->dsc.dsc_split = true; + } else { drm_dbg_kms(&dev_priv->drm, "Cannot split stream to use 2 VDSC instances\n"); return -EINVAL; } - - pipe_config->dsc.dsc_split = true; } ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config); @@ -1643,7 +1648,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, - conn_state, &limits); + conn_state, &limits, 1); if (ret < 0) return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index a54902c713a3..c6539a6915e9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -56,6 +56,11 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder); int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); +int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state, + struct link_config_limits *limits, + int timeslots); bool intel_dp_is_edp(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); @@ -96,6 +101,18 @@ void intel_read_dp_sdp(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, unsigned int type); bool intel_digital_port_connected(struct intel_encoder *encoder); +int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); +u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, + u32 link_clock, u32 lane_count, + u32 mode_clock, u32 mode_hdisplay, + bool bigjoiner, + u32 pipe_bpp, + u32 timeslots); +u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, + int mode_clock, int mode_hdisplay, + bool bigjoiner); +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + int hdisplay, int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 1cdcde56f966..59f80af8d17d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -92,6 +92,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, crtc_state->pbn); if (slots == -EDEADLK) return slots; + if (slots >= 0) { ret = drm_dp_mst_atomic_check(state); /* @@ -142,6 +143,61 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, return 0; } +static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + struct link_config_limits *limits) +{ + struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); + struct intel_dp *intel_dp = &intel_mst->primary->dp; + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + int slots = -EINVAL; + int i, num_bpc; + u8 dsc_bpc[3] = {0}; + int min_bpp, max_bpp; + 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, conn_state->max_requested_bpc); + else + dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc); + + max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp); + min_bpp = limits->min_bpp; + + num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd, + dsc_bpc); + for (i = 0; i < num_bpc; i++) { + if (max_bpp >= dsc_bpc[i] * 3) + if (min_bpp > dsc_bpc[i] * 3) + min_bpp = dsc_bpc[i] * 3; + } + + drm_dbg_kms(&i915->drm, "DSC Sink supported min bpp %d max bpp %d\n", + min_bpp, max_bpp); + + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp, + min_bpp, limits, + conn_state, 2 * 3, true); + + if (slots < 0) + return slots; + + intel_link_compute_m_n(crtc_state->pipe_bpp, + crtc_state->lane_count, + adjusted_mode->crtc_clock, + crtc_state->port_clock, + &crtc_state->dp_m_n, + crtc_state->fec_enable); + crtc_state->dp_m_n.tu = slots; + + return 0; +} static int intel_dp_mst_update_slots(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -218,6 +274,29 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, ret = intel_dp_mst_compute_link_config(encoder, pipe_config, conn_state, &limits); + + if (ret == -EDEADLK) + return ret; + + /* enable compression if the mode doesn't fit available BW */ + drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en); + if (ret || intel_dp->force_dsc_en) { + /* + * Try to get at least some timeslots and then see, if + * we can fit there with DSC. + */ + drm_dbg_kms(&dev_priv->drm, "Trying to find VCPI slots in DSC mode\n"); + + ret = intel_dp_dsc_mst_compute_link_config(encoder, pipe_config, + conn_state, &limits); + if (ret < 0) + return ret; + + ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, + conn_state, &limits, + pipe_config->dp_m_n.tu); + } + if (ret) return ret; @@ -728,6 +807,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; int ret; + bool dsc = false, bigjoiner = false; + u16 dsc_max_output_bpp = 0; + u8 dsc_slice_count = 0; + int target_clock = mode->clock; if (drm_connector_is_unregistered(connector)) { *status = MODE_ERROR; @@ -765,6 +848,48 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } + if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) { + bigjoiner = true; + max_dotclk *= 2; + } + + if (DISPLAY_VER(dev_priv) >= 10 && + drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) { + /* + * TBD pass the connector BPC, + * for now U8_MAX so that max BPC on that platform would be picked + */ + int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX); + + if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) { + dsc_max_output_bpp = + intel_dp_dsc_get_output_bpp(dev_priv, + max_link_clock, + max_lanes, + target_clock, + mode->hdisplay, + bigjoiner, + pipe_bpp, 1) >> 4; + dsc_slice_count = + intel_dp_dsc_get_slice_count(intel_dp, + target_clock, + mode->hdisplay, + bigjoiner); + } + + dsc = dsc_max_output_bpp && dsc_slice_count; + } + + /* + * Big joiner configuration needs DSC for TGL which is not true for + * XE_LPD where uncompressed joiner is supported. + */ + if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc) + return MODE_CLOCK_HIGH; + + if (mode_rate > max_rate && !dsc) + return MODE_CLOCK_HIGH; + *status = intel_mode_valid_max_plane_size(dev_priv, mode, false); return 0; } -- cgit v1.2.3 From d797f67d1e2568b152ee1af2334b11c1a48e5594 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Wed, 23 Nov 2022 12:05:51 +0200 Subject: drm/i915: Extract VESA DSC bpp alignment to separate function We might to use that function separately from intel_dp_dsc_compute_config for DP DSC over MST case, because allocating bandwidth in that case can be a bit more tricky. So in order to avoid code copy-pasta lets extract this to separate function and reuse it for both SST and MST cases. v2: Removed multiple blank lines v3: Rename intel_dp_dsc_nearest_vesa_bpp to intel_dp_dsc_nearest_valid_bpp to reflect its meaning more properly. (Manasi Navare) Signed-off-by: Stanislav Lisovskiy Reviewed-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20221123100551.29080-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 50 ++++++++++++++++++----------- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 - 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6a95c0f5aa4b..ecc14f978721 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -672,6 +672,36 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915) return 6144 * 8; } +u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp) +{ + u32 bits_per_pixel = bpp; + int i; + + /* Error out if the max bpp is less than smallest allowed valid bpp */ + if (bits_per_pixel < valid_dsc_bpp[0]) { + drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n", + bits_per_pixel, valid_dsc_bpp[0]); + return 0; + } + + /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */ + if (DISPLAY_VER(i915) >= 13) { + bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1); + } else { + /* Find the nearest match in the array of known BPPs from VESA */ + for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { + if (bits_per_pixel < valid_dsc_bpp[i + 1]) + break; + } + drm_dbg_kms(&i915->drm, "Set dsc bpp from %d to VESA %d\n", + bits_per_pixel, valid_dsc_bpp[i]); + + bits_per_pixel = valid_dsc_bpp[i]; + } + + return bits_per_pixel; +} + u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, u32 link_clock, u32 lane_count, u32 mode_clock, u32 mode_hdisplay, @@ -680,7 +710,6 @@ u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, u32 timeslots) { u32 bits_per_pixel, max_bpp_small_joiner_ram; - int i; /* * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* @@ -713,24 +742,7 @@ u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner); } - /* Error out if the max bpp is less than smallest allowed valid bpp */ - if (bits_per_pixel < valid_dsc_bpp[0]) { - drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n", - bits_per_pixel, valid_dsc_bpp[0]); - return 0; - } - - /* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */ - if (DISPLAY_VER(i915) >= 13) { - bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1); - } else { - /* Find the nearest match in the array of known BPPs from VESA */ - for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { - if (bits_per_pixel < valid_dsc_bpp[i + 1]) - break; - } - bits_per_pixel = valid_dsc_bpp[i]; - } + bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp); /* * Compressed BPP in U6.4 format so multiply by 16, for Gen 11, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index c6539a6915e9..e4faccf87370 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -120,6 +120,7 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) } u32 intel_dp_mode_to_fec_clock(u32 mode_clock); +u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp); void intel_ddi_update_pipe(struct intel_atomic_state *state, struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 59f80af8d17d..b4f01c01dc1c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -115,7 +115,6 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, return slots; } - static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, -- cgit v1.2.3 From 52f14682ac4d39d9bdae8ff6bae23abf7026ee66 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Wed, 23 Nov 2022 12:07:18 +0200 Subject: drm/i915: Bpp/timeslot calculation fixes for DP MST DSC Fix intel_dp_dsc_compute_config, previously timeslots parameter was used in fact not as a timeslots, but more like a ratio timeslots/64, which of course didn't have any effect for SST DSC, but causes now issues for MST DSC. Secondly we need to calculate pipe_bpp using intel_dp_dsc_compute_bpp only for SST DSC case, while for MST case it has been calculated earlier already with intel_dp_dsc_mst_compute_link_config. Third we also were wrongly determining sink min bpp/max bpp, those limites should be intersected with our limits to find common acceptable bpp's, plus on top of that we should align those with VESA bpps and only then calculate required timeslots amount. Some MST hubs started to work only after third change was made. v2: Make kernel test robot happy(claimed there was unitialzed use, while there is none) v3: Rename intel_dp_dsc_nearest_vesa_bpp to intel_dp_dsc_nearest_valid_bpp (Manasi Navare) Reviewed-by: Manasi Navare Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221123100718.29130-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 69 ++++++++++++++++++++--------- drivers/gpu/drm/i915/display/intel_dp.h | 3 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 69 ++++++++++++++++++++++++----- 3 files changed, 106 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ecc14f978721..bf80f296a8fd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -717,9 +717,14 @@ u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, * for SST -> TimeSlotsPerMTP is 1, * for MST -> TimeSlotsPerMTP has to be calculated */ - bits_per_pixel = (link_clock * lane_count * 8) * timeslots / - intel_dp_mode_to_fec_clock(mode_clock); - drm_dbg_kms(&i915->drm, "Max link bpp: %u\n", bits_per_pixel); + bits_per_pixel = DIV_ROUND_UP((link_clock * lane_count) * timeslots, + intel_dp_mode_to_fec_clock(mode_clock) * 8); + + drm_dbg_kms(&i915->drm, "Max link bpp is %u for %u timeslots " + "total bw %u pixel clock %u\n", + bits_per_pixel, timeslots, + (link_clock * lane_count * 8), + intel_dp_mode_to_fec_clock(mode_clock)); /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / @@ -1048,7 +1053,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock, mode->hdisplay, bigjoiner, - pipe_bpp, 1) >> 4; + pipe_bpp, 64) >> 4; dsc_slice_count = intel_dp_dsc_get_slice_count(intel_dp, target_clock, @@ -1482,7 +1487,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, struct link_config_limits *limits, - int timeslots) + int timeslots, + bool compute_pipe_bpp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); @@ -1497,7 +1503,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, if (!intel_dp_supports_dsc(intel_dp, pipe_config)) return -EINVAL; - pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc); + if (compute_pipe_bpp) + pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc); + else + pipe_bpp = pipe_config->pipe_bpp; if (intel_dp->force_dsc_bpc) { pipe_bpp = intel_dp->force_dsc_bpc * 3; @@ -1528,31 +1537,47 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, true); } else { - u16 dsc_max_output_bpp; + u16 dsc_max_output_bpp = 0; u8 dsc_dp_slice_count; - dsc_max_output_bpp = - intel_dp_dsc_get_output_bpp(dev_priv, - pipe_config->port_clock, - pipe_config->lane_count, - adjusted_mode->crtc_clock, - adjusted_mode->crtc_hdisplay, - pipe_config->bigjoiner_pipes, - pipe_bpp, - timeslots); + if (compute_pipe_bpp) { + dsc_max_output_bpp = + intel_dp_dsc_get_output_bpp(dev_priv, + pipe_config->port_clock, + pipe_config->lane_count, + adjusted_mode->crtc_clock, + adjusted_mode->crtc_hdisplay, + pipe_config->bigjoiner_pipes, + pipe_bpp, + timeslots); + if (!dsc_max_output_bpp) { + drm_dbg_kms(&dev_priv->drm, + "Compressed BPP not supported\n"); + return -EINVAL; + } + } dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, pipe_config->bigjoiner_pipes); - if (!dsc_max_output_bpp || !dsc_dp_slice_count) { + if (!dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, - "Compressed BPP/Slice Count not supported\n"); + "Compressed Slice Count not supported\n"); return -EINVAL; } - pipe_config->dsc.compressed_bpp = min_t(u16, - dsc_max_output_bpp >> 4, - pipe_config->pipe_bpp); + + /* + * compute pipe bpp is set to false for DP MST DSC case + * and compressed_bpp is calculated same time once + * vpci timeslots are allocated, because overall bpp + * calculation procedure is bit different for MST case. + */ + if (compute_pipe_bpp) { + pipe_config->dsc.compressed_bpp = min_t(u16, + dsc_max_output_bpp >> 4, + pipe_config->pipe_bpp); + } pipe_config->dsc.slice_count = dsc_dp_slice_count; drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n", pipe_config->dsc.compressed_bpp, @@ -1660,7 +1685,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, - conn_state, &limits, 1); + conn_state, &limits, 1, true); if (ret < 0) return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index e4faccf87370..ef39e4f7a329 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -60,7 +60,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, struct link_config_limits *limits, - int timeslots); + int timeslots, + bool recompute_pipe_bpp); bool intel_dp_is_edp(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index b4f01c01dc1c..8b0e4defa3f1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -81,12 +81,12 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, } for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) { - crtc_state->pipe_bpp = bpp; - crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, - dsc ? bpp << 4 : crtc_state->pipe_bpp, + dsc ? bpp << 4 : bpp, dsc); + drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); + slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, connector->port, crtc_state->pbn); @@ -108,9 +108,16 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, if (ret && slots >= 0) slots = ret; - if (slots < 0) + if (slots < 0) { drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n", slots); + } else { + if (!dsc) + crtc_state->pipe_bpp = bpp; + else + crtc_state->dsc.compressed_bpp = bpp; + drm_dbg_kms(&i915->drm, "Got %d slots for pipe bpp %d dsc %d\n", slots, bpp, dsc); + } return slots; } @@ -157,8 +164,10 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, int slots = -EINVAL; int i, num_bpc; u8 dsc_bpc[3] = {0}; - int min_bpp, max_bpp; + int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp; u8 dsc_max_bpc; + bool need_timeslot_recalc = false; + u32 last_compressed_bpp; /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */ if (DISPLAY_VER(i915) >= 12) @@ -171,14 +180,28 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd, dsc_bpc); - for (i = 0; i < num_bpc; i++) { - if (max_bpp >= dsc_bpc[i] * 3) - if (min_bpp > dsc_bpc[i] * 3) - min_bpp = dsc_bpc[i] * 3; + + drm_dbg_kms(&i915->drm, "DSC Source supported min bpp %d max bpp %d\n", + min_bpp, max_bpp); + + sink_max_bpp = dsc_bpc[0] * 3; + sink_min_bpp = sink_max_bpp; + + for (i = 1; i < num_bpc; i++) { + if (sink_min_bpp > dsc_bpc[i] * 3) + sink_min_bpp = dsc_bpc[i] * 3; + if (sink_max_bpp < dsc_bpc[i] * 3) + sink_max_bpp = dsc_bpc[i] * 3; } drm_dbg_kms(&i915->drm, "DSC Sink supported min bpp %d max bpp %d\n", - min_bpp, max_bpp); + sink_min_bpp, sink_max_bpp); + + if (min_bpp < sink_min_bpp) + min_bpp = sink_min_bpp; + + if (max_bpp > sink_max_bpp) + max_bpp = sink_max_bpp; slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp, min_bpp, limits, @@ -187,6 +210,28 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder, if (slots < 0) return slots; + last_compressed_bpp = crtc_state->dsc.compressed_bpp; + + crtc_state->dsc.compressed_bpp = intel_dp_dsc_nearest_valid_bpp(i915, + last_compressed_bpp, + crtc_state->pipe_bpp); + + if (crtc_state->dsc.compressed_bpp != last_compressed_bpp) + need_timeslot_recalc = true; + + /* + * Apparently some MST hubs dislike if vcpi slots are not matching precisely + * the actual compressed bpp we use. + */ + if (need_timeslot_recalc) { + slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, + crtc_state->dsc.compressed_bpp, + crtc_state->dsc.compressed_bpp, + limits, conn_state, 2 * 3, true); + if (slots < 0) + return slots; + } + intel_link_compute_m_n(crtc_state->pipe_bpp, crtc_state->lane_count, adjusted_mode->crtc_clock, @@ -293,7 +338,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, conn_state, &limits, - pipe_config->dp_m_n.tu); + pipe_config->dp_m_n.tu, false); } if (ret) @@ -868,7 +913,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, target_clock, mode->hdisplay, bigjoiner, - pipe_bpp, 1) >> 4; + pipe_bpp, 64) >> 4; dsc_slice_count = intel_dp_dsc_get_slice_count(intel_dp, target_clock, -- cgit v1.2.3 From 9a4cea629a36e836ba384b3adeb5942dacdbabbd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 14 Dec 2022 16:14:59 -0800 Subject: drm/i915: ratelimit errors in display engine irq While debugging page table faults it's useful not to kill the machine with thousands of error mesages. Ratelimit all errors in gen8_de_irq_handler(). Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221215001459.3759580-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a815a45a6e6b..2c58d1c58e78 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2447,8 +2447,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) ret = IRQ_HANDLED; gen8_de_misc_irq_handler(dev_priv, iir); } else { - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE MISC)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE MISC)!\n"); } } @@ -2459,8 +2459,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) ret = IRQ_HANDLED; gen11_hpd_irq_handler(dev_priv, iir); } else { - drm_err(&dev_priv->drm, - "The master control interrupt lied, (DE HPD)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied, (DE HPD)!\n"); } } @@ -2509,12 +2509,12 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (!found) - drm_err(&dev_priv->drm, - "Unexpected DE Port interrupt\n"); + drm_err_ratelimited(&dev_priv->drm, + "Unexpected DE Port interrupt\n"); } else - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE PORT)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE PORT)!\n"); } for_each_pipe(dev_priv, pipe) { @@ -2525,8 +2525,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); if (!iir) { - drm_err(&dev_priv->drm, - "The master control interrupt lied (DE PIPE)!\n"); + drm_err_ratelimited(&dev_priv->drm, + "The master control interrupt lied (DE PIPE)!\n"); continue; } @@ -2547,10 +2547,10 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); if (fault_errors) - drm_err(&dev_priv->drm, - "Fault errors on pipe %c: 0x%08x\n", - pipe_name(pipe), - fault_errors); + drm_err_ratelimited(&dev_priv->drm, + "Fault errors on pipe %c: 0x%08x\n", + pipe_name(pipe), + fault_errors); } if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && -- cgit v1.2.3 From 50490ce05b7a50b0bd4108fa7d6db3ca2972fa83 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 14 Dec 2022 11:49:44 -0800 Subject: drm/i915: Remove __maybe_unused from mtl_info The attribute __maybe_unused should remain only until the respective info is not in the pciidlist. The info can't be added together with its definition because that would cause the driver to automatically probe for the device, while it's still not ready for that. However once pciidlist contains it, the attribute can be removed. Fixes: 7835303982d1 ("drm/i915/mtl: Add MeteorLake PCI IDs") Signed-off-by: Lucas De Marchi Reviewed-by: Radhakrishna Sripada Link: https://patchwork.freedesktop.org/patch/msgid/20221214194944.3670344-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 6fc4711ea632..b28ccbebc821 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1130,7 +1130,6 @@ static const struct intel_gt_definition xelpmp_extra_gt[] = { {} }; -__maybe_unused static const struct intel_device_info mtl_info = { XE_HP_FEATURES, XE_LPDP_FEATURES, -- cgit v1.2.3 From f087cfe6fcff58044f7aa3b284965af47f472fb0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Dec 2022 12:59:55 +0200 Subject: drm/i915/dsi: add support for ICL+ native MIPI GPIO sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from ICL, the default for MIPI GPIO sequences seems to be using native GPIOs i.e. GPIOs available in the GPU. These native GPIOs reuse many pins that quite frankly seem scary to poke based on the VBT sequences. We pretty much have to trust that the board is configured such that the relevant HPD, PP_CONTROL and GPIO bits aren't used for anything else. MIPI sequence v4 also adds a flag to fall back to non-native sequences. v5: - Wrap SHOTPLUG_CTL_DDI modification in spin_lock() in icp_irq_handler() too (Ville) - References instead of Closes issue 6131 because this does not fix everything v4: - Wrap SHOTPLUG_CTL_DDI modification in spin_lock_irq() (Ville) v3: - Fix -Wbitwise-conditional-parentheses (kernel test robot ) v2: - Fix HPD pin output set (impacts GPIOs 0 and 5) - Fix GPIO data output direction set (impacts GPIOs 4 and 9) - Reduce register accesses to single intel_de_rwm() References: https://gitlab.freedesktop.org/drm/intel/-/issues/6131 Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221219105955.4014451-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 94 +++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_irq.c | 3 + drivers/gpu/drm/i915/i915_reg.h | 1 + 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index fce69fa446d5..41f025f089d9 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -41,9 +41,11 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dsi.h" #include "intel_dsi_vbt.h" +#include "intel_gmbus_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" #include "vlv_sideband.h" @@ -377,6 +379,85 @@ static void icl_exec_gpio(struct intel_connector *connector, drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n"); } +enum { + MIPI_RESET_1 = 0, + MIPI_AVDD_EN_1, + MIPI_BKLT_EN_1, + MIPI_AVEE_EN_1, + MIPI_VIO_EN_1, + MIPI_RESET_2, + MIPI_AVDD_EN_2, + MIPI_BKLT_EN_2, + MIPI_AVEE_EN_2, + MIPI_VIO_EN_2, +}; + +static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, + int gpio, bool value) +{ + int index; + + if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2)) + return; + + switch (gpio) { + case MIPI_RESET_1: + case MIPI_RESET_2: + index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B; + + /* + * Disable HPD to set the pin to output, and set output + * value. The HPD pin should not be enabled for DSI anyway, + * assuming the board design and VBT are sane, and the pin isn't + * used by a non-DSI encoder. + * + * The locking protects against concurrent SHOTPLUG_CTL_DDI + * modifications in irq setup and handling. + */ + spin_lock_irq(&dev_priv->irq_lock); + intel_de_rmw(dev_priv, SHOTPLUG_CTL_DDI, + SHOTPLUG_CTL_DDI_HPD_ENABLE(index) | + SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index), + value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0); + spin_unlock_irq(&dev_priv->irq_lock); + break; + case MIPI_AVDD_EN_1: + case MIPI_AVDD_EN_2: + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; + + intel_de_rmw(dev_priv, PP_CONTROL(index), PANEL_POWER_ON, + value ? PANEL_POWER_ON : 0); + break; + case MIPI_BKLT_EN_1: + case MIPI_BKLT_EN_2: + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; + + intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, + value ? EDP_BLC_ENABLE : 0); + break; + case MIPI_AVEE_EN_1: + case MIPI_AVEE_EN_2: + index = gpio == MIPI_AVEE_EN_1 ? 1 : 2; + + intel_de_rmw(dev_priv, GPIO(dev_priv, index), + GPIO_CLOCK_VAL_OUT, + GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT | + GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0)); + break; + case MIPI_VIO_EN_1: + case MIPI_VIO_EN_2: + index = gpio == MIPI_VIO_EN_1 ? 1 : 2; + + intel_de_rmw(dev_priv, GPIO(dev_priv, index), + GPIO_DATA_VAL_OUT, + GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT | + GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0)); + break; + default: + MISSING_CASE(gpio); + } +} + static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) { struct drm_device *dev = intel_dsi->base.base.dev; @@ -384,8 +465,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) struct intel_connector *connector = intel_dsi->attached_connector; u8 gpio_source, gpio_index = 0, gpio_number; bool value; - - drm_dbg_kms(&dev_priv->drm, "\n"); + bool native = DISPLAY_VER(dev_priv) >= 11; if (connector->panel.vbt.dsi.seq_version >= 3) gpio_index = *data++; @@ -398,10 +478,18 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) else gpio_source = 0; + if (connector->panel.vbt.dsi.seq_version >= 4 && *data & BIT(1)) + native = false; + /* pull up/down */ value = *data++ & 1; - if (DISPLAY_VER(dev_priv) >= 11) + drm_dbg_kms(&dev_priv->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n", + gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value)); + + if (native) + icl_native_gpio_set_value(dev_priv, gpio_number, value); + else if (DISPLAY_VER(dev_priv) >= 11) icl_exec_gpio(connector, gpio_source, gpio_index, value); else if (IS_VALLEYVIEW(dev_priv)) vlv_exec_gpio(connector, gpio_source, gpio_number, value); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2c58d1c58e78..c4e46da6502c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1973,7 +1973,10 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) if (ddi_hotplug_trigger) { u32 dig_hotplug_reg; + /* Locking due to DSI native GPIO sequences */ + spin_lock(&dev_priv->irq_lock); dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); + spin_unlock(&dev_priv->irq_lock); intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, ddi_hotplug_trigger, dig_hotplug_reg, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7ca676a9c50c..37452140cb93 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5962,6 +5962,7 @@ #define SHOTPLUG_CTL_DDI _MMIO(0xc4030) #define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (_HPD_PIN_DDI(hpd_pin) * 4)) +#define SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(hpd_pin) (0x4 << (_HPD_PIN_DDI(hpd_pin) * 4)) #define SHOTPLUG_CTL_DDI_HPD_STATUS_MASK(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4)) #define SHOTPLUG_CTL_DDI_HPD_NO_DETECT(hpd_pin) (0x0 << (_HPD_PIN_DDI(hpd_pin) * 4)) #define SHOTPLUG_CTL_DDI_HPD_SHORT_DETECT(hpd_pin) (0x1 << (_HPD_PIN_DDI(hpd_pin) * 4)) -- cgit v1.2.3 From 5add4575c298546ed67162c6db5ed8aa4886f803 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 7 Dec 2022 20:24:36 +0530 Subject: drm/i915/ddi: Align timeout for DDI_BUF_CTL active with Bspec For Gen12+ wait for 1ms for Combo Phy and 3ms for TC Phy for DDI_BUF_CTL to be active for TC phy. (Bspec:49190) v2: Minor refactoring for better readability. v3: Rebased and retained the order of checking platforms. (Imre) Signed-off-by: Ankit Nautiyal Signed-off-by: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20221207145436.1510625-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 69595cbb2766..f2fb0e6e6259 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -185,6 +185,8 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, enum port port) { + enum phy phy = intel_port_to_phy(dev_priv, port); + int timeout_us; int ret; /* Wait > 518 usecs for DDI_BUF_CTL to be non idle */ @@ -193,8 +195,19 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, return; } + if (IS_DG2(dev_priv)) { + timeout_us = 1200; + } else if (DISPLAY_VER(dev_priv) >= 12) { + if (intel_phy_is_tc(dev_priv, phy)) + timeout_us = 3000; + else + timeout_us = 1000; + } else { + timeout_us = 500; + } + ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & - DDI_BUF_IS_IDLE), IS_DG2(dev_priv) ? 1200 : 500, 10, 10); + DDI_BUF_IS_IDLE), timeout_us, 10, 10); if (ret) drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n", -- cgit v1.2.3 From 65e75eda82d8857ab8732b98ead6997a8afeab4a Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Sun, 27 Nov 2022 10:52:32 +0530 Subject: drm/i915/ddi: Add missing wait-for-active for HDMI aligning with bspec updates After enabling DDI_BUF_CTL, wait for DDI_BUF_CTL to be active. Bspec:4232,53339,49191,54145 Signed-off-by: Ankit Nautiyal Signed-off-by: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20221127052232.3942831-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index f2fb0e6e6259..1f5a471a0adf 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2946,6 +2946,8 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, } intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl); + intel_wait_ddi_buf_active(dev_priv, port); + intel_audio_codec_enable(encoder, crtc_state, conn_state); } -- cgit v1.2.3 From a561933c571798868b5fa42198427a7e6df56c09 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 20 Dec 2022 16:01:05 +0200 Subject: drm/i915/dsi: fix MIPI_BKLT_EN_1 native GPIO index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to copy-paste fail, MIPI_BKLT_EN_1 would always use PPS index 1, never 0. Fix the sloppiest commit in recent memory. Fixes: f087cfe6fcff ("drm/i915/dsi: add support for ICL+ native MIPI GPIO sequence") Reported-by: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221220140105.313333-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 41f025f089d9..2cbc1292ab38 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -430,7 +430,7 @@ static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, break; case MIPI_BKLT_EN_1: case MIPI_BKLT_EN_2: - index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; + index = gpio == MIPI_BKLT_EN_1 ? 0 : 1; intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, value ? EDP_BLC_ENABLE : 0); -- cgit v1.2.3 From 084aab04cc60e5eab32287d0483c33e12c92da87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Thu, 1 Dec 2022 09:23:08 +0200 Subject: drm/i915/psr: Add continuous full frame bit together with single MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are observing occasionally display flickering or complete freeze. This is narrowed down to be caused by single full frame update (SFF). SFF bit after it's written gets cleared by HW in subsequent vblank i.e. when the update is sent to the panel. SFF bit is required to be written together with partial frame update (PFU) bit. After the SFF bit gets cleared by the HW psr2 man trk ctl register still contains PFU bit. If there is subsequent update for any reason we will end up having selective update/fetch configuration where start line is 0 and end line is 0. Also selective fetch configuration for the planes is not properly performed. This seems to be causing problems with some panels. Using CFF without SFF doesn't work either because it may happen that psr2 man track ctl register is overwritten by next update before vblank triggers sending the update. This is causing problems to psr_invalidate/flush. Using CFF and SFF together solves the problems as SFF is cleared only by HW in subsequent vblank and the update gets sent. Fix the flickering/freeze issue by keeping CFF bit as set when PSR2 is enabled unless there is a properly configured selective update via atomic commit. v2: - Improve commit message and comments - No functional changes This is also workaround for HSD 14014971508 Cc: Ville Syrjälä Cc: José Roberto de Souza Cc: Mika Kahola Reported-by: Lee Shawn C Signed-off-by: Jouni Högander Tested-by: Lee Shawn C Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221201072308.1905679-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 9820e5fdd087..d0d774219cc5 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1521,7 +1521,8 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), man_trk_ctl_enable_bit_get(dev_priv) | man_trk_ctl_partial_frame_bit_get(dev_priv) | - man_trk_ctl_single_full_frame_bit_get(dev_priv)); + man_trk_ctl_single_full_frame_bit_get(dev_priv) | + man_trk_ctl_continuos_full_frame(dev_priv)); /* * Display WA #0884: skl+ @@ -1635,11 +1636,8 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, val |= man_trk_ctl_partial_frame_bit_get(dev_priv); if (full_update) { - /* - * Not applying Wa_14014971508:adlp,mtl as we do not support the - * feature that requires this workaround. - */ val |= man_trk_ctl_single_full_frame_bit_get(dev_priv); + val |= man_trk_ctl_continuos_full_frame(dev_priv); goto exit; } @@ -2318,12 +2316,15 @@ static void _psr_flush_handle(struct intel_dp *intel_dp) /* can we turn CFF off? */ if (intel_dp->psr.busy_frontbuffer_bits == 0) { u32 val = man_trk_ctl_enable_bit_get(dev_priv) | - man_trk_ctl_partial_frame_bit_get(dev_priv) | - man_trk_ctl_single_full_frame_bit_get(dev_priv); + man_trk_ctl_partial_frame_bit_get(dev_priv) | + man_trk_ctl_single_full_frame_bit_get(dev_priv) | + man_trk_ctl_continuos_full_frame(dev_priv); /* - * turn continuous full frame off and do a single - * full frame + * Set psr2_sel_fetch_cff_enabled as false to allow selective + * updates. Still keep cff bit enabled as we don't have proper + * SU configuration in case update is sent for any reason after + * sff bit gets cleared by the HW on next vblank. */ intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), val); -- cgit v1.2.3 From be3ad78dfed2af3c293e01f3c5f13ee1af3395c3 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 20 Dec 2022 18:29:26 +0200 Subject: drm/i915/mtl: Add support of Tile4 to MTL We have some Tile4 tests now skipping, which were supposed to be working. So lets make them work, by adding display_ver 14 as supported. v2: - Remove "14" for Tile 4 CCS formats, as they seem to be not supported by MTL(Juha-Pekka Heikkila) - For generic Tile 4, the opposite - lets use -1 in order to make sure all the next gens support it by default(Juha-Pekka Heikkila) Signed-off-by: Stanislav Lisovskiy Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20221220162926.22805-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 63137ae5ab21..93d0e46e5481 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -174,7 +174,7 @@ static const struct intel_modifier_desc intel_modifiers[] = { .plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC, }, { .modifier = I915_FORMAT_MOD_4_TILED, - .display_ver = { 13, 13 }, + .display_ver = { 13, -1 }, .plane_caps = INTEL_PLANE_CAP_TILING_4, }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, -- cgit v1.2.3 From 6ed879b08f210bd1d312eaada653e6a82894060a Mon Sep 17 00:00:00 2001 From: Jonathan Cavitt Date: Wed, 21 Dec 2022 07:35:14 -0800 Subject: drm/i915: Enable XE_HP 4Tile support Add .has_4tile tag to XE_HP_FEATURES set. Remove duplicate entry from DG2_FEATURES. Signed-off-by: Jonathan Cavitt Cc: Bommu Krishnaiah Cc: Roper Matthew D Cc: Kempczynski Zbigniew Cc: Telukuntla Sreedhar Acked-by: Matt Roper Reviewed-by: Juha-Pekka Heikkila Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221221153514.3874262-1-jonathan.cavitt@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 48225bf6efe7..a65802b252f2 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1017,6 +1017,7 @@ static const struct intel_device_info adl_p_info = { .has_3d_pipeline = 1, \ .has_64bit_reloc = 1, \ .has_flat_ccs = 1, \ + .has_4tile = 1, \ .has_global_mocs = 1, \ .has_gt_uc = 1, \ .has_llc = 1, \ @@ -1061,7 +1062,6 @@ static const struct intel_device_info xehpsdv_info = { .__runtime.graphics.ip.rel = 55, \ .__runtime.media.ip.rel = 55, \ PLATFORM(INTEL_DG2), \ - .has_4tile = 1, \ .has_64k_pages = 1, \ .has_guc_deprivilege = 1, \ .has_heci_pxp = 1, \ -- cgit v1.2.3 From acb041b3f951afe67b782a5fd5441d3668765bdd Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Fri, 30 Dec 2022 15:24:22 -0300 Subject: drm/i915/dmc: Do not require specific versions Currently, i915 interacts with the Hardware and not with any DMC ABI/API, so the API is fixed within the platform, hence no need to get this so-tied version requirement. v2: - Use link to firmware guide from kernel documentation for "References:" instead of mailing list thread. (Rodrigo) - Provide a more elaborate justification in the commit message. (Rodrigo) References: https://www.kernel.org/doc/html/v6.1/driver-api/firmware/firmware-usage-guidelines.html Signed-off-by: Gustavo Sousa Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20221230182422.29680-2-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 35 -------------------------------- drivers/gpu/drm/i915/display/intel_dmc.h | 1 - 2 files changed, 36 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 905b5dcdca14..4124b3d37110 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -53,51 +53,40 @@ #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE #define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) -#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 8) MODULE_FIRMWARE(DG2_DMC_PATH); #define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) -#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); #define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) -#define ADLS_DMC_VERSION_REQUIRED DMC_VERSION(2, 1) MODULE_FIRMWARE(ADLS_DMC_PATH); #define DG1_DMC_PATH DMC_PATH(dg1, 2, 02) -#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2) MODULE_FIRMWARE(DG1_DMC_PATH); #define RKL_DMC_PATH DMC_PATH(rkl, 2, 03) -#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 3) MODULE_FIRMWARE(RKL_DMC_PATH); #define TGL_DMC_PATH DMC_PATH(tgl, 2, 12) -#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 12) MODULE_FIRMWARE(TGL_DMC_PATH); #define ICL_DMC_PATH DMC_PATH(icl, 1, 09) -#define ICL_DMC_VERSION_REQUIRED DMC_VERSION(1, 9) #define ICL_DMC_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(ICL_DMC_PATH); #define GLK_DMC_PATH DMC_PATH(glk, 1, 04) -#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4) #define GLK_DMC_MAX_FW_SIZE 0x4000 MODULE_FIRMWARE(GLK_DMC_PATH); #define KBL_DMC_PATH DMC_PATH(kbl, 1, 04) -#define KBL_DMC_VERSION_REQUIRED DMC_VERSION(1, 4) #define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(KBL_DMC_PATH); #define SKL_DMC_PATH DMC_PATH(skl, 1, 27) -#define SKL_DMC_VERSION_REQUIRED DMC_VERSION(1, 27) #define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(SKL_DMC_PATH); #define BXT_DMC_PATH DMC_PATH(bxt, 1, 07) -#define BXT_DMC_VERSION_REQUIRED DMC_VERSION(1, 7) #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); @@ -765,17 +754,6 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc, return 0; } - if (dmc->required_version && - css_header->version != dmc->required_version) { - drm_info(&i915->drm, "Refusing to load DMC firmware v%u.%u," - " please use v%u.%u\n", - DMC_VERSION_MAJOR(css_header->version), - DMC_VERSION_MINOR(css_header->version), - DMC_VERSION_MAJOR(dmc->required_version), - DMC_VERSION_MINOR(dmc->required_version)); - return 0; - } - dmc->version = css_header->version; return sizeof(struct intel_css_header); @@ -903,49 +881,38 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) if (IS_DG2(dev_priv)) { dmc->fw_path = DG2_DMC_PATH; - dmc->required_version = DG2_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; } else if (IS_ALDERLAKE_P(dev_priv)) { dmc->fw_path = ADLP_DMC_PATH; - dmc->required_version = ADLP_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; } else if (IS_ALDERLAKE_S(dev_priv)) { dmc->fw_path = ADLS_DMC_PATH; - dmc->required_version = ADLS_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_DG1(dev_priv)) { dmc->fw_path = DG1_DMC_PATH; - dmc->required_version = DG1_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_ROCKETLAKE(dev_priv)) { dmc->fw_path = RKL_DMC_PATH; - dmc->required_version = RKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (IS_TIGERLAKE(dev_priv)) { dmc->fw_path = TGL_DMC_PATH; - dmc->required_version = TGL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; } else if (DISPLAY_VER(dev_priv) == 11) { dmc->fw_path = ICL_DMC_PATH; - dmc->required_version = ICL_DMC_VERSION_REQUIRED; dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE; } else if (IS_GEMINILAKE(dev_priv)) { dmc->fw_path = GLK_DMC_PATH; - dmc->required_version = GLK_DMC_VERSION_REQUIRED; dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE; } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv)) { dmc->fw_path = KBL_DMC_PATH; - dmc->required_version = KBL_DMC_VERSION_REQUIRED; dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE; } else if (IS_SKYLAKE(dev_priv)) { dmc->fw_path = SKL_DMC_PATH; - dmc->required_version = SKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE; } else if (IS_BROXTON(dev_priv)) { dmc->fw_path = BXT_DMC_PATH; - dmc->required_version = BXT_DMC_VERSION_REQUIRED; dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE; } @@ -958,8 +925,6 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) } dmc->fw_path = dev_priv->params.dmc_firmware_path; - /* Bypass version check for firmware override. */ - dmc->required_version = 0; } if (!dmc->fw_path) { diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 67e03315ef99..435eab9b016b 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -25,7 +25,6 @@ enum { struct intel_dmc { struct work_struct work; const char *fw_path; - u32 required_version; u32 max_fw_size; /* bytes */ u32 version; struct dmc_fw_info { -- cgit v1.2.3 From 5a9b0c7418448ed3766f61ba0a71d08f259c3181 Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Wed, 21 Dec 2022 09:02:09 +0530 Subject: drm/i915/dp: change aux_ctl reg read to polling read The busy timeout logic checks for the AUX BUSY, then waits for the timeout period and then after timeout reads the register for BUSY or Success. Instead replace interrupt with polling so as to read the AUX CTL register often before the timeout period. Looks like there might be some issue with interrupt-on-read. Hence changing the logic to polling read. v2: replace interrupt with polling read v3: use usleep_rang instead of msleep, updated commit msg v4: use intel_wait_for_regiter internal function v5: use __intel_de_wait_for_register with 500us slow and 10ms fast timeout v6: check return value of __intel_de_wait_for_register v7: using default 2us for intel_de_wait_for_register Signed-off-by: Arun R Murthy Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20221221033209.1284435-1-arun.r.murthy@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 91c93c93e5fc..5a176bfb10a2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -41,20 +41,16 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp) i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); const unsigned int timeout_ms = 10; u32 status; - bool done; - -#define C (((status = intel_de_read_notrace(i915, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) - done = wait_event_timeout(i915->display.gmbus.wait_queue, C, - msecs_to_jiffies_timeout(timeout_ms)); + int ret; - /* just trace the final value */ - trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); + ret = __intel_de_wait_for_register(i915, ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY, 0, + 2, timeout_ms, &status); - if (!done) + if (ret == -ETIMEDOUT) drm_err(&i915->drm, "%s: did not complete or timeout within %ums (status 0x%08x)\n", intel_dp->aux.name, timeout_ms, status); -#undef C return status; } -- cgit v1.2.3 From 157821fb3e9aaa07cf408686b08d117bf27b7de1 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 3 Jan 2023 14:47:01 -0500 Subject: drm/i915: Expand force_probe to block probe of devices as well. There are new cases where we want to block i915 probe, such as when experimenting or developing the new Xe driver. But also, with the new hybrid cards, users or developers might want to use i915 only on integrated and fully block the probe of the i915 for the discrete. Or vice versa. There are even older development and validation reasons, like when you use some distro where the modprobe.blacklist is not present. But in any case, let's introduce a more granular control, but without introducing yet another parameter, but using the existent force_probe one. Just by adding a ! in the begin of the id in the force_probe, like in this case where we would block the probe for Alder Lake: $ insmod i915.ko force_probe='!46a6' v2: Take care of '*' and '!*' cases as pointed out by Gustavo and Jani. Cc: Jani Nikula Cc: Gustavo Sousa Signed-off-by: Rodrigo Vivi Reviewed-by: Jani Nikula Acked-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20230103194701.1492984-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/Kconfig | 15 ++++++++++++--- drivers/gpu/drm/i915/i915_params.c | 2 +- drivers/gpu/drm/i915/i915_pci.c | 33 ++++++++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 3efce05d7b57..8eb3e60aeec9 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -54,24 +54,33 @@ config DRM_I915 If "M" is selected, the module will be called i915. config DRM_I915_FORCE_PROBE - string "Force probe driver for selected new Intel hardware" + string "Force probe i915 for selected Intel hardware IDs" depends on DRM_I915 help This is the default value for the i915.force_probe module parameter. Using the module parameter overrides this option. - Force probe the driver for new Intel graphics devices that are + Force probe the i915 for Intel graphics devices that are recognized but not properly supported by this kernel version. It is recommended to upgrade to a kernel version with proper support as soon as it is available. + It can also be used to block the probe of recognized and fully + supported devices. + Use "" to disable force probe. If in doubt, use this. - Use "[,,...]" to force probe the driver for listed + Use "[,,...]" to force probe the i915 for listed devices. For example, "4500" or "4500,4571". Use "*" to force probe the driver for all known devices. + Use "!" right before the ID to block the probe of the device. For + example, "4500,!4571" forces the probe of 4500 and blocks the probe of + 4571. + + Use "!*" to block the probe of the driver for all known devices. + config DRM_I915_CAPTURE_ERROR bool "Enable capturing GPU state following a hang" depends on DRM_I915 diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index d1e4d528cb17..5b24dd50fb6a 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -122,7 +122,7 @@ i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, "Default: 0"); i915_param_named_unsafe(force_probe, charp, 0400, - "Force probe the driver for specified devices. " + "Force probe options for specified supported devices. " "See CONFIG_DRM_I915_FORCE_PROBE for details."); i915_param_named_unsafe(disable_power_well, int, 0400, diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index a65802b252f2..0f3e0ce416f8 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1253,7 +1253,7 @@ static void i915_pci_remove(struct pci_dev *pdev) } /* is device_id present in comma separated list of ids */ -static bool force_probe(u16 device_id, const char *devices) +static bool device_id_in_list(u16 device_id, const char *devices, bool negative) { char *s, *p, *tok; bool ret; @@ -1262,7 +1262,9 @@ static bool force_probe(u16 device_id, const char *devices) return false; /* match everything */ - if (strcmp(devices, "*") == 0) + if (negative && strcmp(devices, "!*") == 0) + return true; + if (!negative && strcmp(devices, "*") == 0) return true; s = kstrdup(devices, GFP_KERNEL); @@ -1272,6 +1274,12 @@ static bool force_probe(u16 device_id, const char *devices) for (p = s, ret = false; (tok = strsep(&p, ",")) != NULL; ) { u16 val; + if (negative && tok[0] == '!') + tok++; + else if ((negative && tok[0] != '!') || + (!negative && tok[0] == '!')) + continue; + if (kstrtou16(tok, 16, &val) == 0 && val == device_id) { ret = true; break; @@ -1283,6 +1291,16 @@ static bool force_probe(u16 device_id, const char *devices) return ret; } +static bool id_forced(u16 device_id) +{ + return device_id_in_list(device_id, i915_modparams.force_probe, false); +} + +static bool id_blocked(u16 device_id) +{ + return device_id_in_list(device_id, i915_modparams.force_probe, true); +} + bool i915_pci_resource_valid(struct pci_dev *pdev, int bar) { if (!pci_resource_flags(pdev, bar)) @@ -1308,10 +1326,9 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (struct intel_device_info *) ent->driver_data; int err; - if (intel_info->require_force_probe && - !force_probe(pdev->device, i915_modparams.force_probe)) { + if (intel_info->require_force_probe && !id_forced(pdev->device)) { dev_info(&pdev->dev, - "Your graphics device %04x is not properly supported by the driver in this\n" + "Your graphics device %04x is not properly supported by i915 in this\n" "kernel version. To force driver probe anyway, use i915.force_probe=%04x\n" "module parameter or CONFIG_DRM_I915_FORCE_PROBE=%04x configuration option,\n" "or (recommended) check for kernel updates.\n", @@ -1319,6 +1336,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (id_blocked(pdev->device)) { + dev_info(&pdev->dev, "I915 probe blocked for Device ID %04x.\n", + pdev->device); + return -ENODEV; + } + /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both -- cgit v1.2.3 From 7e095a4ca32a7169d7c9cce16318b532c85bb39b Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 5 Jan 2023 21:38:43 +0100 Subject: drm/i915: Update docs in intel_wakeref.h Fix docs for __intel_wakeref_put() and intel_wakeref_get() to reflect current behaviour. Signed-off-by: Nirmoy Das Reviewed-by: Ashutosh Dixit Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230105203843.30663-1-nirmoy.das@intel.com --- drivers/gpu/drm/i915/intel_wakeref.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 4f4c2e15e736..71b8a63f6f10 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -68,11 +68,12 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); * @wf: the wakeref * * Acquire a hold on the wakeref. The first user to do so, will acquire - * the runtime pm wakeref and then call the @fn underneath the wakeref - * mutex. + * the runtime pm wakeref and then call the intel_wakeref_ops->get() + * underneath the wakeref mutex. * - * Note that @fn is allowed to fail, in which case the runtime-pm wakeref - * will be released and the acquisition unwound, and an error reported. + * Note that intel_wakeref_ops->get() is allowed to fail, in which case + * the runtime-pm wakeref will be released and the acquisition unwound, + * and an error reported. * * Returns: 0 if the wakeref was acquired successfully, or a negative error * code otherwise. @@ -130,19 +131,17 @@ intel_wakeref_might_get(struct intel_wakeref *wf) } /** - * intel_wakeref_put_flags: Release the wakeref + * __intel_wakeref_put: Release the wakeref * @wf: the wakeref * @flags: control flags * * Release our hold on the wakeref. When there are no more users, - * the runtime pm wakeref will be released after the @fn callback is called - * underneath the wakeref mutex. + * the runtime pm wakeref will be released after the intel_wakeref_ops->put() + * callback is called underneath the wakeref mutex. * - * Note that @fn is allowed to fail, in which case the runtime-pm wakeref - * is retained and an error reported. + * Note that intel_wakeref_ops->put() is allowed to fail, in which case the + * runtime-pm wakeref is retained. * - * Returns: 0 if the wakeref was released successfully, or a negative error - * code otherwise. */ static inline void __intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) -- cgit v1.2.3 From a6fd6f94d36122d8962ba8a24194299a6bb1ecc1 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Mon, 9 Jan 2023 16:02:10 +0200 Subject: drm/i915: Fix timeslots argument for DP DSC SST case We now accept timeslots param exactly how the variable sounds: amount of timeslots, but not ratio timeslots/64. So for SST case(when we have all timeslots for use), it should be 64, but not 1. This caused some issues in the tests. v2: Fixed comments References: https://gitlab.freedesktop.org/drm/intel/-/issues/6860 Fixes: 52f14682ac4d ("drm/i915: Bpp/timeslot calculation fixes for DP MST DSC") Reviewed-by: Manasi Navare Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20230109140210.25822-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index bf80f296a8fd..30c55f980014 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -713,9 +713,9 @@ u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, /* * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* - * (LinkSymbolClock)* 8 * (TimeSlotsPerMTP) - * for SST -> TimeSlotsPerMTP is 1, - * for MST -> TimeSlotsPerMTP has to be calculated + * (LinkSymbolClock)* 8 * (TimeSlots / 64) + * for SST -> TimeSlots is 64(i.e all TimeSlots that are available) + * for MST -> TimeSlots has to be calculated, based on mode requirements */ bits_per_pixel = DIV_ROUND_UP((link_clock * lane_count) * timeslots, intel_dp_mode_to_fec_clock(mode_clock) * 8); @@ -1685,7 +1685,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, - conn_state, &limits, 1, true); + conn_state, &limits, 64, true); if (ret < 0) return ret; } -- cgit v1.2.3 From 8d4312e2b228ba7a5ac79154458098274ec61e9b Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 23 Dec 2022 15:05:08 +0200 Subject: drm/i915/mtl: limit second scaler vertical scaling in ver >= 14 In newer hardware versions (i.e. display version >= 14), the second scaler doesn't support vertical scaling. The current implementation of the scaling limits is simplified and only occurs when the planes are created, so we don't know which scaler is being used. In order to handle separate scaling limits for horizontal and vertical scaling, and different limits per scaler, split the checks in two phases. We first do a simple check during plane creation and use the best-case scenario (because we don't know the scaler that may be used at a later point) and then do a more specific check when the scalers are actually being set up. Signed-off-by: Luca Coelho Reviewed-by: Stanislav Lisovskiy Signed-off-by: Radhakrishna Sripada Link: https://patchwork.freedesktop.org/patch/msgid/20221223130509.43245-2-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 85 +++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 6621aa245caf..a9a3f3715279 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -41,6 +41,7 @@ #include "intel_global_state.h" #include "intel_hdcp.h" #include "intel_psr.h" +#include "intel_fb.h" #include "skl_universal_plane.h" /** @@ -310,11 +311,11 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, kfree(crtc_state); } -static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, - int num_scalers_need, struct intel_crtc *intel_crtc, - const char *name, int idx, - struct intel_plane_state *plane_state, - int *scaler_id) +static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, + int num_scalers_need, struct intel_crtc *intel_crtc, + const char *name, int idx, + struct intel_plane_state *plane_state, + int *scaler_id) { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); int j; @@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta if (drm_WARN(&dev_priv->drm, *scaler_id < 0, "Cannot find scaler for %s:%d\n", name, idx)) - return; + return -EINVAL; /* set scaler mode */ if (plane_state && plane_state->hw.fb && @@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta mode = SKL_PS_SCALER_MODE_DYN; } + /* + * FIXME: we should also check the scaler factors for pfit, so + * this shouldn't be tied directly to planes. + */ + if (plane_state && plane_state->hw.fb) { + const struct drm_framebuffer *fb = plane_state->hw.fb; + const struct drm_rect *src = &plane_state->uapi.src; + const struct drm_rect *dst = &plane_state->uapi.dst; + int hscale, vscale, max_vscale, max_hscale; + + /* + * FIXME: When two scalers are needed, but only one of + * them needs to downscale, we should make sure that + * the one that needs downscaling support is assigned + * as the first scaler, so we don't reject downscaling + * unnecessarily. + */ + + if (DISPLAY_VER(dev_priv) >= 14) { + /* + * On versions 14 and up, only the first + * scaler supports a vertical scaling factor + * of more than 1.0, while a horizontal + * scaling factor of 3.0 is supported. + */ + max_hscale = 0x30000 - 1; + if (*scaler_id == 0) + max_vscale = 0x30000 - 1; + else + max_vscale = 0x10000; + + } else if (DISPLAY_VER(dev_priv) >= 10 || + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { + max_hscale = 0x30000 - 1; + max_vscale = 0x30000 - 1; + } else { + max_hscale = 0x20000 - 1; + max_vscale = 0x20000 - 1; + } + + /* + * FIXME: We should change the if-else block above to + * support HQ vs dynamic scaler properly. + */ + + /* Check if required scaling is within limits */ + hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale); + vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(&dev_priv->drm, + "Scaler %d doesn't support required plane scaling\n", + *scaler_id); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); + + return -EINVAL; + } + } + drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", intel_crtc->pipe, *scaler_id, name, idx); scaler_state->scalers[*scaler_id].mode = mode; + + return 0; } /** @@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { int *scaler_id; const char *name; - int idx; + int idx, ret; /* skip if scaler not required */ if (!(scaler_state->scaler_users & (1 << i))) @@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, scaler_id = &plane_state->scaler_id; } - intel_atomic_setup_scaler(scaler_state, num_scalers_need, - intel_crtc, name, idx, - plane_state, scaler_id); + ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need, + intel_crtc, name, idx, + plane_state, scaler_id); + if (ret < 0) + return ret; } return 0; -- cgit v1.2.3 From f840834a8b60ffd305f03a53007605ba4dfbbc4b Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Fri, 23 Dec 2022 15:05:09 +0200 Subject: drm/i915/mtl: update scaler source and destination limits for MTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The max source and destination limits for scalers in MTL have changed. Use the new values accordingly. Signed-off-by: José Roberto de Souza Signed-off-by: Animesh Manna Signed-off-by: Luca Coelho Reviewed-by: Stanislav Lisovskiy Signed-off-by: Radhakrishna Sripada Link: https://patchwork.freedesktop.org/patch/msgid/20221223130509.43245-3-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 40 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index d7390067b7d4..01e881293612 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 +#define MTL_MAX_SRC_W 4096 +#define MTL_MAX_SRC_H 8192 +#define MTL_MAX_DST_W 8192 +#define MTL_MAX_DST_H 8192 #define SKL_MIN_YUV_420_SRC_W 16 #define SKL_MIN_YUV_420_SRC_H 16 @@ -103,6 +107,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int min_src_w, min_src_h, min_dst_w, min_dst_h; + int max_src_w, max_src_h, max_dst_w, max_dst_h; /* * Src coordinates are already rotated by 270 degrees for @@ -157,15 +163,33 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, return -EINVAL; } + min_src_w = SKL_MIN_SRC_W; + min_src_h = SKL_MIN_SRC_H; + min_dst_w = SKL_MIN_DST_W; + min_dst_h = SKL_MIN_DST_H; + + if (DISPLAY_VER(dev_priv) < 11) { + max_src_w = SKL_MAX_SRC_W; + max_src_h = SKL_MAX_SRC_H; + max_dst_w = SKL_MAX_DST_W; + max_dst_h = SKL_MAX_DST_H; + } else if (DISPLAY_VER(dev_priv) < 14) { + max_src_w = ICL_MAX_SRC_W; + max_src_h = ICL_MAX_SRC_H; + max_dst_w = ICL_MAX_DST_W; + max_dst_h = ICL_MAX_DST_H; + } else { + max_src_w = MTL_MAX_SRC_W; + max_src_h = MTL_MAX_SRC_H; + max_dst_w = MTL_MAX_DST_W; + max_dst_h = MTL_MAX_DST_H; + } + /* range checks */ - if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H || - dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H || - (DISPLAY_VER(dev_priv) >= 11 && - (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H || - dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) || - (DISPLAY_VER(dev_priv) < 11 && - (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H || - dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) { + if (src_w < min_src_w || src_h < min_src_h || + dst_w < min_dst_w || dst_h < min_dst_h || + src_w > max_src_w || src_h > max_src_h || + dst_w > max_dst_w || dst_h > max_dst_h) { drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: src %ux%u dst %ux%u " "size is out of scaler range\n", -- cgit v1.2.3 From 9d04eb20bc71a383b4d4e383b0b7fac8d38a2e34 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 17 Oct 2022 20:00:37 +0530 Subject: drm/i915/display: Drop check for doublescan mode in modevalid Since the DP/HDMI connector do not set connector->doublescan_allowed, the doublescan modes will get automatically filtered during drm_helper_probe_single_connector_modes(). Therefore check for double scan modes is not required and is dropped from modevalid functions for both DP and HDMI. Signed-off-by: Ankit Nautiyal Reviewed-by: Jani Nikula Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20221017143038.1748319-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 3 --- drivers/gpu/drm/i915/display/intel_hdmi.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 30c55f980014..baf773d7384e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -992,9 +992,6 @@ intel_dp_mode_valid(struct drm_connector *_connector, enum drm_mode_status status; bool dsc = false, bigjoiner = false; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index efa2da080f62..b4323303baba 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1994,9 +1994,6 @@ intel_hdmi_mode_valid(struct drm_connector *connector, bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); bool ycbcr_420_only; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) clock *= 2; -- cgit v1.2.3 From f71c9b7bc35ff7c1fb68d114903876eec658439b Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Thu, 5 Jan 2023 18:11:25 +0530 Subject: drm/i915/display: Prune Interlace modes for Display >=12 Defeature Display Interlace support. Support for interlace modes is removed from Gen 12 onwards. Pruning the interlace modes for HDMI for Display >=12. Bspec: 50490 v2: Add check for both DP and HDMI. (Ville) Get rid of redundant check for interlace mode in modevalid. (Ville) v3: Simplify the condition to avoid interlace modes. (Jani) Signed-off-by: Ankit Nautiyal Reviewed-by: Jani Nikula Signed-off-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20230105124125.1129653-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index baf773d7384e..80d95cec8f9d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2092,7 +2092,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (HAS_GMCH(dev_priv) && + if (!connector->base.interlace_allowed && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) return -EINVAL; @@ -5435,7 +5435,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, drm_connector_init(dev, connector, &intel_dp_connector_funcs, type); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - if (!HAS_GMCH(dev_priv)) + if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12) connector->interlace_allowed = true; intel_connector->polled = DRM_CONNECTOR_POLL_HPD; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index b4323303baba..6a2ee342eab5 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2255,6 +2255,10 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; + if (!connector->interlace_allowed && + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + return -EINVAL; + pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_hdmi, conn_state) && @@ -2956,7 +2960,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, ddc); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); - connector->interlace_allowed = true; + if (DISPLAY_VER(dev_priv) < 12) + connector->interlace_allowed = true; + connector->stereo_allowed = true; if (DISPLAY_VER(dev_priv) >= 10) -- cgit v1.2.3