* Dual-channel DSI
@ 2014-08-05 15:39 Thierry Reding
2014-08-07 6:53 ` Andrzej Hajda
0 siblings, 1 reply; 9+ messages in thread
From: Thierry Reding @ 2014-08-05 15:39 UTC (permalink / raw)
To: Laurent Pinchart, Andrzej Hajda, YoungJun Cho, Tomi Valkeinen,
Ajay Kumar
Cc: devicetree, linux-kernel, dri-devel
[-- Attachment #1.1: Type: text/plain, Size: 5109 bytes --]
Hi everyone,
I've been working on adding support for a panel that uses what's
commonly known as dual-channel DSI. Sometimes this is referred to as
ganged-mode as well.
What is it, you ask? It's essentially a hack to work around the band-
width restrictions of DSI, albeit one that's been commonly implemented
by several SoC vendors.
This typically works by equipping a peripheral with two DSI interfaces,
each of which driving one half of the screen (symmetric left-right mode)
or every other line (symmetric odd-even mode). Apparently there can be
asymmetric modes in addition to those two, but they seem to be the
common ones. Often both of the DSI interfaces need to be configured
using DCS commands and vendor specific registers.
A single display controller is typically used video data transmission.
This is necessary to provide synchronization and avoid tearing and all
kinds of other ugliness. For this to work both DSI controllers need to
be made aware of which chunk of the video data stream is addressing
them.
From a software perspective, this poses two problems:
1) A dual-channel device is composed of two DSI peripheral devices which
cannot be programmed independently of each other. A typical example
is that the frame memory extents need to be configured differently
for each of the devices (using the DCS set_column_address and
set_page_address commands). Therefore each device must know of the
other, or there must be a driver that binds against a dummy device
that pulls in the two real devices.
2) On the DSI host side, each of the controller instances needs to know
the intimate details of the other controller (or alternatively, one
controller needs to be a "master" and the other a "slave").
I'm looking for feedback on how this is handled on other SoCs, hence
adding a few people that I know are working on DSI as well (or have in
the past). If you know of any other people that might have useful advice
on this topic, feel free to include them.
Another goal of this discussion is to come up with a somewhat standard
way to represent this in device tree (oh no!) so that panels can be
easily reused on different SoCs.
What I currently have for Tegra is something along these lines:
dsi@54300000 {
nvidia,ganged-mode = <&dsib>;
panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
secondary = <&secondary>;
};
};
dsib: dsi@54400000 {
nvidia,ganged-mode;
secondary: panel@0 {
reg = <0>;
};
};
There are a couple of other properties in those nodes, such as
regulators and such, but I've omitted them so that the discussion can
focus on the important bits.
In the above the panel driver will bind against dsi@54300000/panel@0 and
use the "secondary" property to obtain a reference to the DSI peripheral
device of the second DSI interface of the device.
Similarly, the dsi@54300000 primary DSI host will obtain a reference to
a "slave" DSI host via the "nvidia,ganged-mode" property. The secondary
DSI host dsi@54400000 will know that it's not a fully functional DSI
output by the presence of the empty "nvidia,ganged-mode" property.
Using the above I can get things to work, but it seems somewhat kludgy.
For example it assumes that both DSI hosts are the same type. I'm not
sure if it makes sense for dual-channel to use completely different DSI
hosts given that they need to be very tightly coupled (take input from
the same display controller, use the same PLL, ...). It's also kind of
redundant to have to specify the dual relationship twice (once for the
peripheral and once for the DSI hosts). There's also the issue that we
should really be specifying a compatible string for the secondary
instance of the DSI peripheral, but that would mean that it will bind
against the same driver and then both would be programmed independently
in the same way (without taking into account the differences between the
two interfaces).
One alternative to the above could be something like this:
dsi@54300000 {
nvidia,ganged-mode = <&dsib>;
nvidia,panel = <&panel>
primary: panel@0 {
compatible = "sharp,lq101r1sx01-left";
reg = <0>;
};
};
dsib: dsi@54400000 {
nvidia,ganged-mode;
secondary: panel@0 {
compatible = "sharp,lq101r1sx01-right";
reg = <0>;
};
};
panel {
compatible = "sharp,lq101r1sx01";
sharp,left = <&primary>;
sharp,right = <&secondary>;
};
Which would give us a more natural way to represent this. On the other
hand we loose information about the device type (/panel is no longer a
DSI device) and associated meta-data (number of DSI lanes, ...).
My primary concern is that this may not work for other SoCs since I've
only tested it against Tegra. But the goal would be that the same panel
connected to a different SoC would still be able to work with the same
device tree binding.
It would be great if anybody could share if they know how this works on
other SoCs and if somebody's thought about how to implement it.
Thierry
[-- Attachment #1.2: Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-05 15:39 Dual-channel DSI Thierry Reding
@ 2014-08-07 6:53 ` Andrzej Hajda
2014-08-07 7:25 ` Thierry Reding
0 siblings, 1 reply; 9+ messages in thread
From: Andrzej Hajda @ 2014-08-07 6:53 UTC (permalink / raw)
To: Thierry Reding, Laurent Pinchart, YoungJun Cho, Tomi Valkeinen,
Ajay Kumar
Cc: dri-devel, devicetree, linux-kernel
Hi Thierry,
Nice case.
On 08/05/2014 05:39 PM, Thierry Reding wrote:
> Hi everyone,
>
> I've been working on adding support for a panel that uses what's
> commonly known as dual-channel DSI. Sometimes this is referred to as
> ganged-mode as well.
>
> What is it, you ask? It's essentially a hack to work around the band-
> width restrictions of DSI, albeit one that's been commonly implemented
> by several SoC vendors.
>
> This typically works by equipping a peripheral with two DSI interfaces,
> each of which driving one half of the screen (symmetric left-right mode)
> or every other line (symmetric odd-even mode). Apparently there can be
> asymmetric modes in addition to those two, but they seem to be the
> common ones. Often both of the DSI interfaces need to be configured
> using DCS commands and vendor specific registers.
>
> A single display controller is typically used video data transmission.
> This is necessary to provide synchronization and avoid tearing and all
> kinds of other ugliness. For this to work both DSI controllers need to
> be made aware of which chunk of the video data stream is addressing
> them.
>
> From a software perspective, this poses two problems:
>
> 1) A dual-channel device is composed of two DSI peripheral devices which
> cannot be programmed independently of each other. A typical example
> is that the frame memory extents need to be configured differently
> for each of the devices (using the DCS set_column_address and
> set_page_address commands). Therefore each device must know of the
> other, or there must be a driver that binds against a dummy device
> that pulls in the two real devices.
I am not sure if I understand correctly, but I see it rather as one
device with two dsi-slave interfaces. Probably panel driver can
create dsi dummy device to program some registers
via second dsi interface but the panel will be attached to one control bus.
It seems to be very similar to mfd/i2c devices with two or more i2c
addresses.
>
> 2) On the DSI host side, each of the controller instances needs to know
> the intimate details of the other controller (or alternatively, one
> controller needs to be a "master" and the other a "slave").
The question is if they need to communicate each other, or they have
to have similar configurations applied?
>
> I'm looking for feedback on how this is handled on other SoCs, hence
> adding a few people that I know are working on DSI as well (or have in
> the past). If you know of any other people that might have useful advice
> on this topic, feel free to include them.
>
> Another goal of this discussion is to come up with a somewhat standard
> way to represent this in device tree (oh no!) so that panels can be
> easily reused on different SoCs.
>
> What I currently have for Tegra is something along these lines:
>
> dsi@54300000 {
> nvidia,ganged-mode = <&dsib>;
>
> panel@0 {
> compatible = "sharp,lq101r1sx01";
> reg = <0>;
>
> secondary = <&secondary>;
> };
> };
>
> dsib: dsi@54400000 {
> nvidia,ganged-mode;
>
> secondary: panel@0 {
> reg = <0>;
> };
> };
>
> There are a couple of other properties in those nodes, such as
> regulators and such, but I've omitted them so that the discussion can
> focus on the important bits.
>
> In the above the panel driver will bind against dsi@54300000/panel@0 and
> use the "secondary" property to obtain a reference to the DSI peripheral
> device of the second DSI interface of the device.
>
> Similarly, the dsi@54300000 primary DSI host will obtain a reference to
> a "slave" DSI host via the "nvidia,ganged-mode" property. The secondary
> DSI host dsi@54400000 will know that it's not a fully functional DSI
> output by the presence of the empty "nvidia,ganged-mode" property.
>
> Using the above I can get things to work, but it seems somewhat kludgy.
> For example it assumes that both DSI hosts are the same type. I'm not
> sure if it makes sense for dual-channel to use completely different DSI
> hosts given that they need to be very tightly coupled (take input from
> the same display controller, use the same PLL, ...). It's also kind of
> redundant to have to specify the dual relationship twice (once for the
> peripheral and once for the DSI hosts). There's also the issue that we
> should really be specifying a compatible string for the secondary
> instance of the DSI peripheral, but that would mean that it will bind
> against the same driver and then both would be programmed independently
> in the same way (without taking into account the differences between the
> two interfaces).
>
> One alternative to the above could be something like this:
>
> dsi@54300000 {
> nvidia,ganged-mode = <&dsib>;
> nvidia,panel = <&panel>
>
> primary: panel@0 {
> compatible = "sharp,lq101r1sx01-left";
> reg = <0>;
> };
> };
>
> dsib: dsi@54400000 {
> nvidia,ganged-mode;
>
> secondary: panel@0 {
> compatible = "sharp,lq101r1sx01-right";
> reg = <0>;
> };
> };
>
> panel {
> compatible = "sharp,lq101r1sx01";
> sharp,left = <&primary>;
> sharp,right = <&secondary>;
> };
>
> Which would give us a more natural way to represent this. On the other
> hand we loose information about the device type (/panel is no longer a
> DSI device) and associated meta-data (number of DSI lanes, ...).
>
> My primary concern is that this may not work for other SoCs since I've
> only tested it against Tegra. But the goal would be that the same panel
> connected to a different SoC would still be able to work with the same
> device tree binding.
>
> It would be great if anybody could share if they know how this works on
> other SoCs and if somebody's thought about how to implement it.
What about strictly following general 'rules' in DT:
1. Control bus is modeled using subnodes.
2. Video bus is modeled using video interface bindings.
Assuming this we will put panel node inside the first dsi node and we
should make
video link to other dsi node. Something like this:
dsiA {
ports {
port@0 {
remote-endpoint = <&dc_port0>;
};
dsiA_port1: port@1 {
remote-endpoint = <&panel_port0>;
};
panel@0 {
compatible = "...";
reg = <0>;
ports {
/* maybe common configuration for all ports */
panel_port0: port@0 {
/* configuration specific for port@0 */
remote-endpoint = <&dsiA_port1>;
};
panel_port1: port@1 {
/* configuration specific for port@1 */
remote-endpoint = <&dsiB_port1>;
};
};
};
};
dsiB {
ports {
port@0 {
remote-endpoint = <&dc_port1>;
};
dsiA_port1: port@1 {
remote-endpoint = <&panel_port1>;
};
};
Regards
Andrzej
>
> Thierry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-07 6:53 ` Andrzej Hajda
@ 2014-08-07 7:25 ` Thierry Reding
2014-08-07 8:39 ` Andrzej Hajda
0 siblings, 1 reply; 9+ messages in thread
From: Thierry Reding @ 2014-08-07 7:25 UTC (permalink / raw)
To: Andrzej Hajda
Cc: devicetree, dri-devel, linux-kernel, Tomi Valkeinen,
Laurent Pinchart, Ajay Kumar
[-- Attachment #1.1: Type: text/plain, Size: 10190 bytes --]
On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
> Hi Thierry,
>
> Nice case.
>
> On 08/05/2014 05:39 PM, Thierry Reding wrote:
> > Hi everyone,
> >
> > I've been working on adding support for a panel that uses what's
> > commonly known as dual-channel DSI. Sometimes this is referred to as
> > ganged-mode as well.
> >
> > What is it, you ask? It's essentially a hack to work around the band-
> > width restrictions of DSI, albeit one that's been commonly implemented
> > by several SoC vendors.
> >
> > This typically works by equipping a peripheral with two DSI interfaces,
> > each of which driving one half of the screen (symmetric left-right mode)
> > or every other line (symmetric odd-even mode). Apparently there can be
> > asymmetric modes in addition to those two, but they seem to be the
> > common ones. Often both of the DSI interfaces need to be configured
> > using DCS commands and vendor specific registers.
> >
> > A single display controller is typically used video data transmission.
> > This is necessary to provide synchronization and avoid tearing and all
> > kinds of other ugliness. For this to work both DSI controllers need to
> > be made aware of which chunk of the video data stream is addressing
> > them.
> >
> > From a software perspective, this poses two problems:
> >
> > 1) A dual-channel device is composed of two DSI peripheral devices which
> > cannot be programmed independently of each other. A typical example
> > is that the frame memory extents need to be configured differently
> > for each of the devices (using the DCS set_column_address and
> > set_page_address commands). Therefore each device must know of the
> > other, or there must be a driver that binds against a dummy device
> > that pulls in the two real devices.
>
> I am not sure if I understand correctly, but I see it rather as one
> device with two dsi-slave interfaces. Probably panel driver can
> create dsi dummy device to program some registers
> via second dsi interface but the panel will be attached to one control bus.
> It seems to be very similar to mfd/i2c devices with two or more i2c
> addresses.
They are in fact attached to two different control busses. The DSI
controllers that talk to each are separate. On Tegra they are the same
type of IP block, but still two separate instances (with their own
clock, reset, etc. inputs).
So the panel driver can't create a dummy device to talk to the second
DSI interface because the second DSI interface uses a different DSI
host.
> > 2) On the DSI host side, each of the controller instances needs to know
> > the intimate details of the other controller (or alternatively, one
> > controller needs to be a "master" and the other a "slave").
>
> The question is if they need to communicate each other, or they have
> to have similar configurations applied?
On Tegra at least the configuration needs to be almost the same. There
are two registers that may need to be programmed differently. But they
don't have to communicate with each other. Essentially the two registers
that require different programming define which parts of the display
controller's data stream they need to capture and turn into DSI packets.
Theoretically it would be possible to make this work with two completely
different DSI controllers, but in practice I'd expect that to never
happen. So I'm not sure we need to consider the case where the register
layout is different between the two DSI host controllers.
> > I'm looking for feedback on how this is handled on other SoCs, hence
> > adding a few people that I know are working on DSI as well (or have in
> > the past). If you know of any other people that might have useful advice
> > on this topic, feel free to include them.
> >
> > Another goal of this discussion is to come up with a somewhat standard
> > way to represent this in device tree (oh no!) so that panels can be
> > easily reused on different SoCs.
> >
> > What I currently have for Tegra is something along these lines:
> >
> > dsi@54300000 {
> > nvidia,ganged-mode = <&dsib>;
> >
> > panel@0 {
> > compatible = "sharp,lq101r1sx01";
> > reg = <0>;
> >
> > secondary = <&secondary>;
> > };
> > };
> >
> > dsib: dsi@54400000 {
> > nvidia,ganged-mode;
> >
> > secondary: panel@0 {
> > reg = <0>;
> > };
> > };
> >
> > There are a couple of other properties in those nodes, such as
> > regulators and such, but I've omitted them so that the discussion can
> > focus on the important bits.
> >
> > In the above the panel driver will bind against dsi@54300000/panel@0 and
> > use the "secondary" property to obtain a reference to the DSI peripheral
> > device of the second DSI interface of the device.
> >
> > Similarly, the dsi@54300000 primary DSI host will obtain a reference to
> > a "slave" DSI host via the "nvidia,ganged-mode" property. The secondary
> > DSI host dsi@54400000 will know that it's not a fully functional DSI
> > output by the presence of the empty "nvidia,ganged-mode" property.
> >
> > Using the above I can get things to work, but it seems somewhat kludgy.
> > For example it assumes that both DSI hosts are the same type. I'm not
> > sure if it makes sense for dual-channel to use completely different DSI
> > hosts given that they need to be very tightly coupled (take input from
> > the same display controller, use the same PLL, ...). It's also kind of
> > redundant to have to specify the dual relationship twice (once for the
> > peripheral and once for the DSI hosts). There's also the issue that we
> > should really be specifying a compatible string for the secondary
> > instance of the DSI peripheral, but that would mean that it will bind
> > against the same driver and then both would be programmed independently
> > in the same way (without taking into account the differences between the
> > two interfaces).
> >
> > One alternative to the above could be something like this:
> >
> > dsi@54300000 {
> > nvidia,ganged-mode = <&dsib>;
> > nvidia,panel = <&panel>
> >
> > primary: panel@0 {
> > compatible = "sharp,lq101r1sx01-left";
> > reg = <0>;
> > };
> > };
> >
> > dsib: dsi@54400000 {
> > nvidia,ganged-mode;
> >
> > secondary: panel@0 {
> > compatible = "sharp,lq101r1sx01-right";
> > reg = <0>;
> > };
> > };
> >
> > panel {
> > compatible = "sharp,lq101r1sx01";
> > sharp,left = <&primary>;
> > sharp,right = <&secondary>;
> > };
> >
> > Which would give us a more natural way to represent this. On the other
> > hand we loose information about the device type (/panel is no longer a
> > DSI device) and associated meta-data (number of DSI lanes, ...).
> >
> > My primary concern is that this may not work for other SoCs since I've
> > only tested it against Tegra. But the goal would be that the same panel
> > connected to a different SoC would still be able to work with the same
> > device tree binding.
> >
> > It would be great if anybody could share if they know how this works on
> > other SoCs and if somebody's thought about how to implement it.
>
> What about strictly following general 'rules' in DT:
> 1. Control bus is modeled using subnodes.
> 2. Video bus is modeled using video interface bindings.
>
> Assuming this we will put panel node inside the first dsi node and we
> should make
> video link to other dsi node. Something like this:
>
> dsiA {
> ports {
> port@0 {
> remote-endpoint = <&dc_port0>;
> };
> dsiA_port1: port@1 {
> remote-endpoint = <&panel_port0>;
> };
> panel@0 {
> compatible = "...";
> reg = <0>;
> ports {
> /* maybe common configuration for all ports */
> panel_port0: port@0 {
> /* configuration specific for port@0 */
> remote-endpoint = <&dsiA_port1>;
> };
> panel_port1: port@1 {
> /* configuration specific for port@1 */
> remote-endpoint = <&dsiB_port1>;
> };
> };
> };
> };
>
> dsiB {
> ports {
> port@0 {
> remote-endpoint = <&dc_port1>;
> };
> dsiA_port1: port@1 {
> remote-endpoint = <&panel_port1>;
> };
> };
Much of that information is redundant. For example the "DC" ports are
dynamically configurable at runtime. Also I think panel_port1 is not
necessary because the panel can work (admittedly somewhat crippled) with
only a single DSI interface. I've come up with another alternative that
works:
dsi@54300000 {
panel: panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
};
};
dsi@54400000 {
panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
master = <&panel>;
};
};
That's about as minimal as it gets. The meaning of the above is that
there are two panel devices, each connected to different DSI hosts, that
form a composite device. The first instance can be used standalone, in
which case it will only display one half of the screen, whereas the
second instance can attach to a master (the first instance). When
attached the master can "enslave" the secondary device and set up dual-
channel mode.
From a driver perspective in the above the two instances share the same
driver, but the slave device will only perform a subset of the
initialization, whereas the master device will be the controlling
instance. Furthermore the DSI host controller driver will check that the
secondary's DSI host is compatible (by comparing the mipi_dsi_host.dev->
driver fields) and configure it in ganged mode.
This does work out pretty nicely and I've added a bit of helper code to
the DSI core to make this easier. I'm considering making this more
explicit by introducing the concept of a mipi_dsi_master that wraps a
mipi_dsi_device and provides callbacks for setting up or tearing down
dual-channel mode when a slave is added or removed.
Thierry
[-- Attachment #1.2: Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-07 7:25 ` Thierry Reding
@ 2014-08-07 8:39 ` Andrzej Hajda
2014-08-07 8:54 ` Thierry Reding
0 siblings, 1 reply; 9+ messages in thread
From: Andrzej Hajda @ 2014-08-07 8:39 UTC (permalink / raw)
To: Thierry Reding
Cc: devicetree, dri-devel, linux-kernel, Tomi Valkeinen,
Laurent Pinchart, Ajay Kumar
On 08/07/2014 09:25 AM, Thierry Reding wrote:
> On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
>> Hi Thierry,
>>
>> Nice case.
>>
>> On 08/05/2014 05:39 PM, Thierry Reding wrote:
>>> Hi everyone,
>>>
>>> I've been working on adding support for a panel that uses what's
>>> commonly known as dual-channel DSI. Sometimes this is referred to as
>>> ganged-mode as well.
>>>
>>> What is it, you ask? It's essentially a hack to work around the band-
>>> width restrictions of DSI, albeit one that's been commonly implemented
>>> by several SoC vendors.
>>>
>>> This typically works by equipping a peripheral with two DSI interfaces,
>>> each of which driving one half of the screen (symmetric left-right mode)
>>> or every other line (symmetric odd-even mode). Apparently there can be
>>> asymmetric modes in addition to those two, but they seem to be the
>>> common ones. Often both of the DSI interfaces need to be configured
>>> using DCS commands and vendor specific registers.
>>>
>>> A single display controller is typically used video data transmission.
>>> This is necessary to provide synchronization and avoid tearing and all
>>> kinds of other ugliness. For this to work both DSI controllers need to
>>> be made aware of which chunk of the video data stream is addressing
>>> them.
>>>
>>> From a software perspective, this poses two problems:
>>>
>>> 1) A dual-channel device is composed of two DSI peripheral devices which
>>> cannot be programmed independently of each other. A typical example
>>> is that the frame memory extents need to be configured differently
>>> for each of the devices (using the DCS set_column_address and
>>> set_page_address commands). Therefore each device must know of the
>>> other, or there must be a driver that binds against a dummy device
>>> that pulls in the two real devices.
>> I am not sure if I understand correctly, but I see it rather as one
>> device with two dsi-slave interfaces. Probably panel driver can
>> create dsi dummy device to program some registers
>> via second dsi interface but the panel will be attached to one control bus.
>> It seems to be very similar to mfd/i2c devices with two or more i2c
>> addresses.
> They are in fact attached to two different control busses. The DSI
> controllers that talk to each are separate. On Tegra they are the same
> type of IP block, but still two separate instances (with their own
> clock, reset, etc. inputs).
>
> So the panel driver can't create a dummy device to talk to the second
> DSI interface because the second DSI interface uses a different DSI
> host.
Why different DSI host does not allow that? The only thing panel needs
is the reference to another DSI host and this can be provided via
DT direct phandle or video interface.
>
>>> 2) On the DSI host side, each of the controller instances needs to know
>>> the intimate details of the other controller (or alternatively, one
>>> controller needs to be a "master" and the other a "slave").
>> The question is if they need to communicate each other, or they have
>> to have similar configurations applied?
> On Tegra at least the configuration needs to be almost the same. There
> are two registers that may need to be programmed differently. But they
> don't have to communicate with each other. Essentially the two registers
> that require different programming define which parts of the display
> controller's data stream they need to capture and turn into DSI packets.
>
> Theoretically it would be possible to make this work with two completely
> different DSI controllers, but in practice I'd expect that to never
> happen. So I'm not sure we need to consider the case where the register
> layout is different between the two DSI host controllers.
So maybe the configuration could be provided by the panel.
>
>>> I'm looking for feedback on how this is handled on other SoCs, hence
>>> adding a few people that I know are working on DSI as well (or have in
>>> the past). If you know of any other people that might have useful advice
>>> on this topic, feel free to include them.
>>>
>>> Another goal of this discussion is to come up with a somewhat standard
>>> way to represent this in device tree (oh no!) so that panels can be
>>> easily reused on different SoCs.
>>>
>>> What I currently have for Tegra is something along these lines:
>>>
>>> dsi@54300000 {
>>> nvidia,ganged-mode = <&dsib>;
>>>
>>> panel@0 {
>>> compatible = "sharp,lq101r1sx01";
>>> reg = <0>;
>>>
>>> secondary = <&secondary>;
>>> };
>>> };
>>>
>>> dsib: dsi@54400000 {
>>> nvidia,ganged-mode;
>>>
>>> secondary: panel@0 {
>>> reg = <0>;
>>> };
>>> };
>>>
>>> There are a couple of other properties in those nodes, such as
>>> regulators and such, but I've omitted them so that the discussion can
>>> focus on the important bits.
>>>
>>> In the above the panel driver will bind against dsi@54300000/panel@0 and
>>> use the "secondary" property to obtain a reference to the DSI peripheral
>>> device of the second DSI interface of the device.
>>>
>>> Similarly, the dsi@54300000 primary DSI host will obtain a reference to
>>> a "slave" DSI host via the "nvidia,ganged-mode" property. The secondary
>>> DSI host dsi@54400000 will know that it's not a fully functional DSI
>>> output by the presence of the empty "nvidia,ganged-mode" property.
>>>
>>> Using the above I can get things to work, but it seems somewhat kludgy.
>>> For example it assumes that both DSI hosts are the same type. I'm not
>>> sure if it makes sense for dual-channel to use completely different DSI
>>> hosts given that they need to be very tightly coupled (take input from
>>> the same display controller, use the same PLL, ...). It's also kind of
>>> redundant to have to specify the dual relationship twice (once for the
>>> peripheral and once for the DSI hosts). There's also the issue that we
>>> should really be specifying a compatible string for the secondary
>>> instance of the DSI peripheral, but that would mean that it will bind
>>> against the same driver and then both would be programmed independently
>>> in the same way (without taking into account the differences between the
>>> two interfaces).
>>>
>>> One alternative to the above could be something like this:
>>>
>>> dsi@54300000 {
>>> nvidia,ganged-mode = <&dsib>;
>>> nvidia,panel = <&panel>
>>>
>>> primary: panel@0 {
>>> compatible = "sharp,lq101r1sx01-left";
>>> reg = <0>;
>>> };
>>> };
>>>
>>> dsib: dsi@54400000 {
>>> nvidia,ganged-mode;
>>>
>>> secondary: panel@0 {
>>> compatible = "sharp,lq101r1sx01-right";
>>> reg = <0>;
>>> };
>>> };
>>>
>>> panel {
>>> compatible = "sharp,lq101r1sx01";
>>> sharp,left = <&primary>;
>>> sharp,right = <&secondary>;
>>> };
>>>
>>> Which would give us a more natural way to represent this. On the other
>>> hand we loose information about the device type (/panel is no longer a
>>> DSI device) and associated meta-data (number of DSI lanes, ...).
>>>
>>> My primary concern is that this may not work for other SoCs since I've
>>> only tested it against Tegra. But the goal would be that the same panel
>>> connected to a different SoC would still be able to work with the same
>>> device tree binding.
>>>
>>> It would be great if anybody could share if they know how this works on
>>> other SoCs and if somebody's thought about how to implement it.
>> What about strictly following general 'rules' in DT:
>> 1. Control bus is modeled using subnodes.
>> 2. Video bus is modeled using video interface bindings.
>>
>> Assuming this we will put panel node inside the first dsi node and we
>> should make
>> video link to other dsi node. Something like this:
>>
>> dsiA {
>> ports {
>> port@0 {
>> remote-endpoint = <&dc_port0>;
>> };
>> dsiA_port1: port@1 {
>> remote-endpoint = <&panel_port0>;
>> };
>> panel@0 {
>> compatible = "...";
>> reg = <0>;
>> ports {
>> /* maybe common configuration for all ports */
>> panel_port0: port@0 {
>> /* configuration specific for port@0 */
>> remote-endpoint = <&dsiA_port1>;
>> };
>> panel_port1: port@1 {
>> /* configuration specific for port@1 */
>> remote-endpoint = <&dsiB_port1>;
>> };
>> };
>> };
>> };
>>
>> dsiB {
>> ports {
>> port@0 {
>> remote-endpoint = <&dc_port1>;
>> };
>> dsiA_port1: port@1 {
>> remote-endpoint = <&panel_port1>;
>> };
>> };
> Much of that information is redundant. For example the "DC" ports are
> dynamically configurable at runtime.
DC ports can be omitted if they are configurable dynamically.
> Also I think panel_port1 is not
> necessary because the panel can work (admittedly somewhat crippled) with
> only a single DSI interface.
In such situation you just removes this port, I see no problem here.
> I've come up with another alternative that
> works:
>
> dsi@54300000 {
> panel: panel@0 {
> compatible = "sharp,lq101r1sx01";
> reg = <0>;
> };
> };
>
> dsi@54400000 {
> panel@0 {
> compatible = "sharp,lq101r1sx01";
> reg = <0>;
>
> master = <&panel>;
> };
> };
But here you have again two compatibles and two devices in DT representing
one HW device. I am not sure if it is better. If you do not like video
interfaces
maybe better would be sth like this:
dsi@54300000 {
panel: panel@0 {
compatible = "sharp,lq101r1sx01";
reg = <0>;
secondary_dsi = <&dsiB>;
};
};
dsiB: dsi@54400000 {
};
Regards
Andrzej
>
> That's about as minimal as it gets. The meaning of the above is that
> there are two panel devices, each connected to different DSI hosts, that
> form a composite device. The first instance can be used standalone, in
> which case it will only display one half of the screen, whereas the
> second instance can attach to a master (the first instance). When
> attached the master can "enslave" the secondary device and set up dual-
> channel mode.
>
> From a driver perspective in the above the two instances share the same
> driver, but the slave device will only perform a subset of the
> initialization, whereas the master device will be the controlling
> instance. Furthermore the DSI host controller driver will check that the
> secondary's DSI host is compatible (by comparing the mipi_dsi_host.dev->
> driver fields) and configure it in ganged mode.
>
> This does work out pretty nicely and I've added a bit of helper code to
> the DSI core to make this easier. I'm considering making this more
> explicit by introducing the concept of a mipi_dsi_master that wraps a
> mipi_dsi_device and provides callbacks for setting up or tearing down
> dual-channel mode when a slave is added or removed.
>
> Thierry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-07 8:39 ` Andrzej Hajda
@ 2014-08-07 8:54 ` Thierry Reding
2014-08-08 7:26 ` Andrzej Hajda
0 siblings, 1 reply; 9+ messages in thread
From: Thierry Reding @ 2014-08-07 8:54 UTC (permalink / raw)
To: Andrzej Hajda
Cc: devicetree, dri-devel, linux-kernel, Tomi Valkeinen,
Laurent Pinchart, Ajay Kumar
[-- Attachment #1.1: Type: text/plain, Size: 6624 bytes --]
On Thu, Aug 07, 2014 at 10:39:36AM +0200, Andrzej Hajda wrote:
> On 08/07/2014 09:25 AM, Thierry Reding wrote:
> > On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
> >> Hi Thierry,
> >>
> >> Nice case.
> >>
> >> On 08/05/2014 05:39 PM, Thierry Reding wrote:
> >>> Hi everyone,
> >>>
> >>> I've been working on adding support for a panel that uses what's
> >>> commonly known as dual-channel DSI. Sometimes this is referred to as
> >>> ganged-mode as well.
> >>>
> >>> What is it, you ask? It's essentially a hack to work around the band-
> >>> width restrictions of DSI, albeit one that's been commonly implemented
> >>> by several SoC vendors.
> >>>
> >>> This typically works by equipping a peripheral with two DSI interfaces,
> >>> each of which driving one half of the screen (symmetric left-right mode)
> >>> or every other line (symmetric odd-even mode). Apparently there can be
> >>> asymmetric modes in addition to those two, but they seem to be the
> >>> common ones. Often both of the DSI interfaces need to be configured
> >>> using DCS commands and vendor specific registers.
> >>>
> >>> A single display controller is typically used video data transmission.
> >>> This is necessary to provide synchronization and avoid tearing and all
> >>> kinds of other ugliness. For this to work both DSI controllers need to
> >>> be made aware of which chunk of the video data stream is addressing
> >>> them.
> >>>
> >>> From a software perspective, this poses two problems:
> >>>
> >>> 1) A dual-channel device is composed of two DSI peripheral devices which
> >>> cannot be programmed independently of each other. A typical example
> >>> is that the frame memory extents need to be configured differently
> >>> for each of the devices (using the DCS set_column_address and
> >>> set_page_address commands). Therefore each device must know of the
> >>> other, or there must be a driver that binds against a dummy device
> >>> that pulls in the two real devices.
> >> I am not sure if I understand correctly, but I see it rather as one
> >> device with two dsi-slave interfaces. Probably panel driver can
> >> create dsi dummy device to program some registers
> >> via second dsi interface but the panel will be attached to one control bus.
> >> It seems to be very similar to mfd/i2c devices with two or more i2c
> >> addresses.
> > They are in fact attached to two different control busses. The DSI
> > controllers that talk to each are separate. On Tegra they are the same
> > type of IP block, but still two separate instances (with their own
> > clock, reset, etc. inputs).
> >
> > So the panel driver can't create a dummy device to talk to the second
> > DSI interface because the second DSI interface uses a different DSI
> > host.
>
> Why different DSI host does not allow that? The only thing panel needs
> is the reference to another DSI host and this can be provided via
> DT direct phandle or video interface.
I'm sure one could find ways to make it work. That doesn't mean it's a
good idea, though. The second peripheral is physically there on the
second DSI host controller's bus, so it the device should be in device
tree because so that the device tree matches reality.
> >>> 2) On the DSI host side, each of the controller instances needs to know
> >>> the intimate details of the other controller (or alternatively, one
> >>> controller needs to be a "master" and the other a "slave").
> >> The question is if they need to communicate each other, or they have
> >> to have similar configurations applied?
> > On Tegra at least the configuration needs to be almost the same. There
> > are two registers that may need to be programmed differently. But they
> > don't have to communicate with each other. Essentially the two registers
> > that require different programming define which parts of the display
> > controller's data stream they need to capture and turn into DSI packets.
> >
> > Theoretically it would be possible to make this work with two completely
> > different DSI controllers, but in practice I'd expect that to never
> > happen. So I'm not sure we need to consider the case where the register
> > layout is different between the two DSI host controllers.
>
> So maybe the configuration could be provided by the panel.
What configuration? I suppose one idea would be for the panel driver to
set the type of dual-channel mode that it's using. Panels can typically
be configured to do symmetric left-right or symmetric odd-even. I think
technically it's possible to have asymmetric modes, too, but to be
honest I don't want to think about those yet.
So I think it's reasonable for the DSI device to provide information as
to what mode it's using. Perhaps that could be done as part of the slave
setup.
> > I've come up with another alternative that works:
> >
> > dsi@54300000 {
> > panel: panel@0 {
> > compatible = "sharp,lq101r1sx01";
> > reg = <0>;
> > };
> > };
> >
> > dsi@54400000 {
> > panel@0 {
> > compatible = "sharp,lq101r1sx01";
> > reg = <0>;
> >
> > master = <&panel>;
> > };
> > };
>
> But here you have again two compatibles and two devices in DT representing
> one HW device.
Because that's what they really are. There are two different devices,
it's just that they happen to be driving two separate halves of the same
panel.
> I am not sure if it is better. If you do not like video
> interfaces
> maybe better would be sth like this:
>
> dsi@54300000 {
> panel: panel@0 {
> compatible = "sharp,lq101r1sx01";
> reg = <0>;
> secondary_dsi = <&dsiB>;
> };
> };
>
> dsiB: dsi@54400000 {
> };
That's pretty much the same thing that I proposed, except that it
reverses the link between the two. In fact I tried something similar to
that before, but it has a couple of problems: if the secondary device
does not have a compatible string (that's probably not valid in device
tree to begin with) then there's no way for the device to report what
format it expects or what number of lanes it uses. But those are
parameters that are needed to set up the DSI (and display controllers).
One other problem with the above is that the dependency implied by your
"secondary_dsi" property is the wrong way around. The above would mean
that &panel requires &dsiB's services to function, but that's not the
case. If anything it's the other way around. &panel could still work
standalone (though only drive the left half of the screen).
Thierry
[-- Attachment #1.2: Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-07 8:54 ` Thierry Reding
@ 2014-08-08 7:26 ` Andrzej Hajda
2014-08-08 10:14 ` Thierry Reding
0 siblings, 1 reply; 9+ messages in thread
From: Andrzej Hajda @ 2014-08-08 7:26 UTC (permalink / raw)
To: Thierry Reding
Cc: devicetree, dri-devel, linux-kernel, Tomi Valkeinen,
Laurent Pinchart, Ajay Kumar
On 08/07/2014 10:54 AM, Thierry Reding wrote:
> On Thu, Aug 07, 2014 at 10:39:36AM +0200, Andrzej Hajda wrote:
>> On 08/07/2014 09:25 AM, Thierry Reding wrote:
>>> On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
>>>> Hi Thierry,
>>>>
>>>> Nice case.
>>>>
>>>> On 08/05/2014 05:39 PM, Thierry Reding wrote:
>>>>> Hi everyone,
>>>>>
>>>>> I've been working on adding support for a panel that uses what's
>>>>> commonly known as dual-channel DSI. Sometimes this is referred to as
>>>>> ganged-mode as well.
>>>>>
>>>>> What is it, you ask? It's essentially a hack to work around the band-
>>>>> width restrictions of DSI, albeit one that's been commonly implemented
>>>>> by several SoC vendors.
>>>>>
>>>>> This typically works by equipping a peripheral with two DSI interfaces,
>>>>> each of which driving one half of the screen (symmetric left-right mode)
>>>>> or every other line (symmetric odd-even mode). Apparently there can be
>>>>> asymmetric modes in addition to those two, but they seem to be the
>>>>> common ones. Often both of the DSI interfaces need to be configured
>>>>> using DCS commands and vendor specific registers.
>>>>>
>>>>> A single display controller is typically used video data transmission.
>>>>> This is necessary to provide synchronization and avoid tearing and all
>>>>> kinds of other ugliness. For this to work both DSI controllers need to
>>>>> be made aware of which chunk of the video data stream is addressing
>>>>> them.
>>>>>
>>>>> From a software perspective, this poses two problems:
>>>>>
>>>>> 1) A dual-channel device is composed of two DSI peripheral devices which
>>>>> cannot be programmed independently of each other. A typical example
>>>>> is that the frame memory extents need to be configured differently
>>>>> for each of the devices (using the DCS set_column_address and
>>>>> set_page_address commands). Therefore each device must know of the
>>>>> other, or there must be a driver that binds against a dummy device
>>>>> that pulls in the two real devices.
>>>> I am not sure if I understand correctly, but I see it rather as one
>>>> device with two dsi-slave interfaces. Probably panel driver can
>>>> create dsi dummy device to program some registers
>>>> via second dsi interface but the panel will be attached to one control bus.
>>>> It seems to be very similar to mfd/i2c devices with two or more i2c
>>>> addresses.
>>> They are in fact attached to two different control busses. The DSI
>>> controllers that talk to each are separate. On Tegra they are the same
>>> type of IP block, but still two separate instances (with their own
>>> clock, reset, etc. inputs).
>>>
>>> So the panel driver can't create a dummy device to talk to the second
>>> DSI interface because the second DSI interface uses a different DSI
>>> host.
>> Why different DSI host does not allow that? The only thing panel needs
>> is the reference to another DSI host and this can be provided via
>> DT direct phandle or video interface.
> I'm sure one could find ways to make it work. That doesn't mean it's a
> good idea, though. The second peripheral is physically there on the
> second DSI host controller's bus, so it the device should be in device
> tree because so that the device tree matches reality.
The question is what is the reality? Do we have two separate dsi
devices? In such case
both devices should appear in DT.
If we have single device attached to two different DSI hosts I suppose
device should appear
only in one location in DT with link to another DSI host.
>
>>>>> 2) On the DSI host side, each of the controller instances needs to know
>>>>> the intimate details of the other controller (or alternatively, one
>>>>> controller needs to be a "master" and the other a "slave").
>>>> The question is if they need to communicate each other, or they have
>>>> to have similar configurations applied?
>>> On Tegra at least the configuration needs to be almost the same. There
>>> are two registers that may need to be programmed differently. But they
>>> don't have to communicate with each other. Essentially the two registers
>>> that require different programming define which parts of the display
>>> controller's data stream they need to capture and turn into DSI packets.
>>>
>>> Theoretically it would be possible to make this work with two completely
>>> different DSI controllers, but in practice I'd expect that to never
>>> happen. So I'm not sure we need to consider the case where the register
>>> layout is different between the two DSI host controllers.
>> So maybe the configuration could be provided by the panel.
> What configuration? I suppose one idea would be for the panel driver to
> set the type of dual-channel mode that it's using. Panels can typically
> be configured to do symmetric left-right or symmetric odd-even. I think
> technically it's possible to have asymmetric modes, too, but to be
> honest I don't want to think about those yet.
>
> So I think it's reasonable for the DSI device to provide information as
> to what mode it's using. Perhaps that could be done as part of the slave
> setup.
>
>>> I've come up with another alternative that works:
>>>
>>> dsi@54300000 {
>>> panel: panel@0 {
>>> compatible = "sharp,lq101r1sx01";
>>> reg = <0>;
>>> };
>>> };
>>>
>>> dsi@54400000 {
>>> panel@0 {
>>> compatible = "sharp,lq101r1sx01";
>>> reg = <0>;
>>>
>>> master = <&panel>;
>>> };
>>> };
>> But here you have again two compatibles and two devices in DT representing
>> one HW device.
> Because that's what they really are. There are two different devices,
> it's just that they happen to be driving two separate halves of the same
> panel.
Compatible string "sharp,lq101r1sx01" clearly indicates that there are
two panels of type LQ101R1SX01.
If you really want to split this panel as two separate devices maybe you
should probably use separate
compatibles to make it more clear, sth like: "sharp,lq101r1sx01_link1",
"sharp,lq101r1sx01_link2".
Anyway it looks odd to me :)
>
>> I am not sure if it is better. If you do not like video
>> interfaces
>> maybe better would be sth like this:
>>
>> dsi@54300000 {
>> panel: panel@0 {
>> compatible = "sharp,lq101r1sx01";
>> reg = <0>;
>> secondary_dsi = <&dsiB>;
>> };
>> };
>>
>> dsiB: dsi@54400000 {
>> };
> That's pretty much the same thing that I proposed, except that it
> reverses the link between the two.
For me it is fundamentally different - in your proposition you have two
different panels, in my you have only one, attached to one dsi with
phandle to 2nd dsi.
> In fact I tried something similar to
> that before, but it has a couple of problems: if the secondary device
> does not have a compatible string (that's probably not valid in device
> tree to begin with) then there's no way for the device to report what
> format it expects or what number of lanes it uses. But those are
> parameters that are needed to set up the DSI (and display controllers).
I2C has:
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
DSI could have something similar, this way you could pass everything you
need.
>
> One other problem with the above is that the dependency implied by your
> "secondary_dsi" property is the wrong way around. The above would mean
> that &panel requires &dsiB's services to function, but that's not the
> case. If anything it's the other way around. &panel could still work
> standalone (though only drive the left half of the screen).
Why? Interpretation of the private property is up to this specific
binding documentation
and it can define the property optional. On the other side if the
property is present
and the panel driver cannot connect to dsiB it is up to the panel driver
what to do,
it can fail or continue to work with single dsi.
Summarizing it seems the core of the problem is to answer the question
if the panel should be represented
as single device or as two devices.
Regards
Andrzej
>
> Thierry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-08 7:26 ` Andrzej Hajda
@ 2014-08-08 10:14 ` Thierry Reding
2014-08-12 16:00 ` Andrzej Hajda
2014-08-14 12:59 ` Tomi Valkeinen
0 siblings, 2 replies; 9+ messages in thread
From: Thierry Reding @ 2014-08-08 10:14 UTC (permalink / raw)
To: Andrzej Hajda
Cc: devicetree, dri-devel, linux-kernel, Tomi Valkeinen,
Laurent Pinchart, Ajay Kumar
[-- Attachment #1.1: Type: text/plain, Size: 9958 bytes --]
On Fri, Aug 08, 2014 at 09:26:17AM +0200, Andrzej Hajda wrote:
> On 08/07/2014 10:54 AM, Thierry Reding wrote:
> > On Thu, Aug 07, 2014 at 10:39:36AM +0200, Andrzej Hajda wrote:
> >> On 08/07/2014 09:25 AM, Thierry Reding wrote:
> >>> On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
> >>>> Hi Thierry,
> >>>>
> >>>> Nice case.
> >>>>
> >>>> On 08/05/2014 05:39 PM, Thierry Reding wrote:
> >>>>> Hi everyone,
> >>>>>
> >>>>> I've been working on adding support for a panel that uses what's
> >>>>> commonly known as dual-channel DSI. Sometimes this is referred to as
> >>>>> ganged-mode as well.
> >>>>>
> >>>>> What is it, you ask? It's essentially a hack to work around the band-
> >>>>> width restrictions of DSI, albeit one that's been commonly implemented
> >>>>> by several SoC vendors.
> >>>>>
> >>>>> This typically works by equipping a peripheral with two DSI interfaces,
> >>>>> each of which driving one half of the screen (symmetric left-right mode)
> >>>>> or every other line (symmetric odd-even mode). Apparently there can be
> >>>>> asymmetric modes in addition to those two, but they seem to be the
> >>>>> common ones. Often both of the DSI interfaces need to be configured
> >>>>> using DCS commands and vendor specific registers.
> >>>>>
> >>>>> A single display controller is typically used video data transmission.
> >>>>> This is necessary to provide synchronization and avoid tearing and all
> >>>>> kinds of other ugliness. For this to work both DSI controllers need to
> >>>>> be made aware of which chunk of the video data stream is addressing
> >>>>> them.
> >>>>>
> >>>>> From a software perspective, this poses two problems:
> >>>>>
> >>>>> 1) A dual-channel device is composed of two DSI peripheral devices which
> >>>>> cannot be programmed independently of each other. A typical example
> >>>>> is that the frame memory extents need to be configured differently
> >>>>> for each of the devices (using the DCS set_column_address and
> >>>>> set_page_address commands). Therefore each device must know of the
> >>>>> other, or there must be a driver that binds against a dummy device
> >>>>> that pulls in the two real devices.
> >>>> I am not sure if I understand correctly, but I see it rather as one
> >>>> device with two dsi-slave interfaces. Probably panel driver can
> >>>> create dsi dummy device to program some registers
> >>>> via second dsi interface but the panel will be attached to one control bus.
> >>>> It seems to be very similar to mfd/i2c devices with two or more i2c
> >>>> addresses.
> >>> They are in fact attached to two different control busses. The DSI
> >>> controllers that talk to each are separate. On Tegra they are the same
> >>> type of IP block, but still two separate instances (with their own
> >>> clock, reset, etc. inputs).
> >>>
> >>> So the panel driver can't create a dummy device to talk to the second
> >>> DSI interface because the second DSI interface uses a different DSI
> >>> host.
> >> Why different DSI host does not allow that? The only thing panel needs
> >> is the reference to another DSI host and this can be provided via
> >> DT direct phandle or video interface.
> > I'm sure one could find ways to make it work. That doesn't mean it's a
> > good idea, though. The second peripheral is physically there on the
> > second DSI host controller's bus, so it the device should be in device
> > tree because so that the device tree matches reality.
>
> The question is what is the reality? Do we have two separate dsi
> devices? In such case
> both devices should appear in DT.
> If we have single device attached to two different DSI hosts I suppose
> device should appear
> only in one location in DT with link to another DSI host.
Doesn't the fact that both devices are connected to different DSI hosts
make them separate device? While it's physically one device only (there
is one panel), device tree defines devices in terms of the control bus
that they are connected to. Since in this case both subdevices are
controlled by different DSI hosts that makes them separate devices.
> >>>>> 2) On the DSI host side, each of the controller instances needs to know
> >>>>> the intimate details of the other controller (or alternatively, one
> >>>>> controller needs to be a "master" and the other a "slave").
> >>>> The question is if they need to communicate each other, or they have
> >>>> to have similar configurations applied?
> >>> On Tegra at least the configuration needs to be almost the same. There
> >>> are two registers that may need to be programmed differently. But they
> >>> don't have to communicate with each other. Essentially the two registers
> >>> that require different programming define which parts of the display
> >>> controller's data stream they need to capture and turn into DSI packets.
> >>>
> >>> Theoretically it would be possible to make this work with two completely
> >>> different DSI controllers, but in practice I'd expect that to never
> >>> happen. So I'm not sure we need to consider the case where the register
> >>> layout is different between the two DSI host controllers.
> >> So maybe the configuration could be provided by the panel.
> > What configuration? I suppose one idea would be for the panel driver to
> > set the type of dual-channel mode that it's using. Panels can typically
> > be configured to do symmetric left-right or symmetric odd-even. I think
> > technically it's possible to have asymmetric modes, too, but to be
> > honest I don't want to think about those yet.
> >
> > So I think it's reasonable for the DSI device to provide information as
> > to what mode it's using. Perhaps that could be done as part of the slave
> > setup.
> >
> >>> I've come up with another alternative that works:
> >>>
> >>> dsi@54300000 {
> >>> panel: panel@0 {
> >>> compatible = "sharp,lq101r1sx01";
> >>> reg = <0>;
> >>> };
> >>> };
> >>>
> >>> dsi@54400000 {
> >>> panel@0 {
> >>> compatible = "sharp,lq101r1sx01";
> >>> reg = <0>;
> >>>
> >>> master = <&panel>;
> >>> };
> >>> };
> >> But here you have again two compatibles and two devices in DT representing
> >> one HW device.
> > Because that's what they really are. There are two different devices,
> > it's just that they happen to be driving two separate halves of the same
> > panel.
>
> Compatible string "sharp,lq101r1sx01" clearly indicates that there are
> two panels of type LQ101R1SX01.
> If you really want to split this panel as two separate devices maybe you
> should probably use separate
> compatibles to make it more clear, sth like: "sharp,lq101r1sx01_link1",
> "sharp,lq101r1sx01_link2".
> Anyway it looks odd to me :)
As best as I can tell both subdevices are actually the same. Although it
seems like commands written to the primary channel have an effect on the
device as a whole. For example if you send a DCS exit_sleep_mode command
to the primary channel then both devices will wake up. Similarly sending
the DCS set_display_on command will turn on the display on both halves,
not just the one. I haven't checked yet whether the same is true when
the commands are sent to the secondary.
One other solution I had thought about looked something like this:
dsi@54300000 {
left: panel@0 {
compatible = "sharp,lq101r1sx01-link";
reg = <0>;
...
};
};
dsi@54400000 {
right: panel@0 {
compatible = "sharp,lq101r1sx01-link";
reg = <0>;
...
};
};
panel: panel {
compatible = "sharp,lq101r1sx01";
links = <&left &right>;
};
The downside of that being that &panel becomes a non-DSI device and we
loose meta information such as the number of lanes etc.
Perhaps this could be solved by using a device_type = "dsi" property and
thereby cause the driver core to instantiate a DSI device rather than a
platform device. Or perhaps even device_type = "dual-dsi" so that it
could directly hook up both channels.
But that's not all that different from the minimal proposal above, and I
don't know if it's worth the trouble. Anyway, it would be good to hear
thoughts on this from the device tree maintainers.
> >> I am not sure if it is better. If you do not like video
> >> interfaces
> >> maybe better would be sth like this:
> >>
> >> dsi@54300000 {
> >> panel: panel@0 {
> >> compatible = "sharp,lq101r1sx01";
> >> reg = <0>;
> >> secondary_dsi = <&dsiB>;
> >> };
> >> };
> >>
> >> dsiB: dsi@54400000 {
> >> };
> > That's pretty much the same thing that I proposed, except that it
> > reverses the link between the two.
> For me it is fundamentally different - in your proposition you have two
> different panels, in my you have only one, attached to one dsi with
> phandle to 2nd dsi.
Looking at the example again I don't see how it could work. The phandle
references the second DSI host, but we need a reference to the second
DSI peripheral. We can't just assume that it's on the same virtual
channel as the first.
> > In fact I tried something similar to
> > that before, but it has a couple of problems: if the secondary device
> > does not have a compatible string (that's probably not valid in device
> > tree to begin with) then there's no way for the device to report what
> > format it expects or what number of lanes it uses. But those are
> > parameters that are needed to set up the DSI (and display controllers).
>
> I2C has:
> struct i2c_client *
> i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
>
> DSI could have something similar, this way you could pass everything you
> need.
We don't need any of that if both devices have a proper compatible
string, which they should have anyway, since then the driver can fill in
those values as appropriate.
Thierry
[-- Attachment #1.2: Type: application/pgp-signature, Size: 819 bytes --]
[-- Attachment #2: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-08 10:14 ` Thierry Reding
@ 2014-08-12 16:00 ` Andrzej Hajda
2014-08-14 12:59 ` Tomi Valkeinen
1 sibling, 0 replies; 9+ messages in thread
From: Andrzej Hajda @ 2014-08-12 16:00 UTC (permalink / raw)
To: Thierry Reding
Cc: Mark Rutland, devicetree, Pawel Moll, Ian Campbell, dri-devel,
linux-kernel, Rob Herring, Tomi Valkeinen, Laurent Pinchart,
Kumar Gala, Ajay Kumar
Added DT maintainers as we have here quite fundamental DT question:
How shall we model hardware connected to multiple buses, in DT?
Here we have panel connected to two MIPI-DSI buses.
Below is the summary of our propositions, followed by lengthly detailed
discussion,
including proposed bindings.
Current propositions (ordered according to my preferences):
1. Subnode of the first DSI master with phandle to 2nd DSI master.
2. Separate node with phandles to both DSI masters.
3. Two different subnodes of both DSI masters with the same compatible
string,
and phandle in one node to another one.
4. Two different subnodes of both DSI masters with the same compatible
string
and separate node with another compatible string with phandles to both
DSI subnodes.
Notes:
- in the first two cases I guess phandles should be accompanied with bus
addresses,
- here we have two DSI buses but the problem will be similar with other
non-discoverable buses,
- case of 3 and 4 are original Thierry propositions, if they are
preferred I would consider to
use different compatible strings for DSI subnodes as they describe
different HW interfaces.
My additional comments below.
On 08/08/2014 12:14 PM, Thierry Reding wrote:
> On Fri, Aug 08, 2014 at 09:26:17AM +0200, Andrzej Hajda wrote:
>> On 08/07/2014 10:54 AM, Thierry Reding wrote:
>>> On Thu, Aug 07, 2014 at 10:39:36AM +0200, Andrzej Hajda wrote:
>>>> On 08/07/2014 09:25 AM, Thierry Reding wrote:
>>>>> On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
>>>>>> Hi Thierry,
>>>>>>
>>>>>> Nice case.
>>>>>>
>>>>>> On 08/05/2014 05:39 PM, Thierry Reding wrote:
>>>>>>> Hi everyone,
>>>>>>>
>>>>>>> I've been working on adding support for a panel that uses what's
>>>>>>> commonly known as dual-channel DSI. Sometimes this is referred to as
>>>>>>> ganged-mode as well.
>>>>>>>
>>>>>>> What is it, you ask? It's essentially a hack to work around the band-
>>>>>>> width restrictions of DSI, albeit one that's been commonly implemented
>>>>>>> by several SoC vendors.
>>>>>>>
>>>>>>> This typically works by equipping a peripheral with two DSI interfaces,
>>>>>>> each of which driving one half of the screen (symmetric left-right mode)
>>>>>>> or every other line (symmetric odd-even mode). Apparently there can be
>>>>>>> asymmetric modes in addition to those two, but they seem to be the
>>>>>>> common ones. Often both of the DSI interfaces need to be configured
>>>>>>> using DCS commands and vendor specific registers.
>>>>>>>
>>>>>>> A single display controller is typically used video data transmission.
>>>>>>> This is necessary to provide synchronization and avoid tearing and all
>>>>>>> kinds of other ugliness. For this to work both DSI controllers need to
>>>>>>> be made aware of which chunk of the video data stream is addressing
>>>>>>> them.
>>>>>>>
>>>>>>> From a software perspective, this poses two problems:
>>>>>>>
>>>>>>> 1) A dual-channel device is composed of two DSI peripheral devices which
>>>>>>> cannot be programmed independently of each other. A typical example
>>>>>>> is that the frame memory extents need to be configured differently
>>>>>>> for each of the devices (using the DCS set_column_address and
>>>>>>> set_page_address commands). Therefore each device must know of the
>>>>>>> other, or there must be a driver that binds against a dummy device
>>>>>>> that pulls in the two real devices.
>>>>>> I am not sure if I understand correctly, but I see it rather as one
>>>>>> device with two dsi-slave interfaces. Probably panel driver can
>>>>>> create dsi dummy device to program some registers
>>>>>> via second dsi interface but the panel will be attached to one control bus.
>>>>>> It seems to be very similar to mfd/i2c devices with two or more i2c
>>>>>> addresses.
>>>>> They are in fact attached to two different control busses. The DSI
>>>>> controllers that talk to each are separate. On Tegra they are the same
>>>>> type of IP block, but still two separate instances (with their own
>>>>> clock, reset, etc. inputs).
>>>>>
>>>>> So the panel driver can't create a dummy device to talk to the second
>>>>> DSI interface because the second DSI interface uses a different DSI
>>>>> host.
>>>> Why different DSI host does not allow that? The only thing panel needs
>>>> is the reference to another DSI host and this can be provided via
>>>> DT direct phandle or video interface.
>>> I'm sure one could find ways to make it work. That doesn't mean it's a
>>> good idea, though. The second peripheral is physically there on the
>>> second DSI host controller's bus, so it the device should be in device
>>> tree because so that the device tree matches reality.
>> The question is what is the reality? Do we have two separate dsi
>> devices? In such case
>> both devices should appear in DT.
>> If we have single device attached to two different DSI hosts I suppose
>> device should appear
>> only in one location in DT with link to another DSI host.
> Doesn't the fact that both devices are connected to different DSI hosts
> make them separate device? While it's physically one device only (there
> is one panel), device tree defines devices in terms of the control bus
> that they are connected to. Since in this case both subdevices are
> controlled by different DSI hosts that makes them separate devices.
>
>>>>>>> 2) On the DSI host side, each of the controller instances needs to know
>>>>>>> the intimate details of the other controller (or alternatively, one
>>>>>>> controller needs to be a "master" and the other a "slave").
>>>>>> The question is if they need to communicate each other, or they have
>>>>>> to have similar configurations applied?
>>>>> On Tegra at least the configuration needs to be almost the same. There
>>>>> are two registers that may need to be programmed differently. But they
>>>>> don't have to communicate with each other. Essentially the two registers
>>>>> that require different programming define which parts of the display
>>>>> controller's data stream they need to capture and turn into DSI packets.
>>>>>
>>>>> Theoretically it would be possible to make this work with two completely
>>>>> different DSI controllers, but in practice I'd expect that to never
>>>>> happen. So I'm not sure we need to consider the case where the register
>>>>> layout is different between the two DSI host controllers.
>>>> So maybe the configuration could be provided by the panel.
>>> What configuration? I suppose one idea would be for the panel driver to
>>> set the type of dual-channel mode that it's using. Panels can typically
>>> be configured to do symmetric left-right or symmetric odd-even. I think
>>> technically it's possible to have asymmetric modes, too, but to be
>>> honest I don't want to think about those yet.
>>>
>>> So I think it's reasonable for the DSI device to provide information as
>>> to what mode it's using. Perhaps that could be done as part of the slave
>>> setup.
>>>
>>>>> I've come up with another alternative that works:
>>>>>
>>>>> dsi@54300000 {
>>>>> panel: panel@0 {
>>>>> compatible = "sharp,lq101r1sx01";
>>>>> reg = <0>;
>>>>> };
>>>>> };
>>>>>
>>>>> dsi@54400000 {
>>>>> panel@0 {
>>>>> compatible = "sharp,lq101r1sx01";
>>>>> reg = <0>;
>>>>>
>>>>> master = <&panel>;
>>>>> };
>>>>> };
>>>> But here you have again two compatibles and two devices in DT representing
>>>> one HW device.
>>> Because that's what they really are. There are two different devices,
>>> it's just that they happen to be driving two separate halves of the same
>>> panel.
>> Compatible string "sharp,lq101r1sx01" clearly indicates that there are
>> two panels of type LQ101R1SX01.
>> If you really want to split this panel as two separate devices maybe you
>> should probably use separate
>> compatibles to make it more clear, sth like: "sharp,lq101r1sx01_link1",
>> "sharp,lq101r1sx01_link2".
>> Anyway it looks odd to me :)
> As best as I can tell both subdevices are actually the same.
The first represents LINK1 according to spec, more specifically
pins 2-16 of the chip, the 2nd represents LINK2 (pins 17-31) :)
The first is probably only for the left part, the 2nd for the right part
of the panel,
or respectively even/odd lines.
What about TE pin? It is single for the whole panel. Where do you want
to place it?
The same question regarding power pins.
> Although it
> seems like commands written to the primary channel have an effect on the
> device as a whole. For example if you send a DCS exit_sleep_mode command
> to the primary channel then both devices will wake up. Similarly sending
> the DCS set_display_on command will turn on the display on both halves,
> not just the one. I haven't checked yet whether the same is true when
> the commands are sent to the secondary.
>
> One other solution I had thought about looked something like this:
>
> dsi@54300000 {
> left: panel@0 {
> compatible = "sharp,lq101r1sx01-link";
> reg = <0>;
> ...
> };
> };
>
> dsi@54400000 {
> right: panel@0 {
> compatible = "sharp,lq101r1sx01-link";
> reg = <0>;
> ...
> };
> };
>
> panel: panel {
> compatible = "sharp,lq101r1sx01";
> links = <&left &right>;
> };
>
> The downside of that being that &panel becomes a non-DSI device and we
> loose meta information such as the number of lanes etc.
>
> Perhaps this could be solved by using a device_type = "dsi" property and
> thereby cause the driver core to instantiate a DSI device rather than a
> platform device. Or perhaps even device_type = "dual-dsi" so that it
> could directly hook up both channels.
>
> But that's not all that different from the minimal proposal above, and I
> don't know if it's worth the trouble. Anyway, it would be good to hear
> thoughts on this from the device tree maintainers.
>
>>>> I am not sure if it is better. If you do not like video
>>>> interfaces
>>>> maybe better would be sth like this:
>>>>
>>>> dsi@54300000 {
>>>> panel: panel@0 {
>>>> compatible = "sharp,lq101r1sx01";
>>>> reg = <0>;
>>>> secondary_dsi = <&dsiB>;
>>>> };
>>>> };
>>>>
>>>> dsiB: dsi@54400000 {
>>>> };
>>> That's pretty much the same thing that I proposed, except that it
>>> reverses the link between the two.
>> For me it is fundamentally different - in your proposition you have two
>> different panels, in my you have only one, attached to one dsi with
>> phandle to 2nd dsi.
> Looking at the example again I don't see how it could work. The phandle
> references the second DSI host, but we need a reference to the second
> DSI peripheral. We can't just assume that it's on the same virtual
> channel as the first.
Phandle can be accompanied by bus address:
secondary_dsi = <&dsiB 0>;
The rest of configuration if necessary can be specified by other properties.
This way the driver can create 2nd device using DSI equivalent of
i2c_new_device.
And we do not have problem where to put TE gpio, regulators, maybe PWM
phandle.
Regards
Andrzej
>
>>> In fact I tried something similar to
>>> that before, but it has a couple of problems: if the secondary device
>>> does not have a compatible string (that's probably not valid in device
>>> tree to begin with) then there's no way for the device to report what
>>> format it expects or what number of lanes it uses. But those are
>>> parameters that are needed to set up the DSI (and display controllers).
>> I2C has:
>> struct i2c_client *
>> i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
>>
>> DSI could have something similar, this way you could pass everything you
>> need.
> We don't need any of that if both devices have a proper compatible
> string, which they should have anyway, since then the driver can fill in
> those values as appropriate.
>
> Thierry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Dual-channel DSI
2014-08-08 10:14 ` Thierry Reding
2014-08-12 16:00 ` Andrzej Hajda
@ 2014-08-14 12:59 ` Tomi Valkeinen
1 sibling, 0 replies; 9+ messages in thread
From: Tomi Valkeinen @ 2014-08-14 12:59 UTC (permalink / raw)
To: Thierry Reding, Andrzej Hajda
Cc: Laurent Pinchart, YoungJun Cho, Ajay Kumar,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
[-- Attachment #1: Type: text/plain, Size: 4481 bytes --]
On 08/08/14 13:14, Thierry Reding wrote:
> On Fri, Aug 08, 2014 at 09:26:17AM +0200, Andrzej Hajda wrote:
>> On 08/07/2014 10:54 AM, Thierry Reding wrote:
>>> On Thu, Aug 07, 2014 at 10:39:36AM +0200, Andrzej Hajda wrote:
>>>> On 08/07/2014 09:25 AM, Thierry Reding wrote:
>>>>> On Thu, Aug 07, 2014 at 08:53:47AM +0200, Andrzej Hajda wrote:
>>>>>> Hi Thierry,
>>>>>>
>>>>>> Nice case.
>>>>>>
>>>>>> On 08/05/2014 05:39 PM, Thierry Reding wrote:
>>>>>>> Hi everyone,
>>>>>>>
>>>>>>> I've been working on adding support for a panel that uses what's
>>>>>>> commonly known as dual-channel DSI. Sometimes this is referred to as
>>>>>>> ganged-mode as well.
>>>>>>>
>>>>>>> What is it, you ask? It's essentially a hack to work around the band-
>>>>>>> width restrictions of DSI, albeit one that's been commonly implemented
>>>>>>> by several SoC vendors.
>>>>>>>
>>>>>>> This typically works by equipping a peripheral with two DSI interfaces,
>>>>>>> each of which driving one half of the screen (symmetric left-right mode)
>>>>>>> or every other line (symmetric odd-even mode). Apparently there can be
>>>>>>> asymmetric modes in addition to those two, but they seem to be the
>>>>>>> common ones. Often both of the DSI interfaces need to be configured
>>>>>>> using DCS commands and vendor specific registers.
>>>>>>>
>>>>>>> A single display controller is typically used video data transmission.
>>>>>>> This is necessary to provide synchronization and avoid tearing and all
>>>>>>> kinds of other ugliness. For this to work both DSI controllers need to
>>>>>>> be made aware of which chunk of the video data stream is addressing
>>>>>>> them.
>>>>>>>
>>>>>>> From a software perspective, this poses two problems:
>>>>>>>
>>>>>>> 1) A dual-channel device is composed of two DSI peripheral devices which
>>>>>>> cannot be programmed independently of each other. A typical example
>>>>>>> is that the frame memory extents need to be configured differently
>>>>>>> for each of the devices (using the DCS set_column_address and
>>>>>>> set_page_address commands). Therefore each device must know of the
>>>>>>> other, or there must be a driver that binds against a dummy device
>>>>>>> that pulls in the two real devices.
I once almost had to write a driver for similar panel, but luckily the project
was canceled. =)
Here are some thoughts:
If we had a panel which is controlled via i2c, but receives the video stream
from two DSI interfaces, I think the DT would look something like:
&i2c1 {
display@48 {
compatible = "sharp,lq101r1sx01";
reg = <0x48>;
ports {
port@0 {
reg = <0>;
lcd_in0: endpoint {
remote-endpoint = <&dsi1_out_ep>;
};
};
port@1 {
reg = <1>;
lcd_in1: endpoint {
remote-endpoint = <&dsi2_out_ep>;
};
};
};
};
};
&dsi1 {
port {
dsi1_out_ep: endpoint {
remote-endpoint = <&lcd_in0>;
lanes = <0 1 2 3 4 5>;
};
};
};
&dsi2 {
port {
dsi2_out_ep: endpoint {
remote-endpoint = <&lcd_in1>;
lanes = <0 1 2 3 4 5>;
};
};
};
And similarly, if the panel would be controlled via DSI, but only via one DSI
interface, I think the DT would look quite similar, except the "display" node
would be a child of "dsi1".
Now, a panel controlled via two DSI interfaces. I have to say the design sounds
rather nasty. What were the HW people thinking about? I guess you are _sure_
that you cannot do the configuration via just a single interface? =)
If you really need the control via two DSI interfaces, I'd suggest something
like this:
&dsi1 {
port {
dsi1_out_ep: endpoint {
remote-endpoint = <&lcd_in0>;
lanes = <0 1 2 3 4 5>;
};
};
display {
compatible = "sharp,lq101r1sx01";
secondary = <&panel_secondary>;
port {
lcd_in0: endpoint {
remote-endpoint = <&dsi1_out_ep>;
};
};
};
};
&dsi2 {
port {
dsi2_out_ep: endpoint {
remote-endpoint = <&lcd_in1>;
lanes = <0 1 2 3 4 5>;
};
};
panel_secondary: display {
compatible = "sharp,lq101r1sx01-secondary";
port {
lcd_in1: endpoint {
remote-endpoint = <&dsi2_out_ep>;
};
};
};
};
I guess the above was already more or less presented in the thread, but I
didn't see it written out.
So there would two two devices, a master and a slave, and in the driver side
the slave would not do anything by itself.
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-08-14 12:59 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-05 15:39 Dual-channel DSI Thierry Reding
2014-08-07 6:53 ` Andrzej Hajda
2014-08-07 7:25 ` Thierry Reding
2014-08-07 8:39 ` Andrzej Hajda
2014-08-07 8:54 ` Thierry Reding
2014-08-08 7:26 ` Andrzej Hajda
2014-08-08 10:14 ` Thierry Reding
2014-08-12 16:00 ` Andrzej Hajda
2014-08-14 12:59 ` Tomi Valkeinen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).