From patchwork Tue Sep 26 06:59:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 9971211 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 78084602D8 for ; Tue, 26 Sep 2017 07:02:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6961628D2B for ; Tue, 26 Sep 2017 07:02:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5E5E928D59; Tue, 26 Sep 2017 07:02:28 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE7AE28D2B for ; Tue, 26 Sep 2017 07:02:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934038AbdIZHCM (ORCPT ); Tue, 26 Sep 2017 03:02:12 -0400 Received: from mirror2.csie.ntu.edu.tw ([140.112.30.76]:52858 "EHLO wens.csie.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S966370AbdIZG7b (ORCPT ); Tue, 26 Sep 2017 02:59:31 -0400 Received: by wens.csie.org (Postfix, from userid 1000) id 73211600C2; Tue, 26 Sep 2017 14:59:25 +0800 (CST) From: Chen-Yu Tsai To: Mark Brown , Maxime Ripard , David Airlie , Michael Turquette , Stephen Boyd , Rob Herring , Mark Rutland Cc: Chen-Yu Tsai , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com Subject: [PATCH v2 06/13] drm/sun4i: hdmi: Allow using second PLL as TMDS clk parent Date: Tue, 26 Sep 2017 14:59:12 +0800 Message-Id: <20170926065919.24446-7-wens@csie.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170926065919.24446-1-wens@csie.org> References: <20170926065919.24446-1-wens@csie.org> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Allwinner SoCs typically have two PLLs reserved for video related usage. At the moment we only support using the first one to feed the HDMI transmitter block's TMDS clock. Let the HDMI encoder's TMDS clock go through all of its parents when calculating possible clock rates. This allows usage of the second video PLL as its parent. Note that this does not handle conflicting pixel clocks. It is entirely possible to have an LCD panel use one pixel clock rate, only to be overridden by the HDMI transmitter's clock rate request when the second display pipeline is enabled. This should be handled by having all the clock drivers honor clock rate ranges, and have the consumers use clk_set_rate_min/clk_set_rate_max. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c | 53 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c index 5cf2527bffc8..e8d4c311b80d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c @@ -67,11 +67,11 @@ static unsigned long sun4i_tmds_calc_divider(unsigned long rate, static int sun4i_tmds_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct clk_hw *parent; + struct clk_hw *parent = NULL; unsigned long best_parent = 0; unsigned long rate = req->rate; int best_div = 1, best_half = 1; - int i, j; + int i, j, p; /* * We only consider PLL3, since the TCON is very likely to be @@ -79,32 +79,37 @@ static int sun4i_tmds_determine_rate(struct clk_hw *hw, * clock, so we should not need to do anything. */ - parent = clk_hw_get_parent_by_index(hw, 0); - if (!parent) - return -EINVAL; - - for (i = 1; i < 3; i++) { - for (j = 1; j < 16; j++) { - unsigned long ideal = rate * i * j; - unsigned long rounded; - - rounded = clk_hw_round_rate(parent, ideal); - - if (rounded == ideal) { - best_parent = rounded; - best_half = i; - best_div = j; - goto out; - } - - if (abs(rate - rounded / i) < - abs(rate - best_parent / best_div)) { - best_parent = rounded; - best_div = i; + for (p = 0; p < clk_hw_get_num_parents(hw); p++) { + parent = clk_hw_get_parent_by_index(hw, p); + if (!parent) + continue; + + for (i = 1; i < 3; i++) { + for (j = 1; j < 16; j++) { + unsigned long ideal = rate * i * j; + unsigned long rounded; + + rounded = clk_hw_round_rate(parent, ideal); + + if (rounded == ideal) { + best_parent = rounded; + best_half = i; + best_div = j; + goto out; + } + + if (abs(rate - rounded / i) < + abs(rate - best_parent / best_div)) { + best_parent = rounded; + best_div = i; + } } } } + if (!parent) + return -EINVAL; + out: req->rate = best_parent / best_half / best_div; req->best_parent_rate = best_parent;