summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-07 17:37:28 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-07 17:37:28 +0200
commit5eccd39d8efa3bc8d557be50f202bbf023837eed (patch)
tree6f1589cd863481a7dfdace2b9a692957dc94afbe /drivers/gpu
parent8fb649f3a174efaa618928cbe0737bf78b456eed (diff)
parent5015d0d945b3d3f2b038d2667880d5762f7d9437 (diff)
downloadlinux-stable-linux-rolling-stable.tar.gz
linux-stable-linux-rolling-stable.zip
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c79
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c28
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c11
5 files changed, 121 insertions, 9 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 941c1a312824..9320e49e4428 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7846,6 +7846,39 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
return status;
}
+/*
+ * Apple Studio Display exposes two SST DP links for a 2x1 tiled panel.
+ * The primary tile advertises the full 5120x2880 mode (with DSC on the
+ * bandwidth-sufficient link) while the secondary carries a per-tile
+ * 2560x2880 timing on a insufficient bandwidth link. Hide the secondary
+ * connector from userspace so compositors configure a single 5K stream
+ * on the primary link only.
+ */
+static bool amdgpu_dm_hide_secondary_tile_from_userspace(struct drm_connector *connector)
+{
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+ if (!aconnector->dc_sink)
+ return false;
+
+ if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
+ return false;
+
+ drm_edid_connector_update(connector, aconnector->drm_edid);
+
+ if (!connector->has_tile)
+ return false;
+
+ if (!connector->tile_h_loc && !connector->tile_v_loc)
+ return false;
+
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] hiding secondary Apple Studio Display tile from userspace\n",
+ connector->base.id, connector->name);
+
+ return true;
+}
+
/**
* amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
*
@@ -7889,6 +7922,9 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
(!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
return amdgpu_dm_connector_poll(aconnector, force);
+ if (amdgpu_dm_hide_secondary_tile_from_userspace(connector))
+ return connector_status_disconnected;
+
return (aconnector->dc_sink ? connector_status_connected :
connector_status_disconnected);
}
@@ -9080,6 +9116,47 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
}
}
+/*
+ * The Apple Studio Display primary tile advertises both the full 5120x2880
+ * mode and the per-tile 2560x2880 timing. As the secondary tile is hidden from
+ * userspace (see amdgpu_dm_hide_secondary_tile_from_userspace()), drop the
+ * per-tile timing from the primary connector so compositors only pick the full
+ * 5K mode.
+ */
+static void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector)
+{
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+ struct drm_display_mode *mode, *t;
+
+ if (!aconnector->dc_sink)
+ return;
+
+ if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
+ return;
+
+ if (!connector->has_tile)
+ return;
+
+ /* Only prune the per-tile timing from the primary tile. */
+ if (connector->tile_h_loc || connector->tile_v_loc)
+ return;
+
+ list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+ if (mode->hdisplay != connector->tile_h_size ||
+ mode->vdisplay != connector->tile_v_size)
+ continue;
+
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] pruning per-tile %dx%d timing from primary Apple Studio Display tile\n",
+ connector->base.id, connector->name,
+ mode->hdisplay, mode->vdisplay);
+
+ list_del(&mode->head);
+ drm_mode_destroy(connector->dev, mode);
+ aconnector->num_modes--;
+ }
+}
+
static void amdgpu_set_panel_orientation(struct drm_connector *connector)
{
struct drm_encoder *encoder;
@@ -9122,6 +9199,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
amdgpu_dm_connector->num_modes =
drm_edid_connector_add_modes(connector);
+ amdgpu_dm_prune_primary_tile_modes(connector);
+
/* sorting the probed modes before calling function
* amdgpu_dm_get_native_mode() since EDID can have
* more than one preferred mode. The modes that are
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index 4c164ae4a4f9..8304e8897a3e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -535,15 +535,27 @@ static bool enable_assr(void *handle, struct dc_link *link)
static void update_config(void *handle, struct cp_psp_stream_config *config)
{
struct hdcp_workqueue *hdcp_work = handle;
- struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;
- int link_index = aconnector->dc_link->link_index;
- unsigned int conn_index = aconnector->base.index;
- struct mod_hdcp_display *display = &hdcp_work[link_index].display;
- struct mod_hdcp_link *link = &hdcp_work[link_index].link;
- struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+ struct amdgpu_dm_connector *aconnector;
+ const struct dc *dc;
+ int link_index;
+ unsigned int conn_index;
+ struct mod_hdcp_display *display;
+ struct mod_hdcp_link *link;
+ struct hdcp_workqueue *hdcp_w;
struct dc_sink *sink = NULL;
bool link_is_hdcp14 = false;
- const struct dc *dc = aconnector->dc_link->dc;
+
+ aconnector = config->dm_stream_ctx;
+ if (!aconnector || !aconnector->dc_link)
+ return;
+
+ link_index = aconnector->dc_link->link_index;
+ display = &hdcp_work[link_index].display;
+ link = &hdcp_work[link_index].link;
+ hdcp_w = &hdcp_work[link_index];
+
+ conn_index = aconnector->base.index;
+ dc = aconnector->dc_link->dc;
if (config->dpms_off) {
hdcp_remove_display(hdcp_work, link_index, aconnector);
@@ -581,7 +593,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.mst_enabled = config->mst_enabled;
link->dp.dp2_enabled = config->dp2_enabled;
link->dp.usb4_enabled = config->usb4_enabled;
- if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
+ if (sink && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
link->hdmi.frl_enabled = config->frl_enabled;
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
link->adjust.auth_delay = 2;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 6be7f6edd0b2..41aa8f9bb152 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -134,6 +134,17 @@ static void apply_edid_quirks(struct dc_link *link, struct edid *edid,
drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id);
link->wa_flags.skip_phy_ssc_reduction = true;
break;
+ /*
+ * Workaround for Apple Studio Display which exposes a 2x1 tiled panel
+ * over two SST DP links. Hide the secondary tile from userspace so
+ * compositors drive a single 5K stream on the primary link only.
+ */
+ case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE3A):
+ case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE42):
+ case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE46):
+ drm_dbg_driver(dev, "Hiding secondary tile on panel id %X\n", panel_id);
+ edid_caps->panel_patch.disable_second_tile = true;
+ break;
default:
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 4ed1efa17270..6482e275e63b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -187,6 +187,7 @@ struct dc_panel_patch {
unsigned int skip_audio_sab_check;
unsigned int mst_start_top_delay;
unsigned int remove_sink_ext_caps;
+ bool disable_second_tile;
unsigned int disable_colorimetry;
uint8_t blankstream_before_otg_off;
bool oled_optimize_display_on;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 20dba02d6175..c5a24dff4b69 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -313,11 +313,20 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
rep->offset = nvbo->offset;
if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50 &&
!nouveau_cli_uvmm(cli)) {
+ int ret;
+
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
+ if (ret)
+ return ret;
+
vma = nouveau_vma_find(nvbo, vmm);
- if (!vma)
+ if (!vma) {
+ ttm_bo_unreserve(&nvbo->bo);
return -EINVAL;
+ }
rep->offset = vma->addr;
+ ttm_bo_unreserve(&nvbo->bo);
} else
rep->offset = 0;