Unifying cape overlays into boot .dtb for BeagleBoard.org boards

Pantelis Antoniou panto at antoniou-consulting.com
Tue Jun 17 12:24:51 PDT 2014


Hi Rusell,

On Jun 17, 2014, at 8:41 PM, Russell King - ARM Linux wrote:

> On Tue, Jun 17, 2014 at 08:10:46PM +0300, Pantelis Antoniou wrote:
>> Hi Russell,
>> 
>> On Jun 17, 2014, at 8:05 PM, Russell King - ARM Linux wrote:
>>> DRM is not hotpluggable in any shape or form, and David Airlie has
>>> indicated that he does strongly opposes moving it in that direction.
>>> 
>>> DRM follows the "card" model, where, at probe time, the hardware is
>>> known and never changes until the "card" is torn down.  No new
>>> connectors can be added once the "card" is initialised, and no
>>> connectors can be removed.  Any changes must be done by tearing down
>>> the entire card and reconstructing it (if reconstructing it with a
>>> reduced set of hardware is appropriate.)
>>> 
>> 
>> That is a limitation of the current DRM implementation.
> 
> ... an implementation which isn't going to change any time soon... and
> certainly is not going to change because someone comes along with a
> dynamic DT infrastructure.
> 

We can't enforce anyone to use the facilities we provide. We can but point
the benefits of such.

>> I seems to be this is born out of some kind of misunderstanding about how
>> DT can (and does) support dynamic changes.
>> 
>> I admit that I haven't done much work on DRM (besides some tinkering with
>> Rob Clark's ti_lcdc DRM driver), but knowing what DT does have a dynamic
>> change notifier support, perhaps it can be made to work.
> 
> It can be made to work in the way that I described above - any change
> to the hardware which makes up a DRM card would need the entire DRM
> card torn down and re-created... as I said above.
> 
> The reason I know this is because I've been involved closely in dealing
> with imx-drm, and Armada DRM, and the mess that people spew trying to
> get their DT representations of their hardware (as multiple, separate
> devices which can be probed asynchronously) to work with DT.
> 
> If DRM supported hot-plugging of components, dealing with that would
> be much easier than it is, but - as I said above - this is not going
> to happen.  So, if it's not going to happen for the case which we
> commonly find on ARM hardware today, it's certainly not going to
> happen because DT wants to become dynamic.
> 

This sounds more like a limitation of DRM than anything that has to do
with DT.

>> As I said, the next thing coming is transactional DT support, perhaps you
>> can share the DT fragment describing your use-case (before/after) and 
>> I'll try to accommodate in the next patch series.
> 
> I don't have any - I'm using it as an example where a device (such as
> the iMX6 SoC) which has quite a complex media infrastructure may be
> extended externally via an FPGA to provide additional interfaces which
> may then require dynamic changes to the DT description, thereby meaning
> that we have to reconstruct the DRM "card" in its entirety.
> 
> If you want some DT to look at...
> 
>                        ldb: ldb at 020e0008 {
>                                #address-cells = <1>;
>                                #size-cells = <0>;
>                                compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb";
>                                gpr = <&gpr>;
>                                status = "disabled";
> 
>                                lvds-channel at 0 {
>                                        #address-cells = <1>;
>                                        #size-cells = <0>;
>                                        reg = <0>;
>                                        status = "disabled";
> 
>                                        port at 0 {
>                                                reg = <0>;
> 
>                                                lvds0_mux_0: endpoint {
>                                                        remote-endpoint = <&ipu1_di0_lvds0>;
>                                                };
>                                        };
> 
>                                        port at 1 {
>                                                reg = <1>;
> 
>                                                lvds0_mux_1: endpoint {
>                                                        remote-endpoint = <&ipu1_di1_lvds0>;
>                                                };
>                                        };
>                                };
> 
>                                lvds-channel at 1 {
>                                        #address-cells = <1>;
>                                        #size-cells = <0>;
>                                        reg = <1>;
>                                        status = "disabled";
> 
>                                        port at 0 {
>                                                reg = <0>;
> 
>                                                lvds1_mux_0: endpoint {
>                                                        remote-endpoint = <&ipu1_di0_lvds1>;
>                                                };
>                                        };
> 
>                                        port at 1 {
>                                                reg = <1>;
> 
>                                                lvds1_mux_1: endpoint {
>                                                        remote-endpoint = <&ipu1_di1_lvds1>;
>                                                };
>                                        };
>                                };
>                        };
> 
>                        hdmi: hdmi at 0120000 {
>                                #address-cells = <1>;
>                                #size-cells = <0>;
>                                reg = <0x00120000 0x9000>;
>                                interrupts = <0 115 0x04>;
>                                gpr = <&gpr>;
>                                clocks = <&clks 123>, <&clks 124>;
>                                clock-names = "iahb", "isfr";
>                                status = "disabled";
> 
>                                port at 0 {
>                                        reg = <0>;
> 
>                                        hdmi_mux_0: endpoint {
>                                                remote-endpoint = <&ipu1_di0_hdmi>;
>                                        };
>                                };
> 
>                                port at 1 {
>                                        reg = <1>;
> 
>                                        hdmi_mux_1: endpoint {
>                                                remote-endpoint = <&ipu1_di1_hdmi>;
>                                        };
>                                };
>                        };
> 
>                        mipi_dsi: mipi at 021e0000 {
>                                #address-cells = <1>;
>                                #size-cells = <0>;
>                                reg = <0x021e0000 0x4000>;
>                                status = "disabled";
> 
>                                port at 0 {
>                                        reg = <0>;
> 
>                                        mipi_mux_0: endpoint {
>                                                remote-endpoint = <&ipu1_di0_mipi>;
>                                        };
>                                };
> 
>                                port at 1 {
>                                        reg = <1>;
> 
>                                        mipi_mux_1: endpoint {
>                                                remote-endpoint = <&ipu1_di1_mipi>;
>                                        };
>                                };
>                        };
> 
>                ipu1: ipu at 02400000 {
>                        #address-cells = <1>;
>                        #size-cells = <0>;
>                        compatible = "fsl,imx6q-ipu";
>                        reg = <0x02400000 0x400000>;
>                        interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
>                                     <0 5 IRQ_TYPE_LEVEL_HIGH>;
>                        clocks = <&clks 130>, <&clks 131>, <&clks 132>;
>                        clock-names = "bus", "di0", "di1";
>                        resets = <&src 2>;
> 
>                        ipu1_di0: port at 2 {
>                                #address-cells = <1>;
>                                #size-cells = <0>;
>                                reg = <2>;
> 
>                                ipu1_di0_disp0: endpoint at 0 {
>                                };
> 
>                                ipu1_di0_hdmi: endpoint at 1 {
>                                        remote-endpoint = <&hdmi_mux_0>;
>                                };
> 
>                                ipu1_di0_mipi: endpoint at 2 {
>                                        remote-endpoint = <&mipi_mux_0>;
>                                };
> 
>                                ipu1_di0_lvds0: endpoint at 3 {
>                                        remote-endpoint = <&lvds0_mux_0>;
>                                };
> 
>                                ipu1_di0_lvds1: endpoint at 4 {
>                                        remote-endpoint = <&lvds1_mux_0>;
>                                };
>                                };
> 
>                                ipu1_di0_lvds1: endpoint at 4 {
>                                        remote-endpoint = <&lvds1_mux_0>;
>                                };
>                        };
> 
>                        ipu1_di1: port at 3 {
>                                #address-cells = <1>;
>                                #size-cells = <0>;
>                                reg = <3>;
> 
>                                ipu1_di0_disp1: endpoint at 0 {
>                                };
> 
>                                ipu1_di1_hdmi: endpoint at 1 {
>                                        remote-endpoint = <&hdmi_mux_1>;
>                                };
> 
>                                ipu1_di1_mipi: endpoint at 2 {
>                                        remote-endpoint = <&mipi_mux_1>;
>                                };
> 
>                                ipu1_di1_lvds0: endpoint at 3 {
>                                        remote-endpoint = <&lvds0_mux_1>;
>                                };
> 
>                                ipu1_di1_lvds1: endpoint at 4 {
>                                        remote-endpoint = <&lvds1_mux_1>;
>                                };
>                        };
>                };
> 
>        display-subsystem {
>                compatible = "fsl,imx-display-subsystem";
>                ports = <&ipu1_di0>, <&ipu1_di1>, <&ipu2_di0>, <&ipu2_di1>;
>        };
> 
> 
> ipu1, mipi_dsi, ldb and hdmi are each separate platform devices, which
> are combined to look like a single DRM device.  Each device can be
> enabled by the platform code.  All enabled devices must be present to
> cause the DRM device to "bind".  The above connectivity is parsed via
> the of_graph helpers, and enumerated by the driver(s).
> 
> Let's say that we have ipu1 and hdmi enabled, but ldb disabled.  ldb is
> connected to an external FPGA.  Someone loads a bitstream after boot
> into the FPGA, and then updates the DT dynamically to enable the ldb
> device.
> 
> Great, so a new platform device gets spawned for the new device.  What
> triggers the ipu or display subsystem level (which is what's really
> needed) to tell it something changed here?
> 

The ipu can register an of_reconfig notifier, and it will be notified of
any changes in the topology. Perhaps this can be part of the DRM core,
I can't be sure.

This is very similar to the way the platform/i2c/spi bus notifiers work
in my patchset; whenever the state of a device node change due to the live
tree changing the status of a child node from/to enabled/disabled the
parent (bus or in this case the ipu) will be notified and then it is
free to take action.

The hairy part (which the patchset provides) is making sure all the 
changes are recorded, applied and potentially rolled back in a controlled
manner, so that the state of the DT tree is consistent at all times.

> This is exactly my point - such stuff has not been thought about, because
> (I reckon) not many people are even aware of DT wanting to become dynamic.
> It's certainly not clear from the use model that we've been basing our
> driver conversions on that DT is anything but static...
> 

FWIW, the changes to support dynamic DT are not that great.
We know that trying to handle cases where each property change has to be
handled gets hairy fast, so what we're trying to do is make thing easier
by performing the device state change in a well defined manner.

So to return in your previous example, when the FPGA bitstream is loaded
and ldb should be enabled, the DT core will notify the parent bus (which 
I can't tell exactly from your fragment but it should be) the platform
bus, which will end up of registering the platform device.

Now if DRM can't handle that, then that's a limitation of the DRM subsystem,
which fortunately is not shared by most of the other subsystems in the kernel.

Regards

-- Pantelis

> -- 
> FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
> improving, and getting towards what was expected from it.




More information about the linux-arm-kernel mailing list