[RFC v2 PATCH] mipi-dsi-bus: add MIPI DSI bus support

Thierry Reding thierry.reding at gmail.com
Mon Dec 9 08:10:50 PST 2013


On Mon, Dec 09, 2013 at 05:05:20PM +0200, Tomi Valkeinen wrote:
> On 2013-12-09 15:10, Thierry Reding wrote:
[...]
> > But even if you have a tree of one-to-one links, you still need some way
> > to address the individual nodes in the tree. The VC ID is the only way
> > by which you can address a node. I don't see how you can possible send
> > packets to more than one node if you keep sending packets to the same
> > address. Where does the missing information magically come from?
> 
> From the DSI hub.
> 
> In the example case below, let's say the DSI panel 1 driver is told to
> send a configuration packet to the panel. The panel driver would call a
> dsi_transmit op, giving as arguments the VC number 0, and the packet data.
> 
> That call would go to the DSI hub driver. It knows how it routes the
> packets (the routing configuration is either hardcoded or passed via DT
> data), and then calls dsi_transmit op on SoC DSI, with VC number 2 and
> the packet data.

So it is the DSI hub driver that translates VC 0 to VC 2? How does it
know that VC 0 should be VC 2 but not VC 3? Does the panel 2 driver pass
in a different VC as panel 1?

> >> For the sake of discussion, let's consider a simple DSI hub setup:
> >>
> >> SoC DSI -> DSI Hub -> DSI panel 1
> >>                    -> DSI panel 2
> >>
> >> The hub would use, say VC0 for hub configuration, and it'd route VC2 to
> >> panel 1 and VC3 to panel2. Both panels would use VC0, so the hub would
> >> translate the VC ID accordingly.
> >>
> >> How would you represent this in Linux?
> > 
> > You keep saying that devices use various VC IDs (VC0 for hub config, VC2
> > and VC3 for panels 1 and 2 in this case). But those are exactly the
> > addresses. You've got to have some way within the kernel to store those.
> > 
> > Given the limited address space of DSI there's no way to accurately
> > represent the hierarchy of the above in the bus/device numbering. But
> > that doesn't mean you can't assign addresses (VC IDs) to the devices. In
> > fact you've given examples yourself.
> 
> Yes, but I guess the difference in our views is that I see the VC IDs as
> "link local" and routing is done by the hubs as they see fit. In other
> words, if I'm not mistaken, you'd have a Linux DSI bus with three
> devices in the bus, each having its own VC ID, whereas I'd have a DSI
> "link" between the SoC and the hub, without any general information
> about the VC IDs used, and two additional DSI links, from the DSI hub to
> each panel.

It's really the same thing. If you define VC IDs in a link local manner
you don't need them at all. What's the point in having them if you can
only reach a single device anyway.

From a software perspective we can always only describe devices from the
viewpoint where things leave software control. In this case the last
point of control is the DSI host. Therefore if we want to send a packet
to any device connected to the DSI host (whether directly or through a
hub), we need to pass some VC ID to the DSI host as a destination. That
number needs to be known up front.

So either you hide that information in some software framework, such as
you seem to be doing given your example above, and make the panel driver
call into the hub driver and have the hub driver translate the VC ID to
a different one.

The alternative would be to pass the correct address to the DSI host
directly. Either way, though, whatever is written into the registers of
the DSI host will end up the same, won't it?

You always address peripherals from the DSI host's viewpoint.

> The panels here should should be inside the hub node for DSI case. They
> are connected to the hub, not the SoC's DSI, and need the hub to be
> powered up and configured to work. And the hub should contain two output
> DSI busses, each having one panel with VC ID 0. Probably something like:
> 
> dsi {
> 	hub at 0 {
> 		dsi at 0 {
> 			panel at 0 {
> 			};
> 		};
> 
> 		dsi at 1 {
> 			panel at 0 {
> 			};
> 		};
> 	};
> };
> 
> That kind of ruins the idea of representing the panels as DSI devices
> with VC IDs of 2 and 3. I don't know how that should be managed then...

Why does that ruin it? You still address panel at 0 using VC 2 and panel at 1
using VC 3, don't you? Therefore I see no reason why they shouldn't be
represented as DSI devices with their respective VC IDs.

> But this DT example shows how DSI is really a one-to-one bus in the
> hardware.

How is that one-to-one? The DSI hub connects to two peripherals, that's
one-to-two.

> >>>> The DSI peripheral driver must know the VC IDs. Often they are hardcoded
> >>>> values, and they can be defined in the driver code.
> >>>
> >>> When you say "often", can you make a guarantee that it will always be
> >>> the case? I don't think so. I can easily imagine somebody making the VC
> >>> configurable via straps, which would come in handy if you wanted to use
> >>> the same IC multiple times within the same design.
> >>
> >> Of course I can't guarantee things like that. But I have never seen a
> >> DSI device that can be configured in such a way. Have you?
> > 
> > I've seen plenty of I2C devices that do so. The reason is usually so
> > that the same IC can be used on the same bus multiple times. Why would
> > DSI be any different? If in your example above, panel 1 and panel 2 are
> > identical panels, they would use the same hardcoded VC IDs, right? So
> > you couldn't address them separately. In such a case, if I were the
> > panel vendor I'd make the VC ID selectable (via straps for example).
> 
> With DSI you always have a hub, which can translate the addresses. With
> my example above, both panels are identical and they have the same VC ID
> of 0.

No. If they had the same VC ID how do you address them differently? When
the transactions originate at the DSI host, you have to tell it where
they should go. If you pass them the same VC ID they will go to the same
device. They have to.

What you say above could only be done if the hub actually had the
possibility to initiate transactions of its own. But in that case it
becomes a DSI host itself, rather than a simple hub.

> >>> In that case you still need some way to specify the VC on a per-board
> >>> basis, either in DT or "platform data".
> >>
> >> I'm not saying we should prevent that kind of device from working. But
> >> if all the known devices use a fixed VC ID scheme, maybe there's not
> >> much point in requiring to enter the VC ID manually in all the dts
> >> files. If there's a device with configurable VC ID, it can still be
> >> supported by custom DT properties.
> > 
> > But we loose any possibility of ever making that code generic. Even if
> > the DSI specification doesn't go into the details (it even explicitly
> > chickens out at that point), it still defines that each DSI bus can have
> > up to 4 peripherals. So by definition the 2 bit VC is something that
> > every DSI host and every DSI peripheral needs to support. There is no
> > reason to represent it using custom properties. It is completely
> > generic.
> 
> Well, afaik, the VC ID is really just data in the packet. There's
> nothing for the HW to support. I mean, the DSI host hardware doesn't
> need to understand anything about the VC ID. This is the case on OMAP,
> the hardware has no configuration related to the VC ID. Maybe other
> hardware does.

Well, at least a hub would need to interpret the VC IDs. Take this
example:

	DSI host --> DSI hub --> peripheral 1 (VC ID 2)
	                     |
	                     --> peripheral 2 (VC ID 3)

If DSI host initiates a transaction addressed at VC 2, the DSI host will
receive the packet, parse the VC and forward it to peripheral 1. In the
same way, when the DSI hub receives a packet addressed at VC 3, it'll
have to forward it to peripheral 2.

So a hub would probably need to have some mechanism to configure which
downstream port corresponds to which VC ID. Upon initialization you need
to program some registers to make the hub do the right thing.

> >> It is possible to have multiple DSI devices behind a single DSI
> >> connection, but it is not a generic solution, and requires one to use
> >> the DSI peripherals in a very controlled manner to make sure no DSI
> >> device is blocking the other ones for too long. I have not seen these in
> >> production, and while I'm just guessing, the reason may be that is so
> >> difficult to make them work well.
> >>
> >> The only standard part of DSI, in my experience, is the DSI packet layer
> >> (maybe there's a better term for it). Anything else is often custom. For
> >> this reason I think the DSI peripheral driver has to be in full control
> >> of the device, and the DSI bus cannot really do anything by itself.
> > 
> > The same is true of I2C. There's no probing or standard registers across
> > devices. But it's still a bus that can have multiple peripherals and a
> > way to address them. Every peripheral has an associated device, which
> > drivers can use to have the I2C master send messages to the correct
> > peripheral.
> 
> Right, but with i2c, the all the devices are actually connected to the
> host. That is not the case with DSI.
> 
> It is normal to have multiple i2c devices on a bus. It's rare (never
> seen such) to have multiple DSI devices behind one DSI connector.

But you can have repeaters and such for I2C as well. Either way, I don't
see how the physical connections are related to whether DSI should or
should not be modeled as a Linux bus. PCI is modeled as a bus and can
easily originate from a single root complex.

> >> There's not much "bus" in DSI in my opinion. No probing, one-to-one
> >> links,
> > 
> > There are one-to-many links as well. You've in fact provided an example
> > of one such device above to prove another point.
> 
> No, my example has three one-to-one links. The physical DSI buses are
> always one-to-one.

You're splitting hairs. The hub is one-to-many by definition. You have
a single connection two the hub and two downstream ports. Even if the
wires to the peripherals downstream are separate, there's still logic
within the hub to switch packets this way or that. You have an packet
stream that's demuxed using the VC ID.

> Maybe we could represent DSI as both a physical one-to-one link tree,
> matching the hardware, and a logical bus, matching how it's used.

We don't have to represent it exactly matching the hardware. What we
should be doing is represent it in a way that makes it convenient to
use.

> But that starts to sound horribly complex for a one-to-one video bus,
> when all the known boards have just a single DSI device, and supporting
> multiple devices would be very tricky in any case.

The original proposal isn't at all complex. It's actually fairly simple.
The bulk of the code is boilerplate to allow devices and drivers to be
registered. And we don't even need to consider all the tricky cases. I'd
very much like to avoid that in fact and rather get something that we
can put to use now.

> >> So... While having a Linux DSI bus, etc. would feel elegant and nice, I
> >> just feel it's not easy and not worth it.
> > 
> > Really the only reason why I've been pushing for this is because Laurent
> > wanted me to represent DSI panels as children of a DSI bus in DT for the
> > simple-panel bindings. The only solution to do this somewhat generically
> > is to have a DSI bus binding and that sort of implies a DSI bus
> > implementation.
> 
> I also think it's good to have DSI panels as children of the DSI host.
> But that doesn't mean a bus implementation. You can as well have
> platform devices as panels, and they may be children of the DSI host.
> That's what I do on omap. That allows me to describe the HW correctly in
> the DT data, but keep the linux driver side simple.

Oh well, I guess you could say the same about I2C and SPI. I don't think
we can reach agreement here.

> > The particular use-case that I care about works without any of this as
> > well.
> > 
> >> What we have in omapdss is far from perfect, but it has been working
> >> quite nicely. DSI is considered just as a data bus, with extra
> >> functionality for sending control messages. A DSI device is either a
> >> platform device if it requires no control or the control is done via
> >> DSI, or it's a device of the control bus like i2c.
> > 
> > So in fact you do consider DSI a control *and* data bus, but you're
> > side-stepping the issue by hiding things within the drivers. But you
> > still need to hook up the DSI device to an I2C master and a DSI host
> > before you can use it. The reason why you can hide that is probably
> > because it isn't generic and you couldn't reuse the peripheral DSI
> > drivers on a different DSI host.
> 
> Hmm, no, I don't see anything omap specific in our implementation. Well,
> ok, it's omap specific, but the DSI peripheral drivers just use generic
> DSI ops which could as well be implemented on any other platform.
> 
> And I don't see it hiding anything. Can you be more specific?

From a quick look what omapdss seems to be doing is allocate and assign
virtual channels dynamically at runtime. I suppose that's a good way to
solve the issue. It might become an issue if you have devices that have
a fixed mapping where you can't program the routing.

> If there was a simple way to have a single Linux device sitting on two
> buses (DSI and I2C), I think it could make sense to have a Linux DSI bus
> and Linux DSI device. But afaik it's not simple, and as we anyway have a
> video "link" for DSI which can easily used for the control side,

But how do we have that? How is it represented? There is no generic
framework that allows this. It's specifically what this patch series is
all about. We need a way to instantiate a device and have it hooked up
to a DSI host such that drivers can use the DSI host to send commands to
the peripherals.

Perhaps you have that in omapdss, the rest of us don't have that. We can
obviously duplicate what you've done to a large extent, but the goal was
to come up with something generic. If generic means that it'll take
endless amounts of discussions, I don't think I want generic for now.
I'd rather focus on something that works for my use-cases and get back
to generic later on.

> it much simpler not to have the DSI bus at all. Especially as the DSI
> bus would have just one device anyway.

You keep saying that, and at the same time you keep bringing forth
arguments why it's important to support things such as DSI hubs. Can we
settle on one way or another?

> > But it will obviously be some work to move to a generic "framework", if
> > you can call it that. The driver will likely need some major rewrite,
> > which I think will be the case anyway because this will be a DRM API and
> > you'll have to move to DRM to use it.
> 
> Yep. I think the most important part is to have somewhat sane DT data
> with all the relevant information. It'd be nice to see an example of
> that kind of data there would be used with this patch.

Well the simplest case, which I think will probably cover about 99% of
use-cases would look something like this:

	/* DSI host */
	dsi at 54300000 {
		#address-cells = <1>;
		#size-cells = <0>;

		/* DSI peripheral */
		panel at 0 {
			reg = <0>;
		};
	};

Which in that case has a hard-coded VC 0 for the panel. Other more
complex use-cases could look like this:

	dsi at 54300000 {
		#address-cells = <1>;
		#size-cells = <0>;

		hub at 0 {
			panel at 2 {
				reg = <2>;
			};

			panel at 3 {
				reg = <3>;
			};
		};
	};

Shouldn't that be able to cover pretty much any scenario in existence?

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131209/8f458fec/attachment.pgp>


More information about the dri-devel mailing list