* [PATCH] drm/amdgpu: pass scanout position values directly
@ 2026-09-08 8:20 Mohammed Anees
0 siblings, 0 replies; only message in thread
From: Mohammed Anees @ 2026-09-08 8:20 UTC (permalink / raw)
To: amd-gfx
Cc: alexander.deucher, christian.koenig, harry.wentland, sunpeng.li,
siqueira, dri-devel, Mohammed Anees
The DC scanout position helper already returns vblank start, vblank end,
horizontal position and vertical position as separate values.
dm_crtc_get_scanoutpos() currently packs these values into the legacy
register-style vbl and position values, only for the amdgpu base driver
to unpack them again.
Change page_flip_get_scanoutpos() to return the individual values
directly.
For the legacy DCE implementations, keep decoding the packed hardware
register values in the backend before returning them through the common
interface. This keeps the register specific representation local to the
DCE code.
Signed-off-by: Mohammed Anees <pvmohammedanees2003@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 22 ++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 8 ++-
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 20 +++++--
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 20 +++++--
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 20 +++++--
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 31 +++++-----
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 +-
.../display/amdgpu_dm/tests/amdgpu_dm_test.c | 56 ++++++++++++-------
9 files changed, 124 insertions(+), 60 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 59ea338b554c..86c806f9fa97 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -1762,7 +1762,8 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev,
int *hpos, ktime_t *stime, ktime_t *etime,
const struct drm_display_mode *mode)
{
- u32 vbl = 0, position = 0;
+ u32 scan_vbl_start = 0, scan_vbl_end = 0;
+ u32 scan_vpos = 0, scan_hpos = 0;
int vbl_start, vbl_end, vtotal, ret = 0;
bool in_vbl = true;
@@ -1774,8 +1775,14 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev,
if (stime)
*stime = ktime_get();
- if (amdgpu_display_page_flip_get_scanoutpos(adev, pipe, &vbl, &position) == 0)
+ if (amdgpu_display_page_flip_get_scanoutpos(adev, pipe,
+ &scan_vbl_start, &scan_vbl_end,
+ &scan_vpos, &scan_hpos) == 0) {
ret |= DRM_SCANOUTPOS_VALID;
+ }
+
+ *vpos = scan_vpos;
+ *hpos = scan_hpos;
/* Get optional system timestamp after query. */
if (etime)
@@ -1783,16 +1790,11 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev,
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
- /* Decode into vertical and horizontal scanout position. */
- *vpos = position & 0x1fff;
- *hpos = (position >> 16) & 0x1fff;
-
/* Valid vblank area boundaries from gpu retrieved? */
- if (vbl > 0) {
- /* Yes: Decode. */
+ if (scan_vbl_start || scan_vbl_end) {
ret |= DRM_SCANOUTPOS_ACCURATE;
- vbl_start = vbl & 0x1fff;
- vbl_end = (vbl >> 16) & 0x1fff;
+ vbl_start = scan_vbl_start;
+ vbl_end = scan_vbl_end;
} else {
/* No: Fake something reasonable which gives at least ok results. */
vbl_start = mode->crtc_vdisplay;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
index 49a29bf47a37..9390154c12a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
@@ -33,7 +33,9 @@
#define amdgpu_display_hpd_get_gpio_reg(adev) (adev)->mode_info.funcs->hpd_get_gpio_reg((adev))
#define amdgpu_display_bandwidth_update(adev) (adev)->mode_info.funcs->bandwidth_update((adev))
#define amdgpu_display_page_flip(adev, crtc, base, async) (adev)->mode_info.funcs->page_flip((adev), (crtc), (base), (async))
-#define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl, pos) (adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), (vbl), (pos))
+#define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl_start, vbl_end, vpos, hpos) \
+ ((adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), \
+ (vbl_start), (vbl_end), (vpos), (hpos)))
#define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c))
#define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 7c784277396a..7033531001cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -277,8 +277,12 @@ struct amdgpu_display_funcs {
/* pageflipping */
void (*page_flip)(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base, bool async);
- int (*page_flip_get_scanoutpos)(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position);
+ int (*page_flip_get_scanoutpos)(struct amdgpu_device *adev,
+ int crtc,
+ u32 *vbl_start,
+ u32 *vbl_end,
+ u32 *vpos,
+ u32 *hpos);
/* display topology setup */
void (*add_encoder)(struct amdgpu_device *adev,
uint32_t encoder_enum,
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 7de7adc8f225..8bbef608c5dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -256,14 +256,26 @@ static void dce_v10_0_page_flip(struct amdgpu_device *adev,
RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
-static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position)
+static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev,
+ int crtc,
+ u32 *vbl_start,
+ u32 *vbl_end,
+ u32 *vpos,
+ u32 *hpos)
{
+ u32 vbl, position;
+
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL;
- *vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
- *position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
+ position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+ *vbl_start = vbl & 0x1fff;
+ *vbl_end = (vbl >> 16) & 0x1fff;
+
+ *vpos = position & 0x1fff;
+ *hpos = (position >> 16) & 0x1fff;
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index 3c1d6901127d..2181fe57dfdd 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -220,14 +220,26 @@ static void dce_v6_0_page_flip(struct amdgpu_device *adev,
RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
-static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position)
+static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev,
+ int crtc,
+ u32 *vbl_start,
+ u32 *vbl_end,
+ u32 *vpos,
+ u32 *hpos)
{
+ u32 vbl, position;
+
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL;
- *vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
- *position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
+ position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+ *vbl_start = vbl & 0x1fff;
+ *vbl_end = (vbl >> 16) & 0x1fff;
+
+ *vpos = position & 0x1fff;
+ *hpos = (position >> 16) & 0x1fff;
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index a17944d5e843..1388f2161ae8 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -204,14 +204,26 @@ static void dce_v8_0_page_flip(struct amdgpu_device *adev,
RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
}
-static int dce_v8_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position)
+static int dce_v8_0_crtc_get_scanoutpos(struct amdgpu_device *adev,
+ int crtc,
+ u32 *vbl_start,
+ u32 *vbl_end,
+ u32 *vpos,
+ u32 *hpos)
{
+ u32 vbl, position;
+
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL;
- *vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
- *position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
+ position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+ *vbl_start = vbl & 0x1fff;
+ *vbl_end = (vbl >> 16) & 0x1fff;
+
+ *vpos = position & 0x1fff;
+ *hpos = (position >> 16) & 0x1fff;
return 0;
}
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 f49cc198fb0d..f77054060d87 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -186,10 +186,13 @@ STATIC_IFN_KUNIT u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
}
EXPORT_IF_KUNIT(dm_vblank_get_counter);
-STATIC_IFN_KUNIT int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position)
+STATIC_IFN_KUNIT int dm_crtc_get_scanoutpos(struct amdgpu_device *adev,
+ int crtc,
+ u32 *vbl_start,
+ u32 *vbl_end,
+ u32 *vpos,
+ u32 *hpos)
{
- u32 v_blank_start = 0, v_blank_end = 0, h_position = 0, v_position = 0;
struct amdgpu_crtc *acrtc = NULL;
struct dc *dc = adev->dm.dc;
@@ -207,18 +210,16 @@ STATIC_IFN_KUNIT int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc
if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed)
dc_allow_idle_optimizations(dc, false);
- /*
- * TODO rework base driver to use values directly.
- * for now parse it back into reg-format
- */
- dc_stream_get_scanoutpos(acrtc->dm_irq_params.stream,
- &v_blank_start,
- &v_blank_end,
- &h_position,
- &v_position);
-
- *position = v_position | (h_position << 16);
- *vbl = v_blank_start | (v_blank_end << 16);
+ if (!dc_stream_get_scanoutpos(acrtc->dm_irq_params.stream,
+ vbl_start,
+ vbl_end,
+ hpos,
+ vpos)) {
+ *vbl_start = 0;
+ *vbl_end = 0;
+ *vpos = 0;
+ *hpos = 0;
+ }
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 089741ba0619..2819b58e8a9e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1167,7 +1167,8 @@ int dm_set_powergating_state(struct amdgpu_ip_block *ip_block,
void dm_bandwidth_update(struct amdgpu_device *adev);
u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc);
int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
- u32 *vbl, u32 *position);
+ u32 *vbl_start, u32 *vbl_end,
+ u32 *vpos, u32 *hpos);
struct dm_atomic_state *dm_atomic_get_new_state(struct drm_atomic_commit *state);
struct drm_private_state *dm_atomic_duplicate_state(struct drm_private_obj *obj);
void dm_atomic_destroy_state(struct drm_private_obj *obj,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index a67774e6db36..4180f519b57b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -158,15 +158,19 @@ static void dm_test_vblank_get_counter_no_stream(struct kunit *test)
static void dm_test_crtc_get_scanoutpos_invalid_crtc(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
- u32 vbl = 0;
- u32 position = 0;
+ u32 vbl_start = 0;
+ u32 vbl_end = 0;
+ u32 vpos = 0;
+ u32 hpos = 0;
adev->mode_info.num_crtc = 1;
- KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, -1, &vbl, &position),
- -EINVAL);
- KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 1, &vbl, &position),
- -EINVAL);
+ KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, -1,
+ &vbl_start, &vbl_end,
+ &vpos, &hpos), -EINVAL);
+ KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 1,
+ &vbl_start, &vbl_end,
+ &vpos, &hpos), -EINVAL);
}
/**
@@ -177,8 +181,10 @@ static void dm_test_crtc_get_scanoutpos_no_stream(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
struct amdgpu_crtc *acrtc;
- u32 vbl = 0;
- u32 position = 0;
+ u32 vbl_start = 0;
+ u32 vbl_end = 0;
+ u32 vpos = 0;
+ u32 hpos = 0;
acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, acrtc);
@@ -186,9 +192,13 @@ static void dm_test_crtc_get_scanoutpos_no_stream(struct kunit *test)
adev->mode_info.num_crtc = 1;
adev->mode_info.crtcs[0] = acrtc;
- KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0, &vbl, &position), 0);
- KUNIT_EXPECT_EQ(test, vbl, 0U);
- KUNIT_EXPECT_EQ(test, position, 0U);
+ KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0,
+ &vbl_start, &vbl_end,
+ &vpos, &hpos), 0);
+ KUNIT_EXPECT_EQ(test, vbl_start, 0U);
+ KUNIT_EXPECT_EQ(test, vbl_end, 0U);
+ KUNIT_EXPECT_EQ(test, vpos, 0U);
+ KUNIT_EXPECT_EQ(test, hpos, 0U);
}
/**
@@ -1211,14 +1221,20 @@ static void dm_test_crtc_get_scanoutpos_unmapped_stream(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
struct dc *dc = dm_kunit_alloc_dc_with_ctx(test);
- u32 vbl = 0xdeadbeef;
- u32 position = 0xdeadbeef;
+ u32 vbl_start = 0xdeadbeef;
+ u32 vbl_end = 0xdeadbeef;
+ u32 vpos = 0xdeadbeef;
+ u32 hpos = 0xdeadbeef;
dm_test_crtc_with_stream(test, adev, dc);
- KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0, &vbl, &position), 0);
- KUNIT_EXPECT_EQ(test, vbl, 0U);
- KUNIT_EXPECT_EQ(test, position, 0U);
+ KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0,
+ &vbl_start, &vbl_end,
+ &vpos, &hpos), 0);
+ KUNIT_EXPECT_EQ(test, vbl_start, 0U);
+ KUNIT_EXPECT_EQ(test, vbl_end, 0U);
+ KUNIT_EXPECT_EQ(test, vpos, 0U);
+ KUNIT_EXPECT_EQ(test, hpos, 0U);
}
/**
@@ -1229,14 +1245,16 @@ static void dm_test_crtc_get_scanoutpos_exits_idle(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
struct dc *dc = dm_kunit_alloc_dc_with_ctx(test);
- u32 vbl = 0;
- u32 position = 0;
+ u32 vbl_start = 0, vbl_end = 0;
+ u32 vpos = 0, hpos = 0;
dm_test_crtc_with_stream(test, adev, dc);
dc->caps.ips_support = true;
dc->idle_optimizations_allowed = true;
- KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0, &vbl, &position), 0);
+ KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0,
+ &vbl_start, &vbl_end,
+ &vpos, &hpos), 0);
}
static struct drm_atomic_commit *dm_test_alloc_commit(struct kunit *test,
--
2.55.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-08 8:21 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 8:20 [PATCH] drm/amdgpu: pass scanout position values directly Mohammed Anees
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox