summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-07-17 10:40:39 +1000
committerDave Airlie <airlied@redhat.com>2026-07-17 10:41:02 +1000
commit2e33bfe53cba8558eb83f3fd327d0a5e21172baa (patch)
tree3db3d70d73a6f39d4fbef9482989954a8e4bd696
parent295a8c0b0e44760ef7e06c55beacbe0caafe1ce7 (diff)
parentec6444a00c49e6c2b5e9a507272a28126677f9ee (diff)
Merge tag 'drm-misc-next-2026-07-16' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for 7.3: UAPI Changes: Cross-subsystem Changes: Core Changes: - blend: allow blend mode property without PREMULTI - bridges: - Rename drm_for_each_bridge_in_chain_scoped to drm_for_each_bridge_in_chain - Drop legacy bridges support - gpusvm: Code reorganization to give drivers more flexibility Driver Changes: - etnaviv: Check if a reset has been successful - nouveau: Create instmem iomapping at first use - panthor: Remove redundant cleanup - qxl: Convert to a simple encoder to a regular one - bridges: - Convert all remaining legacy bridges to atomic - tc358767: clamp the reported AUX read size to the request - panels: - novatek-nt37801: Use mipi_dsi_*_multi() functions - samsung-s6d16d0: Fix prepare error handling Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://patch.msgid.link/20260716-famous-pastel-ostrich-a1aaef@houat
-rw-r--r--.clang-format2
-rw-r--r--drivers/gpu/drm/adp/adp-mipi.c4
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c13
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c13
-rw-r--r--drivers/gpu/drm/bridge/aux-bridge.c4
-rw-r--r--drivers/gpu/drm/bridge/aux-hpd-bridge.c4
-rw-r--r--drivers/gpu/drm/bridge/chrontel-ch7033.c13
-rw-r--r--drivers/gpu/drm/bridge/cros-ec-anx7688.c4
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8713sx.c4
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8912b.c8
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c3
-rw-r--r--drivers/gpu/drm/bridge/lvds-codec.c10
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c3
-rw-r--r--drivers/gpu/drm/bridge/microchip-lvds.c3
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c17
-rw-r--r--drivers/gpu/drm/bridge/of-display-mode-bridge.c4
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c18
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c2
-rw-r--r--drivers/gpu/drm/bridge/sii9234.c39
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c4
-rw-r--r--drivers/gpu/drm/bridge/simple-bridge.c13
-rw-r--r--drivers/gpu/drm/bridge/tc358764.c13
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c2
-rw-r--r--drivers/gpu/drm/bridge/tda998x_drv.c13
-rw-r--r--drivers/gpu/drm/bridge/thc63lvd1024.c14
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c10
-rw-r--r--drivers/gpu/drm/bridge/ti-tpd12s015.c4
-rw-r--r--drivers/gpu/drm/bridge/waveshare-dsi.c14
-rw-r--r--drivers/gpu/drm/display/drm_bridge_connector.c4
-rw-r--r--drivers/gpu/drm/drm_atomic.c2
-rw-r--r--drivers/gpu/drm/drm_blend.c20
-rw-r--r--drivers/gpu/drm/drm_bridge.c65
-rw-r--r--drivers/gpu/drm/drm_gpusvm.c243
-rw-r--r--drivers/gpu/drm/drm_mode_config.c21
-rw-r--r--drivers/gpu/drm/drm_of.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c23
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c14
-rw-r--r--drivers/gpu/drm/imx/dc/dc-ic.c6
-rw-r--r--drivers/gpu/drm/mcde/mcde_dsi.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c10
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c14
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c14
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c14
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c14
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt37801.c110
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6d16d0.c10
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c1
-rw-r--r--drivers/gpu/drm/panthor/panthor_sched.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c12
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c20
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c20
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c20
-rw-r--r--drivers/gpu/drm/tests/drm_bridge_test.c106
-rw-r--r--drivers/gpu/drm/xe/xe_pt.c2
-rw-r--r--drivers/gpu/drm/xe/xe_svm.c66
-rw-r--r--drivers/gpu/drm/xe/xe_svm.h14
-rw-r--r--drivers/gpu/drm/xe/xe_userptr.c5
-rw-r--r--include/drm/drm_bridge.h114
-rw-r--r--include/drm/drm_gpusvm.h67
63 files changed, 728 insertions, 618 deletions
diff --git a/.clang-format b/.clang-format
index 6a3de86ab27a..5ef5743b77c9 100644
--- a/.clang-format
+++ b/.clang-format
@@ -167,7 +167,7 @@ ForEachMacros:
- 'drm_connector_for_each_possible_encoder'
- 'drm_exec_for_each_locked_object'
- 'drm_exec_for_each_locked_object_reverse'
- - 'drm_for_each_bridge_in_chain_scoped'
+ - 'drm_for_each_bridge_in_chain'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_crtc_reverse'
diff --git a/drivers/gpu/drm/adp/adp-mipi.c b/drivers/gpu/drm/adp/adp-mipi.c
index cba7d32150a9..232bb9539423 100644
--- a/drivers/gpu/drm/adp/adp-mipi.c
+++ b/drivers/gpu/drm/adp/adp-mipi.c
@@ -5,6 +5,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_mipi_dsi.h>
@@ -222,6 +223,9 @@ static int adp_dsi_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs adp_dsi_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = adp_dsi_bridge_attach,
};
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index f3fe47b12edc..eba5c6dcb5ad 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -566,7 +566,8 @@ anx6345_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void anx6345_bridge_disable(struct drm_bridge *bridge)
+static void anx6345_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct anx6345 *anx6345 = bridge_to_anx6345(bridge);
@@ -580,7 +581,8 @@ static void anx6345_bridge_disable(struct drm_bridge *bridge)
anx6345_poweroff(anx6345);
}
-static void anx6345_bridge_enable(struct drm_bridge *bridge)
+static void anx6345_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct anx6345 *anx6345 = bridge_to_anx6345(bridge);
int err;
@@ -600,11 +602,14 @@ static void anx6345_bridge_enable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs anx6345_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = anx6345_bridge_attach,
.detach = anx6345_bridge_detach,
.mode_valid = anx6345_bridge_mode_valid,
- .disable = anx6345_bridge_disable,
- .enable = anx6345_bridge_enable,
+ .atomic_disable = anx6345_bridge_disable,
+ .atomic_enable = anx6345_bridge_enable,
};
static void unregister_i2c_dummy_clients(struct anx6345 *anx6345)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
index ba0fc149a9e7..32186efa6f50 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
@@ -937,7 +937,8 @@ anx78xx_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void anx78xx_bridge_disable(struct drm_bridge *bridge)
+static void anx78xx_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
@@ -975,7 +976,8 @@ unlock:
mutex_unlock(&anx78xx->lock);
}
-static void anx78xx_bridge_enable(struct drm_bridge *bridge)
+static void anx78xx_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
int err;
@@ -992,12 +994,15 @@ static void anx78xx_bridge_enable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs anx78xx_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = anx78xx_bridge_attach,
.detach = anx78xx_bridge_detach,
.mode_valid = anx78xx_bridge_mode_valid,
- .disable = anx78xx_bridge_disable,
+ .atomic_disable = anx78xx_bridge_disable,
.mode_set = anx78xx_bridge_mode_set,
- .enable = anx78xx_bridge_enable,
+ .atomic_enable = anx78xx_bridge_enable,
};
static irqreturn_t anx78xx_hpd_threaded_handler(int irq, void *data)
diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c
index 1ed21a8713bf..169939d23310 100644
--- a/drivers/gpu/drm/bridge/aux-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-bridge.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/of.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/bridge/aux-bridge.h>
@@ -104,6 +105,9 @@ static int drm_aux_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs drm_aux_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = drm_aux_bridge_attach,
};
diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
index f02a38a2638a..a2e525aa5788 100644
--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/of.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/bridge/aux-bridge.h>
@@ -165,6 +166,9 @@ static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = drm_aux_hpd_bridge_attach,
};
diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c
index a237c65ebd69..92d464727e41 100644
--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c
+++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c
@@ -330,7 +330,8 @@ static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void ch7033_bridge_disable(struct drm_bridge *bridge)
+static void ch7033_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
@@ -338,7 +339,8 @@ static void ch7033_bridge_disable(struct drm_bridge *bridge)
regmap_update_bits(priv->regmap, 0x52, RESETDB, 0x00);
}
-static void ch7033_bridge_enable(struct drm_bridge *bridge)
+static void ch7033_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
@@ -514,11 +516,14 @@ static void ch7033_bridge_mode_set(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs ch7033_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = ch7033_bridge_attach,
.detach = ch7033_bridge_detach,
.mode_valid = ch7033_bridge_mode_valid,
- .disable = ch7033_bridge_disable,
- .enable = ch7033_bridge_enable,
+ .atomic_disable = ch7033_bridge_disable,
+ .atomic_enable = ch7033_bridge_enable,
.mode_set = ch7033_bridge_mode_set,
};
diff --git a/drivers/gpu/drm/bridge/cros-ec-anx7688.c b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
index a35dae9b56e2..da16c793e3ba 100644
--- a/drivers/gpu/drm/bridge/cros-ec-anx7688.c
+++ b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
@@ -5,6 +5,7 @@
* Copyright 2020 Google LLC
*/
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_print.h>
#include <linux/i2c.h>
@@ -92,6 +93,9 @@ static bool cros_ec_anx7688_bridge_mode_fixup(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs cros_ec_anx7688_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.mode_fixup = cros_ec_anx7688_bridge_mode_fixup,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt8713sx.c b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
index cee485adf5e5..4a6420b876da 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8713sx.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8713sx.c
@@ -18,6 +18,7 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_of.h>
@@ -508,6 +509,9 @@ static const struct attribute_group *lt8713sx_attr_groups[] = {
};
static const struct drm_bridge_funcs lt8713sx_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = lt8713sx_bridge_attach,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 729b12b67470..df5d07e7644c 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -457,7 +457,8 @@ static void lt8912_bridge_mode_set(struct drm_bridge *bridge,
drm_display_mode_to_videomode(adj, &lt->mode);
}
-static void lt8912_bridge_enable(struct drm_bridge *bridge)
+static void lt8912_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct lt8912 *lt = bridge_to_lt8912(bridge);
@@ -634,11 +635,14 @@ static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs lt8912_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = lt8912_bridge_attach,
.detach = lt8912_bridge_detach,
.mode_valid = lt8912_bridge_mode_valid,
.mode_set = lt8912_bridge_mode_set,
- .enable = lt8912_bridge_enable,
+ .atomic_enable = lt8912_bridge_enable,
.detect = lt8912_bridge_detect,
.edid_read = lt8912_bridge_edid_read,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 9427cc2358ae..6625ba23761c 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -465,6 +465,9 @@ static void lt9611uxc_hdmi_audio_shutdown(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = lt9611uxc_bridge_attach,
.mode_valid = lt9611uxc_bridge_mode_valid,
.mode_set = lt9611uxc_bridge_mode_set,
diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c
index d1135dc3b99f..a82ea0c944eb 100644
--- a/drivers/gpu/drm/bridge/lvds-codec.c
+++ b/drivers/gpu/drm/bridge/lvds-codec.c
@@ -43,7 +43,8 @@ static int lvds_codec_attach(struct drm_bridge *bridge,
bridge, flags);
}
-static void lvds_codec_enable(struct drm_bridge *bridge)
+static void lvds_codec_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
int ret;
@@ -59,7 +60,8 @@ static void lvds_codec_enable(struct drm_bridge *bridge)
gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0);
}
-static void lvds_codec_disable(struct drm_bridge *bridge)
+static void lvds_codec_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
int ret;
@@ -100,8 +102,8 @@ lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
static const struct drm_bridge_funcs funcs = {
.attach = lvds_codec_attach,
- .enable = lvds_codec_enable,
- .disable = lvds_codec_disable,
+ .atomic_enable = lvds_codec_enable,
+ .atomic_disable = lvds_codec_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_create_state = drm_atomic_helper_bridge_create_state,
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 2d02cc69f237..25ff0a0acc93 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -214,6 +214,9 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = ge_b850v3_lvds_attach,
.detect = ge_b850v3_lvds_bridge_detect,
.edid_read = ge_b850v3_lvds_edid_read,
diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c
index 5fb8633f43c5..dd4ffc9f4df3 100644
--- a/drivers/gpu/drm/bridge/microchip-lvds.c
+++ b/drivers/gpu/drm/bridge/microchip-lvds.c
@@ -167,6 +167,9 @@ static void mchp_lvds_atomic_disable(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs mchp_lvds_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = mchp_lvds_attach,
.atomic_enable = mchp_lvds_atomic_enable,
.atomic_disable = mchp_lvds_atomic_disable,
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 7acb11f16dc1..a9b4ac2defc9 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -111,7 +111,8 @@ static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
return 0;
}
-static void ptn3460_pre_enable(struct drm_bridge *bridge)
+static void ptn3460_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
int ret;
@@ -139,7 +140,8 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge)
ptn_bridge->enabled = true;
}
-static void ptn3460_disable(struct drm_bridge *bridge)
+static void ptn3460_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
@@ -163,7 +165,7 @@ static const struct drm_edid *ptn3460_edid_read(struct drm_bridge *bridge,
int ret;
power_off = !ptn_bridge->enabled;
- ptn3460_pre_enable(&ptn_bridge->bridge);
+ ptn3460_pre_enable(&ptn_bridge->bridge, NULL);
edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (!edid) {
@@ -182,7 +184,7 @@ static const struct drm_edid *ptn3460_edid_read(struct drm_bridge *bridge,
out:
if (power_off)
- ptn3460_disable(&ptn_bridge->bridge);
+ ptn3460_disable(&ptn_bridge->bridge, NULL);
return drm_edid;
}
@@ -248,8 +250,11 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs ptn3460_bridge_funcs = {
- .pre_enable = ptn3460_pre_enable,
- .disable = ptn3460_disable,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_pre_enable = ptn3460_pre_enable,
+ .atomic_disable = ptn3460_disable,
.attach = ptn3460_bridge_attach,
.edid_read = ptn3460_edid_read,
};
diff --git a/drivers/gpu/drm/bridge/of-display-mode-bridge.c b/drivers/gpu/drm/bridge/of-display-mode-bridge.c
index e66dae168fd0..af3e727e91c9 100644
--- a/drivers/gpu/drm/bridge/of-display-mode-bridge.c
+++ b/drivers/gpu/drm/bridge/of-display-mode-bridge.c
@@ -9,6 +9,7 @@
#include <linux/export.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_modes.h>
#include <drm/drm_probe_helper.h>
@@ -52,6 +53,9 @@ static int of_display_mode_bridge_get_modes(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs of_display_mode_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = of_display_mode_bridge_attach,
.get_modes = of_display_mode_bridge_get_modes,
};
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index f879a1df077d..33844db753aa 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -336,7 +336,8 @@ static const struct backlight_ops ps8622_backlight_ops = {
.update_status = ps8622_backlight_update,
};
-static void ps8622_pre_enable(struct drm_bridge *bridge)
+static void ps8622_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
int ret;
@@ -381,13 +382,15 @@ static void ps8622_pre_enable(struct drm_bridge *bridge)
ps8622->enabled = true;
}
-static void ps8622_disable(struct drm_bridge *bridge)
+static void ps8622_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
/* Delay after panel is disabled */
msleep(PS8622_PWMO_END_T12_MS);
}
-static void ps8622_post_disable(struct drm_bridge *bridge)
+static void ps8622_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
@@ -428,9 +431,12 @@ static int ps8622_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs ps8622_bridge_funcs = {
- .pre_enable = ps8622_pre_enable,
- .disable = ps8622_disable,
- .post_disable = ps8622_post_disable,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_pre_enable = ps8622_pre_enable,
+ .atomic_disable = ps8622_disable,
+ .atomic_post_disable = ps8622_post_disable,
.attach = ps8622_attach,
};
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 5788066d479e..25ab475309e8 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1919,7 +1919,7 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
/*
* of_graph_get_remote_node() produces a noisy error message if port
* node isn't found and the absence of the port is a legit case here,
- * so at first we silently check whether graph presents in the
+ * so at first we silently check whether a graph is present in the
* device-tree node.
*/
if (!of_graph_is_present(np))
diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
index bb1bed03eb5b..be67642ab7d3 100644
--- a/drivers/gpu/drm/bridge/sii9234.c
+++ b/drivers/gpu/drm/bridge/sii9234.c
@@ -13,6 +13,7 @@
* Dharam Kumar <dharam.kr@samsung.com>
*/
#include <drm/bridge/mhl.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
@@ -339,7 +340,7 @@ static int sii9234_cbus_reset(struct sii9234 *ctx)
return sii9234_clear_error(ctx);
}
-/* Require to chek mhl imformation of samsung in cbus_init_register */
+/* Require to check mhl information of samsung in cbus_init_register */
static int sii9234_cbus_init(struct sii9234 *ctx)
{
cbus_writeb(ctx, 0x07, 0xF2);
@@ -614,7 +615,7 @@ static void sii9234_cable_out(struct sii9234 *ctx)
disable_irq(to_i2c_client(ctx->dev)->irq);
tpi_writeb(ctx, TPI_DPD_REG, 0);
- /* Turn on&off hpd festure for only QCT HDMI */
+ /* Turn on&off hpd feature for only QCT HDMI */
sii9234_hw_off(ctx);
ctx->state = ST_OFF;
@@ -708,7 +709,7 @@ static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)
{
int value;
- /* Work_around code to handle wrong interrupt */
+ /* Workaround code to handle wrong interrupt */
if (ctx->state != ST_RGND_1K) {
dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n");
return ST_FAILURE;
@@ -723,9 +724,9 @@ static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)
}
dev_dbg(ctx->dev, "RSEN lost\n");
/*
- * Once RSEN loss is confirmed,we need to check
- * based on cable status and chip power status,whether
- * it is SINK Loss(HDMI cable not connected, TV Off)
+ * Once RSEN loss is confirmed, we need to check
+ * based on cable status and chip power status, whether
+ * it is SINK Loss (HDMI cable not connected, TV Off)
* or MHL cable disconnection
* TODO: Define the below mhl_disconnection()
*/
@@ -820,26 +821,22 @@ static int sii9234_init_resources(struct sii9234 *ctx,
int ret;
if (!ctx->dev->of_node) {
- dev_err(ctx->dev, "not DT device\n");
+ dev_err(ctx->dev, "no DT device\n");
return -ENODEV;
}
ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(ctx->gpio_reset)) {
- dev_err(ctx->dev, "failed to get reset gpio from DT\n");
- return PTR_ERR(ctx->gpio_reset);
- }
+ if (IS_ERR(ctx->gpio_reset))
+ return dev_err_probe(ctx->dev, PTR_ERR(ctx->gpio_reset),
+ "failed to get reset gpio from DT\n");
ctx->supplies[0].supply = "avcc12";
ctx->supplies[1].supply = "avcc33";
ctx->supplies[2].supply = "iovcc18";
ctx->supplies[3].supply = "cvcc12";
ret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(ctx->dev, "regulator_bulk failed\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(ctx->dev, ret, "regulator_bulk failed\n");
ctx->client[I2C_MHL] = client;
@@ -878,6 +875,9 @@ static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs sii9234_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.mode_valid = sii9234_mode_valid,
};
@@ -911,10 +911,9 @@ static int sii9234_probe(struct i2c_client *client)
sii9234_irq_thread,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"sii9234", ctx);
- if (ret < 0) {
- dev_err(dev, "failed to install IRQ handler\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to install IRQ handler\n");
ret = sii9234_init_resources(ctx, client);
if (ret < 0)
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 982306eb4f0a..22c81b38b41e 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -9,6 +9,7 @@
#include <linux/unaligned.h>
#include <drm/bridge/mhl.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
@@ -2280,6 +2281,9 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs sii8620_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = sii8620_attach,
.detach = sii8620_detach,
.mode_fixup = sii8620_mode_fixup,
diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index cc13c98f9be6..3fba7002322e 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -132,7 +132,8 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
return 0;
}
-static void simple_bridge_enable(struct drm_bridge *bridge)
+static void simple_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
int ret;
@@ -146,7 +147,8 @@ static void simple_bridge_enable(struct drm_bridge *bridge)
gpiod_set_value_cansleep(sbridge->enable, 1);
}
-static void simple_bridge_disable(struct drm_bridge *bridge)
+static void simple_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
@@ -157,9 +159,12 @@ static void simple_bridge_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs simple_bridge_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = simple_bridge_attach,
- .enable = simple_bridge_enable,
- .disable = simple_bridge_disable,
+ .atomic_enable = simple_bridge_enable,
+ .atomic_disable = simple_bridge_disable,
};
static int simple_bridge_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index 12b43245bb8f..f55a56cbd88f 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -266,7 +266,8 @@ static void tc358764_reset(struct tc358764 *ctx)
usleep_range(1000, 2000);
}
-static void tc358764_post_disable(struct drm_bridge *bridge)
+static void tc358764_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tc358764 *ctx = bridge_to_tc358764(bridge);
int ret;
@@ -278,7 +279,8 @@ static void tc358764_post_disable(struct drm_bridge *bridge)
dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
}
-static void tc358764_pre_enable(struct drm_bridge *bridge)
+static void tc358764_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tc358764 *ctx = bridge_to_tc358764(bridge);
int ret;
@@ -303,8 +305,11 @@ static int tc358764_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs tc358764_bridge_funcs = {
- .post_disable = tc358764_post_disable,
- .pre_enable = tc358764_pre_enable,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_post_disable = tc358764_post_disable,
+ .atomic_pre_enable = tc358764_pre_enable,
.attach = tc358764_attach,
};
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 966c3eae437e..ce1b73214f26 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -527,7 +527,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
* address-only transfer
*/
if (size)
- size = FIELD_GET(AUX_BYTES, auxstatus);
+ size = min_t(size_t, size, FIELD_GET(AUX_BYTES, auxstatus));
msg->reply = FIELD_GET(AUX_STATUS, auxstatus);
switch (request) {
diff --git a/drivers/gpu/drm/bridge/tda998x_drv.c b/drivers/gpu/drm/bridge/tda998x_drv.c
index 6c427bc75896..16c745591175 100644
--- a/drivers/gpu/drm/bridge/tda998x_drv.c
+++ b/drivers/gpu/drm/bridge/tda998x_drv.c
@@ -1410,7 +1410,8 @@ static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void tda998x_bridge_enable(struct drm_bridge *bridge)
+static void tda998x_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
@@ -1428,7 +1429,8 @@ static void tda998x_bridge_enable(struct drm_bridge *bridge)
}
}
-static void tda998x_bridge_disable(struct drm_bridge *bridge)
+static void tda998x_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
@@ -1745,12 +1747,15 @@ static void tda998x_bridge_hpd_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs tda998x_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = tda998x_bridge_attach,
.detach = tda998x_bridge_detach,
.mode_valid = tda998x_bridge_mode_valid,
- .disable = tda998x_bridge_disable,
+ .atomic_disable = tda998x_bridge_disable,
.mode_set = tda998x_bridge_mode_set,
- .enable = tda998x_bridge_enable,
+ .atomic_enable = tda998x_bridge_enable,
.edid_read = tda998x_bridge_edid_read,
.detect = tda998x_bridge_detect,
.hpd_enable = tda998x_bridge_hpd_enable,
diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index c804222846c3..679b424ba0c3 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -13,6 +13,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_panel.h>
@@ -81,7 +82,8 @@ static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
-static void thc63_enable(struct drm_bridge *bridge)
+static void thc63_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct thc63_dev *thc63 = to_thc63(bridge);
int ret;
@@ -97,7 +99,8 @@ static void thc63_enable(struct drm_bridge *bridge)
gpiod_set_value(thc63->oe, 1);
}
-static void thc63_disable(struct drm_bridge *bridge)
+static void thc63_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct thc63_dev *thc63 = to_thc63(bridge);
int ret;
@@ -112,10 +115,13 @@ static void thc63_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs thc63_bridge_func = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = thc63_attach,
.mode_valid = thc63_mode_valid,
- .enable = thc63_enable,
- .disable = thc63_disable,
+ .atomic_enable = thc63_enable,
+ .atomic_disable = thc63_disable,
};
static int thc63_parse_dt(struct thc63_dev *thc63)
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 6f06f7b4e992..f0a14f52aaac 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -174,14 +174,16 @@ static void tfp410_detach(struct drm_bridge *bridge)
}
}
-static void tfp410_enable(struct drm_bridge *bridge)
+static void tfp410_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
gpiod_set_value_cansleep(dvi->powerdown, 0);
}
-static void tfp410_disable(struct drm_bridge *bridge)
+static void tfp410_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
@@ -242,8 +244,8 @@ static int tfp410_atomic_check(struct drm_bridge *bridge,
static const struct drm_bridge_funcs tfp410_bridge_funcs = {
.attach = tfp410_attach,
.detach = tfp410_detach,
- .enable = tfp410_enable,
- .disable = tfp410_disable,
+ .atomic_enable = tfp410_enable,
+ .atomic_disable = tfp410_disable,
.mode_valid = tfp410_mode_valid,
.atomic_create_state = drm_atomic_helper_bridge_create_state,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c b/drivers/gpu/drm/bridge/ti-tpd12s015.c
index 136e47ad1a10..e7b172ab7f55 100644
--- a/drivers/gpu/drm/bridge/ti-tpd12s015.c
+++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c
@@ -19,6 +19,7 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
struct tpd12s015_device {
@@ -96,6 +97,9 @@ static void tpd12s015_hpd_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs tpd12s015_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = tpd12s015_attach,
.detach = tpd12s015_detach,
.detect = tpd12s015_bridge_detect,
diff --git a/drivers/gpu/drm/bridge/waveshare-dsi.c b/drivers/gpu/drm/bridge/waveshare-dsi.c
index ded57f298d64..9c9825c9b7c5 100644
--- a/drivers/gpu/drm/bridge/waveshare-dsi.c
+++ b/drivers/gpu/drm/bridge/waveshare-dsi.c
@@ -12,6 +12,7 @@
#include <linux/of_graph.h>
#include <linux/regmap.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
@@ -92,7 +93,8 @@ static int ws_bridge_bridge_attach(struct drm_bridge *bridge,
&ws->bridge, flags);
}
-static void ws_bridge_bridge_enable(struct drm_bridge *bridge)
+static void ws_bridge_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ws_bridge *ws = bridge_to_ws_bridge(bridge);
@@ -100,7 +102,8 @@ static void ws_bridge_bridge_enable(struct drm_bridge *bridge)
backlight_enable(ws->backlight);
}
-static void ws_bridge_bridge_disable(struct drm_bridge *bridge)
+static void ws_bridge_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct ws_bridge *ws = bridge_to_ws_bridge(bridge);
@@ -109,8 +112,11 @@ static void ws_bridge_bridge_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs ws_bridge_bridge_funcs = {
- .enable = ws_bridge_bridge_enable,
- .disable = ws_bridge_bridge_disable,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_enable = ws_bridge_bridge_enable,
+ .atomic_disable = ws_bridge_bridge_disable,
.attach = ws_bridge_bridge_attach,
};
diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index 92f8a2d7aab4..8b54069fa53a 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -147,7 +147,7 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
to_drm_bridge_connector(connector);
/* Notify all bridges in the pipeline of hotplug events. */
- drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) {
+ drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge) {
if (bridge->funcs->hpd_notify)
bridge->funcs->hpd_notify(bridge, connector, status);
}
@@ -854,7 +854,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
* detection are available, we don't support hotplug detection at all.
*/
connector_type = DRM_MODE_CONNECTOR_Unknown;
- drm_for_each_bridge_in_chain_scoped(encoder, bridge) {
+ drm_for_each_bridge_in_chain(encoder, bridge) {
if (!bridge->interlace_allowed)
connector->interlace_allowed = false;
if (!bridge->ycbcr_420_allowed)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 735ab7badc2e..e5c8ef06caed 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1554,7 +1554,7 @@ drm_atomic_add_encoder_bridges(struct drm_atomic_commit *state,
"Adding all bridges for [encoder:%d:%s] to %p\n",
encoder->base.id, encoder->name, state);
- drm_for_each_bridge_in_chain_scoped(encoder, bridge) {
+ drm_for_each_bridge_in_chain(encoder, bridge) {
/* Skip bridges that don't implement the atomic state hooks. */
if (!bridge->funcs->atomic_duplicate_state)
continue;
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 2f0d1ba285be..d17ae964fb21 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -563,10 +563,10 @@ EXPORT_SYMBOL(drm_atomic_normalize_zpos);
/**
* drm_plane_create_blend_mode_property - create a new blend mode property
* @plane: drm plane
- * @supported_modes: bitmask of supported modes, must include
- * BIT(DRM_MODE_BLEND_PREMULTI). Current DRM assumption is
- * that alpha is premultiplied, and old userspace can break if
- * the property defaults to anything else.
+ * @supported_modes: bitmask of supported modes. When
+ * BIT(DRM_MODE_BLEND_PREMULTI) is included, it will be used
+ * as the default. Otherwise, the default will fallback to one
+ * of the supported modes.
*
* This creates a new property describing the blend mode.
*
@@ -599,13 +599,14 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane,
{ DRM_MODE_BLEND_PREMULTI, "Pre-multiplied" },
{ DRM_MODE_BLEND_COVERAGE, "Coverage" },
};
+ unsigned int default_mode;
unsigned int valid_mode_mask = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE);
int i;
if (WARN_ON((supported_modes & ~valid_mode_mask) ||
- ((supported_modes & BIT(DRM_MODE_BLEND_PREMULTI)) == 0)))
+ (supported_modes == 0)))
return -EINVAL;
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
@@ -630,7 +631,14 @@ int drm_plane_create_blend_mode_property(struct drm_plane *plane,
}
}
- drm_object_attach_property(&plane->base, prop, DRM_MODE_BLEND_PREMULTI);
+ if (supported_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+ default_mode = DRM_MODE_BLEND_PREMULTI;
+ else if (supported_modes & BIT(DRM_MODE_BLEND_COVERAGE))
+ default_mode = DRM_MODE_BLEND_COVERAGE;
+ else
+ default_mode = DRM_MODE_BLEND_PIXEL_NONE;
+
+ drm_object_attach_property(&plane->base, prop, default_mode);
plane->blend_mode_property = prop;
return 0;
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 6ead9b75ae3d..83f1809a5d37 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -555,11 +555,6 @@ static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = {
.atomic_destroy_state = drm_bridge_atomic_destroy_priv_state,
};
-static bool drm_bridge_is_atomic(struct drm_bridge *bridge)
-{
- return bridge->funcs->atomic_create_state != NULL;
-}
-
/**
* drm_bridge_attach - attach the bridge to an encoder's chain
*
@@ -629,9 +624,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
goto err_reset_bridge;
}
- if (drm_bridge_is_atomic(bridge))
- drm_atomic_private_obj_init(bridge->dev, &bridge->base,
- &drm_bridge_priv_state_funcs);
+ drm_atomic_private_obj_init(bridge->dev, &bridge->base,
+ &drm_bridge_priv_state_funcs);
return 0;
@@ -664,8 +658,7 @@ void drm_bridge_detach(struct drm_bridge *bridge)
if (WARN_ON(!bridge->dev))
return;
- if (drm_bridge_is_atomic(bridge))
- drm_atomic_private_obj_fini(&bridge->base);
+ drm_atomic_private_obj_fini(&bridge->base);
if (bridge->funcs->detach)
bridge->funcs->detach(bridge);
@@ -690,9 +683,9 @@ void drm_bridge_detach(struct drm_bridge *bridge)
* disable the bridge automatically.
*
* The enable and disable operations are split in
- * &drm_bridge_funcs.pre_enable, &drm_bridge_funcs.enable,
- * &drm_bridge_funcs.disable and &drm_bridge_funcs.post_disable to provide
- * finer-grained control.
+ * &drm_bridge_funcs.atomic_pre_enable, &drm_bridge_funcs.atomic_enable,
+ * &drm_bridge_funcs.atomic_disable and &drm_bridge_funcs.atomic_post_disable
+ * to provide finer-grained control.
*
* Bridge drivers may implement the legacy version of those operations, or
* the atomic version (prefixed with atomic\_), in which case they shall also
@@ -833,10 +826,9 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
* @bridge: bridge control structure
* @state: atomic state being committed
*
- * Calls &drm_bridge_funcs.atomic_disable (falls back on
- * &drm_bridge_funcs.disable) op for all the bridges in the encoder chain,
- * starting from the last bridge to the first. These are called before calling
- * &drm_encoder_helper_funcs.atomic_disable
+ * Calls &drm_bridge_funcs.atomic_disable op for all the bridges in the encoder
+ * chain, starting from the last bridge to the first. These are called before
+ * calling &drm_encoder_helper_funcs.atomic_disable
*
* Note: the bridge passed should be the one closest to the encoder
*/
@@ -852,11 +844,8 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
encoder = bridge->encoder;
mutex_lock(&encoder->bridge_chain_mutex);
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
- if (iter->funcs->atomic_disable) {
+ if (iter->funcs->atomic_disable)
iter->funcs->atomic_disable(iter, state);
- } else if (iter->funcs->disable) {
- iter->funcs->disable(iter);
- }
if (iter == bridge)
break;
@@ -870,8 +859,6 @@ static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
{
if (state && bridge->funcs->atomic_post_disable)
bridge->funcs->atomic_post_disable(bridge, state);
- else if (bridge->funcs->post_disable)
- bridge->funcs->post_disable(bridge);
}
/**
@@ -880,10 +867,9 @@ static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
* @bridge: bridge control structure
* @state: atomic state being committed
*
- * Calls &drm_bridge_funcs.atomic_post_disable (falls back on
- * &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain,
- * starting from the first bridge to the last. These are called after completing
- * &drm_encoder_helper_funcs.atomic_disable
+ * Calls &drm_bridge_funcs.atomic_post_disable op for all the bridges in the
+ * encoder chain, starting from the first bridge to the last. These are called
+ * after completing &drm_encoder_helper_funcs.atomic_disable
*
* If a bridge sets @pre_enable_prev_first, then the @post_disable for that
* bridge will be called before the previous one to reverse the @pre_enable
@@ -967,8 +953,6 @@ static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge,
{
if (state && bridge->funcs->atomic_pre_enable)
bridge->funcs->atomic_pre_enable(bridge, state);
- else if (bridge->funcs->pre_enable)
- bridge->funcs->pre_enable(bridge);
}
/**
@@ -977,10 +961,9 @@ static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge,
* @bridge: bridge control structure
* @state: atomic state being committed
*
- * Calls &drm_bridge_funcs.atomic_pre_enable (falls back on
- * &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain,
- * starting from the last bridge to the first. These are called before calling
- * &drm_encoder_helper_funcs.atomic_enable
+ * Calls &drm_bridge_funcs.atomic_pre_enable op for all the bridges in the
+ * encoder chain, starting from the last bridge to the first. These are called
+ * before calling &drm_encoder_helper_funcs.atomic_enable
*
* If a bridge sets @pre_enable_prev_first, then the pre_enable for the
* prev bridge will be called before pre_enable of this bridge.
@@ -1057,10 +1040,9 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
* @first_bridge: bridge control structure
* @state: atomic state being committed
*
- * Calls &drm_bridge_funcs.atomic_enable (falls back on
- * &drm_bridge_funcs.enable) op for all the bridges in the encoder chain,
- * starting from the first bridge to the last. These are called after completing
- * &drm_encoder_helper_funcs.atomic_enable
+ * Calls &drm_bridge_funcs.atomic_enable op for all the bridges in the encoder
+ * chain, starting from the first bridge to the last. These are called after
+ * completing &drm_encoder_helper_funcs.atomic_enable
*
* Note: the bridge passed should be the one closest to the encoder
*/
@@ -1071,11 +1053,8 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *first_bridge,
return;
drm_for_each_bridge_in_chain_from(first_bridge, bridge)
- if (bridge->funcs->atomic_enable) {
+ if (bridge->funcs->atomic_enable)
bridge->funcs->atomic_enable(bridge, state);
- } else if (bridge->funcs->enable) {
- bridge->funcs->enable(bridge);
- }
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
@@ -1717,7 +1696,7 @@ struct drm_bridge *of_drm_get_bridge_by_endpoint(const struct device_node *np,
/*
* of_graph_get_remote_node() produces a noisy error message if port
* node isn't found and the absence of the port is a legit case here,
- * so at first we silently check whether graph is present in the
+ * so at first we silently check whether a graph is present in the
* device-tree node.
*/
if (!of_graph_is_present(np))
@@ -1817,7 +1796,7 @@ static int encoder_bridges_show(struct seq_file *m, void *data)
struct drm_printer p = drm_seq_file_printer(m);
unsigned int idx = 0;
- drm_for_each_bridge_in_chain_scoped(encoder, bridge)
+ drm_for_each_bridge_in_chain(encoder, bridge)
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, true);
return 0;
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 958cb605aedd..fcfe635bc195 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -48,6 +48,47 @@
* event. As mentioned above, ranges are tracked in a notifier's Red-Black
* tree.
*
+ * - Pages:
+ * struct drm_gpusvm_pages holds the DMA mapping state for a range of
+ * CPU virtual addresses: the DMA mapped device addresses,
+ * the device private pagemap, the IOVA state, the per mapping
+ * notifier sequence number, and the drm_device that owns the DMA
+ * mappings.
+ * A driver embeds one or more struct drm_gpusvm_pages alongside its
+ * struct drm_gpusvm_range, choosing one of two layouts:
+ *
+ * 1:1 - one drm_gpusvm_pages per range (one drm_device). Simplest
+ * layout; to mirror a VA range on several devices a driver uses a
+ * separate range (and notifier) per device, so the HMM fault is taken
+ * once per device.
+ *
+ * N:1 - one drm_gpusvm_pages per drm_device, all sharing one range and
+ * notifier; only the per-device DMA mapping differs. The instances must
+ * sit in contiguous memory so a single drm_gpusvm_range_set_unmapped()
+ * can mark them all. A driver can keep one instance inline for the single
+ * device case and switch to a heap array only when more devices join,
+ * e.g.:
+ *
+ * .. code-block:: c
+ *
+ * struct driver_range {
+ * struct drm_gpusvm_range base;
+ * unsigned int num_pages; // 1: inline_pages, >1: pages[]
+ * union {
+ * struct drm_gpusvm_pages inline_pages;
+ * struct drm_gpusvm_pages *pages;
+ * };
+ * };
+ *
+ * In the N:1 case the driver allocates the pages array with a zeroing
+ * allocator (e.g. kcalloc(num_pages, ...)), initialises each entry with
+ * drm_gpusvm_init_pages(), and frees each entry with
+ * drm_gpusvm_free_pages() plus the array itself, from its range free
+ * callback. Each drm_gpusvm_pages is mapped independently by their own
+ * drm_device.
+ * Each drm_gpusvm_pages must be zero-initialised and initialised with
+ * drm_gpusvm_init_pages(), called once per entry.
+ *
* - Operations:
* Define the interface for driver-specific GPU SVM operations such as
* range allocation, notifier allocation, and invalidations.
@@ -92,7 +133,7 @@
* range RB tree and list, as well as the range's DMA mappings and sequence
* number. GPU SVM manages all necessary locking and unlocking operations,
* except for the recheck range's pages being valid
- * (drm_gpusvm_range_pages_valid) when the driver is committing GPU bindings.
+ * (drm_gpusvm_pages_valid) when the driver is committing GPU bindings.
* This lock corresponds to the ``driver->update`` lock mentioned in
* Documentation/mm/hmm.rst. Future revisions may transition from a GPU SVM
* global lock to a per-notifier lock if finer-grained locking is deemed
@@ -140,15 +181,20 @@
*
* .. code-block:: c
*
- * int driver_bind_range(struct drm_gpusvm *gpusvm, struct drm_gpusvm_range *range)
+ * struct driver_range {
+ * struct drm_gpusvm_range base;
+ * struct drm_gpusvm_pages pages;
+ * };
+ *
+ * int driver_bind_range(struct drm_gpusvm *gpusvm, struct driver_range *drange)
* {
* int err = 0;
*
- * driver_alloc_and_setup_memory_for_bind(gpusvm, range);
+ * driver_alloc_and_setup_memory_for_bind(gpusvm, drange);
*
* drm_gpusvm_notifier_lock(gpusvm);
- * if (drm_gpusvm_range_pages_valid(range))
- * driver_commit_bind(gpusvm, range);
+ * if (drm_gpusvm_pages_valid(gpusvm, &drange->pages))
+ * driver_commit_bind(gpusvm, drange);
* else
* err = -EAGAIN;
* drm_gpusvm_notifier_unlock(gpusvm);
@@ -160,6 +206,8 @@
* unsigned long gpuva_start, unsigned long gpuva_end)
* {
* struct drm_gpusvm_ctx ctx = {};
+ * struct driver_range *drange;
+ * struct drm_gpusvm_range *range;
* int err;
*
* driver_svm_lock();
@@ -174,6 +222,7 @@
* err = PTR_ERR(range);
* goto unlock;
* }
+ * drange = container_of(range, struct driver_range, base);
*
* if (driver_migration_policy(range)) {
* err = drm_pagemap_populate_mm(driver_choose_drm_pagemap(),
@@ -183,7 +232,10 @@
* goto retry;
* }
*
- * err = drm_gpusvm_range_get_pages(gpusvm, range, &ctx);
+ * err = drm_gpusvm_get_pages(gpusvm, &drange->pages,
+ * gpusvm->mm, &range->notifier->notifier,
+ * drm_gpusvm_range_start(range),
+ * drm_gpusvm_range_end(range), &ctx);
* if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { // CPU mappings changed
* if (err == -EOPNOTSUPP)
* drm_gpusvm_range_evict(gpusvm, range);
@@ -192,7 +244,7 @@
* goto unlock;
* }
*
- * err = driver_bind_range(gpusvm, range);
+ * err = driver_bind_range(gpusvm, drange);
* if (err == -EAGAIN) // CPU mappings changed
* goto retry
*
@@ -205,6 +257,21 @@
*
* .. code-block:: c
*
+ * // The driver owns the drm_gpusvm_pages lifecycle. ops->range_free is
+ * // the final fallback: drm_gpusvm_free_pages() unmaps any
+ * // lingering DMA mapping and a no-op if already unmapped and frees the
+ * // dma_addr array. The normal flow is to DMA unmap before
+ * // drm_gpusvm_range_remove() (before the range leaves the tree).
+ * void driver_range_free(struct drm_gpusvm_range *range)
+ * {
+ * struct driver_range *drange =
+ * container_of(range, struct driver_range, base);
+ *
+ * drm_gpusvm_free_pages(range->gpusvm, &drange->pages,
+ * drm_gpusvm_range_size(range) >> PAGE_SHIFT);
+ * kfree(drange);
+ * }
+ *
* void __driver_garbage_collector(struct drm_gpusvm *gpusvm,
* struct drm_gpusvm_range *range)
* {
@@ -215,6 +282,14 @@
* drm_gpusvm_range_evict(gpusvm, range);
*
* driver_unbind_range(range);
+ * // The pages must be DMA unmapped before drm_gpusvm_range_remove()
+ * // , so a range is never off the MMU interval tree while still DMA
+ * // mapped as the original drmsvm design flow. Otherwise a concurrent CPU
+ * // munmap's notifier could miss this range and free pages still mapped
+ * // for device DMA. This is the normal unmap point.
+ * drm_gpusvm_unmap_pages(gpusvm, &drange->pages,
+ * drm_gpusvm_range_size(range) >> PAGE_SHIFT,
+ * &(struct drm_gpusvm_ctx){ .in_notifier = false });
* drm_gpusvm_range_remove(gpusvm, range);
* }
*
@@ -236,17 +311,22 @@
* {
* struct drm_gpusvm_ctx ctx = { .in_notifier = true, };
* struct drm_gpusvm_range *range = NULL;
+ * struct driver_range *drange;
*
* driver_invalidate_device_pages(gpusvm, mmu_range->start, mmu_range->end);
*
* drm_gpusvm_for_each_range(range, notifier, mmu_range->start,
* mmu_range->end) {
- * drm_gpusvm_range_unmap_pages(gpusvm, range, &ctx);
+ * drange = container_of(range, struct driver_range, base);
+ *
+ * drm_gpusvm_unmap_pages(gpusvm, &drange->pages,
+ * drm_gpusvm_range_size(range) >> PAGE_SHIFT,
+ * &ctx);
*
* if (mmu_range->event != MMU_NOTIFY_UNMAP)
* continue;
*
- * drm_gpusvm_range_set_unmapped(range, mmu_range);
+ * drm_gpusvm_range_set_unmapped(range, &drange->pages, 1, mmu_range);
* driver_garbage_collector_add(gpusvm, range);
* }
* }
@@ -359,7 +439,6 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
* drm_gpusvm_init() - Initialize the GPU SVM.
* @gpusvm: Pointer to the GPU SVM structure.
* @name: Name of the GPU SVM.
- * @drm: Pointer to the DRM device structure.
* @mm: Pointer to the mm_struct for the address space.
* @mm_start: Start address of GPU SVM.
* @mm_range: Range of the GPU SVM.
@@ -373,7 +452,9 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
* This function initializes the GPU SVM.
*
* Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
- * then only @gpusvm, @name, and @drm are expected. However, the same base
+ * then only @gpusvm and @name are expected. The @drm drm_device for dma
+ * mappings is bound per-pages via drm_gpusvm_init_pages() before the first
+ * drm_gpusvm_get_pages() call. However, the same base
* @gpusvm can also be used with both modes together in which case the full
* setup is needed, where the core drm_gpusvm_pages API will simply never use
* the other fields.
@@ -381,7 +462,7 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
* Return: 0 on success, a negative error code on failure.
*/
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
- const char *name, struct drm_device *drm,
+ const char *name,
struct mm_struct *mm,
unsigned long mm_start, unsigned long mm_range,
unsigned long notifier_size,
@@ -399,7 +480,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
}
gpusvm->name = name;
- gpusvm->drm = drm;
gpusvm->mm = mm;
gpusvm->mm_start = mm_start;
gpusvm->mm_range = mm_range;
@@ -640,8 +720,7 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
range->itree.start = ALIGN_DOWN(fault_addr, chunk_size);
range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
INIT_LIST_HEAD(&range->entry);
- range->pages.notifier_seq = LONG_MAX;
- range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;
+ range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
return range;
}
@@ -929,7 +1008,7 @@ retry:
* mallocs 16k but the CPU VMA is ~128k which results in 64k SVM
* ranges. When migrating the SVM ranges, some processes fail in
* drm_pagemap_migrate_to_devmem with 'migrate.cpages != npages'
- * and then upon drm_gpusvm_range_get_pages device pages from
+ * and then upon drm_gpusvm_get_pages device pages from
* other processes are collected + faulted in which creates all
* sorts of problems. Unsure exactly how this happening, also
* problem goes away if 'xe_exec_system_allocator --r
@@ -1135,11 +1214,16 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
unsigned long npages)
{
struct drm_pagemap *dpagemap = svm_pages->dpagemap;
- struct device *dev = gpusvm->drm->dev;
+ struct device *dev;
unsigned long i, j;
lockdep_assert_held(&gpusvm->notifier_lock);
+ if (!svm_pages->drm)
+ return;
+
+ dev = svm_pages->drm->dev;
+
if (svm_pages->flags.has_dma_mapping) {
struct drm_gpusvm_pages_flags flags = {
.__flags = svm_pages->flags.__flags,
@@ -1222,12 +1306,17 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);
* This function removes the specified GPU SVM range and also removes the parent
* GPU SVM notifier if no more ranges remain in the notifier. The caller must
* hold a lock to protect range and notifier removal.
+ *
+ * This function does not unmap or free the drm_gpusvm_pages, the driver owns
+ * that lifecycle. The caller must DMA unmap the range's pages before calling
+ * this function, so a range is never removed from the MMU interval tree while
+ * still DMA mapped. Typically the driver calls drm_gpusvm_unmap_pages() first.
+ * And the range_free callback's drm_gpusvm_free_pages() is a final fallback safe
+ * net.
*/
void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range)
{
- unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
- drm_gpusvm_range_end(range));
struct drm_gpusvm_notifier *notifier;
drm_gpusvm_driver_lock_held(gpusvm);
@@ -1239,8 +1328,6 @@ void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
return;
drm_gpusvm_notifier_lock(gpusvm);
- __drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages);
- __drm_gpusvm_free_pages(gpusvm, &range->pages);
__drm_gpusvm_range_remove(notifier, range);
drm_gpusvm_notifier_unlock(gpusvm);
@@ -1319,34 +1406,14 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
*
* Return: True if GPU SVM range has valid pages, False otherwise
*/
-static bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_pages *svm_pages)
+bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages)
{
lockdep_assert_held(&gpusvm->notifier_lock);
return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
}
-
-/**
- * drm_gpusvm_range_pages_valid() - GPU SVM range pages valid
- * @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
- *
- * This function determines if a GPU SVM range pages are valid. Expected be
- * called holding gpusvm->notifier_lock and as the last step before committing a
- * GPU binding. This is akin to a notifier seqno check in the HMM documentation
- * but due to wider notifiers (i.e., notifiers which span multiple ranges) this
- * function is required for finer grained checking (i.e., per range) if pages
- * are valid.
- *
- * Return: True if GPU SVM range has valid pages, False otherwise
- */
-bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range)
-{
- return drm_gpusvm_pages_valid(gpusvm, &range->pages);
-}
-EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
+EXPORT_SYMBOL_GPL(drm_gpusvm_pages_valid);
/**
* drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
@@ -1421,6 +1488,9 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
DMA_BIDIRECTIONAL;
struct dma_iova_state *state = &svm_pages->state;
+ if (!svm_pages->drm)
+ return -EINVAL;
+
retry:
if (time_after(jiffies, timeout))
return -EBUSY;
@@ -1520,7 +1590,7 @@ map_pages:
pagemap = page_pgmap(page);
dpagemap = drm_pagemap_page_to_dpagemap(page);
- if (drm_WARN_ON(gpusvm->drm, !dpagemap)) {
+ if (drm_WARN_ON(svm_pages->drm, !dpagemap)) {
/*
* Raced. This is not supposed to happen
* since hmm_range_fault() should've migrated
@@ -1532,10 +1602,10 @@ map_pages:
}
svm_pages->dma_addr[j] =
dpagemap->ops->device_map(dpagemap,
- gpusvm->drm->dev,
+ svm_pages->drm->dev,
page, order,
dma_dir);
- if (dma_mapping_error(gpusvm->drm->dev,
+ if (dma_mapping_error(svm_pages->drm->dev,
svm_pages->dma_addr[j].addr)) {
err = -EFAULT;
goto err_unmap;
@@ -1555,11 +1625,11 @@ map_pages:
}
if (!i)
- dma_iova_try_alloc(gpusvm->drm->dev, state,
+ dma_iova_try_alloc(svm_pages->drm->dev, state,
0, npages * PAGE_SIZE);
if (dma_use_iova(state)) {
- err = dma_iova_link(gpusvm->drm->dev, state,
+ err = dma_iova_link(svm_pages->drm->dev, state,
hmm_pfn_to_phys(pfns[i]),
svm_pages->state_offset,
PAGE_SIZE << order,
@@ -1570,11 +1640,11 @@ map_pages:
addr = state->addr + svm_pages->state_offset;
svm_pages->state_offset += PAGE_SIZE << order;
} else {
- addr = dma_map_page(gpusvm->drm->dev,
+ addr = dma_map_page(svm_pages->drm->dev,
page, 0,
PAGE_SIZE << order,
dma_dir);
- if (dma_mapping_error(gpusvm->drm->dev, addr)) {
+ if (dma_mapping_error(svm_pages->drm->dev, addr)) {
err = -EFAULT;
goto err_unmap;
}
@@ -1590,7 +1660,7 @@ map_pages:
}
if (dma_use_iova(state)) {
- err = dma_iova_sync(gpusvm->drm->dev, state, 0,
+ err = dma_iova_sync(svm_pages->drm->dev, state, 0,
svm_pages->state_offset);
if (err)
goto err_unmap;
@@ -1626,28 +1696,6 @@ err_free:
EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);
/**
- * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
- * @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
- * @ctx: GPU SVM context
- *
- * This function gets pages for a GPU SVM range and ensures they are mapped for
- * DMA access.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx)
-{
- return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
- &range->notifier->notifier,
- drm_gpusvm_range_start(range),
- drm_gpusvm_range_end(range), ctx);
-}
-EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
-
-/**
* drm_gpusvm_unmap_pages() - Unmap GPU svm pages
* @gpusvm: Pointer to the GPU SVM structure
* @svm_pages: Pointer to the GPU SVM pages structure
@@ -1678,29 +1726,6 @@ void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);
/**
- * drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
- * @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
- * @ctx: GPU SVM context
- *
- * This function unmaps pages associated with a GPU SVM range. If @in_notifier
- * is set, it is assumed that gpusvm->notifier_lock is held in write mode; if it
- * is clear, it acquires gpusvm->notifier_lock in read mode. Must be called on
- * each GPU SVM range attached to notifier in gpusvm->ops->invalidate for IOMMU
- * security model.
- */
-void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx)
-{
- unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
- drm_gpusvm_range_end(range));
-
- return drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages, ctx);
-}
-EXPORT_SYMBOL_GPL(drm_gpusvm_range_unmap_pages);
-
-/**
* drm_gpusvm_range_evict() - Evict GPU SVM range
* @gpusvm: Pointer to the GPU SVM structure
* @range: Pointer to the GPU SVM range to be removed
@@ -1784,20 +1809,40 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_has_mapping);
/**
* drm_gpusvm_range_set_unmapped() - Mark a GPU SVM range as unmapped
* @range: Pointer to the GPU SVM range structure.
+ * @pages: Pointer to the GPU SVM pages structure(s).
+ * @pages_count: Number of GPU SVM pages structure(s) passed in.
* @mmu_range: Pointer to the MMU notifier range structure.
*
* This function marks a GPU SVM range as unmapped and sets the partial_unmap flag
* if the range partially falls within the provided MMU notifier range.
*/
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
+ struct drm_gpusvm_pages *pages,
+ unsigned int pages_count,
const struct mmu_notifier_range *mmu_range)
{
+ struct drm_gpusvm_range_flags range_flags = {
+ .__flags = range->flags.__flags,
+ };
+ unsigned int i;
+
lockdep_assert_held_write(&range->gpusvm->notifier_lock);
- range->pages.flags.unmapped = true;
+ range_flags.unmapped = true;
+ for (i = 0; i < pages_count; ++i) {
+ struct drm_gpusvm_pages_flags flags = {
+ .__flags = pages[i].flags.__flags,
+ };
+
+ flags.unmapped = true;
+ /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
+ WRITE_ONCE(pages[i].flags.__flags, flags.__flags);
+ }
if (drm_gpusvm_range_start(range) < mmu_range->start ||
drm_gpusvm_range_end(range) > mmu_range->end)
- range->pages.flags.partial_unmap = true;
+ range_flags.partial_unmap = true;
+ /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
+ WRITE_ONCE(range->flags.__flags, range_flags.__flags);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index f432f485a914..3bcc7bf0900c 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -857,6 +857,25 @@ static void validate_encoder_possible_crtcs(struct drm_encoder *encoder)
encoder->possible_crtcs, crtc_mask);
}
+static void validate_blend_mode_for_alpha_formats(struct drm_plane *plane)
+{
+ const struct drm_format_info *fmt;
+ u32 i;
+
+ /* blend mode property supported, no need to check anything */
+ if (plane->blend_mode_property)
+ return;
+
+ for (i = 0; i < plane->format_count; i++) {
+ fmt = drm_format_info(plane->format_types[i]);
+ if (fmt->has_alpha) {
+ WARN(1, "[PLANE:%d:%s] pixel format with alpha exposed but blend mode not setup",
+ plane->base.id, plane->name);
+ break;
+ }
+ }
+}
+
void drm_mode_config_validate(struct drm_device *dev)
{
struct drm_encoder *encoder;
@@ -915,6 +934,8 @@ void drm_mode_config_validate(struct drm_device *dev)
drm_for_each_plane(plane, dev) {
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
num_primary++;
+
+ validate_blend_mode_for_alpha_formats(plane);
}
WARN(num_primary != dev->mode_config.num_crtc,
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 96eef327bf7e..1f4cff6bb4a7 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -297,7 +297,7 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
/*
* of_graph_get_remote_node() produces a noisy error message if port
* node isn't found and the absence of the port is a legit case here,
- * so at first we silently check whether graph presents in the
+ * so at first we silently check whether a graph is present in the
* device-tree node.
*/
if (!of_graph_is_present(np))
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index c314b3cb5e70..4dbc8a7ea6af 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -584,9 +584,9 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
/* read idle register. */
idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
- /* try resetting again if FE is not idle */
- if ((idle & VIVS_HI_IDLE_STATE_FE) == 0) {
- dev_dbg(gpu->dev, "FE is not idle\n");
+ /* try resetting again if any module is not idle */
+ if ((idle & gpu->idle_mask) != gpu->idle_mask) {
+ dev_dbg(gpu->dev, "GPU modules not idle\n");
continue;
}
@@ -600,6 +600,23 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
continue;
}
+ /* try resetting again if MMUv2 is not disabled */
+ if (gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION) {
+ if (gpu->sec_mode == ETNA_SEC_KERNEL) {
+ if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) &
+ VIVS_MMUv2_SEC_CONTROL_ENABLE) {
+ dev_dbg(gpu->dev, "MMU is not disabled\n");
+ continue;
+ }
+ } else {
+ if (gpu_read(gpu, VIVS_MMUv2_CONTROL) &
+ VIVS_MMUv2_CONTROL_ENABLE) {
+ dev_dbg(gpu->dev, "MMU is not disabled\n");
+ continue;
+ }
+ }
+ }
+
/* enable debug register access */
control &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS;
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index e68c954ec3e6..3069f958137f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -21,6 +21,7 @@
#include <video/of_videomode.h>
#include <video/videomode.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_encoder.h>
#include <drm/drm_print.h>
@@ -228,7 +229,8 @@ static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
writel(reg, mic->reg + MIC_OP);
}
-static void mic_post_disable(struct drm_bridge *bridge)
+static void mic_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct exynos_mic *mic = bridge->driver_private;
@@ -257,7 +259,8 @@ static void mic_mode_set(struct drm_bridge *bridge,
mutex_unlock(&mic_mutex);
}
-static void mic_pre_enable(struct drm_bridge *bridge)
+static void mic_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct exynos_mic *mic = bridge->driver_private;
int ret;
@@ -295,9 +298,12 @@ unlock:
}
static const struct drm_bridge_funcs mic_bridge_funcs = {
- .post_disable = mic_post_disable,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_post_disable = mic_post_disable,
.mode_set = mic_mode_set,
- .pre_enable = mic_pre_enable,
+ .atomic_pre_enable = mic_pre_enable,
};
static int exynos_mic_bind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/imx/dc/dc-ic.c b/drivers/gpu/drm/imx/dc/dc-ic.c
index a270ae4030cd..fa87bf1f4508 100644
--- a/drivers/gpu/drm/imx/dc/dc-ic.c
+++ b/drivers/gpu/drm/imx/dc/dc-ic.c
@@ -14,6 +14,8 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include "dc-drv.h"
+
#define USERINTERRUPTMASK(n) (0x8 + 4 * (n))
#define INTERRUPTENABLE(n) (0x10 + 4 * (n))
#define INTERRUPTPRESET(n) (0x18 + 4 * (n))
@@ -174,8 +176,8 @@ static int dc_ic_probe(struct platform_device *pdev)
regmap_write(data->regs, USERINTERRUPTMASK(i), 0xffffffff);
}
- data->domain = irq_domain_add_linear(dev->of_node, IRQ_COUNT,
- &irq_generic_chip_ops, data);
+ data->domain = irq_domain_create_linear(of_fwnode_handle(dev->of_node), IRQ_COUNT,
+ &irq_generic_chip_ops, data);
if (!data->domain) {
dev_err(dev, "failed to create IRQ domain\n");
pm_runtime_put(dev);
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index 47d45897ed06..5cf44ccb02cf 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -1063,6 +1063,9 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = mcde_dsi_bridge_attach,
.mode_set = mcde_dsi_bridge_mode_set,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 959c994eef24..0e4f430de983 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -850,7 +850,8 @@ static void mtk_dpi_bridge_mode_set(struct drm_bridge *bridge,
drm_mode_copy(&dpi->mode, adjusted_mode);
}
-static void mtk_dpi_bridge_disable(struct drm_bridge *bridge)
+static void mtk_dpi_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
@@ -860,7 +861,8 @@ static void mtk_dpi_bridge_disable(struct drm_bridge *bridge)
pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
}
-static void mtk_dpi_bridge_enable(struct drm_bridge *bridge)
+static void mtk_dpi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
@@ -982,8 +984,8 @@ static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
.attach = mtk_dpi_bridge_attach,
.mode_set = mtk_dpi_bridge_mode_set,
.mode_valid = mtk_dpi_bridge_mode_valid,
- .disable = mtk_dpi_bridge_disable,
- .enable = mtk_dpi_bridge_enable,
+ .atomic_disable = mtk_dpi_bridge_disable,
+ .atomic_enable = mtk_dpi_bridge_enable,
.atomic_check = mtk_dpi_bridge_atomic_check,
.atomic_get_output_bus_fmts = mtk_dpi_bridge_atomic_get_output_bus_fmts,
.atomic_get_input_bus_fmts = mtk_dpi_bridge_atomic_get_input_bus_fmts,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 46faeaae9d94..959daa88b1d0 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -275,7 +275,8 @@ static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
dsi_mgr_phy_disable(id);
}
-static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
+static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -331,7 +332,8 @@ void msm_dsi_manager_tpg_enable(void)
}
}
-static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
+static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
int id = dsi_mgr_bridge_get_id(bridge);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -445,9 +447,12 @@ static int dsi_mgr_bridge_attach(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = dsi_mgr_bridge_attach,
- .pre_enable = dsi_mgr_bridge_pre_enable,
- .post_disable = dsi_mgr_bridge_post_disable,
+ .atomic_pre_enable = dsi_mgr_bridge_pre_enable,
+ .atomic_post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
.mode_valid = dsi_mgr_bridge_mode_valid,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
index 700cea5def35..f128330f30d7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
@@ -297,6 +297,7 @@ r535_fbsr = {
static void *
r535_instmem_dtor(struct nvkm_instmem *imem)
{
+ nv50_instmem_dtor(imem);
kfree(imem->func);
return imem;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
index 6fbaa1e5876d..f4489efc94a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -30,10 +30,14 @@
#include <subdev/gsp.h>
#include <subdev/mmu.h>
+#include <linux/io-mapping.h>
+
struct nv50_instmem {
struct nvkm_instmem base;
u64 addr;
+ struct io_mapping iomap;
+
/* Mappings that can be evicted when BAR2 space has been exhausted. */
struct list_head lru;
};
@@ -124,7 +128,6 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
struct nv50_instobj *eobj;
struct nvkm_memory *memory = &iobj->base.memory;
struct nvkm_subdev *subdev = &imem->base.subdev;
- struct nvkm_device *device = subdev->device;
struct nvkm_vma *bar = NULL, *ebar;
u64 size = nvkm_memory_size(memory);
void *emap;
@@ -155,7 +158,7 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
mutex_unlock(&imem->base.mutex);
if (!eobj)
break;
- iounmap(emap);
+ io_mapping_unmap(emap);
nvkm_vmm_put(vmm, &ebar);
}
@@ -172,8 +175,7 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
/* Make the mapping visible to the host. */
iobj->bar = bar;
- iobj->map = ioremap_wc(device->func->resource_addr(device, NVKM_BAR2_INST) +
- (u32)iobj->bar->addr, size);
+ iobj->map = io_mapping_map_wc(&imem->iomap, (u32)iobj->bar->addr, size);
if (!iobj->map) {
nvkm_warn(subdev, "PRAMIN ioremap failed\n");
nvkm_vmm_put(vmm, &iobj->bar);
@@ -188,6 +190,16 @@ nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
return nvkm_memory_map(memory, offset, vmm, vma, argv, argc);
}
+static bool
+check_io_mapping(struct nv50_instmem *imem)
+{
+ struct nvkm_device *device = imem->base.subdev.device;
+
+ return io_mapping_init_wc(&imem->iomap,
+ device->func->resource_addr(device, NVKM_BAR2_INST),
+ device->func->resource_size(device, NVKM_BAR2_INST)) != NULL;
+}
+
static void
nv50_instobj_release(struct nvkm_memory *memory)
{
@@ -239,7 +251,7 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
/* Attempt to get a direct CPU mapping of the object. */
if ((vmm = nvkm_bar_bar2_vmm(imem->subdev.device))) {
- if (!iobj->map)
+ if (!iobj->map && iobj->imem->iomap.size)
nv50_instobj_kmap(iobj, vmm);
map = iobj->map;
}
@@ -277,7 +289,12 @@ nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm)
iobj->lru.next = NULL;
}
- nv50_instobj_kmap(iobj, vmm);
+ /*
+ * boot is only called on BAR2, if we can't remap the complete
+ * BAR it's unlikely things are functioning well.
+ */
+ if (check_io_mapping(iobj->imem))
+ nv50_instobj_kmap(iobj, vmm);
nvkm_instmem_boot(imem);
mutex_unlock(&imem->mutex);
}
@@ -330,7 +347,7 @@ nv50_instobj_dtor(struct nvkm_memory *memory)
if (map) {
struct nvkm_vmm *vmm = nvkm_bar_bar2_vmm(imem->subdev.device);
- iounmap(map);
+ io_mapping_unmap(map);
if (likely(vmm)) /* Can be NULL during BAR destructor. */
nvkm_vmm_put(vmm, &bar);
}
@@ -406,10 +423,14 @@ nv50_instmem_fini(struct nvkm_instmem *base)
nv50_instmem(base)->addr = ~0ULL;
}
-static void *
+void *
nv50_instmem_dtor(struct nvkm_instmem *base)
{
- return nv50_instmem(base);
+ struct nv50_instmem *imem = nv50_instmem(base);
+
+ if (imem->iomap.size)
+ io_mapping_fini(&imem->iomap);
+ return imem;
}
static const struct nvkm_instmem_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
index 87bbdd786eaa..b423f01f5fcd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -26,6 +26,7 @@ int nv50_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero,
struct nvkm_memory **);
int nv50_instobj_wrap(struct nvkm_instmem *, struct nvkm_memory *vram,
struct nvkm_memory **bar2);
+void *nv50_instmem_dtor(struct nvkm_instmem *base);
void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
enum nvkm_subdev_type, int, struct nvkm_instmem *);
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 9f86db774c39..419915e33816 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -22,6 +22,7 @@
#include <linux/string.h>
#include <linux/sys_soc.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include "dss.h"
@@ -482,7 +483,8 @@ static void dpi_bridge_mode_set(struct drm_bridge *bridge,
dpi->pixelclock = adjusted_mode->clock * 1000;
}
-static void dpi_bridge_enable(struct drm_bridge *bridge)
+static void dpi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
int r;
@@ -533,7 +535,8 @@ err_get_dispc:
regulator_disable(dpi->vdds_dsi_reg);
}
-static void dpi_bridge_disable(struct drm_bridge *bridge)
+static void dpi_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
@@ -552,12 +555,15 @@ static void dpi_bridge_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs dpi_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = dpi_bridge_attach,
.mode_valid = dpi_bridge_mode_valid,
.mode_fixup = dpi_bridge_mode_fixup,
.mode_set = dpi_bridge_mode_set,
- .enable = dpi_bridge_enable,
- .disable = dpi_bridge_disable,
+ .atomic_enable = dpi_bridge_enable,
+ .atomic_disable = dpi_bridge_disable,
};
static void dpi_bridge_init(struct dpi_data *dpi)
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 27fe7bca9e2c..7aaee94f86e4 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -35,6 +35,7 @@
#include <linux/component.h>
#include <linux/sys_soc.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
@@ -4654,7 +4655,8 @@ static void dsi_bridge_mode_set(struct drm_bridge *bridge,
dsi_set_config(&dsi->output, adjusted_mode);
}
-static void dsi_bridge_enable(struct drm_bridge *bridge)
+static void dsi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
struct omap_dss_device *dssdev = &dsi->output;
@@ -4673,7 +4675,8 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
dsi_bus_unlock(dsi);
}
-static void dsi_bridge_disable(struct drm_bridge *bridge)
+static void dsi_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct dsi_data *dsi = drm_bridge_to_dsi(bridge);
struct omap_dss_device *dssdev = &dsi->output;
@@ -4692,11 +4695,14 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs dsi_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = dsi_bridge_attach,
.mode_valid = dsi_bridge_mode_valid,
.mode_set = dsi_bridge_mode_set,
- .enable = dsi_bridge_enable,
- .disable = dsi_bridge_disable,
+ .atomic_enable = dsi_bridge_enable,
+ .atomic_disable = dsi_bridge_disable,
};
static void dsi_bridge_init(struct dsi_data *dsi)
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index df4cbc683e2c..d4a3c0ecaaf2 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/string.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include "dss.h"
@@ -197,7 +198,8 @@ static void sdi_bridge_mode_set(struct drm_bridge *bridge,
sdi->pixelclock = adjusted_mode->clock * 1000;
}
-static void sdi_bridge_enable(struct drm_bridge *bridge)
+static void sdi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
struct dispc_clock_info dispc_cinfo;
@@ -260,7 +262,8 @@ err_get_dispc:
regulator_disable(sdi->vdds_sdi_reg);
}
-static void sdi_bridge_disable(struct drm_bridge *bridge)
+static void sdi_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
@@ -274,12 +277,15 @@ static void sdi_bridge_disable(struct drm_bridge *bridge)
}
static const struct drm_bridge_funcs sdi_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = sdi_bridge_attach,
.mode_valid = sdi_bridge_mode_valid,
.mode_fixup = sdi_bridge_mode_fixup,
.mode_set = sdi_bridge_mode_set,
- .enable = sdi_bridge_enable,
- .disable = sdi_bridge_disable,
+ .atomic_enable = sdi_bridge_enable,
+ .atomic_disable = sdi_bridge_disable,
};
static void sdi_bridge_init(struct sdi_device *sdi)
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 9b5d53dc361e..5416c668a205 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -25,6 +25,7 @@
#include <linux/component.h>
#include <linux/sys_soc.h>
+#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include "omapdss.h"
@@ -614,14 +615,16 @@ static void venc_bridge_mode_set(struct drm_bridge *bridge,
dispc_set_tv_pclk(venc->dss->dispc, 13500000);
}
-static void venc_bridge_enable(struct drm_bridge *bridge)
+static void venc_bridge_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct venc_device *venc = drm_bridge_to_venc(bridge);
venc_power_on(venc);
}
-static void venc_bridge_disable(struct drm_bridge *bridge)
+static void venc_bridge_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct venc_device *venc = drm_bridge_to_venc(bridge);
@@ -653,12 +656,15 @@ static int venc_bridge_get_modes(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs venc_bridge_funcs = {
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.attach = venc_bridge_attach,
.mode_valid = venc_bridge_mode_valid,
.mode_fixup = venc_bridge_mode_fixup,
.mode_set = venc_bridge_mode_set,
- .enable = venc_bridge_enable,
- .disable = venc_bridge_disable,
+ .atomic_enable = venc_bridge_enable,
+ .atomic_disable = venc_bridge_disable,
.get_modes = venc_bridge_get_modes,
};
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt37801.c b/drivers/gpu/drm/panel/panel-novatek-nt37801.c
index 861e999250f9..5e46c4c6d771 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt37801.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt37801.c
@@ -51,61 +51,56 @@ static void novatek_nt37801_reset(struct novatek_nt37801 *ctx)
mipi_dsi_dcs_write_seq_multi((dsi_ctx), NT37801_DCS_SWITCH_PAGE, \
0x55, 0xaa, 0x52, 0x08, (page))
-static int novatek_nt37801_on(struct novatek_nt37801 *ctx)
+static void novatek_nt37801_on(struct mipi_dsi_multi_context *dsi_ctx)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
-
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
-
- novatek_nt37801_switch_page(&dsi_ctx, 0x01);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x01);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc5, 0x0b, 0x0b, 0x0b);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf5, 0x10);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x1b);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x55);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x18);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf8, 0x19);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x00);
- mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 0x059f);
- mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 0x0c7f);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x90, 0x03, 0x03);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x91,
+ dsi_ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ novatek_nt37801_switch_page(dsi_ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc5, 0x0b, 0x0b, 0x0b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x02);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xf5, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x1b);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xf4, 0x55);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x18);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xf8, 0x19);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x0f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfc, 0x00);
+ mipi_dsi_dcs_set_column_address_multi(dsi_ctx, 0x0000, 0x059f);
+ mipi_dsi_dcs_set_page_address_multi(dsi_ctx, 0x0000, 0x0c7f);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x90, 0x03, 0x03);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x91,
0x89, 0x28, 0x00, 0x28, 0xc2, 0x00, 0x02,
0x68, 0x04, 0x6c, 0x00, 0x0a, 0x02, 0x77,
0x01, 0xe9, 0x10, 0xf0);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x23);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfb,
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x81);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x23);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfb,
0x00, 0x01, 0x00, 0x11, 0x33, 0x33, 0x33,
0x55, 0x57, 0xd0, 0x00, 0x00, 0x44, 0x56,
0x77, 0x78, 0x9a, 0xbc, 0xdd, 0xf0);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x06);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0xdc);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x00);
- mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x00, 0x18, 0x00, 0x10);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x6f, 0x06);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xf3, 0xdc);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_SET_GAMMA_CURVE, 0x00);
+ mipi_dsi_dcs_set_tear_on_multi(dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x3b, 0x00, 0x18, 0x00, 0x10);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY,
0x20);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51,
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x51,
0x07, 0xff, 0x07, 0xff, 0x0f, 0xff);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x01);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x00);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x9c, 0x01);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_MEMORY_START);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x00);
-
- novatek_nt37801_switch_page(&dsi_ctx, 0x01);
- mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x55, 0x01, 0xff, 0x03);
- mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
- mipi_dsi_msleep(&dsi_ctx, 120);
- mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
- mipi_dsi_msleep(&dsi_ctx, 20);
-
- return dsi_ctx.accum_err;
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x5a, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x5f, 0x00);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x9c, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, MIPI_DCS_WRITE_MEMORY_START);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x2f, 0x00);
+
+ novatek_nt37801_switch_page(dsi_ctx, 0x01);
+ mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xb2, 0x55, 0x01, 0xff, 0x03);
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 120);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+ mipi_dsi_msleep(dsi_ctx, 20);
}
static int novatek_nt37801_off(struct novatek_nt37801 *ctx)
@@ -127,7 +122,8 @@ static int novatek_nt37801_off(struct novatek_nt37801 *ctx)
static int novatek_nt37801_prepare(struct drm_panel *panel)
{
struct novatek_nt37801 *ctx = to_novatek_nt37801(panel);
- struct device *dev = &ctx->dsi->dev;
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
struct drm_dsc_picture_parameter_set pps;
int ret;
@@ -137,22 +133,12 @@ static int novatek_nt37801_prepare(struct drm_panel *panel)
return ret;
novatek_nt37801_reset(ctx);
-
- ret = novatek_nt37801_on(ctx);
- if (ret < 0)
- goto err;
-
+ novatek_nt37801_on(&dsi_ctx);
drm_dsc_pps_payload_pack(&pps, &ctx->dsc);
-
- ret = mipi_dsi_picture_parameter_set(ctx->dsi, &pps);
- if (ret < 0) {
- dev_err(panel->dev, "failed to transmit PPS: %d\n", ret);
- goto err;
- }
-
- ret = mipi_dsi_compression_mode(ctx->dsi, true);
- if (ret < 0) {
- dev_err(dev, "failed to enable compression mode: %d\n", ret);
+ mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps);
+ mipi_dsi_compression_mode_multi(&dsi_ctx, true);
+ if (dsi_ctx.accum_err) {
+ ret = dsi_ctx.accum_err;
goto err;
}
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
index 1b14aa4efe35..54a65abf7e89 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
@@ -88,16 +88,22 @@ static int s6d16d0_prepare(struct drm_panel *panel)
MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (ret) {
dev_err(s6->dev, "failed to enable vblank TE (%d)\n", ret);
- return ret;
+ goto err_power_off;
}
/* Exit sleep mode and power on */
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret) {
dev_err(s6->dev, "failed to exit sleep mode (%d)\n", ret);
- return ret;
+ goto err_power_off;
}
return 0;
+
+err_power_off:
+ gpiod_set_value_cansleep(s6->reset_gpio, 1);
+ regulator_disable(s6->supply);
+
+ return ret;
}
static int s6d16d0_enable(struct drm_panel *panel)
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 784e36d72c2b..36cc2e67a308 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -21,6 +21,7 @@
#include <drm/drm_utils.h>
#include "panfrost_device.h"
+#include "panfrost_drv.h"
#include "panfrost_gem.h"
#include "panfrost_mmu.h"
#include "panfrost_job.h"
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 298b046c95ed..5832dccfc093 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3446,7 +3446,6 @@ queue_timedout_job(struct drm_sched_job *sched_job)
static void queue_free_job(struct drm_sched_job *sched_job)
{
- drm_sched_job_cleanup(sched_job);
panthor_job_put(sched_job);
}
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a026bd35ef48..7f4178800afd 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -31,12 +31,12 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_helper.h>
@@ -1095,6 +1095,10 @@ static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
.best_encoder = qxl_best_encoder,
};
+static const struct drm_encoder_funcs qxl_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static enum drm_connector_status qxl_conn_detect(
struct drm_connector *connector,
bool force)
@@ -1169,10 +1173,10 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
drm_connector_init(dev, &qxl_output->base,
&qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
- ret = drm_simple_encoder_init(dev, &qxl_output->enc,
- DRM_MODE_ENCODER_VIRTUAL);
+ ret = drm_encoder_init(dev, &qxl_output->enc, &qxl_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret) {
- drm_err(dev, "drm_simple_encoder_init() failed, error %d\n",
+ drm_err(dev, "drm_encoder_init() failed, error %d\n",
ret);
goto err_drm_connector_cleanup;
}
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 7484d3c3f4ed..b48099468eb9 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -209,7 +209,8 @@ static void dvo_debugfs_init(struct sti_dvo *dvo, struct drm_minor *minor)
minor->debugfs_root, minor);
}
-static void sti_dvo_disable(struct drm_bridge *bridge)
+static void sti_dvo_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_dvo *dvo = bridge->driver_private;
@@ -232,7 +233,8 @@ static void sti_dvo_disable(struct drm_bridge *bridge)
dvo->enabled = false;
}
-static void sti_dvo_pre_enable(struct drm_bridge *bridge)
+static void sti_dvo_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_dvo *dvo = bridge->driver_private;
struct dvo_config *config = dvo->config;
@@ -320,16 +322,20 @@ static void sti_dvo_set_mode(struct drm_bridge *bridge,
dvo->config = &rgb_24bit_de_cfg;
}
-static void sti_dvo_bridge_nope(struct drm_bridge *bridge)
+static void sti_dvo_bridge_nope(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
/* do nothing */
}
static const struct drm_bridge_funcs sti_dvo_bridge_funcs = {
- .pre_enable = sti_dvo_pre_enable,
- .enable = sti_dvo_bridge_nope,
- .disable = sti_dvo_disable,
- .post_disable = sti_dvo_bridge_nope,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_pre_enable = sti_dvo_pre_enable,
+ .atomic_enable = sti_dvo_bridge_nope,
+ .atomic_disable = sti_dvo_disable,
+ .atomic_post_disable = sti_dvo_bridge_nope,
.mode_set = sti_dvo_set_mode,
};
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index b9f8f68f01f9..b4def2b25cec 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -404,7 +404,8 @@ static void sti_hda_configure_awg(struct sti_hda *hda, u32 *awg_instr, int nb)
hda_write(hda, 0, HDA_SYNC_AWGI + i * 4);
}
-static void sti_hda_disable(struct drm_bridge *bridge)
+static void sti_hda_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_hda *hda = drm_bridge_to_sti_hda(bridge);
u32 val;
@@ -429,7 +430,8 @@ static void sti_hda_disable(struct drm_bridge *bridge)
hda->enabled = false;
}
-static void sti_hda_pre_enable(struct drm_bridge *bridge)
+static void sti_hda_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_hda *hda = drm_bridge_to_sti_hda(bridge);
u32 val, i, mode_idx;
@@ -563,16 +565,20 @@ static void sti_hda_set_mode(struct drm_bridge *bridge,
mode->clock * 1000);
}
-static void sti_hda_bridge_nope(struct drm_bridge *bridge)
+static void sti_hda_bridge_nope(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
/* do nothing */
}
static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
- .pre_enable = sti_hda_pre_enable,
- .enable = sti_hda_bridge_nope,
- .disable = sti_hda_disable,
- .post_disable = sti_hda_bridge_nope,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_pre_enable = sti_hda_pre_enable,
+ .atomic_enable = sti_hda_bridge_nope,
+ .atomic_disable = sti_hda_disable,
+ .atomic_post_disable = sti_hda_bridge_nope,
.mode_set = sti_hda_set_mode,
};
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index f8222e60b1e0..7ba9e0b7ba6c 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -752,7 +752,8 @@ static void hdmi_debugfs_init(struct sti_hdmi *hdmi, struct drm_minor *minor)
minor->debugfs_root, minor);
}
-static void sti_hdmi_disable(struct drm_bridge *bridge)
+static void sti_hdmi_disable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_hdmi *hdmi = drm_bridge_to_sti_hdmi(bridge);
@@ -884,7 +885,8 @@ static int hdmi_audio_configure(struct sti_hdmi *hdmi)
return hdmi_audio_infoframe_config(hdmi);
}
-static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
+static void sti_hdmi_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
struct sti_hdmi *hdmi = drm_bridge_to_sti_hdmi(bridge);
@@ -964,16 +966,20 @@ static void sti_hdmi_set_mode(struct drm_bridge *bridge,
}
}
-static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
+static void sti_hdmi_bridge_nope(struct drm_bridge *bridge,
+ struct drm_atomic_commit *commit)
{
/* do nothing */
}
static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
- .pre_enable = sti_hdmi_pre_enable,
- .enable = sti_hdmi_bridge_nope,
- .disable = sti_hdmi_disable,
- .post_disable = sti_hdmi_bridge_nope,
+ .atomic_create_state = drm_atomic_helper_bridge_create_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_pre_enable = sti_hdmi_pre_enable,
+ .atomic_enable = sti_hdmi_bridge_nope,
+ .atomic_disable = sti_hdmi_disable,
+ .atomic_post_disable = sti_hdmi_bridge_nope,
.mode_set = sti_hdmi_set_mode,
};
diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c
index 10a32620e962..15583ade8494 100644
--- a/drivers/gpu/drm/tests/drm_bridge_test.c
+++ b/drivers/gpu/drm/tests/drm_bridge_test.c
@@ -74,26 +74,6 @@ static void drm_test_bridge_priv_destroy(struct drm_bridge *bridge)
priv->destroyed = true;
}
-static void drm_test_bridge_enable(struct drm_bridge *bridge)
-{
- struct drm_bridge_priv *priv = bridge_to_priv(bridge);
-
- priv->enable_count++;
-}
-
-static void drm_test_bridge_disable(struct drm_bridge *bridge)
-{
- struct drm_bridge_priv *priv = bridge_to_priv(bridge);
-
- priv->disable_count++;
-}
-
-static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = {
- .destroy = drm_test_bridge_priv_destroy,
- .enable = drm_test_bridge_enable,
- .disable = drm_test_bridge_disable,
-};
-
static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
@@ -695,35 +675,8 @@ retry_state:
drm_modeset_acquire_fini(&ctx);
}
-/*
- * Test that drm_bridge_get_current_state() returns NULL for a
- * non-atomic bridge.
- */
-static void drm_test_drm_bridge_get_current_state_legacy(struct kunit *test)
-{
- struct drm_bridge_init_priv *priv;
- struct drm_bridge *bridge;
-
- priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
-
- /*
- * NOTE: Strictly speaking, we should take the bridge->base.lock
- * before calling that function. However, bridge->base is only
- * initialized if the bridge is atomic, while we explicitly
- * initialize one that isn't there.
- *
- * In order to avoid unnecessary warnings, let's skip the
- * locking. The function would return NULL in all cases anyway,
- * so we don't really have any concurrency to worry about.
- */
- bridge = &priv->test_bridge->bridge;
- KUNIT_EXPECT_NULL(test, drm_bridge_get_current_state(bridge));
-}
-
static struct kunit_case drm_bridge_get_current_state_tests[] = {
KUNIT_CASE(drm_test_drm_bridge_get_current_state_atomic),
- KUNIT_CASE(drm_test_drm_bridge_get_current_state_legacy),
{ }
};
@@ -829,62 +782,6 @@ retry_reset:
}
/*
- * Test that a non-atomic bridge is properly power-cycled when calling
- * drm_bridge_helper_reset_crtc().
- */
-static void drm_test_drm_bridge_helper_reset_crtc_legacy(struct kunit *test)
-{
- struct drm_modeset_acquire_ctx ctx;
- struct drm_bridge_init_priv *priv;
- struct drm_display_mode *mode;
- struct drm_bridge_priv *bridge_priv;
- int ret;
-
- priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
-
- mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
-
- drm_modeset_acquire_init(&ctx, 0);
-
-retry_commit:
- ret = drm_kunit_helper_enable_crtc_connector(test,
- &priv->drm, priv->crtc,
- priv->connector,
- mode,
- &ctx);
- if (ret == -EDEADLK) {
- drm_modeset_backoff(&ctx);
- goto retry_commit;
- }
- KUNIT_ASSERT_EQ(test, ret, 0);
-
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
-
- bridge_priv = priv->test_bridge;
- KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 1);
- KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0);
-
- drm_modeset_acquire_init(&ctx, 0);
-
-retry_reset:
- ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx);
- if (ret == -EDEADLK) {
- drm_modeset_backoff(&ctx);
- goto retry_reset;
- }
- KUNIT_ASSERT_EQ(test, ret, 0);
-
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
-
- KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 2);
- KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 1);
-}
-
-/*
* Test that a bridge using the drm_atomic_helper_bridge_get_hdmi_output_bus_fmts()
* function for &drm_bridge_funcs.atomic_get_output_bus_fmts behaves as expected
* for an HDMI connector bridge. Does so by creating an HDMI bridge connector
@@ -970,7 +867,6 @@ retry_commit:
static struct kunit_case drm_bridge_helper_reset_crtc_tests[] = {
KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic),
KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic_disabled),
- KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_legacy),
KUNIT_CASE(drm_test_drm_bridge_helper_hdmi_output_bus_fmts),
{ }
};
@@ -1071,7 +967,7 @@ static void drm_test_bridge_chain_verify_fmt(struct kunit *test,
struct drm_bridge_state *bstate;
unsigned int i = 0;
- drm_for_each_bridge_in_chain_scoped(&priv->encoder, bridge) {
+ drm_for_each_bridge_in_chain(&priv->encoder, bridge) {
KUNIT_ASSERT_LT(test, i, num_expected);
bstate = drm_bridge_get_current_state(bridge);
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 5fdad444009f..c48ddc888cb0 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -760,7 +760,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
return -EAGAIN;
}
if (xe_svm_range_has_dma_mapping(range)) {
- xe_res_first_dma(range->base.pages.dma_addr, 0,
+ xe_res_first_dma(range->pages.dma_addr, 0,
xe_svm_range_size(range),
&curs);
xe_svm_range_debug(range, "BIND PREPARE - MIXED");
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index e0f0c23d172d..b228a737cfd6 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -66,7 +66,7 @@ static bool xe_svm_range_in_vram(struct xe_svm_range *range)
struct drm_gpusvm_pages_flags flags = {
/* Pairs with WRITE_ONCE in drm_gpusvm.c */
- .__flags = READ_ONCE(range->base.pages.flags.__flags),
+ .__flags = READ_ONCE(range->pages.flags.__flags),
};
return flags.has_devmem_pages;
@@ -96,7 +96,7 @@ static struct xe_vm *range_to_vm(struct drm_gpusvm_range *r)
(r__)->base.gpusvm, \
xe_svm_range_in_vram((r__)) ? 1 : 0, \
xe_svm_range_has_vram_binding((r__)) ? 1 : 0, \
- (r__)->base.pages.notifier_seq, \
+ (r__)->pages.notifier_seq, \
xe_svm_range_start((r__)), xe_svm_range_end((r__)), \
xe_svm_range_size((r__)))
@@ -115,6 +115,7 @@ xe_svm_range_alloc(struct drm_gpusvm *gpusvm)
return NULL;
INIT_LIST_HEAD(&range->garbage_collector_link);
+ drm_gpusvm_init_pages(&range->pages, &gpusvm_to_vm(gpusvm)->xe->drm);
xe_vm_get(gpusvm_to_vm(gpusvm));
return &range->base;
@@ -122,8 +123,10 @@ xe_svm_range_alloc(struct drm_gpusvm *gpusvm)
static void xe_svm_range_free(struct drm_gpusvm_range *range)
{
+ drm_gpusvm_free_pages(range->gpusvm, &(to_xe_range(range)->pages),
+ drm_gpusvm_range_size(range) >> PAGE_SHIFT);
xe_vm_put(range_to_vm(range));
- kfree(range);
+ kfree(to_xe_range(range));
}
static void
@@ -134,7 +137,8 @@ xe_svm_garbage_collector_add_range(struct xe_vm *vm, struct xe_svm_range *range,
range_debug(range, "GARBAGE COLLECTOR ADD");
- drm_gpusvm_range_set_unmapped(&range->base, mmu_range);
+ drm_gpusvm_range_set_unmapped(&range->base, &range->pages, 1,
+ mmu_range);
spin_lock(&vm->svm.garbage_collector.lock);
if (list_empty(&range->garbage_collector_link))
@@ -166,7 +170,7 @@ xe_svm_range_notifier_event_begin(struct xe_vm *vm, struct drm_gpusvm_range *r,
range_debug(range, "NOTIFIER");
/* Skip if already unmapped or if no binding exist */
- if (range->base.pages.flags.unmapped || !range->tile_present)
+ if (range->base.flags.unmapped || !range->tile_present)
return 0;
range_debug(range, "NOTIFIER - EXECUTE");
@@ -208,7 +212,8 @@ xe_svm_range_notifier_event_end(struct xe_vm *vm, struct drm_gpusvm_range *r,
xe_svm_assert_in_notifier(vm);
- drm_gpusvm_range_unmap_pages(&vm->svm.gpusvm, r, &ctx);
+ drm_gpusvm_unmap_pages(&vm->svm.gpusvm, &(to_xe_range(r)->pages),
+ drm_gpusvm_range_size(r) >> PAGE_SHIFT, &ctx);
if (!xe_vm_is_closed(vm) && mmu_range->event == MMU_NOTIFY_UNMAP)
xe_svm_garbage_collector_add_range(vm, to_xe_range(r),
mmu_range);
@@ -299,6 +304,7 @@ range_notifier_event_end:
static int __xe_svm_garbage_collector(struct xe_vm *vm,
struct xe_svm_range *range)
{
+ struct drm_gpusvm_ctx ctx = { .in_notifier = false, };
struct dma_fence *fence;
range_debug(range, "GARBAGE COLLECTOR");
@@ -310,6 +316,10 @@ static int __xe_svm_garbage_collector(struct xe_vm *vm,
return PTR_ERR(fence);
dma_fence_put(fence);
+ drm_gpusvm_unmap_pages(&vm->svm.gpusvm, &range->pages,
+ drm_gpusvm_range_size(&range->base) >> PAGE_SHIFT,
+ &ctx);
+
drm_gpusvm_range_remove(&vm->svm.gpusvm, &range->base);
return 0;
@@ -901,7 +911,7 @@ int xe_svm_init(struct xe_vm *vm)
return err;
}
- err = drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM", &vm->xe->drm,
+ err = drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM",
current->mm, 0, vm->size,
xe_modparam.svm_notifier_size * SZ_1M,
&gpusvm_ops, fault_chunk_sizes,
@@ -915,7 +925,7 @@ int xe_svm_init(struct xe_vm *vm)
}
} else {
err = drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM (simple)",
- &vm->xe->drm, NULL, 0, 0, 0, NULL,
+ NULL, 0, 0, 0, NULL,
NULL, 0);
}
@@ -944,15 +954,28 @@ void xe_svm_close(struct xe_vm *vm)
*/
void xe_svm_fini(struct xe_vm *vm)
{
+ struct drm_gpusvm_notifier *notifier, *next;
+ struct drm_gpusvm_ctx ctx = { .in_notifier = false, };
+
xe_assert(vm->xe, xe_vm_is_closed(vm));
+ drm_gpusvm_for_each_notifier_safe(notifier, next, &vm->svm.gpusvm, 0, LONG_MAX) {
+ struct drm_gpusvm_range *range, *__next;
+
+ drm_gpusvm_for_each_range_safe(range, __next, notifier, 0, LONG_MAX)
+ drm_gpusvm_unmap_pages(&vm->svm.gpusvm,
+ &(to_xe_range(range)->pages),
+ drm_gpusvm_range_size(range) >> PAGE_SHIFT,
+ &ctx);
+ }
+
drm_gpusvm_fini(&vm->svm.gpusvm);
}
static bool xe_svm_range_has_pagemap_locked(const struct xe_svm_range *range,
const struct drm_pagemap *dpagemap)
{
- return range->base.pages.dpagemap == dpagemap;
+ return range->pages.dpagemap == dpagemap;
}
static bool xe_svm_range_has_pagemap(struct xe_svm_range *range,
@@ -1017,7 +1040,7 @@ bool xe_svm_range_validate(struct xe_vm *vm,
if (dpagemap)
ret = ret && xe_svm_range_has_pagemap_locked(range, dpagemap);
else
- ret = ret && !range->base.pages.dpagemap;
+ ret = ret && !range->pages.dpagemap;
xe_svm_notifier_unlock(vm);
@@ -1135,8 +1158,12 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
{
struct xe_vm *vm = range_to_vm(&range->base);
u64 range_size = xe_svm_range_size(range);
+ struct drm_gpusvm_range_flags flags = {
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ .__flags = READ_ONCE(range->base.flags.__flags),
+ };
- if (!range->base.pages.flags.migrate_devmem || !dpagemap)
+ if (!flags.migrate_devmem || !dpagemap)
return false;
xe_assert(vm->xe, IS_DGFX(vm->xe));
@@ -1220,6 +1247,7 @@ static int __xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
struct xe_validation_ctx vctx;
struct drm_exec exec;
struct xe_svm_range *range;
+ struct drm_gpusvm_range_flags range_flags;
struct dma_fence *fence;
struct drm_pagemap *dpagemap;
struct xe_tile *tile = gt_to_tile(gt);
@@ -1248,7 +1276,9 @@ retry:
xe_svm_range_fault_count_stats_incr(gt, range);
- if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem)
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ range_flags.__flags = READ_ONCE(range->base.flags.__flags);
+ if (ctx.devmem_only && !range_flags.migrate_devmem)
return -EACCES;
if (xe_svm_range_is_valid(range, tile, ctx.devmem_only, dpagemap)) {
@@ -1505,7 +1535,11 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range,
{
int err = 0;
- err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, &range->base, ctx);
+ err = drm_gpusvm_get_pages(&vm->svm.gpusvm, &range->pages,
+ vm->svm.gpusvm.mm,
+ &range->base.notifier->notifier,
+ drm_gpusvm_range_start(&range->base),
+ drm_gpusvm_range_end(&range->base), ctx);
if (err == -EOPNOTSUPP) {
range_debug(range, "PAGE FAULT - EVICT PAGES");
drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base);
@@ -1620,8 +1654,12 @@ int xe_svm_alloc_vram(struct xe_svm_range *range, const struct drm_gpusvm_ctx *c
struct xe_device *xe = vm->xe;
int err, retries = 1;
bool write_locked = false;
+ struct drm_gpusvm_range_flags flags = {
+ /* READ_ONCE pairs with WRITE_ONCE in drm_gpusvm_range_set_unmapped() */
+ .__flags = READ_ONCE(range->base.flags.__flags),
+ };
- xe_assert(range_to_vm(&range->base)->xe, range->base.pages.flags.migrate_devmem);
+ xe_assert(range_to_vm(&range->base)->xe, flags.migrate_devmem);
range_debug(range, "ALLOCATE VRAM");
migration_state = drm_gpusvm_scan_mm(&range->base,
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 3ca46a6f98c7..a921556d3466 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -31,6 +31,8 @@ struct xe_vram_region;
struct xe_svm_range {
/** @base: base drm_gpusvm_range */
struct drm_gpusvm_range base;
+ /** @pages: Page/DMA mapping state for this range (single drm_device). */
+ struct drm_gpusvm_pages pages;
/**
* @garbage_collector_link: Link into VM's garbage collect SVM range
* list. Protected by VM's garbage collect lock.
@@ -74,7 +76,7 @@ struct xe_pagemap {
*/
static inline bool xe_svm_range_pages_valid(struct xe_svm_range *range)
{
- return drm_gpusvm_range_pages_valid(range->base.gpusvm, &range->base);
+ return drm_gpusvm_pages_valid(range->base.gpusvm, &range->pages);
}
int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr);
@@ -132,7 +134,7 @@ void *xe_svm_private_page_owner(struct xe_vm *vm, bool force_smem);
static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range)
{
lockdep_assert_held(&range->base.gpusvm->notifier_lock);
- return range->base.pages.flags.has_dma_mapping;
+ return range->pages.flags.has_dma_mapping;
}
/**
@@ -210,10 +212,10 @@ struct xe_vram_region;
struct xe_svm_range {
struct {
struct interval_tree_node itree;
- struct {
- const struct drm_pagemap_addr *dma_addr;
- } pages;
} base;
+ struct {
+ const struct drm_pagemap_addr *dma_addr;
+ } pages;
u32 tile_present;
u32 tile_invalidated;
};
@@ -233,7 +235,7 @@ static inline
int xe_svm_init(struct xe_vm *vm)
{
#if IS_ENABLED(CONFIG_DRM_GPUSVM)
- return drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM (simple)", &vm->xe->drm,
+ return drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM (simple)",
NULL, 0, 0, 0, NULL, NULL, 0);
#else
return 0;
diff --git a/drivers/gpu/drm/xe/xe_userptr.c b/drivers/gpu/drm/xe/xe_userptr.c
index 1d2ab678faf5..8b2d461ea0b2 100644
--- a/drivers/gpu/drm/xe/xe_userptr.c
+++ b/drivers/gpu/drm/xe/xe_userptr.c
@@ -390,19 +390,20 @@ int xe_userptr_setup(struct xe_userptr_vma *uvma, unsigned long start,
unsigned long range)
{
struct xe_userptr *userptr = &uvma->userptr;
+ struct xe_vm *vm = xe_vma_vm(&uvma->vma);
int err;
INIT_LIST_HEAD(&userptr->invalidate_link);
INIT_LIST_HEAD(&userptr->repin_link);
+ drm_gpusvm_init_pages(&userptr->pages, &vm->xe->drm);
+
err = mmu_interval_notifier_insert(&userptr->notifier, current->mm,
start, range,
&vma_userptr_notifier_ops);
if (err)
return err;
- userptr->pages.notifier_seq = LONG_MAX;
-
return 0;
}
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 18f3db367dc1..3ac84ed57ab2 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -173,52 +173,6 @@ struct drm_bridge_funcs {
bool (*mode_fixup)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
- /**
- * @disable:
- *
- * This callback should disable the bridge. It is called right before
- * the preceding element in the display pipe is disabled. If the
- * preceding element is a bridge this means it's called before that
- * bridge's @disable vfunc. If the preceding element is a &drm_encoder
- * it's called right before the &drm_encoder_helper_funcs.disable,
- * &drm_encoder_helper_funcs.prepare or &drm_encoder_helper_funcs.dpms
- * hook.
- *
- * The bridge can assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is still running when this callback is called.
- *
- * The @disable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_disable.
- */
- void (*disable)(struct drm_bridge *bridge);
-
- /**
- * @post_disable:
- *
- * This callback should disable the bridge. It is called right after the
- * preceding element in the display pipe is disabled. If the preceding
- * element is a bridge this means it's called after that bridge's
- * @post_disable function. If the preceding element is a &drm_encoder
- * it's called right after the encoder's
- * &drm_encoder_helper_funcs.disable, &drm_encoder_helper_funcs.prepare
- * or &drm_encoder_helper_funcs.dpms hook.
- *
- * The bridge must assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is no longer running when this callback is
- * called.
- *
- * The @post_disable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_post_disable.
- */
- void (*post_disable)(struct drm_bridge *bridge);
/**
* @mode_set:
@@ -249,55 +203,6 @@ struct drm_bridge_funcs {
void (*mode_set)(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode);
- /**
- * @pre_enable:
- *
- * This callback should enable the bridge. It is called right before
- * the preceding element in the display pipe is enabled. If the
- * preceding element is a bridge this means it's called before that
- * bridge's @pre_enable function. If the preceding element is a
- * &drm_encoder it's called right before the encoder's
- * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
- * &drm_encoder_helper_funcs.dpms hook.
- *
- * The display pipe (i.e. clocks and timing signals) feeding this bridge
- * will not yet be running when this callback is called. The bridge must
- * not enable the display link feeding the next bridge in the chain (if
- * there is one) when this callback is called.
- *
- * The @pre_enable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_pre_enable.
- */
- void (*pre_enable)(struct drm_bridge *bridge);
-
- /**
- * @enable:
- *
- * This callback should enable the bridge. It is called right after
- * the preceding element in the display pipe is enabled. If the
- * preceding element is a bridge this means it's called after that
- * bridge's @enable function. If the preceding element is a
- * &drm_encoder it's called right after the encoder's
- * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or
- * &drm_encoder_helper_funcs.dpms hook.
- *
- * The bridge can assume that the display pipe (i.e. clocks and timing
- * signals) feeding it is running when this callback is called. This
- * callback must enable the display link feeding the next bridge in the
- * chain if there is one.
- *
- * The @enable callback is optional.
- *
- * NOTE:
- *
- * This is deprecated, do not use!
- * New drivers shall use &drm_bridge_funcs.atomic_enable.
- */
- void (*enable)(struct drm_bridge *bridge);
/**
* @atomic_pre_enable:
@@ -1359,14 +1264,6 @@ drm_bridge_get_current_state(struct drm_bridge *bridge)
if (!bridge)
return NULL;
- /*
- * Only atomic bridges will have bridge->base initialized by
- * drm_atomic_private_obj_init(), so we need to make sure we're
- * working with one before we try to use the lock.
- */
- if (!bridge->funcs || !bridge->funcs->atomic_create_state)
- return NULL;
-
drm_modeset_lock_assert_held(&bridge->base.lock);
if (!bridge->base.state)
@@ -1474,9 +1371,9 @@ static inline struct drm_bridge *__drm_for_each_bridge_in_chain_next(struct drm_
DEFINE_FREE(__drm_for_each_bridge_in_chain_cleanup, struct drm_bridge *,
if (_T) { mutex_unlock(&_T->encoder->bridge_chain_mutex); drm_bridge_put(_T); })
-/* Internal to drm_for_each_bridge_in_chain_scoped() */
+/* Internal to drm_for_each_bridge_in_chain() */
static inline struct drm_bridge *
-__drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
+__drm_for_each_bridge_in_chain_start(struct drm_encoder *encoder)
{
mutex_lock(&encoder->bridge_chain_mutex);
@@ -1489,8 +1386,7 @@ __drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
}
/**
- * drm_for_each_bridge_in_chain_scoped - iterate over all bridges attached
- * to an encoder
+ * drm_for_each_bridge_in_chain - iterate over all bridges attached to an encoder
* @encoder: the encoder to iterate bridges on
* @bridge: a bridge pointer updated to point to the current bridge at each
* iteration
@@ -1500,9 +1396,9 @@ __drm_for_each_bridge_in_chain_scoped_start(struct drm_encoder *encoder)
* Automatically gets/puts the bridge reference while iterating and locks
* the encoder chain mutex to prevent chain modifications while iterating.
*/
-#define drm_for_each_bridge_in_chain_scoped(encoder, bridge) \
+#define drm_for_each_bridge_in_chain(encoder, bridge) \
for (struct drm_bridge *bridge __free(__drm_for_each_bridge_in_chain_cleanup) = \
- __drm_for_each_bridge_in_chain_scoped_start((encoder)); \
+ __drm_for_each_bridge_in_chain_start((encoder)); \
bridge; \
bridge = __drm_for_each_bridge_in_chain_next(bridge)) \
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 8a4d7134a9a7..b7d987bf76aa 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -109,9 +109,7 @@ struct drm_gpusvm_notifier {
/**
* struct drm_gpusvm_pages_flags - Structure representing a GPU SVM pages flags
*
- * @migrate_devmem: Flag indicating whether the pages can be migrated to device memory
* @unmapped: Flag indicating if the pages has been unmapped
- * @partial_unmap: Flag indicating if the pages has been partially unmapped
* @has_devmem_pages: Flag indicating if the pages has devmem pages
* @has_dma_mapping: Flag indicating if the pages has a DMA mapping
* @__flags: Flags for pages in u16 form (used for READ_ONCE)
@@ -119,11 +117,8 @@ struct drm_gpusvm_notifier {
struct drm_gpusvm_pages_flags {
union {
struct {
- /* All flags below must be set upon creation */
- u16 migrate_devmem : 1;
/* All flags below must be set / cleared under notifier lock */
u16 unmapped : 1;
- u16 partial_unmap : 1;
u16 has_devmem_pages : 1;
u16 has_dma_mapping : 1;
};
@@ -134,6 +129,7 @@ struct drm_gpusvm_pages_flags {
/**
* struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
*
+ * @drm: The DRM device that owns the dma mappings
* @dma_addr: Device address array
* @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
* Note this is assuming only one drm_pagemap per range is allowed.
@@ -143,6 +139,7 @@ struct drm_gpusvm_pages_flags {
* @flags: Flags for the range; see &struct drm_gpusvm_pages_flags
*/
struct drm_gpusvm_pages {
+ struct drm_device *drm;
struct drm_pagemap_addr *dma_addr;
struct drm_pagemap *dpagemap;
struct dma_iova_state state;
@@ -152,6 +149,27 @@ struct drm_gpusvm_pages {
};
/**
+ * struct drm_gpusvm_range_flags - Range-level GPU SVM flags
+ *
+ * @migrate_devmem: Flag indicating whether the range can be migrated to device memory
+ * @unmapped: Flag indicating if the range has been unmapped
+ * @partial_unmap: Flag indicating if the range has been partially unmapped
+ * @__flags: All flags in u16 form (used for READ_ONCE)
+ */
+struct drm_gpusvm_range_flags {
+ union {
+ struct {
+ /* All flags below must be set upon creation */
+ u16 migrate_devmem : 1;
+ /* All flags below must be set / cleared under notifier lock */
+ u16 unmapped : 1;
+ u16 partial_unmap : 1;
+ };
+ u16 __flags;
+ };
+};
+
+/**
* struct drm_gpusvm_range - Structure representing a GPU SVM range
*
* @gpusvm: Pointer to the GPU SVM structure
@@ -159,7 +177,7 @@ struct drm_gpusvm_pages {
* @refcount: Reference count for the range
* @itree: Interval tree node for the range (inserted in GPU SVM notifier)
* @entry: List entry to fast interval tree traversal
- * @pages: The pages for this range.
+ * @flags: Flags for range see &struct drm_gpusvm_range_flags
*
* This structure represents a GPU SVM range used for tracking memory ranges
* mapped in a DRM device.
@@ -170,14 +188,13 @@ struct drm_gpusvm_range {
struct kref refcount;
struct interval_tree_node itree;
struct list_head entry;
- struct drm_gpusvm_pages pages;
+ struct drm_gpusvm_range_flags flags;
};
/**
* struct drm_gpusvm - GPU SVM structure
*
* @name: Name of the GPU SVM
- * @drm: Pointer to the DRM device structure
* @mm: Pointer to the mm_struct for the address space
* @mm_start: Start address of GPU SVM
* @mm_range: Range of the GPU SVM
@@ -201,7 +218,6 @@ struct drm_gpusvm_range {
*/
struct drm_gpusvm {
const char *name;
- struct drm_device *drm;
struct mm_struct *mm;
unsigned long mm_start;
unsigned long mm_range;
@@ -253,7 +269,7 @@ struct drm_gpusvm_ctx {
};
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
- const char *name, struct drm_device *drm,
+ const char *name,
struct mm_struct *mm,
unsigned long mm_start, unsigned long mm_range,
unsigned long notifier_size,
@@ -287,16 +303,8 @@ drm_gpusvm_range_get(struct drm_gpusvm_range *range);
void drm_gpusvm_range_put(struct drm_gpusvm_range *range);
-bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range);
-
-int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx);
-
-void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx);
+bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages);
bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
unsigned long end);
@@ -310,6 +318,8 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
unsigned long end);
void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
+ struct drm_gpusvm_pages *pages,
+ unsigned int pages_count,
const struct mmu_notifier_range *mmu_range);
int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
@@ -329,6 +339,23 @@ void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
unsigned long npages);
/**
+ * drm_gpusvm_init_pages() - Initialize a freshly allocated drm_gpusvm_pages
+ * @svm_pages: Pointer to the drm_gpusvm_pages to initialize.
+ * @drm: The DRM device that will own DMA mappings for this pages object.
+ *
+ * Drivers that embed one or more drm_gpusvm_pages in their own range
+ * structure must call this once on each pages instance after allocation,
+ * before the first drm_gpusvm_get_pages() / unmap / free.
+ */
+static inline void drm_gpusvm_init_pages(struct drm_gpusvm_pages *svm_pages,
+ struct drm_device *drm)
+{
+ memset(svm_pages, 0, sizeof(*svm_pages));
+ svm_pages->drm = drm;
+ svm_pages->notifier_seq = LONG_MAX;
+}
+
+/**
* enum drm_gpusvm_scan_result - Scan result from the drm_gpusvm_scan_mm() function.
* @DRM_GPUSVM_SCAN_UNPOPULATED: At least one page was not present or inaccessible.
* @DRM_GPUSVM_SCAN_EQUAL: All pages belong to the struct dev_pagemap indicated as