atmel-hlcdc select pixel-clock outside of given range
Boris Brezillon
boris.brezillon at bootlin.com
Fri Aug 24 08:00:37 UTC 2018
Hi Peter,
On Wed, 22 Aug 2018 13:50:47 +0200
Peter Rosin <peda at axentia.se> wrote:
> Hi!
>
> I just discovered that the atmel-hlcdc driver picks a pixel-clock
> way outside the given range when used with a panel with these
> timings from the device tree.
>
> panel-timing {
> // 1024x768 @ 60Hz (typical)
> clock-frequency = <53350000 65000000 80000000>;
> hactive = <1024>;
> vactive = <768>;
> hfront-porch = <48 88 88>;
> hback-porch = <96 168 168>;
> hsync-len = <32 64 64>;
> vfront-porch = <8 13 14>;
> vback-porch = <8 13 14>;
> vsync-len = <8 12 14>;
> };
>
> IIUC, the atmel-hlcdc driver uses this code to set the pixel-clock
>
> cfg = 0;
>
> prate = clk_get_rate(crtc->dc->hlcdc->sys_clk);
> mode_rate = adj->crtc_clock * 1000;
> if ((prate / 2) < mode_rate) {
> prate *= 2;
> cfg |= ATMEL_HLCDC_CLKSEL;
> }
>
> div = DIV_ROUND_UP(prate, mode_rate);
> if (div < 2)
> div = 2;
>
> cfg |= ATMEL_HLCDC_CLKDIV(div);
>
> regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0),
> ATMEL_HLCDC_CLKSEL | ATMEL_HLCDC_CLKDIV_MASK |
> ATMEL_HLCDC_CLKPOL, cfg);
>
> I.e., the driver sets the divider so that the output frequency is as high
> as possible, but not above the target frequency, which seems sane enough.
> Until you realize that the target frequency is the typical frequency
> from the above device tree (i.e. 65MHz) without regard to the range of
> allowed frequencies.
Yes. I don't know what's the status now, but when I developed this
driver, the accepted range was not exposed. Now there's a way to define
that in the panel desc, but I'm not sure this information is propagated
to the drm_display_mode that is passed to the CRTC.
>
> In my case, which happens to be really unfortunate, sys_clk is running
> at 132MHz so the above results in div set to 3 which gives an output
> frequency of 44MHz. This is way outside the given 53.35-80Mhz range.
> Why was the mode allowed at all when the constraint was not met?
> Further, selecting a div of 2 gets 66MHz, which is really close to the
> target frequency and well inside the given range.
>
> Given the overall picture, selecting div = 3 seems totally buggy.
Absolutely.
>
> Sure, I can work around it by saying
> clock-frequency = <53350000 66000000 80000000>;
> but that is ... just an inappropriate workaround.
I agree. The proper solution would probably involve exposing
accepted timing ranges in drm_display_mode.
>
> Side note, while looking at the above code, I wonder why ATMEL_HLCDC_CLKSEL
> is not set most of the time, instead of only when it absolutely has to?
That sounds like a good idea. Feel free to propose a patch changing
that.
> Dividing the doubled frequency (which seems to be what the flag is doing)
> increases the accuracy of the output frequency. E.g. I would have gotten
> 52.8Mhz instead of 44MHz. So, still not inside the range, but much closer...
>
> Side note, there is no sanity check in the code for too large div. That
> will cause bits to be written outside the divider field in the register
> and an output frequency that is not what the driver intended. But it is
> probably not that important since div will probably be small most of the
> time?
Adding a check on div makes sense too.
Thanks for reporting the bug and proposing options to fix it.
Boris
More information about the dri-devel
mailing list