From patchwork Mon May 6 17:39:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 2524791 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 1ABB43FD85 for ; Mon, 6 May 2013 17:40:46 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 19F99E60E6 for ; Mon, 6 May 2013 10:40:46 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from oproxy6-pub.bluehost.com (oproxy6-pub.bluehost.com [67.222.54.6]) by gabe.freedesktop.org (Postfix) with SMTP id 3C85FE60D4 for ; Mon, 6 May 2013 10:39:36 -0700 (PDT) Received: (qmail 26613 invoked by uid 0); 6 May 2013 17:39:35 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by cpoproxy3.bluehost.com with SMTP; 6 May 2013 17:39:35 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuousgeek.org; s=default; h=Message-Id:Date:Subject:To:From; bh=V235l5xH6gviGTip650DCnY8ocmb1busA5cTw6T/FU4=; b=d4ybG9R8/Tu+93zX0A/i9ZP0QCfTQQyz4/7Av/7IwuRioDt+TOHpPSTXgkG5bFh0FPICrHJC0A2JDfsymVNIEF42PA/oA8LfNqRbUl7y0nf4kQu7fKW7iwMw0xw2dVMI; Received: from [67.161.37.189] (port=42798 helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.80) (envelope-from ) id 1UZPNu-0004kr-Up for intel-gfx@lists.freedesktop.org; Mon, 06 May 2013 11:39:35 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Mon, 6 May 2013 10:39:33 -0700 Message-Id: <1367861973-6164-1-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.9.5 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.161.37.189 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915: get mode clock when reading the pipe config v3 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org We need this for comparing modes between configuration changes. v2: try harder to calulate non-simple pixel clocks (Daniel) call get_clock after getting the encoder config, needed for pixel multiply (Jesse) v3: drop get_clock now that the pixel_multiply has been moved into get_pipe_config Signed-off-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_display.c | 96 +++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 3 ++ 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 924932f..c1826cc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -45,6 +45,11 @@ bool intel_pipe_has_type(struct drm_crtc *crtc, int type); static void intel_increase_pllclock(struct drm_crtc *crtc); static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); +static void i9xx_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config); +static void ironlake_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config); + typedef struct { int min, max; } intel_range_t; @@ -4982,6 +4987,11 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, intel_get_pipe_timings(crtc, pipe_config); + /* FIXME: SDVO & HDMI pixel repeat */ + pipe_config->pixel_multiplier = 1; + + i9xx_crtc_clock_get(crtc, pipe_config); + return true; } @@ -5883,7 +5893,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t tmp; + uint32_t tmp, dpa; tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) @@ -5899,8 +5909,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, ironlake_get_fdi_m_n_config(crtc, pipe_config); } + dpa = I915_READ(DP_A); + if ((dpa & DP_PORT_EN) && ((dpa & DP_PIPE_MASK) >> 30) == crtc->pipe) { + if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ) + pipe_config->cpu_edp_link_rate = 162000; + else + pipe_config->cpu_edp_link_rate = 270000; + } + intel_get_pipe_timings(crtc, pipe_config); + /* FIXME: SDVO & HDMI pixel repeat */ + pipe_config->pixel_multiplier = 1; + + ironlake_crtc_clock_get(crtc, pipe_config); + return true; } @@ -6049,6 +6072,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, intel_get_pipe_timings(crtc, pipe_config); + /* FIXME: SDVO & HDMI pixel repeat */ + pipe_config->pixel_multiplier = 1; + + ironlake_crtc_clock_get(crtc, pipe_config); + return true; } @@ -6910,11 +6938,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, } /* Returns the clock of the currently programmed mode of the given pipe. */ -static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) +static void i9xx_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) { + struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; + int pipe = pipe_config->cpu_transcoder; u32 dpll = I915_READ(DPLL(pipe)); u32 fp; intel_clock_t clock; @@ -6953,7 +6982,8 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) default: DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed " "mode\n", (int)(dpll & DPLL_MODE_MASK)); - return 0; + pipe_config->adjusted_mode.clock = 0; + return; } /* XXX: Handle the 100Mhz refclk */ @@ -6992,8 +7022,56 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) * i830PllIsValid() because it relies on the xf86_config connector * configuration being accurate, which it isn't necessarily. */ + pipe_config->adjusted_mode.clock = clock.dot; +} + +static void ironlake_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; + int link_freq, repeat; + u64 clock; + u32 link_m, link_n; + + /* FIXME: Haswell bits */ + + repeat = pipe_config->pixel_multiplier; + + /* + * The calculation for the data clock is: + * pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp + * But we want to avoid losing precison if possible, so: + * pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp)) + * + * and the link clock is simpler: + * link_clock = (m * link_clock * repeat) / n + */ + + /* + * We need to get the FDI or DP link clock here to derive + * the M/N dividers. + * + * For FDI, we read it from the BIOS or use a fixed 2.7GHz. + * For DP, it's either 1.62GHz or 2.7GHz. + * We do our calculations in 10*MHz since we don't need much precison. + */ + if (pipe_config->has_pch_encoder) + link_freq = intel_fdi_link_freq(dev) * 10000; + else + link_freq = pipe_config->cpu_edp_link_rate; + + link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder)); + link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder)); - return clock.dot; + if (!link_m || !link_n) + return; + + clock = (u64)link_m * (u64)link_freq * (u64)repeat; + do_div(clock, link_n); + + pipe_config->adjusted_mode.clock = clock; } /** Returns the currently programmed mode of the given pipe. */ @@ -7004,6 +7082,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct drm_display_mode *mode; + struct intel_crtc_config pipe_config; int htot = I915_READ(HTOTAL(cpu_transcoder)); int hsync = I915_READ(HSYNC(cpu_transcoder)); int vtot = I915_READ(VTOTAL(cpu_transcoder)); @@ -7013,7 +7092,10 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, if (!mode) return NULL; - mode->clock = intel_crtc_clock_get(dev, crtc); + pipe_config.cpu_transcoder = intel_crtc->pipe; + i9xx_crtc_clock_get(intel_crtc, &pipe_config); + + mode->clock = pipe_config.adjusted_mode.clock; mode->hdisplay = (htot & 0xffff) + 1; mode->htotal = ((htot & 0xffff0000) >> 16) + 1; mode->hsync_start = (hsync & 0xffff) + 1; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index abc4aa8..622acf0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -265,6 +265,9 @@ struct intel_crtc_config { /* FDI configuration, only valid if has_pch_encoder is set. */ int fdi_lanes; struct intel_link_m_n fdi_m_n; + + /* CPU eDP config */ + int cpu_edp_link_rate; }; struct intel_crtc {