From owner-svn-src-head@freebsd.org Sat Nov 26 11:12:59 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 93110C5405D; Sat, 26 Nov 2016 11:12:59 +0000 (UTC) (envelope-from manu@bidouilliste.com) Received: from mail.blih.net (mail.blih.net [212.83.177.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mail.blih.net", Issuer "mail.blih.net" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id AA96D955; Sat, 26 Nov 2016 11:12:58 +0000 (UTC) (envelope-from manu@bidouilliste.com) Received: from mail.blih.net (mail.blih.net [212.83.177.182]) by mail.blih.net (OpenSMTPD) with ESMTP id e36ca4a8; Sat, 26 Nov 2016 12:12:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=bidouilliste.com; h=date :from:to:subject:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=mail; bh=kM/MtCIIEyKi tiBrZUcKIXh27Vk=; b=mRY2+kmGbROplX44wlKByum1bPZl9q508F1sKPLsTnZH WG2lmTOWfrFoiqRbdbLedKf2DfdcsgHe4qOrkJQFz1VY1nP3wyg4mRUwwC1m1Fqn 39CGajSVQNDHw+h6q9x44rdCCuupnKaSABqCvxGo8PmOmpfv81bS8XClURZHQ4k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=bidouilliste.com; h=date :from:to:subject:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; q=dns; s=mail; b=in2utB iXUW92y3l7p/0J7ZmTWHvxW6Nlv7+mEJyVaahIlMvHCOXNrWrGGnZbQuctnmQIcz I9LXNeqZSttftBCnza2SJlcLvO2LMAPMVFO2jkykURZfjul75MgqoVCtHONvVP0t VYonnna14qV7tu28v+dWJwvDggLaf0SjQw+TU= Received: from knuckles.blih.net (ip-54.net-82-216-203.roubaix.rev.numericable.fr [82.216.203.54]) by mail.blih.net (OpenSMTPD) with ESMTPSA id 2cf6621a TLS version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO; Sat, 26 Nov 2016 12:12:49 +0100 (CET) Date: Sat, 26 Nov 2016 12:12:49 +0100 From: Emmanuel Vadot To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r309190 - head/sys/arm/allwinner/clk Message-Id: <20161126121249.de3b773a1da87c67458f61d2@bidouilliste.com> In-Reply-To: <201611261036.uAQAam0Z047291@repo.freebsd.org> References: <201611261036.uAQAam0Z047291@repo.freebsd.org> X-Mailer: Sylpheed 3.5.1 (GTK+ 2.24.29; amd64-portbld-freebsd12.0) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Nov 2016 11:12:59 -0000 I should have added that this fix HDMI video output when booting in non-verbose. The PLL wasn't correctly calculated because of the non-usage of the fractional mode. The issue doesn't appears on verbose because the clock framework print out the clock value when created. To get the clock value it calls the recalc_freq method of the clock, which read directly the divisor and other factor from the register. As U-Boot leave the clock enable and setup, the clock framework will get the value set by U-Boot. When choosing the best video mode, we usually end up with the same choice as U-Boot (because both U-Boot and the driver use EDID to get the monitor capabilities), meaning we will get the same dotclock frequency. When setting the PLL to the dotclock frequency, the clock framework first compare the current and desired frequency, as they are the same the underlying methods for setting the clock weren't called. When booting in non-verbose mode, the current clock wasn't known so the methods were called but they wrongly calculated the best frequency for the dotclock. On Sat, 26 Nov 2016 10:36:48 +0000 (UTC) Emmanuel Vadot wrote: > Author: manu > Date: Sat Nov 26 10:36:48 2016 > New Revision: 309190 > URL: https://svnweb.freebsd.org/changeset/base/309190 > > Log: > PLL3 have a fractional mode where an explicit frequency (297Mhz or 270) > can be selected for it. If the desired frequency is one of those two, use > this mode instead of the integer one. > When calculating the PLL3 freq for the dotclock, check if it is a multiple > of the fracional frequencies. > > MFC after: 2 weeks > > Modified: > head/sys/arm/allwinner/clk/aw_lcdclk.c > head/sys/arm/allwinner/clk/aw_pll.c > > Modified: head/sys/arm/allwinner/clk/aw_lcdclk.c > ============================================================================== > --- head/sys/arm/allwinner/clk/aw_lcdclk.c Sat Nov 26 10:33:53 2016 (r309189) > +++ head/sys/arm/allwinner/clk/aw_lcdclk.c Sat Nov 26 10:36:48 2016 (r309190) > @@ -78,6 +78,8 @@ __FBSDID("$FreeBSD$"); > #define CH1_CLK_DIV_RATIO_M_SHIFT 0 > > #define TCON_PLLREF 3000000ULL > +#define TCON_PLLREF_FRAC1 297000000ULL > +#define TCON_PLLREF_FRAC2 270000000ULL > #define TCON_PLL_M_MIN 1 > #define TCON_PLL_M_MAX 15 > #define TCON_PLL_N_MIN 9 > @@ -290,7 +292,7 @@ aw_lcdclk_recalc_freq(struct clknode *cl > } > > static void > -calc_tcon_pll(uint64_t fin, uint64_t fout, uint32_t *pm, uint32_t *pn) > +calc_tcon_pll_integer(uint64_t fin, uint64_t fout, uint32_t *pm, uint32_t *pn) > { > int64_t diff, fcur, best; > int m, n; > @@ -310,14 +312,86 @@ calc_tcon_pll(uint64_t fin, uint64_t fou > } > > static int > +calc_tcon_pll_fractional(uint64_t fin, uint64_t fout, int *clk_div) > +{ > + int m; > + > + /* Test for 1X match */ > + for (m = TCON_PLL_M_MIN; m <= TCON_PLL_M_MAX; m++) { > + if (fout == (fin / m)) { > + *clk_div = m; > + return (CH0_CLK_SRC_SEL_PLL3_1X); > + } > + } > + > + /* Test for 2X match */ > + for (m = TCON_PLL_M_MIN; m <= TCON_PLL_M_MAX; m++) { > + if (fout == ((fin * 2) / m)) { > + *clk_div = m; > + return (CH0_CLK_SRC_SEL_PLL3_2X); > + } > + } > + > + return (-1); > +} > + > +static int > +calc_tcon_pll(uint64_t fin, uint64_t fout, uint64_t *pll_freq, int *tcon_pll_div) > +{ > + uint32_t m, m2, n, n2; > + uint64_t fsingle, fdouble; > + int src_sel; > + bool dbl; > + > + /* Test fractional freq first */ > + src_sel = calc_tcon_pll_fractional(TCON_PLLREF_FRAC1, fout, > + tcon_pll_div); > + if (src_sel != -1) { > + *pll_freq = TCON_PLLREF_FRAC1; > + return src_sel; > + } > + src_sel = calc_tcon_pll_fractional(TCON_PLLREF_FRAC2, fout, > + tcon_pll_div); > + if (src_sel != -1) { > + *pll_freq = TCON_PLLREF_FRAC2; > + return src_sel; > + } > + > + m = n = m2 = n2 = 0; > + dbl = false; > + > + /* Find the frequency closes to the target dot clock, using > + * both 1X and 2X PLL inputs as possible candidates. > + */ > + calc_tcon_pll_integer(TCON_PLLREF, fout, &m, &n); > + calc_tcon_pll_integer(TCON_PLLREF * 2, fout, &m2, &n2); > + > + fsingle = m ? (n * TCON_PLLREF) / m : 0; > + fdouble = m2 ? (n2 * TCON_PLLREF * 2) / m2 : 0; > + > + if (fdouble > fsingle) { > + dbl = true; > + m = m2; > + n = n2; > + } > + > + /* Set desired parent frequency */ > + *pll_freq = n * TCON_PLLREF; > + *tcon_pll_div = m; > + > + /* Return the desired source clock */ > + return (dbl ? CH0_CLK_SRC_SEL_PLL3_2X : > + CH0_CLK_SRC_SEL_PLL3_1X); > +} > + > +static int > aw_lcdclk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, > int flags, int *stop) > { > struct aw_lcdclk_softc *sc; > - uint32_t val, m, m2, n, n2, src_sel; > - uint64_t fsingle, fdouble; > - int error; > - bool dbl; > + uint64_t pll_freq; > + uint32_t val, src_sel; > + int error, tcon_pll_div; > > sc = clknode_get_softc(clk); > > @@ -329,26 +403,7 @@ aw_lcdclk_set_freq(struct clknode *clk, > if (sc->id != CLK_IDX_CH1_SCLK2) > return (ENXIO); > > - m = n = m2 = n2 = 0; > - dbl = false; > - > - /* Find the frequency closes to the target dot clock, using > - * both 1X and 2X PLL inputs as possible candidates. > - */ > - calc_tcon_pll(TCON_PLLREF, *fout, &m, &n); > - calc_tcon_pll(TCON_PLLREF * 2, *fout, &m2, &n2); > - > - fsingle = m ? (n * TCON_PLLREF) / m : 0; > - fdouble = m2 ? (n2 * TCON_PLLREF * 2) / m2 : 0; > - > - if (fdouble > fsingle) { > - dbl = true; > - m = m2; > - n = n2; > - } > - > - src_sel = dbl ? CH0_CLK_SRC_SEL_PLL3_2X : > - CH0_CLK_SRC_SEL_PLL3_1X; > + src_sel = calc_tcon_pll(fin, *fout, &pll_freq, &tcon_pll_div); > > /* Switch parent clock if necessary */ > if (src_sel != clknode_get_parent_idx(clk)) { > @@ -357,10 +412,8 @@ aw_lcdclk_set_freq(struct clknode *clk, > return (error); > } > > - /* Set desired parent frequency */ > - fin = n * TCON_PLLREF; > - > - error = clknode_set_freq(clknode_get_parent(clk), fin, 0, 0); > + error = clknode_set_freq(clknode_get_parent(clk), pll_freq, > + 0, 0); > if (error != 0) > return (error); > > @@ -369,7 +422,7 @@ aw_lcdclk_set_freq(struct clknode *clk, > return (error); > > /* Fetch new input frequency */ > - error = clknode_get_freq(clknode_get_parent(clk), &fin); > + error = clknode_get_freq(clknode_get_parent(clk), &pll_freq); > if (error != 0) > return (error); > > @@ -377,11 +430,11 @@ aw_lcdclk_set_freq(struct clknode *clk, > DEVICE_LOCK(sc); > LCDCLK_READ(sc, &val); > val &= ~CH1_CLK_DIV_RATIO_M; > - val |= ((m - 1) << CH1_CLK_DIV_RATIO_M_SHIFT); > + val |= ((tcon_pll_div - 1) << CH1_CLK_DIV_RATIO_M_SHIFT); > LCDCLK_WRITE(sc, val); > DEVICE_UNLOCK(sc); > > - *fout = fin / m; > + *fout = pll_freq / tcon_pll_div; > *stop = 1; > > break; > > Modified: head/sys/arm/allwinner/clk/aw_pll.c > ============================================================================== > --- head/sys/arm/allwinner/clk/aw_pll.c Sat Nov 26 10:33:53 2016 (r309189) > +++ head/sys/arm/allwinner/clk/aw_pll.c Sat Nov 26 10:36:48 2016 (r309190) > @@ -482,11 +482,20 @@ a10_pll3_set_freq(struct aw_pll_sc *sc, > { > uint32_t val, m, mode, func; > > - m = *fout / A10_PLL3_REF_FREQ; > - > - mode = A10_PLL3_MODE_SEL_INT; > - func = 0; > - *fout = m * A10_PLL3_REF_FREQ; > + if (*fout == 297000000) { > + func = A10_PLL3_FUNC_SET_297MHZ; > + mode = A10_PLL3_MODE_SEL_FRACT; > + m = 0; > + } else if (*fout == 270000000) { > + func = A10_PLL3_FUNC_SET_270MHZ; > + mode = A10_PLL3_MODE_SEL_FRACT; > + m = 0; > + } else { > + mode = A10_PLL3_MODE_SEL_INT; > + func = 0; > + m = *fout / A10_PLL3_REF_FREQ; > + *fout = m * A10_PLL3_REF_FREQ; > + } > > DEVICE_LOCK(sc); > PLL_READ(sc, &val); -- Emmanuel Vadot