From patchwork Fri Aug 5 10:45:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 9265195 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6A63F60760 for ; Fri, 5 Aug 2016 10:45:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5BDEF2843B for ; Fri, 5 Aug 2016 10:45:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 50A472843E; Fri, 5 Aug 2016 10:45:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9E5382843B for ; Fri, 5 Aug 2016 10:45:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A3FA16EB68; Fri, 5 Aug 2016 10:45:40 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x243.google.com (mail-wm0-x243.google.com [IPv6:2a00:1450:400c:c09::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2C9C96EB60; Fri, 5 Aug 2016 10:45:39 +0000 (UTC) Received: by mail-wm0-x243.google.com with SMTP id i5so3216787wmg.2; Fri, 05 Aug 2016 03:45:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=Wmjp6lr9shDbU1zdO5Ne3GCvBYXLvviL9uQH/0YOipU=; b=mzGBvdxYSFLDsPYzQ2WmUktwuqxFmB+clUbMt7myXq4SWGo2mmB/e3OXEIY9e1KWEC 07CU/dfI9nOtLSTSPr1Kd/ughTYFj/lqD0EMgbkC2zYoxfo4oFTNDqMg0NGm+bJYJvOr 0+2MqV7ETEpU5Ktacqkjug5s8QAGq1UU8IlBRPPz26A6FA24svYxBXtG/bacxx2DYBU7 XTw34IKABZfhQhF4Wx5yrAhyM5EefvBVdtu6X0Ot628YtW4Amd1qWzk7ZOMDYHtTOBUV NMDvQrsfTOlKm6IzG+PZiAoDcDU2jBHhfdEAsvnp+hMGWgQUXaverKiO2X6pOAzEBGxL ZnUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=Wmjp6lr9shDbU1zdO5Ne3GCvBYXLvviL9uQH/0YOipU=; b=cOmoaak2QIKIz10C1ww73u2NdjItlfyymKTXdtipJV0HExMAmGk0mBhuTox22WYj5U /cny5W9ne8LVBFobeuoiWM/Ix8+0kTJBqYzxFIJTezHaevfY9/9oQI5dtvnO9h3YKcnz P5oz/GAJttKlbXwhKj/f519aWh/UpQGMTHpFim4e61+x7y6SXpksBCCiGav8X9CAbFsT GyJkohggi1qV6vZB8wUI+XFhBtQVouJp4Sj9LiPOO8xc0Eplgyy+1VNhWTvpEHqfpvu/ 01Nj3aqba8U8dG3YJdMUxhZMev1EgkOwwivER4vsaz/Q8czKIea4ZF7e0nfmd/pPm8sb DOHQ== X-Gm-Message-State: AEkoouvw1021syKDd3QvMgQqkG9EzYQPa44Vs5VbHT5CPLMq6RS4TZrFLHkqpmSSsJaYmg== X-Received: by 10.28.111.4 with SMTP id k4mr2954484wmc.94.1470393937675; Fri, 05 Aug 2016 03:45:37 -0700 (PDT) Received: from cizrna.lan ([109.72.12.111]) by smtp.gmail.com with ESMTPSA id xa2sm17252629wjc.0.2016.08.05.03.45.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 05 Aug 2016 03:45:36 -0700 (PDT) From: Tomeu Vizoso To: linux-kernel@vger.kernel.org Subject: [PATCH v4 3/4] drm/i915: Use new CRC debugfs API Date: Fri, 5 Aug 2016 12:45:04 +0200 Message-Id: <1470393905-6640-4-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1470393905-6640-1-git-send-email-tomeu.vizoso@collabora.com> References: <1470393905-6640-1-git-send-email-tomeu.vizoso@collabora.com> Cc: Tomeu Vizoso , intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, Daniel Vetter , Emil Velikov X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The core provides now an ABI to userspace for generation of frame CRCs, so implement the ->set_crc_source() callback and reuse as much code as possible with the previous ABI implementation. v2: - Leave the legacy implementation in place as the ABI implementation in the core is incompatible with it. v3: - Use the "cooked" vblank counter so we have a whole 32 bits. - Make sure we don't mess with the state of the legacy CRC capture ABI implementation. v4: - Keep use of get_vblank_counter as in the legacy code, will be changed in a followup commit. Signed-off-by: Tomeu Vizoso --- drivers/gpu/drm/i915/i915_irq.c | 69 ++++++++++++------- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_pipe_crc.c | 124 ++++++++++++++++++++++++---------- 4 files changed, 133 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1c2aec392412..e5fb9fa86358 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1492,41 +1492,58 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_pipe_crc_entry *entry; - int head, tail; + struct drm_crtc *crtc = intel_get_crtc_for_pipe(&dev_priv->drm, pipe); + struct drm_driver *driver = dev_priv->drm.driver; + uint32_t crcs[5]; + int head, tail, ret; + u32 frame; spin_lock(&pipe_crc->lock); + if (pipe_crc->source) { + if (!pipe_crc->entries) { + spin_unlock(&pipe_crc->lock); + DRM_DEBUG_KMS("spurious interrupt\n"); + return; + } - if (!pipe_crc->entries) { - spin_unlock(&pipe_crc->lock); - DRM_DEBUG_KMS("spurious interrupt\n"); - return; - } - - head = pipe_crc->head; - tail = pipe_crc->tail; + head = pipe_crc->head; + tail = pipe_crc->tail; - if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { - spin_unlock(&pipe_crc->lock); - DRM_ERROR("CRC buffer overflowing\n"); - return; - } + if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { + spin_unlock(&pipe_crc->lock); + DRM_ERROR("CRC buffer overflowing\n"); + return; + } - entry = &pipe_crc->entries[head]; + entry = &pipe_crc->entries[head]; - entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, - pipe); - entry->crc[0] = crc0; - entry->crc[1] = crc1; - entry->crc[2] = crc2; - entry->crc[3] = crc3; - entry->crc[4] = crc4; + entry->frame = driver->get_vblank_counter(&dev_priv->drm, pipe); + entry->crc[0] = crc0; + entry->crc[1] = crc1; + entry->crc[2] = crc2; + entry->crc[3] = crc3; + entry->crc[4] = crc4; - head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - pipe_crc->head = head; + head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); + pipe_crc->head = head; - spin_unlock(&pipe_crc->lock); + spin_unlock(&pipe_crc->lock); - wake_up_interruptible(&pipe_crc->wq); + wake_up_interruptible(&pipe_crc->wq); + } else { + spin_unlock(&pipe_crc->lock); + spin_lock(&crtc->crc.lock); + crcs[0] = crc0; + crcs[1] = crc1; + crcs[2] = crc2; + crcs[3] = crc3; + crcs[4] = crc4; + frame = driver->get_vblank_counter(&dev_priv->drm, pipe); + ret = drm_crtc_add_crc_entry(crtc, true, frame, crcs); + spin_unlock(&crtc->crc.lock); + if (!ret) + wake_up_interruptible(&crtc->crc.wq); + } } #else static inline void diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index baeb75388dbe..ccb251fcdf46 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13966,6 +13966,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .page_flip = intel_crtc_page_flip, .atomic_duplicate_state = intel_crtc_duplicate_state, .atomic_destroy_state = intel_crtc_destroy_state, + .set_crc_source = intel_crtc_set_crc_source, }; /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d1af85c97a80..1790bb48ebcf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1797,6 +1797,8 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state); /* intel_pipe_crc.c */ int intel_pipe_crc_create(struct drm_minor *minor); void intel_pipe_crc_cleanup(struct drm_minor *minor); +int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, + size_t *values_cnt); extern const struct file_operations i915_display_crc_ctl_fops; #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index e7e1ddfa0f9d..5d13471e789e 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -624,15 +624,62 @@ static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } +static int do_set_crc_source(struct drm_device *dev, enum pipe pipe, + enum intel_pipe_crc_source source) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, + pipe)); + u32 val = 0; /* shut up gcc */ + int ret; + + if (IS_GEN2(dev)) + ret = i8xx_pipe_crc_ctl_reg(&source, &val); + else if (INTEL_INFO(dev)->gen < 5) + ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val); + else if (IS_GEN5(dev) || IS_GEN6(dev)) + ret = ilk_pipe_crc_ctl_reg(&source, &val); + else + ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val); + + if (ret) + return ret; + + if (source) { + /* + * When IPS gets enabled, the pipe CRC changes. Since IPS gets + * enabled and disabled dynamically based on package C states, + * user space can't make reliable use of the CRCs, so let's just + * completely disable it. + */ + hsw_disable_ips(crtc); + } + + I915_WRITE(PIPE_CRC_CTL(pipe), val); + POSTING_READ(PIPE_CRC_CTL(pipe)); + + if (source == INTEL_PIPE_CRC_SOURCE_NONE) { + if (IS_G4X(dev)) + g4x_undo_pipe_scramble_reset(dev, pipe); + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + vlv_undo_pipe_scramble_reset(dev, pipe); + else if (IS_HASWELL(dev) && pipe == PIPE_A) + hsw_trans_edp_pipe_A_crc_wa(dev, false); + + hsw_enable_ips(crtc); + } + + return 0; +} + static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, enum intel_pipe_crc_source source) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, - pipe)); enum intel_display_power_domain power_domain; - u32 val = 0; /* shut up gcc */ int ret; if (pipe_crc->source == source) @@ -648,20 +695,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, return -EIO; } - if (IS_GEN2(dev)) - ret = i8xx_pipe_crc_ctl_reg(&source, &val); - else if (INTEL_INFO(dev)->gen < 5) - ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val); - else if (IS_GEN5(dev) || IS_GEN6(dev)) - ret = ilk_pipe_crc_ctl_reg(&source, &val); - else - ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val); - - if (ret != 0) - goto out; - /* none -> real source transition */ if (source) { struct intel_pipe_crc_entry *entries; @@ -677,14 +710,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, goto out; } - /* - * When IPS gets enabled, the pipe CRC changes. Since IPS gets - * enabled and disabled dynamically based on package C states, - * user space can't make reliable use of the CRCs, so let's just - * completely disable it. - */ - hsw_disable_ips(crtc); - spin_lock_irq(&pipe_crc->lock); kfree(pipe_crc->entries); pipe_crc->entries = entries; @@ -693,10 +718,11 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, spin_unlock_irq(&pipe_crc->lock); } - pipe_crc->source = source; + ret = do_set_crc_source(dev, pipe, source); + if (ret) + goto out; - I915_WRITE(PIPE_CRC_CTL(pipe), val); - POSTING_READ(PIPE_CRC_CTL(pipe)); + pipe_crc->source = source; /* real source -> none transition */ if (source == INTEL_PIPE_CRC_SOURCE_NONE) { @@ -720,15 +746,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, spin_unlock_irq(&pipe_crc->lock); kfree(entries); - - if (IS_G4X(dev)) - g4x_undo_pipe_scramble_reset(dev, pipe); - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - vlv_undo_pipe_scramble_reset(dev, pipe); - else if (IS_HASWELL(dev) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev, false); - - hsw_enable_ips(crtc); } ret = 0; @@ -821,6 +838,11 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s) { int i; + if (!buf) { + *s = INTEL_PIPE_CRC_SOURCE_NONE; + return 0; + } + for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++) if (!strcmp(buf, pipe_crc_sources[i])) { *s = i; @@ -949,3 +971,31 @@ void intel_pipe_crc_cleanup(struct drm_minor *minor) drm_debugfs_remove_files(info_list, 1, minor); } } + +int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, + size_t *values_cnt) +{ + struct drm_i915_private *dev_priv = crtc->dev->dev_private; + enum intel_display_power_domain power_domain; + enum intel_pipe_crc_source source; + int ret; + + if (display_crc_ctl_parse_source(source_name, &source) < 0) { + DRM_DEBUG_DRIVER("unknown source %s\n", source_name); + return -EINVAL; + } + + power_domain = POWER_DOMAIN_PIPE(crtc->index); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { + DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); + return -EIO; + } + + ret = do_set_crc_source(crtc->dev, crtc->index, source); + + intel_display_power_put(dev_priv, power_domain); + + *values_cnt = 5; + + return ret; +}