From patchwork Tue Oct 21 10:56:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dheeraj Jamwal X-Patchwork-Id: 5121191 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B17589F349 for ; Tue, 21 Oct 2014 11:59:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A232120138 for ; Tue, 21 Oct 2014 11:59:37 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 89B77200F4 for ; Tue, 21 Oct 2014 11:59:36 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D8EAE1345; Tue, 21 Oct 2014 11:12:44 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 9FEE0C8D for ; Tue, 21 Oct 2014 11:12:42 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id D5BF21F8A8 for ; Tue, 21 Oct 2014 11:12:41 +0000 (UTC) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 21 Oct 2014 04:12:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,761,1406617200"; d="scan'208";a="617799858" Received: from ubuntu-desktop.png.intel.com ([10.221.122.25]) by fmsmga002.fm.intel.com with ESMTP; 21 Oct 2014 04:12:16 -0700 From: Dheeraj Jamwal To: ltsi-dev@lists.linuxfoundation.org Date: Tue, 21 Oct 2014 18:56:38 +0800 Message-Id: <1413889294-31328-799-git-send-email-dheerajx.s.jamwal@intel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1413889294-31328-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1413889294-31328-1-git-send-email-dheerajx.s.jamwal@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 Subject: [LTSI-dev] [PATCH 0798/1094] drm/i915/chv: find the best divisor for the target clock v4 X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org X-Virus-Scanned: ClamAV using ClamSMTP From: Chon Ming Lee Based on the chv clock limit, find the best divisor. The divisor data has been verified with this spreadsheet. P1273_DPLL_Programming Spreadsheet. v2: Rebase the code and change the chv_find_best_dpll based on new standard way to use intel_PLL_is_valid. Besides, clean up some extra variables. v3: Ville suggest better fixed point for m2 calculation. v4: -Add comment for the limit is compute using fast clock. (Ville) -Don't pass the request clock to chv_clock, as the same function will be use clock readout, which doens't have request clock. (Ville) -Add and use DIV_ROUND_CLOSEST_ULL to consistent with other clock calculation. (Ville) -Fix the dp m2 after m2 has stored fixed point. (Ville) Signed-off-by: Chon Ming Lee [vsyrjala: Avoid div-by-zero in chv_clock()] Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter (cherry picked from commit ef9348c8605264342513f78d6256262886b63eab) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 86 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 21 +++++++++ 2 files changed, 107 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2cd3210..d8b7517 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -41,6 +41,9 @@ #include #include +#define DIV_ROUND_CLOSEST_ULL(ll, d) \ + ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) + static void intel_increase_pllclock(struct drm_crtc *crtc); static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); @@ -328,6 +331,22 @@ static const intel_limit_t intel_limits_vlv = { .p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */ }; +static const intel_limit_t intel_limits_chv = { + /* + * These are the data rate limits (measured in fast clocks) + * since those are the strictest limits we have. The fast + * clock and actual rate limits are more relaxed, so checking + * them would make no difference. + */ + .dot = { .min = 25000 * 5, .max = 540000 * 5}, + .vco = { .min = 4860000, .max = 6700000 }, + .n = { .min = 1, .max = 1 }, + .m1 = { .min = 2, .max = 2 }, + .m2 = { .min = 24 << 22, .max = 175 << 22 }, + .p1 = { .min = 2, .max = 4 }, + .p2 = { .p2_slow = 1, .p2_fast = 14 }, +}; + static void vlv_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m1 * clock->m2; @@ -412,6 +431,8 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) limit = &intel_limits_pineview_lvds; else limit = &intel_limits_pineview_sdvo; + } else if (IS_CHERRYVIEW(dev)) { + limit = &intel_limits_chv; } else if (IS_VALLEYVIEW(dev)) { limit = &intel_limits_vlv; } else if (!IS_GEN2(dev)) { @@ -456,6 +477,17 @@ static void i9xx_clock(int refclk, intel_clock_t *clock) clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); } +static void chv_clock(int refclk, intel_clock_t *clock) +{ + clock->m = clock->m1 * clock->m2; + clock->p = clock->p1 * clock->p2; + if (WARN_ON(clock->n == 0 || clock->p == 0)) + return; + clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m, + clock->n << 22); + clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); +} + #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) /** * Returns whether the given set of divisors are valid for a given refclk with @@ -731,6 +763,58 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, return found; } +static bool +chv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock) +{ + struct drm_device *dev = crtc->dev; + intel_clock_t clock; + uint64_t m2; + int found = false; + + memset(best_clock, 0, sizeof(*best_clock)); + + /* + * Based on hardware doc, the n always set to 1, and m1 always + * set to 2. If requires to support 200Mhz refclk, we need to + * revisit this because n may not 1 anymore. + */ + clock.n = 1, clock.m1 = 2; + target *= 5; /* fast clock */ + + for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { + for (clock.p2 = limit->p2.p2_fast; + clock.p2 >= limit->p2.p2_slow; + clock.p2 -= clock.p2 > 10 ? 2 : 1) { + + clock.p = clock.p1 * clock.p2; + + m2 = DIV_ROUND_CLOSEST_ULL(((uint64_t)target * clock.p * + clock.n) << 22, refclk * clock.m1); + + if (m2 > INT_MAX/clock.m1) + continue; + + clock.m2 = m2; + + chv_clock(refclk, &clock); + + if (!intel_PLL_is_valid(dev, limit, &clock)) + continue; + + /* based on hardware requirement, prefer bigger p + */ + if (clock.p > best_clock->p) { + *best_clock = clock; + found = true; + } + } + } + + return found; +} + bool intel_crtc_active(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -10997,6 +11081,8 @@ static void intel_init_display(struct drm_device *dev) if (HAS_PCH_SPLIT(dev) || IS_G4X(dev)) dev_priv->display.find_dpll = g4x_find_best_dpll; + else if (IS_CHERRYVIEW(dev)) + dev_priv->display.find_dpll = chv_find_best_dpll; else if (IS_VALLEYVIEW(dev)) dev_priv->display.find_dpll = vlv_find_best_dpll; else if (IS_PINEVIEW(dev)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index db64b9c..8da7e7f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -64,6 +64,24 @@ static const struct dp_link_dpll vlv_dpll[] = { { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } }; +/* + * CHV supports eDP 1.4 that have more link rates. + * Below only provides the fixed rate but exclude variable rate. + */ +static const struct dp_link_dpll chv_dpll[] = { + /* + * CHV requires to program fractional division for m2. + * m2 is stored in fixed point format using formula below + * (m2_int << 22) | m2_fraction + */ + { DP_LINK_BW_1_62, /* m2_int = 32, m2_fraction = 1677722 */ + { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, + { DP_LINK_BW_2_7, /* m2_int = 27, m2_fraction = 0 */ + { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, + { DP_LINK_BW_5_4, /* m2_int = 27, m2_fraction = 0 */ + { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } +}; + /** * is_edp - is the given port attached to an eDP panel (either CPU or PCH) * @intel_dp: DP struct @@ -743,6 +761,9 @@ intel_dp_set_clock(struct intel_encoder *encoder, } else if (HAS_PCH_SPLIT(dev)) { divisor = pch_dpll; count = ARRAY_SIZE(pch_dpll); + } else if (IS_CHERRYVIEW(dev)) { + divisor = chv_dpll; + count = ARRAY_SIZE(chv_dpll); } else if (IS_VALLEYVIEW(dev)) { divisor = vlv_dpll; count = ARRAY_SIZE(vlv_dpll);