Re: [RFC v2 6/8] MIPS: DTS: jz4780: account for Synopsys HDMI driver and LCD controller

25 views
Skip to first unread message

H. Nikolaus Schaller

unread,
Mar 11, 2020, 8:43:59 AM3/11/20
to Paul Cercueil, Paul Boddie, David Airlie, Daniel Vetter, Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, Linus Walleij, Andi Kleen, Krzysztof Kozlowski, Geert Uytterhoeven, Eric W. Biederman, Miquel Raynal, open list:DRM PANEL DRIVERS, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Linux Kernel Mailing List, linux...@vger.kernel.org, open list:GPIO SUBSYSTEM, Discussions about the Letux Kernel, MIPS Creator CI20 Development
Hi Paul,

> Am 02.03.2020 um 20:27 schrieb Paul Cercueil <pa...@crapouillou.net>:
>
> Hi Nikolaus,
>
>
> Le ven., févr. 28, 2020 at 19:19, H. Nikolaus Schaller <h...@goldelico.com> a écrit :
>> From: Paul Boddie <pa...@boddie.org.uk>
>> A specialisation of the generic Synopsys HDMI driver is employed for JZ4780
>> HDMI support. This requires a new driver, plus device tree and configuration
>> modifications.
>> Signed-off-by: Paul Boddie <pa...@boddie.org.uk>
>> Signed-off-by: H. Nikolaus Schaller <h...@goldelico.com>
>> ---
>> arch/mips/boot/dts/ingenic/jz4780.dtsi | 32 ++++++++++++++++++++++++++
>> 1 file changed, 32 insertions(+)
>> diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi
>> index f928329b034b..391d4e1efd35 100644
>> --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi
>> +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
>> @@ -433,4 +433,36 @@
>> status = "disabled";
>> };
>> +
>> + hdmi: hdmi@10180000 {
>> + compatible = "ingenic,jz4780-dw-hdmi";
>> + reg = <0x10180000 0x8000>;
>> + reg-io-width = <4>;
>> +
>> + clocks = <&cgu JZ4780_CLK_HDMI>, <&cgu JZ4780_CLK_AHB0>;
>> + clock-names = "isfr" , "iahb";
>> +
>> + assigned-clocks = <&cgu JZ4780_CLK_HDMI>;
>> + assigned-clock-rates = <27000000>;
>
> I *think* this should go to the board file.
>
>> +
>> + interrupt-parent = <&intc>;
>> + interrupts = <3>;
>> +
>> + /* ddc-i2c-bus = <&i2c4>; */
>> +
>> + status = "disabled";
>> + };
>> +
>> + lcd: lcd@13050000 {
>
> The node name should be 'lcd-controller'.
>
>> + compatible = "ingenic,jz4740-lcd";
>
> The JZ4780's LCD controller is much newer than the JZ4740 one, so even if it works with the "ingenic,jz4740-lcd" compatible string, you want it as a fallback.
> So this should be: compatible = "ingenic,jz4780-lcd", "ingenic,jz4740-lcd".
>
> That means the YAML should be updated too.

I have started to look into jz4780 HDMI setup again.

Well, there is no driver compatible to "ingenic,jz4780-lcd" so far
and it is questionalbe if we need a different one.

I think we should rather make the driver also compatible
than adding a fallback to ingenic,jz4740-lcdto the DTS.

The reason why this is better even if both LCDC are almost
compatible is that the jz4780 allows for much bigger displays
and therefore should have its own jz_soc_info with 4k x 2k
as maximum.

Next I tried to find out if the LCDC are really compatible.

Well the jz4780 has two lcdc instances but they are separated
by the reg addr. Next, there are unique features (like picture in
picture with alpha blending) but those are probably disabled
if not programmed from reset state. This may become a reason
to separate or augment the driver for the jz4780 but at the
moment we can ignore that.

There are also subtly different bit definitions and register
widths (e.g. 24 bit in addition to 16/18 bit modes or more bits
for the sync position) but it looks as if the ingenic_drm
driver already handles this.

Then I tried to read back the registers. Strangely they
are all 0x00000000. So there is no programming of the
lcd-controller in our DT setup with HDMI at all!

I also checked that ingenic_drm_probe() is called and
returns successfully 0. It also reports that a /dev/fb
has been created:

[ 7.908830] ingenic-drm 13050000.lcd-controller: fb0: ingenic-drmdrmf frame buffer device

But for example ingenic_drm_encoder_atomic_mode_set() is
never called which should write some registers of the LCDC.

I only did see some calls to ingenic_drm_encoder_atomic_check().

This of course explains why we have no HDMI signals despite
proper HPD and a /dev/fb0. Because the LCDC is not being
programmed.

Any ideas / hints how to check or improve?

BR and thanks,
Nikolaus

Paul Cercueil

unread,
Mar 11, 2020, 9:20:20 AM3/11/20
to H. Nikolaus Schaller, Paul Boddie, David Airlie, Daniel Vetter, Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, Linus Walleij, Andi Kleen, Krzysztof Kozlowski, Geert Uytterhoeven, Eric W. Biederman, Miquel Raynal, open list:DRM PANEL DRIVERS, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Linux Kernel Mailing List, linux...@vger.kernel.org, open list:GPIO SUBSYSTEM, Discussions about the Letux Kernel, MIPS Creator CI20 Development
Hi Nikolaus,


Le mer., mars 11, 2020 at 13:43, H. Nikolaus Schaller
Sure, feel free to extend the driver.

> Next I tried to find out if the LCDC are really compatible.
>
> Well the jz4780 has two lcdc instances but they are separated
> by the reg addr. Next, there are unique features (like picture in
> picture with alpha blending) but those are probably disabled
> if not programmed from reset state. This may become a reason
> to separate or augment the driver for the jz4780 but at the
> moment we can ignore that.

Two LCDC instances -> two lcd-controller@... nodes. It's that simple.

The other features you listed are outside the LCDC, so outside the
scope of this driver.

> There are also subtly different bit definitions and register
> widths (e.g. 24 bit in addition to 16/18 bit modes or more bits
> for the sync position) but it looks as if the ingenic_drm
> driver already handles this.
>
> Then I tried to read back the registers. Strangely they
> are all 0x00000000. So there is no programming of the
> lcd-controller in our DT setup with HDMI at all!

How did you read them?
Do it from the regmap: should be "cat
/sys/kernel/debug/regmap/13050000.lcd-controller/registers" (not sure
about the path)

> I also checked that ingenic_drm_probe() is called and
> returns successfully 0. It also reports that a /dev/fb
> has been created:
>
> [ 7.908830] ingenic-drm 13050000.lcd-controller: fb0:
> ingenic-drmdrmf frame buffer device
>
> But for example ingenic_drm_encoder_atomic_mode_set() is
> never called which should write some registers of the LCDC.
>
> I only did see some calls to ingenic_drm_encoder_atomic_check().
>
> This of course explains why we have no HDMI signals despite
> proper HPD and a /dev/fb0. Because the LCDC is not being
> programmed.

It won't be called until the HDMI driver says that the cable is
plugged, and there's a client application (e.g. fbdev emulation)
running. So the problem is most likely within the HDMI driver.

Cheers,
-Paul

H. Nikolaus Schaller

unread,
Mar 11, 2020, 9:30:36 AM3/11/20
to Paul Cercueil, Paul Boddie, David Airlie, Daniel Vetter, Rob Herring, Mark Rutland, Ralf Baechle, Paul Burton, Linus Walleij, Andi Kleen, Krzysztof Kozlowski, Geert Uytterhoeven, Eric W. Biederman, Miquel Raynal, open list:DRM PANEL DRIVERS, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Linux Kernel Mailing List, linux...@vger.kernel.org, open list:GPIO SUBSYSTEM, Discussions about the Letux Kernel, MIPS Creator CI20 Development
Hi Paul,

> Am 11.03.2020 um 14:20 schrieb Paul Cercueil <pa...@crapouillou.net>:
>
> Hi Nikolaus,
>
>
> Le mer., mars 11, 2020 at 13:43, H. Nikolaus Schaller <h...@goldelico.com> a écrit :
>> Hi Paul,
>>> The JZ4780's LCD controller is much newer than the JZ4740 one, so even if it works with the "ingenic,jz4740-lcd" compatible string, you want it as a fallback.
>>> So this should be: compatible = "ingenic,jz4780-lcd", "ingenic,jz4740-lcd".
>>> That means the YAML should be updated too.
>> I have started to look into jz4780 HDMI setup again.
>> Well, there is no driver compatible to "ingenic,jz4780-lcd" so far
>> and it is questionalbe if we need a different one.
>> I think we should rather make the driver also compatible
>> than adding a fallback to ingenic,jz4740-lcdto the DTS.
>> The reason why this is better even if both LCDC are almost
>> compatible is that the jz4780 allows for much bigger displays
>> and therefore should have its own jz_soc_info with 4k x 2k
>> as maximum.
>
> Sure, feel free to extend the driver.
>
>> Next I tried to find out if the LCDC are really compatible.
>> Well the jz4780 has two lcdc instances but they are separated
>> by the reg addr. Next, there are unique features (like picture in
>> picture with alpha blending) but those are probably disabled
>> if not programmed from reset state. This may become a reason
>> to separate or augment the driver for the jz4780 but at the
>> moment we can ignore that.
>
> Two LCDC instances -> two lcd-controller@... nodes. It's that simple.

Indeed :)

>
> The other features you listed are outside the LCDC, so outside the scope of this driver.

Well, in the description they are mixed but I think we do not have
to care about now.
>
>> There are also subtly different bit definitions and register
>> widths (e.g. 24 bit in addition to 16/18 bit modes or more bits
>> for the sync position) but it looks as if the ingenic_drm
>> driver already handles this.
>> Then I tried to read back the registers. Strangely they
>> are all 0x00000000. So there is no programming of the
>> lcd-controller in our DT setup with HDMI at all!
>
> How did you read them?

I used devmem2 (may be an omap tool I have recompiled for MIPS - it uses /dev/mem).

> Do it from the regmap: should be "cat /sys/kernel/debug/regmap/13050000.lcd-controller/registers" (not sure about the path)

Well seems to give the same result:

root@letux:~# cat /sys/kernel/debug/regmap/13050000.lcd-controller/registers
00: 00000000
04: 00000000
08: 00000000
0c: 00000000
10: 00000000
14: 00000000
18: 00000000
1c: 00000000
20: 00000000
24: 00000000
28: 00000000
2c: 00000000
30: 00000000
34: 00000000
38: 00000000
3c: 00000000
40: 00000000
44: 00000000
48: 00000000
4c: 00000000
50: 00000000
54: 00000000
58: 00000000
5c: 00000000
root@letux:~#

>
>> I also checked that ingenic_drm_probe() is called and
>> returns successfully 0. It also reports that a /dev/fb
>> has been created:
>> [ 7.908830] ingenic-drm 13050000.lcd-controller: fb0: ingenic-drmdrmf frame buffer device
>> But for example ingenic_drm_encoder_atomic_mode_set() is
>> never called which should write some registers of the LCDC.
>> I only did see some calls to ingenic_drm_encoder_atomic_check().
>> This of course explains why we have no HDMI signals despite
>> proper HPD and a /dev/fb0. Because the LCDC is not being
>> programmed.
>
> It won't be called until the HDMI driver says that the cable is plugged, and there's a client application (e.g. fbdev emulation) running. So the problem is most likely within the HDMI driver.

Ok!

The HDMI subsystem says (with some printk inserted) on cable unplug/replug:

root@letux:~# [ 3894.370706] dw_hdmi_update_power
[ 3894.373984] dw_hdmi_update_power: hdmi->force=0
[ 3894.378759] dw_hdmi_update_power: hdmi->disabled=0
[ 3894.383756] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.388947] dw_hdmi_update_power: hdmi->rxsense=1
[ 3894.393831] dw_hdmi_update_power: force=2
[ 3894.397895] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.403200] dw_hdmi_phy_update_hpd
[ 3894.406784] dw_hdmi_update_power
[ 3894.410054] dw_hdmi_update_power: hdmi->force=0
[ 3894.414766] dw_hdmi_update_power: hdmi->disabled=0
[ 3894.419611] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.424928] dw_hdmi_update_power: hdmi->rxsense=1
[ 3894.429699] dw_hdmi_update_power: force=2
[ 3894.433876] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.439068] dw_hdmi_phy_update_hpd
[ 3894.452316] dw_hdmi_update_power
[ 3894.455596] dw_hdmi_update_power: hdmi->force=0
[ 3894.460150] dw_hdmi_update_power: hdmi->disabled=0
[ 3894.464967] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.470131] dw_hdmi_update_power: hdmi->rxsense=1
[ 3894.475051] dw_hdmi_update_power: force=2
[ 3894.479111] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.484423] dw_hdmi_phy_update_hpd
[ 3894.488007] dw_hdmi_update_power
[ 3894.491278] dw_hdmi_update_power: hdmi->force=0
[ 3894.495982] dw_hdmi_update_power: hdmi->disabled=0
[ 3894.500823] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.506139] dw_hdmi_update_power: hdmi->rxsense=0
[ 3894.510895] dw_hdmi_update_power: force=1
[ 3894.515063] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3894.520252] dw_hdmi_poweroff
[ 3894.523284] dw_hdmi_phy_disable
[ 3894.526480] dw_hdmi_phy_power_off
[ 3894.529823] dw_hdmi_phy_gen2_txpwron
[ 3894.533567] dw-hdmi-jz4780 10180000.hdmi: PHY powered down in 0 iterations
[ 3894.540496] dw_hdmi_phy_gen2_pddq
[ 3894.543966] dw_hdmi_phy_update_hpd
[ 3894.547435] dw-hdmi-jz4780 10180000.hdmi: EVENT=plugout
[ 3897.079560] dw_hdmi_update_power
[ 3897.082840] dw_hdmi_update_power: hdmi->force=0
[ 3897.087394] dw_hdmi_update_power: hdmi->disabled=0
[ 3897.092207] dw_hdmi_update_power: hdmi->bridge_is_on=0
[ 3897.097370] dw_hdmi_update_power: hdmi->rxsense=1
[ 3897.102316] dw_hdmi_update_power: force=2
[ 3897.106380] dw_hdmi_update_power: hdmi->bridge_is_on=0
[ 3897.111667] dw_hdmi_poweron
[ 3897.114518] dw_hdmi_setup
[ 3897.117163] hdmi_disable_overflow_interrupts
[ 3897.121478] dw-hdmi-jz4780 10180000.hdmi: Non-CEA mode used in HDMI
[ 3897.127930] hdmi_av_composer
[ 3897.130848] dw-hdmi-jz4780 10180000.hdmi: final pixclk = 0
[ 3897.136506] dw_hdmi_phy_init
[ 3897.139440] dw_hdmi_phy_sel_data_en_pol
[ 3897.143428] dw_hdmi_phy_sel_interface_control
[ 3897.147840] hdmi_phy_configure
[ 3897.150922] dw_hdmi_phy_power_off
[ 3897.154415] dw_hdmi_phy_gen2_txpwron
[ 3897.158043] dw-hdmi-jz4780 10180000.hdmi: PHY powered down in 0 iterations
[ 3897.165094] dw_hdmi_phy_gen2_pddq
[ 3897.168468] dw_hdmi_set_high_tmds_clock_ratio
[ 3897.173002] hdmi_phy_configure_dwc_hdmi_3d_tx
[ 3897.186578] dw_hdmi_phy_power_on
[ 3897.189847] dw_hdmi_phy_gen2_txpwron
[ 3897.193586] dw_hdmi_phy_gen2_pddq
[ 3897.217640] dw-hdmi-jz4780 10180000.hdmi: PHY PLL locked 1 iterations
[ 3897.224226] dw_hdmi_phy_sel_data_en_pol
[ 3897.228107] dw_hdmi_phy_sel_interface_control
[ 3897.232631] hdmi_phy_configure
[ 3897.235739] dw_hdmi_phy_power_off
[ 3897.239082] dw_hdmi_phy_gen2_txpwron
[ 3897.242826] dw-hdmi-jz4780 10180000.hdmi: PHY powered down in 0 iterations
[ 3897.249754] dw_hdmi_phy_gen2_pddq
[ 3897.253239] dw_hdmi_set_high_tmds_clock_ratio
[ 3897.257658] hdmi_phy_configure_dwc_hdmi_3d_tx
[ 3897.271264] dw_hdmi_phy_power_on
[ 3897.274659] dw_hdmi_phy_gen2_txpwron
[ 3897.278292] dw_hdmi_phy_gen2_pddq
[ 3897.283840] dw-hdmi-jz4780 10180000.hdmi: PHY PLL locked 1 iterations
[ 3897.290346] dw_hdmi_enable_video_path
[ 3897.294240] dw-hdmi-jz4780 10180000.hdmi: sink has audio support
[ 3897.300324] dw-hdmi-jz4780 10180000.hdmi: dw_hdmi_setup HDMI mode
[ 3897.306596] hdmi_config_AVI
[ 3897.309467] hdmi_config_vendor_specific_infoframe
[ 3897.314336] hdmi_config_drm_infoframe
[ 3897.318096] hdmi_tx_hdcp_config
[ 3897.321270] dw_hdmi_clear_overflow
[ 3897.324831] dw_hdmi_phy_update_hpd
[ 3897.328298] dw-hdmi-jz4780 10180000.hdmi: EVENT=plugin
[ 3897.333704] dw_hdmi_update_power
[ 3897.336990] dw_hdmi_update_power: hdmi->force=0
[ 3897.341551] dw_hdmi_update_power: hdmi->disabled=0
[ 3897.346528] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3897.351858] dw_hdmi_update_power: hdmi->rxsense=1
[ 3897.356615] dw_hdmi_update_power: force=2
[ 3897.360655] dw_hdmi_update_power: hdmi->bridge_is_on=1
[ 3897.365980] dw_hdmi_phy_update_hpd

So the plugout/plugin events are not processed further.

One thing looks strange:

[ 3897.127930] hdmi_av_composer
[ 3897.130848] dw-hdmi-jz4780 10180000.hdmi: final pixclk = 0

But I have no idea if this is the reason or the consequence
of the uninitialized lcdc.

So we need some DRM specialist to take a look on it.

BR and thanks,
Nikolaus

H. Nikolaus Schaller

unread,
Jun 4, 2020, 11:18:14 AM6/4/20
to Paul Boddie, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel
Hi Paul,

> Am 04.06.2020 um 12:50 schrieb H. Nikolaus Schaller <h...@goldelico.com>:
>
> Hi Paul,
> picking up an old discussion,
now it becomes interesting.

I have booted the latest letux-5.7 and now, the lcdc got initialized!
So maybe something has improved in the DRM subsystem without our activity.

root@letux:~# cat /sys/kernel/debug/regmap/13050000.lcdc0/registers
00: 00f00840
04: 00000003
08: 0000000d
0c: 0520026e
10: 011b051b
14: 0014026c
18: 00000000
1c: 00000000
20: 00000000
24: 00000000
28: 00000000
2c: 00000000
30: 24002008
34: 00000004
38: 00000000
3c: 00000000
40: 0e2ee000
44: 01000000
48: deafbead
4c: 00096000
50: 0007626f
54: 01050010
58: 2d544d47
5c: 00000032
root@letux:~#

Still there is no image.

>
> I did now boot with the Imagination system in Flash memory.
> It is an 3.0.8-Kernel. And my HDMI monitor works out of the box.

I did boot with both kernel and did run my scripts (using devmem2)
on both devices. The register values of each kernel are attached.

Main difference for the PHY seems to be in the audio area, but there
are also some HDMI_IH, HDMI_VP and HDMI_FC registers where I don't
have any idea what they are about.

As mentioned above the LCDC has been initialized (without me
recognising this first). But register values are completely different.

BR,
Nikolaus

hdmi-5.7.txt
hdmi-3.0.8.txt

Paul Boddie

unread,
Jun 4, 2020, 1:29:49 PM6/4/20
to H. Nikolaus Schaller, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel
On Thursday 4. June 2020 17.18.09 H. Nikolaus Schaller wrote:
>
> I have booted the latest letux-5.7 and now, the lcdc got initialized!
> So maybe something has improved in the DRM subsystem without our activity.
>
> root@letux:~# cat /sys/kernel/debug/regmap/13050000.lcdc0/registers
> 00: 00f00840

This is the configuration register, set up fairly normally.

> 04: 00000003
> 08: 0000000d

These are the sync pulse definitions.

> 0c: 0520026e

These are the "virtual" display dimensions: 1312x622.

> 10: 011b051b
> 14: 0014026c

And these are the horizontal and vertical picture settings: 283-1307 and
20-620, suggesting a resolution of 1044x600, I guess.

> 18: 00000000
> 1c: 00000000
> 20: 00000000
> 24: 00000000
> 28: 00000000
> 2c: 00000000

These should probably all be zero.

> 30: 24002008

This indicates that the LCD controller is enabled. It's the fairly standard
configuration for the controller with end-of-frame interrupts enabled, and so
on.

> 34: 00000004

Here, we see the "FIFO 0" underrun condition, although that occurs in the
3.0.8 kernel, too, from your earlier output. Maybe I shouldn't be so worried
about that.

> 38: 00000000

This should be the frame identifier (see below).

> 3c: 00000000

This should probably be zero.

> 40: 0e2ee000

This is the DMA descriptor #0 physical address.

> 44: 01000000
> 48: deafbead
> 4c: 00096000

And these are the framebuffer physical address, frame identifier and command
(framebuffer size of 614400 words).

> 50: 0007626f

This is the DMA descriptor #1 physical address.

> 54: 01050010
> 58: 2d544d47
> 5c: 00000032

These are the registers affected by descriptor #1, quite possibly not set up
to sensible values.

> root@letux:~#
>
> Still there is no image.
>
> > I did now boot with the Imagination system in Flash memory.
> > It is an 3.0.8-Kernel. And my HDMI monitor works out of the box.
>
> I did boot with both kernel and did run my scripts (using devmem2)
> on both devices. The register values of each kernel are attached.

Thanks for doing this: it may be useful to see what differences there are.
Looking at the 3.0.8 LCD controller registers, there are many familiar things
from the source code (and from the 3.18 sources).

> Main difference for the PHY seems to be in the audio area, but there
> are also some HDMI_IH, HDMI_VP and HDMI_FC registers where I don't
> have any idea what they are about.

IH is interrupt handling, VP is video packetization and FC is frame composer.
Although the latter two are not entirely self-explanatory, I now have some
idea of what they do.

> As mentioned above the LCDC has been initialized (without me
> recognising this first). But register values are completely different.

One thing to note about the 3.0.8 kernel is that it might not be very clever
about picking a display resolution. At the moment, though, the upstream LCD
driver is not likely to be doing anything specific for the JZ4780, and I think
that some of the extra features may be needed to produce a picture via HDMI,
such as the RGB control register. It is also possible that the on-screen
display (OSD) functionality is somehow involved.

Paul

H. Nikolaus Schaller

unread,
Jun 4, 2020, 2:58:43 PM6/4/20
to Paul Boddie, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel
Hi Paul,
Indeed. The more working / non-working examples we have the better we
can understand what makes the difference.

>
>> Main difference for the PHY seems to be in the audio area, but there
>> are also some HDMI_IH, HDMI_VP and HDMI_FC registers where I don't
>> have any idea what they are about.
>
> IH is interrupt handling, VP is video packetization and FC is frame composer.
> Although the latter two are not entirely self-explanatory, I now have some
> idea of what they do.

Ok, good to know.

>
>> As mentioned above the LCDC has been initialized (without me
>> recognising this first). But register values are completely different.
>
> One thing to note about the 3.0.8 kernel is that it might not be very clever
> about picking a display resolution. At the moment, though, the upstream LCD
> driver is not likely to be doing anything specific for the JZ4780, and I think
> that some of the extra features may be needed to produce a picture via HDMI,
> such as the RGB control register. It is also possible that the on-screen
> display (OSD) functionality is somehow involved.

I checked again and ingenic_drm_crtc_update_timings() is still never called.

Called are:
ingenic_drm_probe()
ingenic_drm_encoder_atomic_check()
ingenic_drm_crtc_atomic_check()
ingenic_drm_crtc_atomic_flush()

It takes ca. 40 seconds for ingenic_drm_probe() to complete. Probably by
some timeout ([CRTC:32:crtc-0] vblank wait timed out).

Therefore I think the key problem is that ingenic_drm_crtc_update_timings()
is not called when it should leaving the LCDC in a partially initialized
state...

Well, ingenic_drm_crtc_atomic_flush() should call it if "drm_atomic_crtc_needs_modeset".

It should also set some pixel formats and set the clock rate. If that does
not happen we have to expect a problem...

I tried to make it always happen and then ingenic_drm_crtc_update_timings()
is called. But still only timeouts.

Well the timeouts may be related to that ingenic_drm_irq_handler() is never called.
And I could not see a call to ingenic_drm_enable_vblank(). This means
that

[ 42.809191] WARNING: CPU: 0 PID: 5 at drivers/gpu/drm/drm_atomic_helper.c:1495 drm_atomic_helper_wait_for_vblanks+0x220/0x2a8 [drm_kms_helper]
[ 42.809198] [CRTC:32:crtc-0] vblank wait timed out

waits without enabling vblank before... This seems to be called by

https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_atomic_helper.c#L1543

Finally, ingenic_drm_encoder_atomic_mode_set() isn't called either.

So basically the ingenic-drm driver is probed but not initialized completely.

BR,
Nikolaus


H. Nikolaus Schaller

unread,
Jun 5, 2020, 1:17:41 AM6/5/20
to Paul Boddie, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel
Hi Paul,

> Am 04.06.2020 um 19:29 schrieb Paul Boddie <pa...@boddie.org.uk>:
>
> On Thursday 4. June 2020 17.18.09 H. Nikolaus Schaller wrote:
>>
>> I have booted the latest letux-5.7 and now, the lcdc got initialized!
>> So maybe something has improved in the DRM subsystem without our activity.
>>
>> root@letux:~# cat /sys/kernel/debug/regmap/13050000.lcdc0/registers
>> 00: 00f00840
>
> This is the configuration register, set up fairly normally.
>
>> 04: 00000003
>> 08: 0000000d
>
> These are the sync pulse definitions.
> ...


Still there are big differences between the 3.0.8 kernel and the 5.7
for the same hdmi monitor.

diff hdmi-3.0.8.txt hdmi-5.7.txt | fgrep JZ_REG
< 0x13050000 12f00440 JZ_REG_LCD_CFG
< 0x13050004 00000005 JZ_REG_LCD_VSYNC
< 0x13050008 0000002c JZ_REG_LCD_HSYNC
< 0x1305000c 08980465 JZ_REG_LCD_VAT
< 0x13050010 00c00840 JZ_REG_LCD_DAH
< 0x13050014 00290461 JZ_REG_LCD_DAV
> 0x13050000 00f00840 JZ_REG_LCD_CFG
> 0x13050004 00000003 JZ_REG_LCD_VSYNC
> 0x13050008 0000000d JZ_REG_LCD_HSYNC
> 0x1305000c 0520026e JZ_REG_LCD_VAT
> 0x13050010 011b051b JZ_REG_LCD_DAH
> 0x13050014 0014026c JZ_REG_LCD_DAV
< 0x13050030 4000080d JZ_REG_LCD_CTRL
< 0x13050034 00000024 JZ_REG_LCD_STATE
> 0x13050030 24002008 JZ_REG_LCD_CTRL
> 0x13050034 00000004 JZ_REG_LCD_STATE

>> Main difference for the PHY seems to be in the audio area, but there
>> are also some HDMI_IH, HDMI_VP and HDMI_FC registers where I don't
>> have any idea what they are about.
>
> IH is interrupt handling, VP is video packetization and FC is frame composer.
> Although the latter two are not entirely self-explanatory, I now have some
> idea of what they do.

I have now also studied the differences in the HDMI_PHY registers and there
are some:

< 0x1018c000 000000ce HDMI_PHY_CONF0
> 0x1018c000 0000000e HDMI_PHY_CONF0
< 0x1018c018 000000f1 HDMI_PHY_MASK0
< 0x1018c01c 000000f1 HDMI_PHY_POL0
> 0x1018c018 00000001 HDMI_PHY_MASK0
> 0x1018c01c 00000000 HDMI_PHY_POL0

So there is different CONF. And what I have found is a patch like
this:

https://lists.denx.de/pipermail/u-boot/2012-October/136234.html

where people set the HDMI_PHY_CONF0_PDZ_MASK and HDMI_PHY_CONF0_ENTMDS_MASK
like I did find with the 3.0.8 kernel but not with 5.7.

Also the MASK (lane mask?) and POL (polarity?) differ.

So we may not only have a problem with initializing the LCDC but also the
HDMI PHY.

I am tempted to try to write all the 3.0.8 register values through devmem2...
i.e. override the setup done by the kernel drivers.

But maybe I should study the TILCDC (BeagleBone) driver which seems to have
a comparable structure (except that it has no vblank). This might help to
better understand the (broken) call chain for initialization.

BR,
Nikolaus

Paul Boddie

unread,
Jun 5, 2020, 4:48:39 PM6/5/20
to H. Nikolaus Schaller, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel, pa...@crapouillou.net
[CC'ing Paul since he had been in contact with me and might be interested.]

On Friday 5. June 2020 07.17.27 H. Nikolaus Schaller wrote:
>
> Still there are big differences between the 3.0.8 kernel and the 5.7
> for the same hdmi monitor.
>
> diff hdmi-3.0.8.txt hdmi-5.7.txt | fgrep JZ_REG
> < 0x13050000 12f00440 JZ_REG_LCD_CFG
> < 0x13050004 00000005 JZ_REG_LCD_VSYNC
> < 0x13050008 0000002c JZ_REG_LCD_HSYNC
> < 0x1305000c 08980465 JZ_REG_LCD_VAT
> < 0x13050010 00c00840 JZ_REG_LCD_DAH
> < 0x13050014 00290461 JZ_REG_LCD_DAV
>
> > 0x13050000 00f00840 JZ_REG_LCD_CFG
> > 0x13050004 00000003 JZ_REG_LCD_VSYNC
> > 0x13050008 0000000d JZ_REG_LCD_HSYNC
> > 0x1305000c 0520026e JZ_REG_LCD_VAT
> > 0x13050010 011b051b JZ_REG_LCD_DAH
> > 0x13050014 0014026c JZ_REG_LCD_DAV

The sync pulse differences are a bit strange, and the dimensions are quite
different, but perhaps a different resolution has made its way to the DRM
driver instead of the one you would expect.

> < 0x13050030 4000080d JZ_REG_LCD_CTRL
> < 0x13050034 00000024 JZ_REG_LCD_STATE
>
> > 0x13050030 24002008 JZ_REG_LCD_CTRL
> > 0x13050034 00000004 JZ_REG_LCD_STATE

The state no longer shows end-of-frame interrupts. Generally, I would not
expect the control or config registers to work in the 5.7 kernel. I can say
this with confidence because I finally got a picture on the screen in my L4Re
test environment, so there are some things that seem to be necessary that are
not being done in the upstream DRM driver. More on this below.

> I have now also studied the differences in the HDMI_PHY registers and there
> are some:
>
> < 0x1018c000 000000ce HDMI_PHY_CONF0
> > 0x1018c000 0000000e HDMI_PHY_CONF0

The difference is the lack of PDZ and ENTMDS bits, which are what I call
"powerdown disable" and "enable TMDS". This indicates that the signal is not
active.

> < 0x1018c018 000000f1 HDMI_PHY_MASK0
> < 0x1018c01c 000000f1 HDMI_PHY_POL0
>
> > 0x1018c018 00000001 HDMI_PHY_MASK0
> > 0x1018c01c 00000000 HDMI_PHY_POL0

Here, it seems that in the older kernel, only the hotplug interrupt is enabled
(PHY_MASK0 has bit 1 clear). In the newer kernel, all the "rx sense"
interrupts are enabled as well, presumably to sense activity initiated by the
other device on the cable.

> So there is different CONF. And what I have found is a patch like
> this:
>
> https://lists.denx.de/pipermail/u-boot/2012-October/136234.html
>
> where people set the HDMI_PHY_CONF0_PDZ_MASK and HDMI_PHY_CONF0_ENTMDS_MASK
> like I did find with the 3.0.8 kernel but not with 5.7.
>
> Also the MASK (lane mask?) and POL (polarity?) differ.
>
> So we may not only have a problem with initializing the LCDC but also the
> HDMI PHY.

The U-Boot patch is interesting because I wouldn't have expected support for
this peripheral in U-Boot given that Imagination/Ingenic didn't include it in
their U-Boot version, but perhaps it was a distraction, not entirely necessary
given that debugging can be done over the UART, and once U-Boot can boot Linux
you can leave it to the driver there to do all the work.

> I am tempted to try to write all the 3.0.8 register values through
> devmem2... i.e. override the setup done by the kernel drivers.
>
> But maybe I should study the TILCDC (BeagleBone) driver which seems to have
> a comparable structure (except that it has no vblank). This might help to
> better understand the (broken) call chain for initialization.

I haven't looked at the Linux kernel mechanics for a while, but I can now be
quite sure that the HDMI initialisation in the kernel should be able to work
because I borrowed a lot of the details for my L4Re implementation. This
involved the initialisation of interrupt handling to detect hotplugging, the
use of I2C for retrieving the EDID, the use of some other I2C registers for
communication with the PHY, facilitating PHY initialisation, then the
initialisation of various different functional blocks.

Indeed, my L4Re implementation actually only supports DVI mode, which works
with my VGA- and DVI-capable monitor, but I think it should probably work even
on HDMI-capable monitors due to the heritage of the technology. This has
allowed me to ignore various HDMI details but also to establish the minimum
functionality to get this working. Also, I have ignored audio altogether
because I don't have the Ingenic I2S peripheral supported at the moment.

The tricky part of all this has actually been the LCD controller. I did make a
couple of stupid mistakes, and this is where your register dumps helped a lot
because they made me check what I had written to the config register and I saw
that I had written bit numbers (25, 28) instead of shifted bits (1 << 25, 1 <<
28) to the register, which are easy enough to make when tired and distracted
by lots of details. Fixing this explained a problem with the signal not being
generated when using these JZ4780-specific bits.

However, there do seem to be some important elements to producing a signal for
the HDMI peripheral. Reviewing your register dumps made me consider the role
of the second DMA descriptor. This seemed to be superfluous, and in the 3.0.8
kernel driver some commentary suggests that it isn't needed (or used) after
being set up. But then I understood that it still needs to be set up because
the LCD controller (or the OSD functionality) still expects something to be
present at the address found in the descriptor address register. And making
sure that a flag is cleared in the command word of the descriptor probably
ensures that the DMA channel doesn't do anything and that the LCD/OSD
functionality remains happy.

(I will actually test without the "new" descriptors and OSD, if possible, just
to see what the dependencies are on these things.)

So, what we probably need to do is to make sure that the descriptors are set
up, mostly as they are in 3.18. We also need to deal with the issue of
encodings and formats. Since I took various shortcuts with the HDMI
functionality, effectively asserting RGB data for input and output, with this
working just fine, I think that finding a way of doing that (at least for
input from the LCD controller) will configure everything appropriately.

One obstacle previously mentioned was that of end-of-frame interrupts. Having
configured those in my test environment, I can indeed receive these interrupts
(or at least some kind of interrupt condition) at a frequency that suggests
that the end-of-frame condition is causing interrupts to be delivered. In
other words, I can count 60 of them every second or so. Therefore, it should
be possible to get the LCD controller into an appropriate state to pass the
"vblank" test, although I imagine that the initialisation sequencing still
remains a challenge: the HDMI peripheral may need to be active first, but
there may be expectations of an input signal being available before the HDMI
peripheral is activated; something will need to short-circuit any such logic.

Anyway, those are my findings right now. I guess I will try and see if I can
translate them to further progress, however.

Thanks once again for the register dumps! They proved valuable in getting me
to check my work.

Paul

Maarten ter Huurne

unread,
Jun 5, 2020, 8:15:32 PM6/5/20
to H. Nikolaus Schaller, mips-creat...@googlegroups.com, RIccardo Mottola, MIPS Creator CI20 Development, Discussions about the Letux Kernel, pa...@crapouillou.net, Paul Boddie
On Friday, 5 June 2020 22:48:13 CEST Paul Boddie wrote:

> One obstacle previously mentioned was that of end-of-frame interrupts.
> Having configured those in my test environment, I can indeed receive
> these interrupts (or at least some kind of interrupt condition) at a
> frequency that suggests that the end-of-frame condition is causing
> interrupts to be delivered. In other words, I can count 60 of them
> every second or so. Therefore, it should be possible to get the LCD
> controller into an appropriate state to pass the "vblank" test,
> although I imagine that the initialisation sequencing still remains a
> challenge: the HDMI peripheral may need to be active first, but there
> may be expectations of an input signal being available before the
> HDMI peripheral is activated; something will need to short-circuit
> any such logic.

On the JZ4770 we found that end-of-frame interrupts would occur when the
DMA descriptor had been processed instead of when the transfer ends. We
put a dummy black line in a second DMA descriptor chained after the
first one and used that to detect the end of the frame.

I don't know if the JZ4780 does the same thing, but in general the SoCs
in the series have more similarities than differences.

Bye,
Maarten



Paul Boddie

unread,
Jun 6, 2020, 5:54:43 AM6/6/20
to Maarten ter Huurne, H. Nikolaus Schaller, mips-creat...@googlegroups.com, RIccardo Mottola, Discussions about the Letux Kernel, pa...@crapouillou.net
On Saturday 6. June 2020 02.15.29 Maarten ter Huurne wrote:
>
> On the JZ4770 we found that end-of-frame interrupts would occur when the
> DMA descriptor had been processed instead of when the transfer ends. We
> put a dummy black line in a second DMA descriptor chained after the
> first one and used that to detect the end of the frame.

This kind of chaining arrangement reminds me of my PIC32 VGA signal generation
experiment where I had to manually generate the black level after each display
line. :-)

But with regard to the JZ4780, the manual says this about the LCD command
register:

"When EOFINT = 1, the DMAC sets the end of frame bit (LCDSTATE.EOF) after
fetching the last word in the frame buffer. In dual-panel mode, LCDSTATE.EOF
is set only when both channels reach the end of frame and both frame
descriptors have EOFINT set."

So, this is the documented behaviour, at least (and maybe it is also described
in this way in any JZ4770 manual). I suppose that if there is a delay between
this final transfer and delivering the data to the display, it will make some
kind of difference. Maybe if it causes problems, the OSD end-of-frame
interrupts can be used instead.

> I don't know if the JZ4780 does the same thing, but in general the SoCs
> in the series have more similarities than differences.

I noted to Paul that there are some differences that are probably related to
functional changes. The pixel depth in the LCD control register does not seem
to be modifiable, but this information is probably now configured via "new"
descriptors (and thus via the LCD_CPOSx registers). Meanwhile, palette support
for displays is supposedly missing (according to comments in the 3.0.8 driver,
but there is also no palette bit in the command register) and there may not be
support for limited pixel depths any more, although I haven't tested this.

It would also be interesting to know what your experiences have been with the
OSD functionality. It seems that this is always on in the JZ4780, and it also
seems that the foreground planes must be configured regardless of whether they
will be used, as noted in my earlier message.

After my message yesterday, I tested a few things...

I tried to use 4-word descriptors instead of the "new" 8-word descriptors just
to see if the extra words are superfluous and reasonable defaults are used,
but there was no picture (black screen). This was the case even with two
descriptors set up.

I found that the RGB control register does not have to be set up, so I wonder
what this actually does. Maybe I should have looked to see whether it was
enabled, anyway, despite the manual indicating that it should be zero
initially.

It doesn't seem to be necessary to use 64-word burst transfers: 16-word
transfers also worked. Maybe this is advisible for performance or stability,
however.

Paul

Maarten ter Huurne

unread,
Jun 6, 2020, 6:46:23 AM6/6/20
to Paul Boddie, H. Nikolaus Schaller, mips-creat...@googlegroups.com, RIccardo Mottola, Discussions about the Letux Kernel, pa...@crapouillou.net
On Saturday, 6 June 2020 11:54:22 CEST Paul Boddie wrote:
> On Saturday 6. June 2020 02.15.29 Maarten ter Huurne wrote:
> > On the JZ4770 we found that end-of-frame interrupts would occur when
> > the DMA descriptor had been processed instead of when the transfer
> > ends. We put a dummy black line in a second DMA descriptor chained
> > after the first one and used that to detect the end of the frame.
>
> This kind of chaining arrangement reminds me of my PIC32 VGA signal
> generation experiment where I had to manually generate the black
> level after each display line. :-)
>
> But with regard to the JZ4780, the manual says this about the LCD
> command register:
>
> "When EOFINT = 1, the DMAC sets the end of frame bit (LCDSTATE.EOF)
> after fetching the last word in the frame buffer. In dual-panel mode,
> LCDSTATE.EOF is set only when both channels reach the end of frame
> and both frame descriptors have EOFINT set."
>
> So, this is the documented behaviour, at least (and maybe it is also
> described in this way in any JZ4770 manual). I suppose that if there
> is a delay between this final transfer and delivering the data to the
> display, it will make some kind of difference. Maybe if it causes
> problems, the OSD end-of-frame interrupts can be used instead.

No, the behavior we saw was that it generated the end-of-frame interrupt
way before it fetched all the data to display. When we used the end-of-
frame interrupt for page flipping, we'd see the page being overpainted
by the application, a sign that scanout was still reading from the
framebuffer even though end-of-frame had been signalled.

> It would also be interesting to know what your experiences have been
> with the OSD functionality. It seems that this is always on in the
> JZ4780, and it also seems that the foreground planes must be
> configured regardless of whether they will be used, as noted in my
> earlier message.

I haven't used the OSD, but Paul recently did some tests with it (on
JZ4770, I think) and got a test image showing overlaid above the
framebuffer.

> It doesn't seem to be necessary to use 64-word burst transfers:
> 16-word transfers also worked. Maybe this is advisible for
> performance or stability, however.

I would assume that longer bursts have less overhead, but since they
keep the bus occupied for longer they may negatively affect latency of
other subsystems, like the CPU trying to fill a cache line.

Something I noticed the other day is that JZ4770 components on the AHB0
bus (like LCDC) have their own custom DMA controllers, while components
on the AHB2 bus use the generic DMA controller. Which makes sense, but I
didn't realize before that this is the pattern that determines which
components have their own DMA.

Bye,
Maarten



H. Nikolaus Schaller

unread,
Jul 18, 2020, 2:03:39 PM7/18/20
to Discussions about the Letux Kernel, Paul Boddie, MIPS Creator CI20 Development, RIccardo Mottola
Hi Paul,
I have removed my debug printk and not it boots and the drm interrupts come to an end.
BTW: Ethernet was broken with the printk inserted but is now working again.
So the logging code was standing on some brake.

> Am 04.06.2020 um 17:18 schrieb H. Nikolaus Schaller <h...@goldelico.com>:
>
> BR,
> Nikolaus
>
> <hdmi-5.7.txt><hdmi-3.0.8.txt>

Here is a hdmi-5.8-rc5.txt created on the latest kernel but by the same script.

hdmi-5.8-rc5.txt

Paul Boddie

unread,
Jul 18, 2020, 4:57:18 PM7/18/20
to H. Nikolaus Schaller, Discussions about the Letux Kernel, MIPS Creator CI20 Development, RIccardo Mottola
On Saturday, 18 July 2020 20:03:35 CEST H. Nikolaus Schaller wrote:
>
> Here is a hdmi-5.8-rc5.txt created on the latest kernel but by the same
> script.

> If you do a diff to the working hdmi-3.0.8.txt you may check for significant
> and insignificant differences. Most worrying to me is that the LCDC has some
> quite different parameters. Using exactly the same panel it should be
> almost the same...

Yes, there are some curious differences.

The LCD configuration register has negative hsync polarity in the 5.8-rc5
kernel register dump, presumably because I didn't set the appropriate mode
flags to assert positive hsync and negative vsync. Looking for guidance, I
found the drivers/gpu/drm/bridge/nwl-dsi.c file that uses a mode_fixup
operation to introduce these settings. And there was also a way of setting the
bus flags for pixel clock polarity. So, thanks to our friends at NXP and
Purism for the examples!

I'm not going to claim that the other register differences are not important,
but there can be some legitimate variation. One thing that indicates that the
peripheral is active in the 5.8-rc5 configuration is the presence of a value
in the JZ_REG_LCD_IID register. Here, it is using one of the values that I
have set in the driver for the JZ_REG_LCD_FID0 and JZ_REG_LCD_FID1 registers,
indicating that a frame successfully caused an interrupt condition. I don't
think the 3.0.8 kernel uses interrupts in the same way, and that influences
the control register and various other registers.

Testing some changes to the mode and bus flags doesn't give a picture, and
although the modetest utility claims that the "CRTC" uses positive hsync and
vsync, a message I sent to various driver maintainers a while ago also
indicated this. Only inspection of the registers might indicate success or
otherwise, here.

Anyway, I just pushed these most recent changes.

Paul


Reply all
Reply to author
Forward
0 new messages