[PATCH] drm: rcar-du: Improve non-DPLL clock selection
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue Aug 21 15:52:44 UTC 2018
Hi Laurent, Jacopo,
On 21/08/18 09:08, Laurent Pinchart wrote:
> Hi Jacopo,
>
> (CC'ing Kieran)
>
> On Tuesday, 21 August 2018 10:33:57 EEST jacopo mondi wrote:
>> On Tue, Aug 21, 2018 at 01:12:40AM +0300, Laurent Pinchart wrote:
>>> On Tuesday, 21 August 2018 00:49:41 EEST Laurent Pinchart wrote:
>>>> From: Jacopo Mondi <jacopo at jmondi.org>
>>>>
>>>> DU channels not equipped with a DPLL use an SoC internal (provided by
>>>> the CPG) or external clock source combined with a DU internal divider to
>>>> generate the desired output dot clock frequency.
>>>>
>>>> The current clock selection procedure does not fully exploit the ability
>>>> of external clock sources to generate the exact dot clock frequency by
>>>> themselves, but relies instead on tuning the internal DU clock divider
>>>> only, resulting in a less precise clock generation process.
>>>>
>>>> When possible, and desirable, ask the external clock source for the
>>>> exact output dot clock frequency, and select the clock source that
>>>> produces the frequency closest to the desired output dot clock.
>>>>
>>>> This patch specifically targets platforms (like Salvator-X[S] and ULCBs)
>>>> where the DU's input dotclock.in is generated by the versaclock VC5
>>>> clock source, which is capable of generating the exact rate the DU needs
>>>> as pixel clock output.
>>>>
>>>> This patch fixes higher resolution modes which requires an high pixel
>>>> clock output currently not working on non-HDMI DU channel (such as
>>>> 1920x1080 at 60Hz on the VGA output).
>>>
>>> Just for the record, with this patch the following modes (as printed by
>>>
>>> modetest) on the VGA output now produce correct result with my monitor:
>>> 1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 flags: nhsync,
>>> nvsync
>>> 1600x1200 60 1600 1664 1856 2160 1200 1201 1204 1250 flags: phsync,
>>> pvsync
>>> 1360x768 60 1360 1424 1536 1792 768 771 777 795 flags: phsync, pvsync
>>>
>>> The second mode used to not display at all, with a message telling that
>>> timings were out of range, and the other two modes used to produce a
>>> displayed image partly shifted or scaled out of the screen boundaries.
>>>
>>> The following modes still produce an image partly out of the screen
>>> boundaries.
>>>
>>> 1600x900 60 1600 1624 1704 1800 900 901 904 1000 flags: phsync, pvsync
>>> 1280x960 60 1280 1376 1488 1800 960 961 964 1000 flags: phsync, pvsync
>>> 1366x768 60 1366 1436 1579 1792 768 771 774 798 flags: phsync, pvsync
>>> 1366x768 60 1366 1380 1436 1500 768 769 772 800 flags: phsync, pvsync
>>> 1280x720 60 1280 1390 1430 1650 720 725 730 750 flags: phsync, pvsync
>>>
>>> And this one is reported to be out of range.
>>>
>>> 1920x1200 60 1920 2056 2256 2592 1200 1203 1209 1245 flags: nhsync,
>>> pvsync
>>>
>>> There is thus still room for improvement (some of the issues are possibly
>>> due to my monitor though), but there's also an improvement, and no
>>> noticeable regression.
>>>
>>>> Fixes: 1b30dbde8596 ("drm: rcar-du: Add support for external pixel
>>>> clock")
>>>> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
>>>> [Factor out code to a helper function]
>>>> Signed-off-by: Laurent Pinchart
>>>> <laurent.pinchart+renesas at ideasonboard.com>
>>>> ---
>>>>
>>>> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 86 +++++++++++++++++++---------
>>>> 1 file changed, 55 insertions(+), 31 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index
>>>> f8068170905a..2c9405458bbf
>>>> 100644
>>>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
>>>> @@ -165,6 +165,48 @@ static void rcar_du_dpll_divider(struct
>>>> rcar_du_crtc *rcrtc,
>>>> best_diff);
>>>> }
>>>>
>>>> +struct du_clk_params {
>>>> + struct clk *clk;
>>>> + unsigned long rate;
>>>> + unsigned long diff;
>>>> + u32 escr;
>>>> +};
>>>> +
>>>> +static void rcar_du_escr_divider(struct rcar_du_crtc *rcrtc, struct clk
>>>> *clk,
>>>> + unsigned long target, u32 escr,
>>>> + struct du_clk_params *params)
>>
>> I don't see the rcrtc parameter ever being used in this function.
>> Do you want to keep it anyhow?
>
> You're right, I'll remove it.
>
>>>> +{
>>>> + unsigned long rate;
>>>> + unsigned long diff;
>>>> + u32 div;
>>>> +
>>>> + /*
>>>> + * If the target rate has already been achieved perfectly we can't do
>>>> + * better.
>>>> + */
>>>> + if (params->diff == 0)
>>>> + return;
>>>> +
>>>> + /*
>>>> + * Compute the input clock rate and internal divisor values to obtain
>>>> + * the clock rate closest to the target frequency.
>>>> + */
>>>> + rate = clk_round_rate(clk, target);
>>>> + div = clamp(DIV_ROUND_CLOSEST(rate, target), 1UL, 64UL) - 1;
>>>> + diff = abs(rate / (div + 1) - target);
>>>> +
>>>> + /*
>>>> + * If the resulting frequency is better than any previously obtained,
>>
>> s/obtained,/obtained one,/ ?
>
> Any opinion from a native English speaker ? :-)
I'd probably write:
Store the parameters if the resulting frequency is better than any
previously calculated value.
>> Will get back with some testing results on a different VGA monitor...
>
> Thank you.
>
>>>> + * store the parameters.
>>>> + */
>>>> + if (diff < params->diff) {
>>>> + params->clk = clk;
>>>> + params->rate = rate;
>>>> + params->diff = diff;
>>>> + params->escr = escr | div;
>>>> + }
>>>> +}
>
> [snip]
>
--
Regards
--
Kieran
More information about the dri-devel
mailing list