drm/i915/dsi: fix DSI DCS backlight port handling
cover drm/i915/dsi: fix DSI DCS backlight port handling
Hopefully fix a null pointer dereference in DSI DCS backlight handling.
Jani Nikula (3):
drm/i915/dsi: filter invalid backlight and CABC ports drm/i915/dsi: fix dual-link DSI backlight and CABC ports for display
11+
drm/i915/dsi: use VBT backlight and CABC port definitions directly
drivers/gpu/drm/i915/display/icl_dsi.c | 7 +++++-- drivers/gpu/drm/i915/display/intel_bios.c | 10 ++++++---- drivers/gpu/drm/i915/display/intel_dsi.h | 3 --- .../gpu/drm/i915/display/intel_dsi_dcs_backlight.c | 14 ++++++++------ drivers/gpu/drm/i915/display/vlv_dsi.c | 7 +++++-- 5 files changed, 24 insertions(+), 17 deletions(-)
Signature · 1 line
2.34.1
PATCH 1/3 drm/i915/dsi: filter invalid backlight and CABC ports
Avoid using ports that aren't initialized in case the VBT backlight or CABC ports have invalid values. This fixes a NULL pointer dereference of intel_dsi->dsi_hosts[port] in such cases.
--- drivers/gpu/drm/i915/display/icl_dsi.c | 7 +++++++ drivers/gpu/drm/i915/display/vlv_dsi.c | 7 +++++++ 2 files changed, 14 insertions(+)
drivers/gpu/drm/i915/display/icl_dsi.c +7 -0
@@ -2070,7 +2070,14 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)else intel_dsi->ports =BIT (port); +if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; + intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports; + +if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; + intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports;for_each_dsi_port (port, intel_dsi->ports) {
drivers/gpu/drm/i915/display/vlv_dsi.c +7 -0
@@ -1933,7 +1933,14 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)else intel_dsi->ports =BIT (port); +if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; + intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports; + +if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) + intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; + intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports;/* Create a DSI host (and a device) for each port. */
Signature · 1 line
2.34.1
PATCH 2/3 drm/i915/dsi: fix dual-link DSI backlight and CABC ports for display 11+
In reply to Jani NikulaThe VBT dual-link DSI backlight and CABC still use ports A and C, both in Bspec and code, while display 11+ DSI only supports ports A and B. Assume port C actually means port B for display 11+ when parsing VBT.
Bspec: 20154
--- drivers/gpu/drm/i915/display/intel_bios.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/display/intel_bios.c +6 -4
@@ -1596,6 +1596,8 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915, struct intel_panel *panel, enum port port) { +enum port port_bc =DISPLAY_VER (i915) >=11 ?PORT_B :PORT_C ; +if (!panel->vbt.dsi.config->dual_link || i915->vbt.version <197 ) { panel->vbt.dsi.bl_ports =BIT (port);if (panel->vbt.dsi.config->cabc_supported)
@@ -1609,11 +1611,11 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915, panel->vbt.dsi.bl_ports =BIT (PORT_A );break ;case DL_DCS_PORT_C : - panel->vbt.dsi.bl_ports =BIT (PORT_C ); + panel->vbt.dsi.bl_ports =BIT (port_bc);break ;default :case DL_DCS_PORT_A_AND_C : - panel->vbt.dsi.bl_ports =BIT (PORT_A ) |BIT (PORT_C ); + panel->vbt.dsi.bl_ports =BIT (PORT_A ) |BIT (port_bc);break ; }
@@ -1625,12 +1627,12 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915, panel->vbt.dsi.cabc_ports =BIT (PORT_A );break ;case DL_DCS_PORT_C : - panel->vbt.dsi.cabc_ports =BIT (PORT_C ); + panel->vbt.dsi.cabc_ports =BIT (port_bc);break ;default :case DL_DCS_PORT_A_AND_C : panel->vbt.dsi.cabc_ports = -BIT (PORT_A ) |BIT (PORT_C ); +BIT (PORT_A ) |BIT (port_bc);break ; } }
Signature · 1 line
2.34.1
PATCH 3/3 drm/i915/dsi: use VBT backlight and CABC port definitions directly
In reply to Jani NikulaDrop the intermediate values stored in intel_dsi and use the VBT values directly, now that they're conveniently stored in panel->vbt.
--- drivers/gpu/drm/i915/display/icl_dsi.c | 4 ---- drivers/gpu/drm/i915/display/intel_dsi.h | 3 --- .../gpu/drm/i915/display/intel_dsi_dcs_backlight.c | 14 ++++++++------ drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ---- 4 files changed, 8 insertions(+), 17 deletions(-)
drivers/gpu/drm/i915/display/icl_dsi.c +0 -4
@@ -2073,13 +2073,9 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; - intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports; -if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; - intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports; -for_each_dsi_port (port, intel_dsi->ports) {struct intel_dsi_host *host;
drivers/gpu/drm/i915/display/intel_dsi.h +0 -3
@@ -89,9 +89,6 @@ struct intel_dsi {u8 escape_clk_div;u8 dual_link; -u16 dcs_backlight_ports; -u16 dcs_cabc_ports; -/* RGB or BGR */ bool bgr_enabled;
drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c +8 -6
@@ -53,7 +53,7 @@ static u32 dcs_get_backlight(struct intel_connector *connector, enum pipe unusedenum port port;size_t len = panel->backlight.max >U8_MAX ?2 :1 ; -for_each_dsi_port (port, intel_dsi->dcs_backlight_ports) { +for_each_dsi_port (port, panel->vbt.dsi.bl_ports) { dsi_device = intel_dsi->dsi_hosts[port]->device;mipi_dsi_dcs_read (dsi_device,MIPI_DCS_GET_DISPLAY_BRIGHTNESS , &data, len);
@@ -80,7 +80,7 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 data[1 ] = level; } -for_each_dsi_port (port, intel_dsi->dcs_backlight_ports) { +for_each_dsi_port (port, panel->vbt.dsi.bl_ports) { dsi_device = intel_dsi->dsi_hosts[port]->device; mode_flags = dsi_device->mode_flags; dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM ;
@@ -93,12 +93,13 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32static void dcs_disable_backlight (const struct drm_connector_state *conn_state,u32 level) {struct intel_dsi *intel_dsi =enc_to_intel_dsi (to_intel_encoder (conn_state->best_encoder)); +struct intel_panel *panel = &to_intel_connector (conn_state->connector)->panel;struct mipi_dsi_device *dsi_device;enum port port;dcs_set_backlight (conn_state,0 ); -for_each_dsi_port (port, intel_dsi->dcs_cabc_ports) { +for_each_dsi_port (port, panel->vbt.dsi.cabc_ports) {u8 cabc =POWER_SAVE_OFF ; dsi_device = intel_dsi->dsi_hosts[port]->device;
@@ -106,7 +107,7 @@ static void dcs_disable_backlight(const struct drm_connector_state *conn_state, &cabc, sizeof(cabc)); } -for_each_dsi_port (port, intel_dsi->dcs_backlight_ports) { +for_each_dsi_port (port, panel->vbt.dsi.bl_ports) {u8 ctrl =0 ; dsi_device = intel_dsi->dsi_hosts[port]->device;
@@ -127,10 +128,11 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, u32 level) {struct intel_dsi *intel_dsi =enc_to_intel_dsi (to_intel_encoder (conn_state->best_encoder)); +struct intel_panel *panel = &to_intel_connector (conn_state->connector)->panel;struct mipi_dsi_device *dsi_device;enum port port; -for_each_dsi_port (port, intel_dsi->dcs_backlight_ports) { +for_each_dsi_port (port, panel->vbt.dsi.bl_ports) {u8 ctrl =0 ; dsi_device = intel_dsi->dsi_hosts[port]->device;
@@ -146,7 +148,7 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state, &ctrl, sizeof(ctrl)); } -for_each_dsi_port (port, intel_dsi->dcs_cabc_ports) { +for_each_dsi_port (port, panel->vbt.dsi.cabc_ports) {u8 cabc =POWER_SAVE_MEDIUM ; dsi_device = intel_dsi->dsi_hosts[port]->device;
drivers/gpu/drm/i915/display/vlv_dsi.c +0 -4
@@ -1936,13 +1936,9 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; - intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports; -if (drm_WARN_ON (&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; - intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports; -/* Create a DSI host (and a device) for each port. */ for_each_dsi_port (port, intel_dsi->ports) {struct intel_dsi_host *host;
Signature · 1 line
2.34.1