From patchwork Tue Dec 16 17:00:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 5502491 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 91374BEEA8 for ; Tue, 16 Dec 2014 17:00:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1431720A25 for ; Tue, 16 Dec 2014 17:00:26 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id A1EAA20A23 for ; Tue, 16 Dec 2014 17:00:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 98AAC6E92D; Tue, 16 Dec 2014 09:00:22 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-pd0-f182.google.com (mail-pd0-f182.google.com [209.85.192.182]) by gabe.freedesktop.org (Postfix) with ESMTP id 699DB6E8F4; Tue, 16 Dec 2014 09:00:21 -0800 (PST) Received: by mail-pd0-f182.google.com with SMTP id p10so14165790pdj.41 for ; Tue, 16 Dec 2014 09:00:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; bh=hN2G0nGB9WwQM0wSA5EZG4um7dtdalcxgfftaHcledQ=; b=cCsG8Dplr6IWMzvtmVVNganLQVCrNxPLnb4k/Mb3zfMhnVHmWSY1UFrd1UNJnpq6pr VM7LXTk4mmiBBy6GlDWu7v7nooLn4a15tdP1ii3uJFOTs8jmHIqQGEfczowr8oVFrBpf BXkQZnio/2XQl8vY14Sl7ssGcAZgZfsL02QK9ZKw193038pAG3r8/4G+nb8qpX/9GO7E uZki/aCpD6oNxLYFGNN4ZWNUaIFAago4TcK3qPglUp6ckWHrI5vu5SmYhP+DjPIB8nh2 gcY7QCGYoFDDJcWKDr0cROEVbX6uSujoCqW+/T+qamVrbd7UGRP/goHPt5BlKdjFZZRq ZklQ== X-Received: by 10.70.61.130 with SMTP id p2mr43189987pdr.0.1418749219376; Tue, 16 Dec 2014 09:00:19 -0800 (PST) Received: from localhost ([216.228.120.20]) by mx.google.com with ESMTPSA id hs10sm1493693pdb.33.2014.12.16.09.00.17 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Dec 2014 09:00:18 -0800 (PST) From: Thierry Reding To: dri-devel@lists.freedesktop.org Date: Tue, 16 Dec 2014 18:00:14 +0100 Message-Id: <1418749214-17433-1-git-send-email-thierry.reding@gmail.com> X-Mailer: git-send-email 2.1.3 MIME-Version: 1.0 Cc: intel-gfx@lists.freedesktop.org, Ben Skeggs , Alex Deucher , Daniel Vetter , =?UTF-8?q?Christian=20K=C3=B6nig?= Subject: [Intel-gfx] [PATCH] drm: Move ->get_scanout_position() to struct drm_crtc_funcs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FILL_THIS_FORM_LOAN,FREEMAIL_FROM,RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding None of the drivers use this in legacy mode, so it can be converted to use struct drm_crtc * directly. While at it, also make the sole user of the callback, drm_calc_vbltimestamp_from_scanoutpos(), pass through the CRTC directly. Cc: Daniel Vetter Cc: Jani Nikula Cc: Ben Skeggs Cc: Alex Deucher Cc: Christian König Signed-off-by: Thierry Reding --- Note: This is compile-tested only. It is a straightforward conversion so I wouldn't expect any fallout, but it'd certainly be best if this can be tested on all three drivers. drivers/gpu/drm/drm_irq.c | 34 +++++++++------------- drivers/gpu/drm/i915/i915_irq.c | 15 +++++----- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 25 ++++------------ drivers/gpu/drm/nouveau/nouveau_display.h | 4 +-- drivers/gpu/drm/nouveau/nouveau_drm.c | 1 - drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/radeon/radeon_display.c | 39 ++++++++++++------------- drivers/gpu/drm/radeon/radeon_drv.c | 1 - drivers/gpu/drm/radeon/radeon_kms.c | 2 +- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- drivers/gpu/drm/radeon/radeon_pm.c | 4 ++- include/drm/drmP.h | 47 ------------------------------- include/drm/drm_crtc.h | 45 +++++++++++++++++++++++++++++ 16 files changed, 104 insertions(+), 121 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 37b536c57cd2..18f1ccad7ee0 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -161,14 +161,14 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. * */ -int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - unsigned int pipe, +int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc, int *max_error, struct timeval *vblank_time, unsigned flags, const struct drm_crtc *refcrtc, const struct drm_display_mode *mode) { + const struct drm_crtc_funcs *funcs = crtc->funcs; struct timeval tv_etime; ktime_t stime, etime; int vbl_status; @@ -176,16 +176,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; bool invbl; - if (pipe >= dev->num_crtcs) { - DRM_ERROR("Invalid crtc %u\n", pipe); - return -EINVAL; - } - /* Scanout position query not supported? Should not happen. */ - if (!dev->driver->get_scanout_position) { - DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); - return -EIO; - } + if (WARN_ON(funcs->get_scanout_position == NULL)) + return -ENOSYS; /* Durations of frames, lines, pixels in nanoseconds. */ framedur_ns = refcrtc->framedur_ns; @@ -196,7 +189,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * Happens during initial modesetting of a crtc. */ if (framedur_ns == 0) { - DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); + DRM_DEBUG("crtc %x: Noop due to uninitialized mode.\n", + crtc->base.id); return -EAGAIN; } @@ -212,13 +206,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos, - &hpos, &stime, &etime); + vbl_status = funcs->get_scanout_position(crtc, flags, &vpos, + &hpos, &stime, &etime); /* Return as no-op if scanout query unsupported or failed. */ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { - DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n", - pipe, vbl_status); + DRM_DEBUG("crtc %x: scanoutpos query failed [%d].\n", + crtc->base.id, vbl_status); return -EIO; } @@ -232,8 +226,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, /* Noisy system timing? */ if (i == DRM_TIMESTAMP_MAXRETRIES) { - DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n", - pipe, duration_ns/1000, *max_error/1000, i); + DRM_DEBUG("crtc %x: Noisy timestamp %d us > %d us [%d reps].\n", + crtc->base.id, duration_ns/1000, *max_error/1000, i); } /* Return upper bound of timestamp precision error. */ @@ -266,8 +260,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_to_timeval(etime); - DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", - pipe, (int)vbl_status, hpos, vpos, + DRM_DEBUG("crtc %x: v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", + crtc->base.id, (int)vbl_status, hpos, vpos, (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, duration_ns/1000, i); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 996c2931c499..bc6dc51abe95 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -662,14 +662,15 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) return (position + crtc->scanline_offset) % vtotal; } -static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, - unsigned int flags, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime) +int i915_get_crtc_scanoutpos(struct drm_crtc *crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode; + enum pipe pipe = intel_crtc->pipe; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; @@ -824,7 +825,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, } /* Helper routine in DRM core does all the work: */ - return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, + return drm_calc_vbltimestamp_from_scanoutpos(crtc, max_error, vblank_time, flags, crtc, &to_intel_crtc(crtc)->config.adjusted_mode); @@ -4360,10 +4361,8 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (!IS_GEN2(dev_priv)) dev->vblank_disable_immediate = true; - if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; - dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; - } if (IS_CHERRYVIEW(dev_priv)) { dev->driver->irq_handler = cherryview_irq_handler; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 518815df51bd..e4e1119e6031 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11660,6 +11660,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .set_config = intel_crtc_set_config, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, + .get_scanout_position = i915_get_crtc_scanoutpos, }; static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 25fdbb16d4e0..4217faeb75e0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -805,6 +805,9 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) return dev_priv->pm.irqs_enabled; } +int i915_get_crtc_scanoutpos(struct drm_crtc *crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime); int intel_get_crtc_scanline(struct intel_crtc *crtc); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 38402ade6835..9071ff9580d1 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1089,6 +1089,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = { .set_config = nouveau_crtc_set_config, .page_flip = nouveau_crtc_page_flip, .destroy = nv_crtc_destroy, + .get_scanout_position = nouveau_display_scanoutpos, }; static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 5d93902a91ab..da040508fdb2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -92,8 +92,9 @@ calc(int blanks, int blanke, int total, int line) } int -nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime) +nouveau_display_scanoutpos(struct drm_crtc *crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime) { struct { struct nv04_disp_mthd_v0 base; @@ -131,22 +132,6 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, } int -nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (nouveau_crtc(crtc)->index == head) { - return nouveau_display_scanoutpos_head(crtc, vpos, hpos, - stime, etime); - } - } - - return 0; -} - -int nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error, struct timeval *time, unsigned flags) { @@ -154,8 +139,8 @@ nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error, list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (nouveau_crtc(crtc)->index == head) { - return drm_calc_vbltimestamp_from_scanoutpos(dev, - head, max_error, time, flags, crtc, + return drm_calc_vbltimestamp_from_scanoutpos(crtc, + max_error, time, flags, crtc, &crtc->hwmode); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index be3d5947c6be..e427034f0265 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -67,8 +67,8 @@ int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_device *, int); void nouveau_display_vblank_disable(struct drm_device *, int); -int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, - int *, int *, ktime_t *, ktime_t *); +int nouveau_display_scanoutpos(struct drm_crtc *, unsigned int, int *, int *, + ktime_t *, ktime_t *); int nouveau_display_vblstamp(struct drm_device *, int, int *, struct timeval *, unsigned); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 22d49438b136..b69c47a63bd9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -958,7 +958,6 @@ driver_stub = { .get_vblank_counter = drm_vblank_count, .enable_vblank = nouveau_display_vblank_enable, .disable_vblank = nouveau_display_vblank_disable, - .get_scanout_position = nouveau_display_scanoutpos, .get_vblank_timestamp = nouveau_display_vblstamp, .ioctls = nouveau_ioctls, diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 490b90866baf..18acbeea16bb 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1386,6 +1386,7 @@ static const struct drm_crtc_funcs nv50_crtc_func = { .set_config = nouveau_crtc_set_config, .destroy = nv50_crtc_destroy, .page_flip = nouveau_crtc_page_flip, + .get_scanout_position = nouveau_display_scanoutpos, }; static int diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 102116902a07..2d0f9be23112 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -322,9 +322,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) * to complete in this vblank? */ if (update_pending && - (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, + (DRM_SCANOUTPOS_VALID & radeon_crtc_get_scanoutpos(&radeon_crtc->base, 0, &vpos, &hpos, NULL, NULL)) && - ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || + ((vpos >= (99 * radeon_crtc->base.hwmode.crtc_vdisplay)/100) || (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { /* crtc didn't flip in this target vblank interval, * but flip is pending in crtc. Based on the current @@ -641,6 +641,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = { .set_config = radeon_crtc_set_config, .destroy = radeon_crtc_destroy, .page_flip = radeon_crtc_page_flip, + .get_scanout_position = radeon_crtc_get_scanoutpos, }; static void radeon_crtc_init(struct drm_device *dev, int index) @@ -1758,7 +1759,6 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * Retrieve current video scanout position of crtc on a given gpu, and * an optional accurate timestamp of when query happened. * - * \param dev Device to query. * \param crtc Crtc to query. * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). * \param *vpos Location where vertical scanout position should be stored. @@ -1782,14 +1782,15 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * unknown small number of scanlines wrt. real scanout position. * */ -int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, +int radeon_crtc_get_scanoutpos(struct drm_crtc *crtc, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); u32 stat_crtc = 0, vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; bool in_vbl = true; - struct radeon_device *rdev = dev->dev_private; + struct radeon_device *rdev = crtc->dev->dev_private; /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ @@ -1798,42 +1799,42 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl *stime = ktime_get(); if (ASIC_IS_DCE4(rdev)) { - if (crtc == 0) { + if (radeon_crtc->crtc_id == 0) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC0_REGISTER_OFFSET); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 1) { + if (radeon_crtc->crtc_id == 1) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC1_REGISTER_OFFSET); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 2) { + if (radeon_crtc->crtc_id == 2) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC2_REGISTER_OFFSET); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 3) { + if (radeon_crtc->crtc_id == 3) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC3_REGISTER_OFFSET); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 4) { + if (radeon_crtc->crtc_id == 4) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC4_REGISTER_OFFSET); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 5) { + if (radeon_crtc->crtc_id == 5) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + @@ -1841,19 +1842,19 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl ret |= DRM_SCANOUTPOS_VALID; } } else if (ASIC_IS_AVIVO(rdev)) { - if (crtc == 0) { + if (radeon_crtc->crtc_id == 0) { vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 1) { + if (radeon_crtc->crtc_id == 1) { vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); ret |= DRM_SCANOUTPOS_VALID; } } else { /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ - if (crtc == 0) { + if (radeon_crtc->crtc_id == 0) { /* Assume vbl_end == 0, get vbl_start from * upper 16 bits. */ @@ -1867,7 +1868,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl ret |= DRM_SCANOUTPOS_VALID; } - if (crtc == 1) { + if (radeon_crtc->crtc_id == 1) { vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; @@ -1898,7 +1899,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl } else { /* No: Fake something reasonable which gives at least ok results. */ - vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vbl_start = crtc->hwmode.crtc_vdisplay; vbl_end = 0; } @@ -1914,7 +1915,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { - vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vtotal = crtc->hwmode.crtc_vtotal; *vpos = *vpos - vtotal; } @@ -1936,8 +1937,8 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl * We only do this if DRM_CALLED_FROM_VBLIRQ. */ if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { - vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; - vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + vbl_start = crtc->hwmode.crtc_vdisplay; + vtotal = crtc->hwmode.crtc_vtotal; if (vbl_start - *vpos < vtotal / 100) { *vpos -= vtotal; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4f50fb0e3d93..d1b0250dde48 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -567,7 +567,6 @@ static struct drm_driver kms_driver = { .enable_vblank = radeon_enable_vblank_kms, .disable_vblank = radeon_disable_vblank_kms, .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, - .get_scanout_position = radeon_get_crtc_scanoutpos, #if defined(CONFIG_DEBUG_FS) .debugfs_init = radeon_debugfs_init, .debugfs_cleanup = radeon_debugfs_cleanup, diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3cf9c1fa6475..652f65b1080f 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -804,7 +804,7 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, return -EINVAL; /* Helper routine in DRM core does all the work: */ - return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, + return drm_calc_vbltimestamp_from_scanoutpos(drmcrtc, max_error, vblank_time, flags, drmcrtc, &drmcrtc->hwmode); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 390db897f322..3c9fa1353261 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -820,7 +820,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); extern void radeon_cursor_reset(struct drm_crtc *crtc); -extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, +extern int radeon_crtc_get_scanoutpos(struct drm_crtc *crtc, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 32522cc940a1..aa9843b09ac8 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1553,8 +1553,10 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) * otherwise return in_vbl == false. */ for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + if (rdev->pm.active_crtcs & (1 << crtc)) { - vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL); + vbl_status = radeon_crtc_get_scanoutpos(&radeon_crtc->base, 0, &vpos, &hpos, NULL, NULL); if ((vbl_status & DRM_SCANOUTPOS_VALID) && !(vbl_status & DRM_SCANOUTPOS_IN_VBLANK)) in_vbl = false; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4809b6f8be8b..90230ef1b73f 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -401,11 +401,6 @@ struct drm_master { #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) #define DRM_VBLANKTIME_IN_VBLANK (1 << 1) -/* get_scanout_position() return flags */ -#define DRM_SCANOUTPOS_VALID (1 << 0) -#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) -#define DRM_SCANOUTPOS_ACCURATE (1 << 2) - /** * struct drm_driver - DRM driver structure * @load: @@ -546,41 +541,6 @@ struct drm_driver { int (*device_is_agp) (struct drm_device *dev); /** - * Called by vblank timestamping code. - * - * Return the current display scanout position from a crtc, and an - * optional accurate ktime_get timestamp of when position was measured. - * - * \param dev DRM device. - * \param crtc Id of the crtc to query. - * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0). - * \param *vpos Target location for current vertical scanout position. - * \param *hpos Target location for current horizontal scanout position. - * \param *stime Target location for timestamp taken immediately before - * scanout position query. Can be NULL to skip timestamp. - * \param *etime Target location for timestamp taken immediately after - * scanout position query. Can be NULL to skip timestamp. - * - * Returns vpos as a positive number while in active scanout area. - * Returns vpos as a negative number inside vblank, counting the number - * of scanlines to go until end of vblank, e.g., -1 means "one scanline - * until start of active scanout / end of vblank." - * - * \return Flags, or'ed together as follows: - * - * DRM_SCANOUTPOS_VALID = Query successful. - * DRM_SCANOUTPOS_INVBL = Inside vblank. - * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of - * this flag means that returned position may be offset by a constant - * but unknown small number of scanlines wrt. real scanout position. - * - */ - int (*get_scanout_position) (struct drm_device *dev, int crtc, - unsigned int flags, - int *vpos, int *hpos, ktime_t *stime, - ktime_t *etime); - - /** * Called by \c drm_get_last_vbltimestamp. Should return a precise * timestamp when the most recent VBLANK interval ended or will end. * @@ -1081,13 +1041,6 @@ extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe); extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe); extern void drm_vblank_cleanup(struct drm_device *dev); -extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - unsigned int pipe, int *max_error, - struct timeval *vblank_time, - unsigned flags, - const struct drm_crtc *refcrtc, - const struct drm_display_mode *mode); - /** * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC * @crtc: which CRTC's vblank waitqueue to retrieve diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c1b639f55401..e9c6278921cd 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -276,6 +276,11 @@ struct drm_crtc_state { struct drm_atomic_state *state; }; +/* get_scanout_position() return flags */ +#define DRM_SCANOUTPOS_VALID (1 << 0) +#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) +#define DRM_SCANOUTPOS_ACCURATE (1 << 2) + /** * struct drm_crtc_funcs - control CRTCs for a given device * @save: save CRTC state @@ -292,6 +297,7 @@ struct drm_crtc_state { * @atomic_duplicate_state: duplicate the atomic state for this CRTC * @atomic_destroy_state: destroy an atomic state for this CRTC * @atomic_set_property: set a property on an atomic state for this CRTC + * @get_scanout_position: return the current scanout position * * The drm_crtc_funcs structure is the central CRTC management structure * in the DRM. Each CRTC controls one or more connectors (note that the name @@ -351,6 +357,38 @@ struct drm_crtc_funcs { struct drm_crtc_state *state, struct drm_property *property, uint64_t val); + + /** + * Called by vblank timestamping code. + * + * Return the current display scanout position from a crtc, and an + * optional accurate ktime_get timestamp of when position was measured. + * + * \param crtc CRTC to query. + * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0). + * \param *vpos Target location for current vertical scanout position. + * \param *hpos Target location for current horizontal scanout position. + * \param *stime Target location for timestamp taken immediately before + * scanout position query. Can be NULL to skip timestamp. + * \param *etime Target location for timestamp taken immediately after + * scanout position query. Can be NULL to skip timestamp. + * + * Returns vpos as a positive number while in active scanout area. + * Returns vpos as a negative number inside vblank, counting the number + * of scanlines to go until end of vblank, e.g., -1 means "one scanline + * until start of active scanout / end of vblank." + * + * \return Flags, or'ed together as follows: + * + * DRM_SCANOUTPOS_VALID = Query successful. + * DRM_SCANOUTPOS_INVBL = Inside vblank. + * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of + * this flag means that returned position may be offset by a constant + * but unknown small number of scanlines wrt. real scanout position. + */ + int (*get_scanout_position)(struct drm_crtc *crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime); }; /** @@ -1159,6 +1197,13 @@ extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); +extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags, + const struct drm_crtc *refcrtc, + const struct drm_display_mode *mode); + extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode);