From patchwork Wed Aug 8 17:15:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Zanoni X-Patchwork-Id: 1296961 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 30155DF223 for ; Wed, 8 Aug 2012 17:21:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1BB0EA0A7B for ; Wed, 8 Aug 2012 10:21:41 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-yw0-f49.google.com (mail-yw0-f49.google.com [209.85.213.49]) by gabe.freedesktop.org (Postfix) with ESMTP id 5282AA0A8A for ; Wed, 8 Aug 2012 10:16:34 -0700 (PDT) Received: by mail-yw0-f49.google.com with SMTP id j52so1095279yhj.36 for ; Wed, 08 Aug 2012 10:16:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=2UJPAjCmpjlN1/7ETwLcZBiYrc8fQqm4FovYfww05vc=; b=B8Ip5yH0SFluyeapsil7YLa444eiS3N+Kz+VxPAHhOSTIdwLxHg1jHO96hSfqnGxw5 jnP5w6O4Yvd0Q8r1IV1abtpT1Y4ESx13a0cPco3PTjir6y2NypKv04gIQVVv0WUwtigF //F0GXmRQK94RV8zrl+BTVJugtpQ1xeTk0nqZ66+hhBlZLiNz5ZN8GcB0SYbvVqzCXUB Edp7Eb3F1LFHlBJ0Pgj8GC9OKqrs90O6bUAd728O78IKwMmPqedzqMx14U6pq9PA0AxE EptNvmBL4aG9IzQ2VekEsT8fJaV3GOwB/M1NE8AEWFOslsIsaZuxdj1Q39U5+rFJ9wWn VTsQ== Received: by 10.236.138.138 with SMTP id a10mr17274218yhj.39.1344446194148; Wed, 08 Aug 2012 10:16:34 -0700 (PDT) Received: from vicky.domain.invalid ([177.40.34.45]) by mx.google.com with ESMTPS id s17sm7583724anj.13.2012.08.08.10.16.32 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 08 Aug 2012 10:16:33 -0700 (PDT) From: Paulo Zanoni To: intel-gfx@lists.freedesktop.org Date: Wed, 8 Aug 2012 14:15:34 -0300 Message-Id: <1344446134-3704-9-git-send-email-przanoni@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1344446134-3704-1-git-send-email-przanoni@gmail.com> References: <1344446134-3704-1-git-send-email-przanoni@gmail.com> Cc: Paulo Zanoni Subject: [Intel-gfx] [PATCH 8/8] drm/i915: try to use WR PLL 2 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 From: Paulo Zanoni The current situation is: we use WR PLL1 for everything, so if we have 2 HDMI outputs they will share the same PLL. As a consequence, when you set a mode on HDMI2, HDMI1 will change its refresh rate. If the modes are too different, setting a mode on HDMI2 may make the HDMI1 screen blank (with one of those error messages from your monitor). So now we at least try to use WR PLL 2. This will improve the case where we have 2 HDMI outputs and don't keep crazily changing ports, but it's still not the perfect solution: - We need to select PORT_CLK_SEL_NONE when we stop using a port, so we will be able to reuse its PLL. - We need to move the whole DDI PLL selection code to a place where we can properly fail and return an error code, possibly undoing the mode set. Right now, instead of failing we're hijacking WR PLL 2. This patch is not the perfect solution, but it's at least better than the current one. Future patches will fix the remaining problems. Signed-off-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_ddi.c | 41 ++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index db242cf..80b9902 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -659,7 +659,10 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); int port = intel_hdmi->ddi_port; int pipe = intel_crtc->pipe; - int p, n2, r2; + uint32_t pll_reg[] = {WRPLL_CTL1, WRPLL_CTL2}; + uint32_t pll_sel[] = {PORT_CLK_SEL_WRPLL1, PORT_CLK_SEL_WRPLL2}; + int p, n2, r2, pll; + bool used; u32 temp, i; /* On Haswell, we need to enable the clocks and prepare DDI function to @@ -667,6 +670,35 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, */ DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe)); + for (pll = 0; pll < 2; pll++) { + used = false; + for (i = PORT_A; i <= PORT_E; i++) { + if (i == port) + continue; + + if (I915_READ(PORT_CLK_SEL(i)) == pll_sel[pll]) { + used = true; + break; + } + } + if (!used) + break; + } + if (pll == 2) { + /* FIXME: just claiming failure and returning from this function + * won't help us at all. So instead we hijack WR PLL 2 and hope + * we don't break the other output (if the refresh rates are + * similar we may survive). We should definitely move the PLL + * code to somewhere else, where we may be able to properly + * fail. Also, we should write code to select PORT_CLK_SEL_NONE + * when we stop using the port, so other ports will be able to + * reuse the WR PLL. */ + DRM_ERROR("No WR PLL available\n"); + pll = 1; + } + + DRM_DEBUG_KMS("Using WR PLL %d\n", pll+1); + for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock) break; @@ -688,9 +720,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, I915_WRITE(LCPLL_CTL, temp & ~LCPLL_PLL_DISABLE); - /* Configure WR PLL 1, program the correct divider values for - * the desired frequency and wait for warmup */ - I915_WRITE(WRPLL_CTL1, + I915_WRITE(pll_reg[pll], WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | WRPLL_DIVIDER_REFERENCE(r2) | @@ -702,8 +732,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, /* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use * this port for connection. */ - I915_WRITE(PORT_CLK_SEL(port), - PORT_CLK_SEL_WRPLL1); + I915_WRITE(PORT_CLK_SEL(port), pll_sel[pll]); I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));